expo-helium 0.8.2 → 0.8.4
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/README.md +18 -125
- package/build/HeliumPaywallSdk.types.d.ts +3 -0
- package/build/HeliumPaywallSdk.types.d.ts.map +1 -1
- package/build/HeliumPaywallSdk.types.js.map +1 -1
- package/build/HeliumPaywallSdkModule.d.ts +6 -0
- package/build/HeliumPaywallSdkModule.d.ts.map +1 -1
- package/build/HeliumPaywallSdkModule.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +36 -5
- package/build/index.js.map +1 -1
- package/build/revenuecat/revenuecat.d.ts +1 -0
- package/build/revenuecat/revenuecat.d.ts.map +1 -1
- package/build/revenuecat/revenuecat.js +30 -6
- package/build/revenuecat/revenuecat.js.map +1 -1
- package/ios/HeliumPaywallSdk.podspec +1 -1
- package/ios/HeliumPaywallSdkModule.swift +65 -1
- package/package.json +1 -1
- package/src/HeliumPaywallSdk.types.ts +3 -0
- package/src/HeliumPaywallSdkModule.ts +9 -0
- package/src/index.ts +46 -6
- package/src/revenuecat/revenuecat.ts +29 -6
package/README.md
CHANGED
|
@@ -1,139 +1,32 @@
|
|
|
1
1
|
# helium-expo-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Helium is an upsell experimentation and optimization platform for mobile apps of all sizes.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## How to Integrate
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Follow our [official documentation here](https://docs.tryhelium.com/sdk/quickstart-react-native) to integrate Helium into your Expo / React Native app!
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Contributing
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Helpful: expo [module documentation here](https://docs.expo.dev/modules/native-module-tutorial/) and [API here](https://docs.expo.dev/modules/module-api/)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
npx expo install expo-helium
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
We recommend using Expo 53 and up.
|
|
18
|
-
|
|
19
|
-
## **Configuration**
|
|
20
|
-
|
|
21
|
-
### Initialization
|
|
22
|
-
|
|
23
|
-
Initialize Helium by calling `initialize()` early in your app's lifecycle, typically in your root component.
|
|
24
|
-
`initialize` takes in a configuration object that includes your purchase config, event handlers, and other settings. (If you are using **RevenueCat**, skip to the next section.)
|
|
25
|
-
|
|
26
|
-
```tsx
|
|
27
|
-
import { initialize, createCustomPurchaseConfig, HELIUM_CTA_NAMES } from 'expo-helium';
|
|
13
|
+
### Run the Example Project
|
|
28
14
|
|
|
29
|
-
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
initialize({
|
|
32
|
-
// Helium provided api key
|
|
33
|
-
apiKey: '<your-helium-api-key>',
|
|
15
|
+
Start the TypeScript compiler to watch for changes.
|
|
34
16
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// Purchase configuration (see next section if using RevenueCat)
|
|
39
|
-
purchaseConfig: createCustomPurchaseConfig({
|
|
40
|
-
makePurchase: async (productId) => {
|
|
41
|
-
// Your purchase logic here
|
|
42
|
-
return { status: 'purchased' };
|
|
43
|
-
},
|
|
44
|
-
restorePurchases: async () => {
|
|
45
|
-
// Your restore logic here
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
}),
|
|
49
|
-
|
|
50
|
-
// Event handler for paywall events
|
|
51
|
-
onHeliumPaywallEvent: (event) => {
|
|
52
|
-
switch (event.type) {
|
|
53
|
-
case 'paywallOpen':
|
|
54
|
-
break;
|
|
55
|
-
case 'ctaPressed':
|
|
56
|
-
if (event.ctaName === HELIUM_CTA_NAMES.SCHEDULE_CALL) {
|
|
57
|
-
// Handle schedule call
|
|
58
|
-
}
|
|
59
|
-
break;
|
|
60
|
-
case 'subscriptionSucceeded':
|
|
61
|
-
// Handle successful subscription
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
// Custom user traits
|
|
67
|
-
customUserTraits: {
|
|
68
|
-
"example_trait": "example_value",
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
});
|
|
72
|
-
}, []);
|
|
73
|
-
}
|
|
17
|
+
```shell
|
|
18
|
+
npm run build
|
|
74
19
|
```
|
|
75
20
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
**Important** Make sure that you've already:
|
|
21
|
+
In a separate terminal window, run the example app.
|
|
79
22
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const asyncHeliumInit = async () => {
|
|
89
|
-
initialize({
|
|
90
|
-
apiKey: '<your-helium-api-key>',
|
|
91
|
-
customUserId: '<your-custom-user-id>',
|
|
92
|
-
purchaseConfig: createRevenueCatPurchaseConfig(),
|
|
93
|
-
onHeliumPaywallEvent: (event) => {
|
|
94
|
-
switch (event.type) {
|
|
95
|
-
case 'subscriptionFailed':
|
|
96
|
-
// Custom logic
|
|
97
|
-
break;
|
|
98
|
-
case 'subscriptionSucceeded':
|
|
99
|
-
// Handle a subscription success event
|
|
100
|
-
// e.g. navigate to a premium page
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
revenueCatAppUserId: await Purchases.getAppUserID()
|
|
105
|
-
});
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
void asyncHeliumInit();
|
|
110
|
-
}, []);
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## **Presenting Paywalls**
|
|
114
|
-
|
|
115
|
-
`presentUpsell` takes in a dictionary specifying the `triggerName` as well as an optional `onFallback` parameter defining custom fallback behavior (in case the user didn't have a network connection)
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
import { presentUpsell } from 'expo-helium';
|
|
119
|
-
|
|
120
|
-
function YourComponent() {
|
|
121
|
-
const handlePremiumPress = () => {
|
|
122
|
-
presentUpsell({
|
|
123
|
-
triggerName: 'premium_feature_press',
|
|
124
|
-
onFallback: () => {
|
|
125
|
-
// Implement logic to open a default paywall
|
|
126
|
-
console.log('[Helium] onFallback called!');
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
return (
|
|
132
|
-
<Button title="Try Premium" onPress={handlePremiumPress} />
|
|
133
|
-
);
|
|
134
|
-
}
|
|
23
|
+
```shell
|
|
24
|
+
cd example
|
|
25
|
+
# Run the example app on Android
|
|
26
|
+
npx expo run:android
|
|
27
|
+
# Run the example app on iOS
|
|
28
|
+
npx expo run:ios
|
|
29
|
+
# or
|
|
30
|
+
npx expo run:ios --device
|
|
135
31
|
```
|
|
136
32
|
|
|
137
|
-
## **Paywall Events**
|
|
138
|
-
|
|
139
|
-
Helium emits various events during the lifecycle of a paywall. You can handle these events in your payment delegate. See the [Helium Events](https://docs.tryhelium.com/sdk/helium-events) for more details.
|
|
@@ -57,6 +57,7 @@ export interface HeliumConfig {
|
|
|
57
57
|
purchaseConfig: HeliumPurchaseConfig;
|
|
58
58
|
/** Callback for receiving all Helium paywall events. */
|
|
59
59
|
onHeliumPaywallEvent: (event: HeliumPaywallEvent) => void;
|
|
60
|
+
fallbackBundle?: object;
|
|
60
61
|
triggers?: string[];
|
|
61
62
|
customUserId?: string;
|
|
62
63
|
customAPIEndpoint?: string;
|
|
@@ -69,6 +70,8 @@ export interface NativeHeliumConfig {
|
|
|
69
70
|
customAPIEndpoint?: string;
|
|
70
71
|
customUserTraits?: Record<string, any>;
|
|
71
72
|
revenueCatAppUserId?: string;
|
|
73
|
+
fallbackBundleUrlString?: string;
|
|
74
|
+
fallbackBundleString?: string;
|
|
72
75
|
}
|
|
73
76
|
export interface PaywallInfo {
|
|
74
77
|
paywallTemplateName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeliumPaywallSdk.types.d.ts","sourceRoot":"","sources":["../src/HeliumPaywallSdk.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,oBAAoB,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC3D,qBAAqB,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;CAC9D,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AACF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,kBAAkB,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AACpG,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,uBAAuB,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AACF,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,YAAY,GAAG,kBAAkB,CAAC;AAI7G,8DAA8D;AAE9D,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnE,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzC,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAGD,wBAAgB,0BAA0B,CAAC,SAAS,EAAE;IACpD,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnE,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1C,GAAG,oBAAoB,CAKvB;AAED,MAAM,WAAW,YAAY;IAC3B,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,mGAAmG;IACnG,cAAc,EAAE,oBAAoB,CAAC;IACrC,wDAAwD;IACxD,oBAAoB,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAG1D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACvC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACvC,mBAAmB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"HeliumPaywallSdk.types.d.ts","sourceRoot":"","sources":["../src/HeliumPaywallSdk.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeliumPaywallSdk.types.js","sourceRoot":"","sources":["../src/HeliumPaywallSdk.types.ts"],"names":[],"mappings":"AAwDA,sDAAsD;AACtD,MAAM,UAAU,0BAA0B,CAAC,SAG1C;IACC,OAAO;QACL,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,gBAAgB,EAAE,SAAS,CAAC,gBAAgB;KAC7C,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"HeliumPaywallSdk.types.js","sourceRoot":"","sources":["../src/HeliumPaywallSdk.types.ts"],"names":[],"mappings":"AAwDA,sDAAsD;AACtD,MAAM,UAAU,0BAA0B,CAAC,SAG1C;IACC,OAAO;QACL,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,gBAAgB,EAAE,SAAS,CAAC,gBAAgB;KAC7C,CAAC;AACJ,CAAC;AAkCD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,aAAa,EAAE,eAAe;IAC9B,gBAAgB,EAAE,kBAAkB;CACrC,CAAA","sourcesContent":["import type { StyleProp, ViewStyle } from 'react-native';\n\nexport type OnLoadEventPayload = {\n url: string;\n};\n\nexport type HeliumPaywallSdkModuleEvents = {\n onHeliumPaywallEvent: (params: HeliumPaywallEvent) => void;\n onDelegateActionEvent: (params: DelegateActionEvent) => void;\n};\nexport type HeliumPaywallEvent = {\n type: string;\n triggerName?: string;\n paywallTemplateName?: string;\n productKey?: string;\n ctaName?: string;\n configId?: string;\n numAttempts?: number;\n downloadTimeTakenMS?: number;\n webviewRenderTimeTakenMS?: number;\n imagesDownloadTimeTakenMS?: number;\n fontsDownloadTimeTakenMS?: number;\n bundleDownloadTimeMS?: number;\n dismissAll?: boolean;\n errorDescription?: string;\n};\nexport type DelegateActionEvent = {\n type: 'purchase' | 'restore';\n productId?: string;\n};\n\nexport type HeliumPaywallSdkViewProps = {\n url: string;\n onLoad: (event: { nativeEvent: OnLoadEventPayload }) => void;\n style?: StyleProp<ViewStyle>;\n};\n\nexport type HeliumTransactionStatus = 'purchased' | 'failed' | 'cancelled' | 'pending' | 'restored';\nexport type HeliumPurchaseResult = {\n status: HeliumTransactionStatus;\n error?: string; // Optional error message\n};\nexport type HeliumDownloadStatus = 'downloadSuccess' | 'downloadFailure' | 'inProgress' | 'notDownloadedYet';\n\n// --- Purchase Configuration Types ---\n\n/** Interface for providing custom purchase handling logic. */\n\nexport interface HeliumPurchaseConfig {\n makePurchase: (productId: string) => Promise<HeliumPurchaseResult>;\n restorePurchases: () => Promise<boolean>;\n\n /** Optional RevenueCat API Key. If not provided, RevenueCat must be configured elsewhere. */\n apiKey?: string;\n}\n\n// Helper function for creating Custom Purchase Config\nexport function createCustomPurchaseConfig(callbacks: {\n makePurchase: (productId: string) => Promise<HeliumPurchaseResult>;\n restorePurchases: () => Promise<boolean>;\n}): HeliumPurchaseConfig {\n return {\n makePurchase: callbacks.makePurchase,\n restorePurchases: callbacks.restorePurchases,\n };\n}\n\nexport interface HeliumConfig {\n /** Your Helium API Key */\n apiKey: string;\n /** Configuration for handling purchases. Can be custom functions or a pre-built handler config. */\n purchaseConfig: HeliumPurchaseConfig;\n /** Callback for receiving all Helium paywall events. */\n onHeliumPaywallEvent: (event: HeliumPaywallEvent) => void; // Still mandatory\n\n // Optional configurations\n fallbackBundle?: object;\n triggers?: string[];\n customUserId?: string;\n customAPIEndpoint?: string;\n customUserTraits?: Record<string, any>;\n revenueCatAppUserId?: string;\n}\n\nexport interface NativeHeliumConfig {\n apiKey: string;\n customUserId?: string;\n customAPIEndpoint?: string;\n customUserTraits?: Record<string, any>;\n revenueCatAppUserId?: string;\n fallbackBundleUrlString?: string;\n fallbackBundleString?: string;\n}\n\nexport interface PaywallInfo {\n paywallTemplateName: string;\n shouldShow: boolean;\n}\n\nexport const HELIUM_CTA_NAMES = {\n SCHEDULE_CALL: 'schedule_call',\n SUBSCRIBE_BUTTON: 'subscribe_button',\n}\n"]}
|
|
@@ -5,16 +5,22 @@ interface PaywallInfoResult {
|
|
|
5
5
|
templateName?: string;
|
|
6
6
|
shouldShow?: boolean;
|
|
7
7
|
}
|
|
8
|
+
interface CanPresentUpsellResult {
|
|
9
|
+
canPresent?: boolean;
|
|
10
|
+
reason?: string;
|
|
11
|
+
}
|
|
8
12
|
declare class HeliumPaywallSdkModule extends NativeModule<HeliumPaywallSdkModuleEvents> {
|
|
9
13
|
initialize(config: NativeHeliumConfig): void;
|
|
10
14
|
presentUpsell(triggerName: string): void;
|
|
11
15
|
hideUpsell(): void;
|
|
12
16
|
hideAllUpsells(): void;
|
|
13
17
|
getDownloadStatus(): HeliumDownloadStatus;
|
|
18
|
+
canPresentUpsell(trigger: string): CanPresentUpsellResult;
|
|
14
19
|
fallbackOpenOrCloseEvent(trigger: string, isOpen: boolean, viewType: string): void;
|
|
15
20
|
handlePurchaseResult(statusString: HeliumTransactionStatus, errorMsg?: string): void;
|
|
16
21
|
handleRestoreResult(success: boolean): void;
|
|
17
22
|
getPaywallInfo(trigger: string): PaywallInfoResult;
|
|
23
|
+
handleDeepLink(urlString: string): boolean;
|
|
18
24
|
}
|
|
19
25
|
declare const _default: HeliumPaywallSdkModule;
|
|
20
26
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeliumPaywallSdkModule.d.ts","sourceRoot":"","sources":["../src/HeliumPaywallSdkModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAElC,UAAU,iBAAiB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,OAAO,OAAO,sBAAuB,SAAQ,YAAY,CAAC,4BAA4B,CAAC;IACrF,UAAU,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAE5C,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAExC,UAAU,IAAI,IAAI;IAElB,cAAc,IAAI,IAAI;IAEtB,iBAAiB,IAAI,oBAAoB;IAEzC,wBAAwB,CACtB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,GACf,IAAI;IAEP,oBAAoB,CAClB,YAAY,EAAE,uBAAuB,EACrC,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI;IAEP,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAE3C,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB;
|
|
1
|
+
{"version":3,"file":"HeliumPaywallSdkModule.d.ts","sourceRoot":"","sources":["../src/HeliumPaywallSdkModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAElC,UAAU,iBAAiB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,sBAAsB;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,OAAO,OAAO,sBAAuB,SAAQ,YAAY,CAAC,4BAA4B,CAAC;IACrF,UAAU,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAE5C,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAExC,UAAU,IAAI,IAAI;IAElB,cAAc,IAAI,IAAI;IAEtB,iBAAiB,IAAI,oBAAoB;IAEzC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB;IAEzD,wBAAwB,CACtB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,GACf,IAAI;IAEP,oBAAoB,CAClB,YAAY,EAAE,uBAAuB,EACrC,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI;IAEP,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAE3C,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB;IAElD,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;CAC3C;;AAGD,wBAA+E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeliumPaywallSdkModule.js","sourceRoot":"","sources":["../src/HeliumPaywallSdkModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"HeliumPaywallSdkModule.js","sourceRoot":"","sources":["../src/HeliumPaywallSdkModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAmDzD,yDAAyD;AACzD,eAAe,mBAAmB,CAAyB,kBAAkB,CAAC,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo\";\n\nimport {\n HeliumDownloadStatus,\n HeliumPaywallSdkModuleEvents,\n HeliumTransactionStatus,\n NativeHeliumConfig,\n} from \"./HeliumPaywallSdk.types\";\n\ninterface PaywallInfoResult {\n errorMsg?: string;\n templateName?: string;\n shouldShow?: boolean;\n}\n\ninterface CanPresentUpsellResult {\n canPresent?: boolean;\n reason?: string;\n}\n\ndeclare class HeliumPaywallSdkModule extends NativeModule<HeliumPaywallSdkModuleEvents> {\n initialize(config: NativeHeliumConfig): void;\n\n presentUpsell(triggerName: string): void;\n\n hideUpsell(): void;\n\n hideAllUpsells(): void;\n\n getDownloadStatus(): HeliumDownloadStatus;\n\n canPresentUpsell(trigger: string): CanPresentUpsellResult;\n\n fallbackOpenOrCloseEvent(\n trigger: string,\n isOpen: boolean,\n viewType: string,\n ): void;\n\n handlePurchaseResult(\n statusString: HeliumTransactionStatus,\n errorMsg?: string,\n ): void;\n\n handleRestoreResult(success: boolean): void;\n\n getPaywallInfo(trigger: string): PaywallInfoResult;\n\n handleDeepLink(urlString: string): boolean;\n}\n\n// This call loads the native module object from the JSI.\nexport default requireNativeModule<HeliumPaywallSdkModule>(\"HeliumPaywallSdk\");\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare const hideUpsell: () => void;
|
|
|
10
10
|
export declare const hideAllUpsells: () => void;
|
|
11
11
|
export declare const getDownloadStatus: () => import("./HeliumPaywallSdk.types").HeliumDownloadStatus;
|
|
12
12
|
export declare const getPaywallInfo: (trigger: string) => PaywallInfo | undefined;
|
|
13
|
+
export declare const handleDeepLink: (url: string | null) => boolean;
|
|
13
14
|
export { createCustomPurchaseConfig, HELIUM_CTA_NAMES } from './HeliumPaywallSdk.types';
|
|
14
15
|
export type { HeliumTransactionStatus, HeliumConfig, } from './HeliumPaywallSdk.types';
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EAEQ,WAAW,EAChC,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EAEQ,WAAW,EAChC,MAAM,0BAA0B,CAAC;AAKlC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAEnD,cAAe,0BAA0B,CAAC;AAW1C,eAAO,MAAM,UAAU,GAAI,QAAQ,YAAY,SA2C9C,CAAC;AAyCF,eAAO,MAAM,aAAa,GAAI,6BAGG;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB,SAmBA,CAAC;AAEF,eAAO,MAAM,UAAU,YAAoC,CAAC;AAC5D,eAAO,MAAM,cAAc,YAAwC,CAAC;AACpE,eAAO,MAAM,iBAAiB,+DAA2C,CAAC;AAE1E,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,WAAW,GAAG,SAc9D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,GAAG,IAAI,YAOhD,CAAC;AAEF,OAAO,EAAC,0BAA0B,EAAE,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;AAEtF,YAAY,EACV,uBAAuB,EACvB,YAAY,GACb,MAAM,0BAA0B,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import HeliumPaywallSdkModule from "./HeliumPaywallSdkModule";
|
|
2
|
+
import * as ExpoFileSystem from 'expo-file-system';
|
|
2
3
|
export { default } from './HeliumPaywallSdkModule';
|
|
3
4
|
// export { default as HeliumPaywallSdkView } from './HeliumPaywallSdkView';
|
|
4
5
|
export * from './HeliumPaywallSdk.types';
|
|
@@ -48,22 +49,44 @@ export const initialize = (config) => {
|
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
});
|
|
52
|
+
nativeInitializeAsync(config).catch(error => {
|
|
53
|
+
console.error('[Helium] Initialization failed:', error);
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
const nativeInitializeAsync = async (config) => {
|
|
57
|
+
let fallbackBundleUrlString;
|
|
58
|
+
let fallbackBundleString;
|
|
59
|
+
if (config.fallbackBundle) {
|
|
60
|
+
try {
|
|
61
|
+
const jsonContent = JSON.stringify(config.fallbackBundle);
|
|
62
|
+
// Write to documents directory
|
|
63
|
+
fallbackBundleUrlString = `${ExpoFileSystem.documentDirectory}helium-fallback.json`;
|
|
64
|
+
// This is ASYNC but that's ok because helium initialize in swift code is async anyways.
|
|
65
|
+
await ExpoFileSystem.writeAsStringAsync(fallbackBundleUrlString, jsonContent);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// Fallback to string approach if unexpected error occurs
|
|
69
|
+
console.log('[Helium] expo-file-system not available, attempting to pass fallback bundle as string.');
|
|
70
|
+
fallbackBundleString = JSON.stringify(config.fallbackBundle);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
51
73
|
// Create native config object
|
|
52
74
|
const nativeConfig = {
|
|
53
75
|
apiKey: config.apiKey,
|
|
54
76
|
customUserId: config.customUserId,
|
|
55
77
|
customAPIEndpoint: config.customAPIEndpoint,
|
|
56
78
|
customUserTraits: config.customUserTraits,
|
|
57
|
-
revenueCatAppUserId: config.revenueCatAppUserId
|
|
79
|
+
revenueCatAppUserId: config.revenueCatAppUserId,
|
|
80
|
+
fallbackBundleUrlString: fallbackBundleUrlString,
|
|
81
|
+
fallbackBundleString: fallbackBundleString,
|
|
58
82
|
};
|
|
59
83
|
// Initialize the native module
|
|
60
84
|
HeliumPaywallSdkModule.initialize(nativeConfig);
|
|
61
85
|
};
|
|
62
86
|
export const presentUpsell = ({ triggerName, onFallback }) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
console.log(`Helium trigger "${triggerName}" not found or download status not successful. Status:`, downloadStatus);
|
|
87
|
+
const { canPresent, reason } = HeliumPaywallSdkModule.canPresentUpsell(triggerName);
|
|
88
|
+
if (!canPresent) {
|
|
89
|
+
console.log(`[Helium] Cannot present trigger "${triggerName}". Reason: ${reason}`);
|
|
67
90
|
onFallback?.();
|
|
68
91
|
HeliumPaywallSdkModule.fallbackOpenOrCloseEvent(triggerName, true, 'presented');
|
|
69
92
|
return;
|
|
@@ -95,5 +118,13 @@ export const getPaywallInfo = (trigger) => {
|
|
|
95
118
|
shouldShow: result.shouldShow ?? true,
|
|
96
119
|
};
|
|
97
120
|
};
|
|
121
|
+
export const handleDeepLink = (url) => {
|
|
122
|
+
if (url) {
|
|
123
|
+
const handled = HeliumPaywallSdkModule.handleDeepLink(url);
|
|
124
|
+
console.log('[Helium] Handled deep link:', handled);
|
|
125
|
+
return handled;
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
};
|
|
98
129
|
export { createCustomPurchaseConfig, HELIUM_CTA_NAMES } from './HeliumPaywallSdk.types';
|
|
99
130
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DelegateActionEvent,\n HeliumConfig,\n HeliumPaywallEvent,\n NativeHeliumConfig, PaywallInfo,\n} from \"./HeliumPaywallSdk.types\";\nimport HeliumPaywallSdkModule from \"./HeliumPaywallSdkModule\";\nimport { EventSubscription } from 'expo-modules-core';\n\nexport { default } from './HeliumPaywallSdkModule';\n// export { default as HeliumPaywallSdkView } from './HeliumPaywallSdkView';\nexport * from './HeliumPaywallSdk.types';\n\nfunction addHeliumPaywallEventListener(listener: (event: HeliumPaywallEvent) => void): EventSubscription {\n return HeliumPaywallSdkModule.addListener('onHeliumPaywallEvent', listener);\n}\n\nfunction addDelegateActionEventListener(listener: (event: DelegateActionEvent) => void): EventSubscription {\n return HeliumPaywallSdkModule.addListener('onDelegateActionEvent', listener);\n}\n\nlet isInitialized = false;\nexport const initialize = (config: HeliumConfig) => {\n if (isInitialized) {\n return;\n }\n isInitialized = true;\n\n HeliumPaywallSdkModule.removeAllListeners('onHeliumPaywallEvent');\n HeliumPaywallSdkModule.removeAllListeners('onDelegateActionEvent');\n\n // Set up listener for paywall events\n addHeliumPaywallEventListener((event) => {\n config.onHeliumPaywallEvent(event);\n });\n\n // Set up delegate action listener for purchase and restore operations\n addDelegateActionEventListener(async (event) => {\n try {\n if (event.type === 'purchase') {\n if (event.productId) {\n const result = await config.purchaseConfig.makePurchase(event.productId);\n HeliumPaywallSdkModule.handlePurchaseResult(result.status, result.error);\n } else {\n HeliumPaywallSdkModule.handlePurchaseResult('failed', 'No product ID for purchase event.');\n }\n }\n else if (event.type === 'restore') {\n const success = await config.purchaseConfig.restorePurchases();\n HeliumPaywallSdkModule.handleRestoreResult(success);\n }\n } catch (error) {\n // Send failure result based on action type\n if (event.type === 'purchase') {\n console.log('[Helium] Unexpected error: ', error);\n HeliumPaywallSdkModule.handlePurchaseResult('failed');\n } else if (event.type === 'restore') {\n HeliumPaywallSdkModule.handleRestoreResult(false);\n }\n }\n });\n\n // Create native config object\n const nativeConfig: NativeHeliumConfig = {\n apiKey: config.apiKey,\n customUserId: config.customUserId,\n customAPIEndpoint: config.customAPIEndpoint,\n customUserTraits: config.customUserTraits,\n revenueCatAppUserId: config.revenueCatAppUserId\n };\n\n // Initialize the native module\n HeliumPaywallSdkModule.initialize(nativeConfig);\n};\n\nexport const presentUpsell = ({\n triggerName,\n onFallback\n }: {\n triggerName: string;\n onFallback?: () => void;\n}) => {\n // todo check HeliumBridge.getFetchedTriggerNames((triggerNames: string[]) ??\n const downloadStatus = getDownloadStatus();\n if (downloadStatus !== 'downloadSuccess') {\n console.log(\n `Helium trigger \"${triggerName}\" not found or download status not successful. Status:`,\n downloadStatus\n );\n onFallback?.();\n HeliumPaywallSdkModule.fallbackOpenOrCloseEvent(triggerName, true, 'presented');\n return;\n }\n\n try {\n HeliumPaywallSdkModule.presentUpsell(triggerName);\n } catch (error) {\n console.log('Helium present error', error);\n onFallback?.();\n HeliumPaywallSdkModule.fallbackOpenOrCloseEvent(triggerName, true, 'presented');\n }\n};\n\nexport const hideUpsell = HeliumPaywallSdkModule.hideUpsell;\nexport const hideAllUpsells = HeliumPaywallSdkModule.hideAllUpsells;\nexport const getDownloadStatus = HeliumPaywallSdkModule.getDownloadStatus;\n\nexport const getPaywallInfo = (trigger: string): PaywallInfo | undefined => {\n const result = HeliumPaywallSdkModule.getPaywallInfo(trigger);\n if (!result) {\n console.log('[Helium] getPaywallInfo unexpected error.');\n return;\n }\n if (result.errorMsg) {\n console.log(`[Helium] ${result.errorMsg}`);\n return;\n }\n return {\n paywallTemplateName: result.templateName ?? 'unknown template',\n shouldShow: result.shouldShow ?? true,\n };\n};\n\nexport {createCustomPurchaseConfig, HELIUM_CTA_NAMES} from './HeliumPaywallSdk.types';\n\nexport type {\n HeliumTransactionStatus,\n HeliumConfig,\n} from './HeliumPaywallSdk.types';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DelegateActionEvent,\n HeliumConfig,\n HeliumPaywallEvent,\n NativeHeliumConfig, PaywallInfo,\n} from \"./HeliumPaywallSdk.types\";\nimport HeliumPaywallSdkModule from \"./HeliumPaywallSdkModule\";\nimport { EventSubscription } from 'expo-modules-core';\nimport * as ExpoFileSystem from 'expo-file-system';\n\nexport { default } from './HeliumPaywallSdkModule';\n// export { default as HeliumPaywallSdkView } from './HeliumPaywallSdkView';\nexport * from './HeliumPaywallSdk.types';\n\nfunction addHeliumPaywallEventListener(listener: (event: HeliumPaywallEvent) => void): EventSubscription {\n return HeliumPaywallSdkModule.addListener('onHeliumPaywallEvent', listener);\n}\n\nfunction addDelegateActionEventListener(listener: (event: DelegateActionEvent) => void): EventSubscription {\n return HeliumPaywallSdkModule.addListener('onDelegateActionEvent', listener);\n}\n\nlet isInitialized = false;\nexport const initialize = (config: HeliumConfig) => {\n if (isInitialized) {\n return;\n }\n isInitialized = true;\n\n HeliumPaywallSdkModule.removeAllListeners('onHeliumPaywallEvent');\n HeliumPaywallSdkModule.removeAllListeners('onDelegateActionEvent');\n\n // Set up listener for paywall events\n addHeliumPaywallEventListener((event) => {\n config.onHeliumPaywallEvent(event);\n });\n\n // Set up delegate action listener for purchase and restore operations\n addDelegateActionEventListener(async (event) => {\n try {\n if (event.type === 'purchase') {\n if (event.productId) {\n const result = await config.purchaseConfig.makePurchase(event.productId);\n HeliumPaywallSdkModule.handlePurchaseResult(result.status, result.error);\n } else {\n HeliumPaywallSdkModule.handlePurchaseResult('failed', 'No product ID for purchase event.');\n }\n }\n else if (event.type === 'restore') {\n const success = await config.purchaseConfig.restorePurchases();\n HeliumPaywallSdkModule.handleRestoreResult(success);\n }\n } catch (error) {\n // Send failure result based on action type\n if (event.type === 'purchase') {\n console.log('[Helium] Unexpected error: ', error);\n HeliumPaywallSdkModule.handlePurchaseResult('failed');\n } else if (event.type === 'restore') {\n HeliumPaywallSdkModule.handleRestoreResult(false);\n }\n }\n });\n\n nativeInitializeAsync(config).catch(error => {\n console.error('[Helium] Initialization failed:', error);\n });\n};\n\nconst nativeInitializeAsync = async (config: HeliumConfig) => {\n let fallbackBundleUrlString;\n let fallbackBundleString;\n if (config.fallbackBundle) {\n try {\n const jsonContent = JSON.stringify(config.fallbackBundle);\n\n // Write to documents directory\n fallbackBundleUrlString = `${ExpoFileSystem.documentDirectory}helium-fallback.json`;\n // This is ASYNC but that's ok because helium initialize in swift code is async anyways.\n await ExpoFileSystem.writeAsStringAsync(\n fallbackBundleUrlString,\n jsonContent\n );\n } catch (error) {\n // Fallback to string approach if unexpected error occurs\n console.log(\n '[Helium] expo-file-system not available, attempting to pass fallback bundle as string.'\n );\n fallbackBundleString = JSON.stringify(config.fallbackBundle);\n }\n }\n\n\n // Create native config object\n const nativeConfig: NativeHeliumConfig = {\n apiKey: config.apiKey,\n customUserId: config.customUserId,\n customAPIEndpoint: config.customAPIEndpoint,\n customUserTraits: config.customUserTraits,\n revenueCatAppUserId: config.revenueCatAppUserId,\n fallbackBundleUrlString: fallbackBundleUrlString,\n fallbackBundleString: fallbackBundleString,\n };\n\n // Initialize the native module\n HeliumPaywallSdkModule.initialize(nativeConfig);\n};\n\nexport const presentUpsell = ({\n triggerName,\n onFallback\n }: {\n triggerName: string;\n onFallback?: () => void;\n}) => {\n const { canPresent, reason } = HeliumPaywallSdkModule.canPresentUpsell(triggerName);\n\n if (!canPresent) {\n console.log(\n `[Helium] Cannot present trigger \"${triggerName}\". Reason: ${reason}`\n );\n onFallback?.();\n HeliumPaywallSdkModule.fallbackOpenOrCloseEvent(triggerName, true, 'presented');\n return;\n }\n\n try {\n HeliumPaywallSdkModule.presentUpsell(triggerName);\n } catch (error) {\n console.log('Helium present error', error);\n onFallback?.();\n HeliumPaywallSdkModule.fallbackOpenOrCloseEvent(triggerName, true, 'presented');\n }\n};\n\nexport const hideUpsell = HeliumPaywallSdkModule.hideUpsell;\nexport const hideAllUpsells = HeliumPaywallSdkModule.hideAllUpsells;\nexport const getDownloadStatus = HeliumPaywallSdkModule.getDownloadStatus;\n\nexport const getPaywallInfo = (trigger: string): PaywallInfo | undefined => {\n const result = HeliumPaywallSdkModule.getPaywallInfo(trigger);\n if (!result) {\n console.log('[Helium] getPaywallInfo unexpected error.');\n return;\n }\n if (result.errorMsg) {\n console.log(`[Helium] ${result.errorMsg}`);\n return;\n }\n return {\n paywallTemplateName: result.templateName ?? 'unknown template',\n shouldShow: result.shouldShow ?? true,\n };\n};\n\nexport const handleDeepLink = (url: string | null) => {\n if (url) {\n const handled = HeliumPaywallSdkModule.handleDeepLink(url);\n console.log('[Helium] Handled deep link:', handled);\n return handled;\n }\n return false;\n};\n\nexport {createCustomPurchaseConfig, HELIUM_CTA_NAMES} from './HeliumPaywallSdk.types';\n\nexport type {\n HeliumTransactionStatus,\n HeliumConfig,\n} from './HeliumPaywallSdk.types';\n"]}
|
|
@@ -6,6 +6,7 @@ export declare class RevenueCatHeliumHandler {
|
|
|
6
6
|
private productIdToPackageMapping;
|
|
7
7
|
private isMappingInitialized;
|
|
8
8
|
private initializationPromise;
|
|
9
|
+
private rcProductToPackageMapping;
|
|
9
10
|
constructor(apiKey?: string);
|
|
10
11
|
private initializePackageMapping;
|
|
11
12
|
private ensureMappingInitialized;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revenuecat.d.ts","sourceRoot":"","sources":["../../src/revenuecat/revenuecat.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,oBAAoB,EAAE,oBAAoB,EAAC,MAAM,2BAA2B,CAAC;AAGrF,wBAAgB,8BAA8B,CAAC,MAAM,CAAC,EAAE;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,oBAAoB,CAOvB;AAED,qBAAa,uBAAuB;IAChC,OAAO,CAAC,yBAAyB,CAAwC;IACzE,OAAO,CAAC,oBAAoB,CAAkB;IAC9C,OAAO,CAAC,qBAAqB,CAA8B;
|
|
1
|
+
{"version":3,"file":"revenuecat.d.ts","sourceRoot":"","sources":["../../src/revenuecat/revenuecat.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,oBAAoB,EAAE,oBAAoB,EAAC,MAAM,2BAA2B,CAAC;AAGrF,wBAAgB,8BAA8B,CAAC,MAAM,CAAC,EAAE;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,oBAAoB,CAOvB;AAED,qBAAa,uBAAuB;IAChC,OAAO,CAAC,yBAAyB,CAAwC;IACzE,OAAO,CAAC,oBAAoB,CAAkB;IAC9C,OAAO,CAAC,qBAAqB,CAA8B;IAE3D,OAAO,CAAC,yBAAyB,CAA6C;gBAElE,MAAM,CAAC,EAAE,MAAM;YAQb,wBAAwB;YAyBxB,wBAAwB;IAQhC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA+EpE,OAAO,CAAC,eAAe;IAMjB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;CAS7C"}
|
|
@@ -12,6 +12,7 @@ export class RevenueCatHeliumHandler {
|
|
|
12
12
|
productIdToPackageMapping = {};
|
|
13
13
|
isMappingInitialized = false;
|
|
14
14
|
initializationPromise = null;
|
|
15
|
+
rcProductToPackageMapping = {};
|
|
15
16
|
constructor(apiKey) {
|
|
16
17
|
if (apiKey) {
|
|
17
18
|
Purchases.configure({ apiKey });
|
|
@@ -27,15 +28,14 @@ export class RevenueCatHeliumHandler {
|
|
|
27
28
|
this.initializationPromise = (async () => {
|
|
28
29
|
try {
|
|
29
30
|
const offerings = await Purchases.getOfferings();
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
const allOfferings = offerings.all;
|
|
32
|
+
for (const offering of Object.values(allOfferings)) {
|
|
33
|
+
offering.availablePackages.forEach((pkg) => {
|
|
32
34
|
if (pkg.product?.identifier) {
|
|
33
35
|
this.productIdToPackageMapping[pkg.product.identifier] = pkg;
|
|
34
36
|
}
|
|
35
37
|
});
|
|
36
38
|
}
|
|
37
|
-
else {
|
|
38
|
-
}
|
|
39
39
|
this.isMappingInitialized = true;
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
@@ -58,11 +58,35 @@ export class RevenueCatHeliumHandler {
|
|
|
58
58
|
async makePurchase(productId) {
|
|
59
59
|
await this.ensureMappingInitialized();
|
|
60
60
|
const pkg = this.productIdToPackageMapping[productId];
|
|
61
|
+
let rcProduct;
|
|
61
62
|
if (!pkg) {
|
|
62
|
-
|
|
63
|
+
// Use cached if available
|
|
64
|
+
rcProduct = this.rcProductToPackageMapping[productId];
|
|
65
|
+
if (!rcProduct) {
|
|
66
|
+
// Try to retrieve now
|
|
67
|
+
try {
|
|
68
|
+
const rcProducts = await Purchases.getProducts([productId]);
|
|
69
|
+
rcProduct = rcProducts.length > 0 ? rcProducts[0] : undefined;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// 'failed' status will be returned
|
|
73
|
+
}
|
|
74
|
+
if (rcProduct) {
|
|
75
|
+
this.rcProductToPackageMapping[productId] = rcProduct;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
63
78
|
}
|
|
64
79
|
try {
|
|
65
|
-
|
|
80
|
+
let customerInfo;
|
|
81
|
+
if (pkg) {
|
|
82
|
+
customerInfo = (await Purchases.purchasePackage(pkg)).customerInfo;
|
|
83
|
+
}
|
|
84
|
+
else if (rcProduct) {
|
|
85
|
+
customerInfo = (await Purchases.purchaseStoreProduct(rcProduct)).customerInfo;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
return { status: 'failed', error: `RevenueCat Product/Package not found for ID: ${productId}` };
|
|
89
|
+
}
|
|
66
90
|
const isActive = this.isProductActive(customerInfo, productId);
|
|
67
91
|
if (isActive) {
|
|
68
92
|
return { status: 'purchased' };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revenuecat.js","sourceRoot":"","sources":["../../src/revenuecat/revenuecat.ts"],"names":[],"mappings":"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","sourcesContent":["import Purchases, { PURCHASES_ERROR_CODE } from 'react-native-purchases';\nimport type { PurchasesError, PurchasesPackage, CustomerInfoUpdateListener, CustomerInfo, PurchasesEntitlementInfo } from 'react-native-purchases';\nimport {HeliumPurchaseConfig, HeliumPurchaseResult} from \"../HeliumPaywallSdk.types\";\n\n// Rename the factory function\nexport function createRevenueCatPurchaseConfig(config?: {\n apiKey?: string;\n}): HeliumPurchaseConfig {\n const rcHandler = new RevenueCatHeliumHandler(config?.apiKey);\n return {\n apiKey: config?.apiKey,\n makePurchase: rcHandler.makePurchase.bind(rcHandler),\n restorePurchases: rcHandler.restorePurchases.bind(rcHandler),\n };\n}\n\nexport class RevenueCatHeliumHandler {\n private productIdToPackageMapping: Record<string, PurchasesPackage> = {};\n private isMappingInitialized: boolean = false;\n private initializationPromise: Promise<void> | null = null;\n\n constructor(apiKey?: string) {\n if (apiKey) {\n Purchases.configure({ apiKey });\n } else {\n }\n this.initializePackageMapping();\n }\n\n private async initializePackageMapping(): Promise<void> {\n if (this.initializationPromise) {\n return this.initializationPromise;\n }\n this.initializationPromise = (async () => {\n try {\n const offerings = await Purchases.getOfferings();\n if (offerings.current?.availablePackages) {\n offerings.current.availablePackages.forEach((pkg: PurchasesPackage) => {\n if (pkg.product?.identifier) {\n this.productIdToPackageMapping[pkg.product.identifier] = pkg;\n }\n });\n } else {\n }\n this.isMappingInitialized = true;\n } catch (error) {\n this.isMappingInitialized = false;\n } finally {\n this.initializationPromise = null;\n }\n })();\n return this.initializationPromise;\n }\n\n private async ensureMappingInitialized(): Promise<void> {\n if (!this.isMappingInitialized && !this.initializationPromise) {\n await this.initializePackageMapping();\n } else if (this.initializationPromise) {\n await this.initializationPromise;\n }\n }\n\n async makePurchase(productId: string): Promise<HeliumPurchaseResult> {\n await this.ensureMappingInitialized();\n\n const pkg: PurchasesPackage | undefined = this.productIdToPackageMapping[productId];\n if (!pkg) {\n return { status: 'failed', error: `RevenueCat Package not found for ID: ${productId}` };\n }\n\n try {\n const { customerInfo } = await Purchases.purchasePackage(pkg);\n const isActive = this.isProductActive(customerInfo, productId);\n if (isActive) {\n return { status: 'purchased' };\n } else {\n // This case might occur if the purchase succeeded but the entitlement wasn't immediately active\n // or if a different product became active.\n // Consider if polling/listening might be needed here too, similar to pending.\n // For now, returning failed as the specific product isn't confirmed active.\n return { status: 'failed', error: 'Purchase possibly complete but entitlement/subscription not active for this product.' };\n }\n } catch (error) {\n const purchasesError = error as PurchasesError;\n\n if (purchasesError?.code === PURCHASES_ERROR_CODE.PAYMENT_PENDING_ERROR) {\n // Wait for a terminal state for up to 5 seconds\n return new Promise((resolve) => {\n // Define the listener function separately to remove it later\n const updateListener: CustomerInfoUpdateListener = (updatedCustomerInfo: CustomerInfo) => {\n const isActive = this.isProductActive(updatedCustomerInfo, productId);\n if (isActive) {\n clearTimeout(timeoutId);\n // Remove listener using the function reference\n Purchases.removeCustomerInfoUpdateListener(updateListener);\n resolve({ status: 'purchased' });\n }\n };\n\n const timeoutId = setTimeout(() => {\n // Remove listener using the function reference on timeout\n Purchases.removeCustomerInfoUpdateListener(updateListener);\n resolve({ status: 'pending' });\n }, 5000);\n\n // Add the listener\n Purchases.addCustomerInfoUpdateListener(updateListener);\n });\n }\n\n if (purchasesError?.code === PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR) {\n return { status: 'cancelled' };\n }\n\n // Handle other errors\n return { status: 'failed', error: purchasesError?.message || 'RevenueCat purchase failed.' };\n }\n }\n\n // Helper function to check if a product is active in CustomerInfo\n private isProductActive(customerInfo: CustomerInfo, productId: string): boolean {\n return Object.values(customerInfo.entitlements.active).some((entitlement: PurchasesEntitlementInfo) => entitlement.productIdentifier === productId)\n || customerInfo.activeSubscriptions.includes(productId)\n || customerInfo.allPurchasedProductIdentifiers.includes(productId);\n }\n\n async restorePurchases(): Promise<boolean> {\n try {\n const customerInfo = await Purchases.restorePurchases();\n const isActive = Object.keys(customerInfo.entitlements.active).length > 0;\n return isActive;\n } catch (error) {\n return false;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"revenuecat.js","sourceRoot":"","sources":["../../src/revenuecat/revenuecat.ts"],"names":[],"mappings":"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","sourcesContent":["import Purchases, {PURCHASES_ERROR_CODE, PurchasesStoreProduct} from 'react-native-purchases';\nimport type { PurchasesError, PurchasesPackage, CustomerInfoUpdateListener, CustomerInfo, PurchasesEntitlementInfo } from 'react-native-purchases';\nimport {HeliumPurchaseConfig, HeliumPurchaseResult} from \"../HeliumPaywallSdk.types\";\n\n// Rename the factory function\nexport function createRevenueCatPurchaseConfig(config?: {\n apiKey?: string;\n}): HeliumPurchaseConfig {\n const rcHandler = new RevenueCatHeliumHandler(config?.apiKey);\n return {\n apiKey: config?.apiKey,\n makePurchase: rcHandler.makePurchase.bind(rcHandler),\n restorePurchases: rcHandler.restorePurchases.bind(rcHandler),\n };\n}\n\nexport class RevenueCatHeliumHandler {\n private productIdToPackageMapping: Record<string, PurchasesPackage> = {};\n private isMappingInitialized: boolean = false;\n private initializationPromise: Promise<void> | null = null;\n\n private rcProductToPackageMapping: Record<string, PurchasesStoreProduct> = {};\n\n constructor(apiKey?: string) {\n if (apiKey) {\n Purchases.configure({ apiKey });\n } else {\n }\n this.initializePackageMapping();\n }\n\n private async initializePackageMapping(): Promise<void> {\n if (this.initializationPromise) {\n return this.initializationPromise;\n }\n this.initializationPromise = (async () => {\n try {\n const offerings = await Purchases.getOfferings();\n const allOfferings = offerings.all;\n for (const offering of Object.values(allOfferings)) {\n offering.availablePackages.forEach((pkg: PurchasesPackage) => {\n if (pkg.product?.identifier) {\n this.productIdToPackageMapping[pkg.product.identifier] = pkg;\n }\n });\n }\n this.isMappingInitialized = true;\n } catch (error) {\n this.isMappingInitialized = false;\n } finally {\n this.initializationPromise = null;\n }\n })();\n return this.initializationPromise;\n }\n\n private async ensureMappingInitialized(): Promise<void> {\n if (!this.isMappingInitialized && !this.initializationPromise) {\n await this.initializePackageMapping();\n } else if (this.initializationPromise) {\n await this.initializationPromise;\n }\n }\n\n async makePurchase(productId: string): Promise<HeliumPurchaseResult> {\n await this.ensureMappingInitialized();\n\n const pkg: PurchasesPackage | undefined = this.productIdToPackageMapping[productId];\n let rcProduct: PurchasesStoreProduct | undefined;\n if (!pkg) {\n // Use cached if available\n rcProduct = this.rcProductToPackageMapping[productId];\n if (!rcProduct) {\n // Try to retrieve now\n try {\n const rcProducts = await Purchases.getProducts([productId]);\n rcProduct = rcProducts.length > 0 ? rcProducts[0] : undefined;\n } catch {\n // 'failed' status will be returned\n }\n if (rcProduct) {\n this.rcProductToPackageMapping[productId] = rcProduct;\n }\n }\n }\n\n try {\n let customerInfo: CustomerInfo;\n if (pkg) {\n customerInfo = (await Purchases.purchasePackage(pkg)).customerInfo;\n } else if (rcProduct) {\n customerInfo = (await Purchases.purchaseStoreProduct(rcProduct)).customerInfo;\n } else {\n return { status: 'failed', error: `RevenueCat Product/Package not found for ID: ${productId}` };\n }\n const isActive = this.isProductActive(customerInfo, productId);\n if (isActive) {\n return { status: 'purchased' };\n } else {\n // This case might occur if the purchase succeeded but the entitlement wasn't immediately active\n // or if a different product became active.\n // Consider if polling/listening might be needed here too, similar to pending.\n // For now, returning failed as the specific product isn't confirmed active.\n return { status: 'failed', error: 'Purchase possibly complete but entitlement/subscription not active for this product.' };\n }\n } catch (error) {\n const purchasesError = error as PurchasesError;\n\n if (purchasesError?.code === PURCHASES_ERROR_CODE.PAYMENT_PENDING_ERROR) {\n // Wait for a terminal state for up to 5 seconds\n return new Promise((resolve) => {\n // Define the listener function separately to remove it later\n const updateListener: CustomerInfoUpdateListener = (updatedCustomerInfo: CustomerInfo) => {\n const isActive = this.isProductActive(updatedCustomerInfo, productId);\n if (isActive) {\n clearTimeout(timeoutId);\n // Remove listener using the function reference\n Purchases.removeCustomerInfoUpdateListener(updateListener);\n resolve({ status: 'purchased' });\n }\n };\n\n const timeoutId = setTimeout(() => {\n // Remove listener using the function reference on timeout\n Purchases.removeCustomerInfoUpdateListener(updateListener);\n resolve({ status: 'pending' });\n }, 5000);\n\n // Add the listener\n Purchases.addCustomerInfoUpdateListener(updateListener);\n });\n }\n\n if (purchasesError?.code === PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR) {\n return { status: 'cancelled' };\n }\n\n // Handle other errors\n return { status: 'failed', error: purchasesError?.message || 'RevenueCat purchase failed.' };\n }\n }\n\n // Helper function to check if a product is active in CustomerInfo\n private isProductActive(customerInfo: CustomerInfo, productId: string): boolean {\n return Object.values(customerInfo.entitlements.active).some((entitlement: PurchasesEntitlementInfo) => entitlement.productIdentifier === productId)\n || customerInfo.activeSubscriptions.includes(productId)\n || customerInfo.allPurchasedProductIdentifiers.includes(productId);\n }\n\n async restorePurchases(): Promise<boolean> {\n try {\n const customerInfo = await Purchases.restorePurchases();\n const isActive = Object.keys(customerInfo.entitlements.active).length > 0;\n return isActive;\n } catch (error) {\n return false;\n }\n }\n}\n"]}
|
|
@@ -28,6 +28,13 @@ struct PaywallInfoResult: Record {
|
|
|
28
28
|
var shouldShow: Bool? = nil
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
struct CanPresentPaywallResult: Record {
|
|
32
|
+
@Field
|
|
33
|
+
var canPresent: Bool = false
|
|
34
|
+
@Field
|
|
35
|
+
var reason: String? = nil
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
public class HeliumPaywallSdkModule: Module {
|
|
32
39
|
// Single continuations for ongoing operations
|
|
33
40
|
private var currentProductId: String? = nil
|
|
@@ -54,6 +61,8 @@ public class HeliumPaywallSdkModule: Module {
|
|
|
54
61
|
// todo use Record here? https://docs.expo.dev/modules/module-api/#records
|
|
55
62
|
Function("initialize") { (config: [String : Any]) in
|
|
56
63
|
let userTraitsMap = config["customUserTraits"] as? [String : Any]
|
|
64
|
+
let fallbackBundleURLString = config["fallbackBundleUrlString"] as? String
|
|
65
|
+
let fallbackBundleString = config["fallbackBundleString"] as? String
|
|
57
66
|
|
|
58
67
|
// Create delegate with closures that send events to JavaScript
|
|
59
68
|
let delegate = InternalDelegate(
|
|
@@ -101,6 +110,21 @@ public class HeliumPaywallSdkModule: Module {
|
|
|
101
110
|
}
|
|
102
111
|
)
|
|
103
112
|
|
|
113
|
+
// Handle fallback bundle - either as URL string or JSON string
|
|
114
|
+
var fallbackBundleURL: URL? = nil
|
|
115
|
+
if let urlString = fallbackBundleURLString {
|
|
116
|
+
fallbackBundleURL = URL(string: urlString)
|
|
117
|
+
} else if let jsonString = fallbackBundleString {
|
|
118
|
+
// write the string to a temp file
|
|
119
|
+
let tempURL = FileManager.default.temporaryDirectory
|
|
120
|
+
.appendingPathComponent("helium-fallback.json")
|
|
121
|
+
|
|
122
|
+
if let data = jsonString.data(using: .utf8) {
|
|
123
|
+
try? data.write(to: tempURL)
|
|
124
|
+
fallbackBundleURL = tempURL
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
104
128
|
Helium.shared.initialize(
|
|
105
129
|
apiKey: config["apiKey"] as? String ?? "",
|
|
106
130
|
heliumPaywallDelegate: delegate,
|
|
@@ -108,7 +132,8 @@ public class HeliumPaywallSdkModule: Module {
|
|
|
108
132
|
customUserId: config["customUserId"] as? String,
|
|
109
133
|
customAPIEndpoint: config["customAPIEndpoint"] as? String,
|
|
110
134
|
customUserTraits: userTraitsMap != nil ? HeliumUserTraits(userTraitsMap!) : nil,
|
|
111
|
-
revenueCatAppUserId: config["revenueCatAppUserId"] as? String
|
|
135
|
+
revenueCatAppUserId: config["revenueCatAppUserId"] as? String,
|
|
136
|
+
fallbackBundleURL: fallbackBundleURL
|
|
112
137
|
)
|
|
113
138
|
}
|
|
114
139
|
|
|
@@ -185,6 +210,45 @@ public class HeliumPaywallSdkModule: Module {
|
|
|
185
210
|
)
|
|
186
211
|
}
|
|
187
212
|
|
|
213
|
+
Function("canPresentUpsell") { (trigger: String) in
|
|
214
|
+
// Check if paywalls are downloaded successfully
|
|
215
|
+
let paywallsLoaded = Helium.shared.paywallsLoaded()
|
|
216
|
+
|
|
217
|
+
// Check if trigger exists in fetched triggers
|
|
218
|
+
let triggerNames = HeliumFetchedConfigManager.shared.getFetchedTriggerNames()
|
|
219
|
+
let hasTrigger = triggerNames.contains(trigger)
|
|
220
|
+
|
|
221
|
+
let canPresent: Bool
|
|
222
|
+
let reason: String
|
|
223
|
+
|
|
224
|
+
if paywallsLoaded && hasTrigger {
|
|
225
|
+
// Normal case - paywall is ready
|
|
226
|
+
canPresent = true
|
|
227
|
+
reason = "ready"
|
|
228
|
+
} else if HeliumFallbackViewManager.shared.getFallbackInfo(trigger: trigger) != nil {
|
|
229
|
+
// Fallback is available (via downloaded bundle)
|
|
230
|
+
canPresent = true
|
|
231
|
+
reason = "fallback_ready"
|
|
232
|
+
} else {
|
|
233
|
+
// No paywall and no fallback bundle
|
|
234
|
+
canPresent = false
|
|
235
|
+
reason = !paywallsLoaded ? "download status - \(Helium.shared.getDownloadStatus().rawValue)" : "trigger_not_found"
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return CanPresentPaywallResult(
|
|
239
|
+
canPresent: canPresent,
|
|
240
|
+
reason: reason
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
Function("handleDeepLink") { (urlString: String) in
|
|
245
|
+
guard let url = URL(string: urlString) else {
|
|
246
|
+
return false
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return Helium.shared.handleDeepLink(url)
|
|
250
|
+
}
|
|
251
|
+
|
|
188
252
|
// Defines a JavaScript function that always returns a Promise and whose native code
|
|
189
253
|
// is by default dispatched on the different thread than the JavaScript runtime runs on.
|
|
190
254
|
// AsyncFunction("setValueAsync") { (value: String) in
|
package/package.json
CHANGED
|
@@ -74,6 +74,7 @@ export interface HeliumConfig {
|
|
|
74
74
|
onHeliumPaywallEvent: (event: HeliumPaywallEvent) => void; // Still mandatory
|
|
75
75
|
|
|
76
76
|
// Optional configurations
|
|
77
|
+
fallbackBundle?: object;
|
|
77
78
|
triggers?: string[];
|
|
78
79
|
customUserId?: string;
|
|
79
80
|
customAPIEndpoint?: string;
|
|
@@ -87,6 +88,8 @@ export interface NativeHeliumConfig {
|
|
|
87
88
|
customAPIEndpoint?: string;
|
|
88
89
|
customUserTraits?: Record<string, any>;
|
|
89
90
|
revenueCatAppUserId?: string;
|
|
91
|
+
fallbackBundleUrlString?: string;
|
|
92
|
+
fallbackBundleString?: string;
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
export interface PaywallInfo {
|
|
@@ -13,6 +13,11 @@ interface PaywallInfoResult {
|
|
|
13
13
|
shouldShow?: boolean;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
interface CanPresentUpsellResult {
|
|
17
|
+
canPresent?: boolean;
|
|
18
|
+
reason?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
declare class HeliumPaywallSdkModule extends NativeModule<HeliumPaywallSdkModuleEvents> {
|
|
17
22
|
initialize(config: NativeHeliumConfig): void;
|
|
18
23
|
|
|
@@ -24,6 +29,8 @@ declare class HeliumPaywallSdkModule extends NativeModule<HeliumPaywallSdkModule
|
|
|
24
29
|
|
|
25
30
|
getDownloadStatus(): HeliumDownloadStatus;
|
|
26
31
|
|
|
32
|
+
canPresentUpsell(trigger: string): CanPresentUpsellResult;
|
|
33
|
+
|
|
27
34
|
fallbackOpenOrCloseEvent(
|
|
28
35
|
trigger: string,
|
|
29
36
|
isOpen: boolean,
|
|
@@ -38,6 +45,8 @@ declare class HeliumPaywallSdkModule extends NativeModule<HeliumPaywallSdkModule
|
|
|
38
45
|
handleRestoreResult(success: boolean): void;
|
|
39
46
|
|
|
40
47
|
getPaywallInfo(trigger: string): PaywallInfoResult;
|
|
48
|
+
|
|
49
|
+
handleDeepLink(urlString: string): boolean;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
52
|
// This call loads the native module object from the JSI.
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "./HeliumPaywallSdk.types";
|
|
7
7
|
import HeliumPaywallSdkModule from "./HeliumPaywallSdkModule";
|
|
8
8
|
import { EventSubscription } from 'expo-modules-core';
|
|
9
|
+
import * as ExpoFileSystem from 'expo-file-system';
|
|
9
10
|
|
|
10
11
|
export { default } from './HeliumPaywallSdkModule';
|
|
11
12
|
// export { default as HeliumPaywallSdkView } from './HeliumPaywallSdkView';
|
|
@@ -60,13 +61,44 @@ export const initialize = (config: HeliumConfig) => {
|
|
|
60
61
|
}
|
|
61
62
|
});
|
|
62
63
|
|
|
64
|
+
nativeInitializeAsync(config).catch(error => {
|
|
65
|
+
console.error('[Helium] Initialization failed:', error);
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const nativeInitializeAsync = async (config: HeliumConfig) => {
|
|
70
|
+
let fallbackBundleUrlString;
|
|
71
|
+
let fallbackBundleString;
|
|
72
|
+
if (config.fallbackBundle) {
|
|
73
|
+
try {
|
|
74
|
+
const jsonContent = JSON.stringify(config.fallbackBundle);
|
|
75
|
+
|
|
76
|
+
// Write to documents directory
|
|
77
|
+
fallbackBundleUrlString = `${ExpoFileSystem.documentDirectory}helium-fallback.json`;
|
|
78
|
+
// This is ASYNC but that's ok because helium initialize in swift code is async anyways.
|
|
79
|
+
await ExpoFileSystem.writeAsStringAsync(
|
|
80
|
+
fallbackBundleUrlString,
|
|
81
|
+
jsonContent
|
|
82
|
+
);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
// Fallback to string approach if unexpected error occurs
|
|
85
|
+
console.log(
|
|
86
|
+
'[Helium] expo-file-system not available, attempting to pass fallback bundle as string.'
|
|
87
|
+
);
|
|
88
|
+
fallbackBundleString = JSON.stringify(config.fallbackBundle);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
63
93
|
// Create native config object
|
|
64
94
|
const nativeConfig: NativeHeliumConfig = {
|
|
65
95
|
apiKey: config.apiKey,
|
|
66
96
|
customUserId: config.customUserId,
|
|
67
97
|
customAPIEndpoint: config.customAPIEndpoint,
|
|
68
98
|
customUserTraits: config.customUserTraits,
|
|
69
|
-
revenueCatAppUserId: config.revenueCatAppUserId
|
|
99
|
+
revenueCatAppUserId: config.revenueCatAppUserId,
|
|
100
|
+
fallbackBundleUrlString: fallbackBundleUrlString,
|
|
101
|
+
fallbackBundleString: fallbackBundleString,
|
|
70
102
|
};
|
|
71
103
|
|
|
72
104
|
// Initialize the native module
|
|
@@ -80,12 +112,11 @@ export const presentUpsell = ({
|
|
|
80
112
|
triggerName: string;
|
|
81
113
|
onFallback?: () => void;
|
|
82
114
|
}) => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
115
|
+
const { canPresent, reason } = HeliumPaywallSdkModule.canPresentUpsell(triggerName);
|
|
116
|
+
|
|
117
|
+
if (!canPresent) {
|
|
86
118
|
console.log(
|
|
87
|
-
`Helium trigger "${triggerName}"
|
|
88
|
-
downloadStatus
|
|
119
|
+
`[Helium] Cannot present trigger "${triggerName}". Reason: ${reason}`
|
|
89
120
|
);
|
|
90
121
|
onFallback?.();
|
|
91
122
|
HeliumPaywallSdkModule.fallbackOpenOrCloseEvent(triggerName, true, 'presented');
|
|
@@ -121,6 +152,15 @@ export const getPaywallInfo = (trigger: string): PaywallInfo | undefined => {
|
|
|
121
152
|
};
|
|
122
153
|
};
|
|
123
154
|
|
|
155
|
+
export const handleDeepLink = (url: string | null) => {
|
|
156
|
+
if (url) {
|
|
157
|
+
const handled = HeliumPaywallSdkModule.handleDeepLink(url);
|
|
158
|
+
console.log('[Helium] Handled deep link:', handled);
|
|
159
|
+
return handled;
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
};
|
|
163
|
+
|
|
124
164
|
export {createCustomPurchaseConfig, HELIUM_CTA_NAMES} from './HeliumPaywallSdk.types';
|
|
125
165
|
|
|
126
166
|
export type {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Purchases, {
|
|
1
|
+
import Purchases, {PURCHASES_ERROR_CODE, PurchasesStoreProduct} from 'react-native-purchases';
|
|
2
2
|
import type { PurchasesError, PurchasesPackage, CustomerInfoUpdateListener, CustomerInfo, PurchasesEntitlementInfo } from 'react-native-purchases';
|
|
3
3
|
import {HeliumPurchaseConfig, HeliumPurchaseResult} from "../HeliumPaywallSdk.types";
|
|
4
4
|
|
|
@@ -19,6 +19,8 @@ export class RevenueCatHeliumHandler {
|
|
|
19
19
|
private isMappingInitialized: boolean = false;
|
|
20
20
|
private initializationPromise: Promise<void> | null = null;
|
|
21
21
|
|
|
22
|
+
private rcProductToPackageMapping: Record<string, PurchasesStoreProduct> = {};
|
|
23
|
+
|
|
22
24
|
constructor(apiKey?: string) {
|
|
23
25
|
if (apiKey) {
|
|
24
26
|
Purchases.configure({ apiKey });
|
|
@@ -34,13 +36,13 @@ export class RevenueCatHeliumHandler {
|
|
|
34
36
|
this.initializationPromise = (async () => {
|
|
35
37
|
try {
|
|
36
38
|
const offerings = await Purchases.getOfferings();
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
const allOfferings = offerings.all;
|
|
40
|
+
for (const offering of Object.values(allOfferings)) {
|
|
41
|
+
offering.availablePackages.forEach((pkg: PurchasesPackage) => {
|
|
39
42
|
if (pkg.product?.identifier) {
|
|
40
43
|
this.productIdToPackageMapping[pkg.product.identifier] = pkg;
|
|
41
44
|
}
|
|
42
45
|
});
|
|
43
|
-
} else {
|
|
44
46
|
}
|
|
45
47
|
this.isMappingInitialized = true;
|
|
46
48
|
} catch (error) {
|
|
@@ -64,12 +66,33 @@ export class RevenueCatHeliumHandler {
|
|
|
64
66
|
await this.ensureMappingInitialized();
|
|
65
67
|
|
|
66
68
|
const pkg: PurchasesPackage | undefined = this.productIdToPackageMapping[productId];
|
|
69
|
+
let rcProduct: PurchasesStoreProduct | undefined;
|
|
67
70
|
if (!pkg) {
|
|
68
|
-
|
|
71
|
+
// Use cached if available
|
|
72
|
+
rcProduct = this.rcProductToPackageMapping[productId];
|
|
73
|
+
if (!rcProduct) {
|
|
74
|
+
// Try to retrieve now
|
|
75
|
+
try {
|
|
76
|
+
const rcProducts = await Purchases.getProducts([productId]);
|
|
77
|
+
rcProduct = rcProducts.length > 0 ? rcProducts[0] : undefined;
|
|
78
|
+
} catch {
|
|
79
|
+
// 'failed' status will be returned
|
|
80
|
+
}
|
|
81
|
+
if (rcProduct) {
|
|
82
|
+
this.rcProductToPackageMapping[productId] = rcProduct;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
69
85
|
}
|
|
70
86
|
|
|
71
87
|
try {
|
|
72
|
-
|
|
88
|
+
let customerInfo: CustomerInfo;
|
|
89
|
+
if (pkg) {
|
|
90
|
+
customerInfo = (await Purchases.purchasePackage(pkg)).customerInfo;
|
|
91
|
+
} else if (rcProduct) {
|
|
92
|
+
customerInfo = (await Purchases.purchaseStoreProduct(rcProduct)).customerInfo;
|
|
93
|
+
} else {
|
|
94
|
+
return { status: 'failed', error: `RevenueCat Product/Package not found for ID: ${productId}` };
|
|
95
|
+
}
|
|
73
96
|
const isActive = this.isProductActive(customerInfo, productId);
|
|
74
97
|
if (isActive) {
|
|
75
98
|
return { status: 'purchased' };
|