@revenuecat/purchases-capacitor-ui 12.1.2 → 12.2.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/Package.swift +1 -1
- package/RevenuecatPurchasesCapacitorUI.podspec +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/revenuecat/purchases/capacitor/ui/RevenueCatUIPlugin.kt +119 -1
- package/dist/esm/definitions.d.ts +113 -1
- package/dist/esm/definitions.js +12 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.js +175 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +20 -0
- package/dist/esm/web.js +12 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.js +199 -1
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/RevenuecatPurchasesCapacitorUI/RevenueCatUIPlugin.swift +168 -25
- package/package.json +2 -2
package/Package.swift
CHANGED
|
@@ -11,7 +11,7 @@ let package = Package(
|
|
|
11
11
|
],
|
|
12
12
|
dependencies: [
|
|
13
13
|
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"),
|
|
14
|
-
.package(url: "https://github.com/RevenueCat/purchases-hybrid-common.git", exact: "17.
|
|
14
|
+
.package(url: "https://github.com/RevenueCat/purchases-hybrid-common.git", exact: "17.41.1")
|
|
15
15
|
],
|
|
16
16
|
targets: [
|
|
17
17
|
.target(
|
|
@@ -13,6 +13,6 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
14
|
s.ios.deployment_target = '15.0'
|
|
15
15
|
s.dependency 'Capacitor'
|
|
16
|
-
s.dependency 'PurchasesHybridCommonUI', '17.
|
|
16
|
+
s.dependency 'PurchasesHybridCommonUI', '17.41.1'
|
|
17
17
|
s.swift_version = '5.1'
|
|
18
18
|
end
|
package/android/build.gradle
CHANGED
|
@@ -51,6 +51,6 @@ repositories {
|
|
|
51
51
|
dependencies {
|
|
52
52
|
implementation project(':capacitor-android')
|
|
53
53
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
54
|
-
implementation 'com.revenuecat.purchases:purchases-hybrid-common-ui:17.
|
|
54
|
+
implementation 'com.revenuecat.purchases:purchases-hybrid-common-ui:17.41.1'
|
|
55
55
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:2.2.20"
|
|
56
56
|
}
|
|
@@ -10,9 +10,11 @@ import com.getcapacitor.PluginCall
|
|
|
10
10
|
import com.getcapacitor.PluginMethod
|
|
11
11
|
import com.getcapacitor.annotation.CapacitorPlugin
|
|
12
12
|
import com.revenuecat.purchases.PresentedOfferingContext
|
|
13
|
+
import com.revenuecat.purchases.hybridcommon.ui.PaywallListenerWrapper
|
|
13
14
|
import com.revenuecat.purchases.hybridcommon.ui.PaywallResultListener
|
|
14
15
|
import com.revenuecat.purchases.hybridcommon.ui.PaywallSource
|
|
15
16
|
import com.revenuecat.purchases.hybridcommon.ui.PresentPaywallOptions
|
|
17
|
+
import com.revenuecat.purchases.hybridcommon.ui.HybridPurchaseLogicBridge
|
|
16
18
|
import com.revenuecat.purchases.hybridcommon.ui.presentPaywallFromFragment
|
|
17
19
|
import com.revenuecat.purchases.ui.revenuecatui.customercenter.ShowCustomerCenter
|
|
18
20
|
import org.json.JSONObject
|
|
@@ -81,6 +83,50 @@ class RevenueCatUIPlugin : Plugin(), PaywallResultListener {
|
|
|
81
83
|
)
|
|
82
84
|
}
|
|
83
85
|
|
|
86
|
+
@PluginMethod
|
|
87
|
+
fun resumePurchaseInitiated(call: PluginCall) {
|
|
88
|
+
call.withRequiredRequestId { requestId ->
|
|
89
|
+
val shouldProceed = call.getBoolean("shouldProceed") ?: true
|
|
90
|
+
PaywallListenerWrapper.resumePurchasePackageInitiated(requestId, shouldProceed)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@PluginMethod
|
|
95
|
+
fun resumePurchaseLogicPurchase(call: PluginCall) {
|
|
96
|
+
resolvePurchaseLogicResult(call)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@PluginMethod
|
|
100
|
+
fun resumePurchaseLogicRestore(call: PluginCall) {
|
|
101
|
+
resolvePurchaseLogicResult(call)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private fun resolvePurchaseLogicResult(call: PluginCall) {
|
|
105
|
+
val requestId = call.getString("requestId")
|
|
106
|
+
if (requestId == null) {
|
|
107
|
+
call.reject("PAYWALL_ERROR", "Missing requestId")
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
val resultString = call.getString("result")
|
|
111
|
+
if (resultString == null) {
|
|
112
|
+
call.reject("PAYWALL_ERROR", "Missing result")
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
val errorMessage = call.getObject("error")?.optString("message")
|
|
116
|
+
HybridPurchaseLogicBridge.resolveResult(requestId, resultString, errorMessage)
|
|
117
|
+
call.resolve()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private fun PluginCall.withRequiredRequestId(block: (String) -> Unit) {
|
|
121
|
+
val requestId = getString("requestId")
|
|
122
|
+
if (requestId == null) {
|
|
123
|
+
reject("PAYWALL_ERROR", "Missing requestId")
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
block(requestId)
|
|
127
|
+
resolve()
|
|
128
|
+
}
|
|
129
|
+
|
|
84
130
|
/**
|
|
85
131
|
* Shared implementation for presenting a paywall
|
|
86
132
|
*/
|
|
@@ -111,6 +157,9 @@ class RevenueCatUIPlugin : Plugin(), PaywallResultListener {
|
|
|
111
157
|
return
|
|
112
158
|
}
|
|
113
159
|
|
|
160
|
+
val hasPaywallListener = call.getBoolean("hasPaywallListener") ?: false
|
|
161
|
+
val hasPurchaseLogic = call.getBoolean("hasPurchaseLogic") ?: false
|
|
162
|
+
|
|
114
163
|
val presentedOfferingContext = presentedOfferingContext?.let { jsContext ->
|
|
115
164
|
val offeringId = jsContext.optString("offeringIdentifier").takeUnless { it.isNullOrEmpty() }
|
|
116
165
|
if (offeringId == null) { return@let null }
|
|
@@ -140,17 +189,86 @@ class RevenueCatUIPlugin : Plugin(), PaywallResultListener {
|
|
|
140
189
|
PaywallSource.DefaultOffering
|
|
141
190
|
}
|
|
142
191
|
|
|
192
|
+
val listener = if (hasPaywallListener) createPaywallListenerWrapper() else null
|
|
193
|
+
val purchaseLogic = if (hasPurchaseLogic) createPurchaseLogicBridge() else null
|
|
194
|
+
|
|
143
195
|
val options = PresentPaywallOptions(
|
|
144
196
|
paywallSource = paywallSource,
|
|
145
197
|
requiredEntitlementIdentifier = requiredEntitlementIdentifier,
|
|
146
198
|
shouldDisplayDismissButton = displayCloseButton,
|
|
147
|
-
paywallResultListener = this
|
|
199
|
+
paywallResultListener = this,
|
|
200
|
+
paywallListener = listener,
|
|
201
|
+
purchaseLogic = purchaseLogic,
|
|
148
202
|
)
|
|
149
203
|
|
|
150
204
|
presentPaywallFromFragment(currentActivity, options)
|
|
151
205
|
notifyListeners("paywallDisplayed", JSObject())
|
|
152
206
|
}
|
|
153
207
|
|
|
208
|
+
private fun createPaywallListenerWrapper(): PaywallListenerWrapper {
|
|
209
|
+
return object : PaywallListenerWrapper() {
|
|
210
|
+
override fun onPurchaseStarted(rcPackage: Map<String, Any?>) {
|
|
211
|
+
notifyListeners("onPurchaseStarted", JSObject().apply {
|
|
212
|
+
put("packageBeingPurchased", JSONObject(rcPackage))
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
override fun onPurchaseCompleted(
|
|
217
|
+
customerInfo: Map<String, Any?>,
|
|
218
|
+
storeTransaction: Map<String, Any?>,
|
|
219
|
+
) {
|
|
220
|
+
notifyListeners("onPurchaseCompleted", JSObject().apply {
|
|
221
|
+
put("customerInfo", JSONObject(customerInfo))
|
|
222
|
+
put("storeTransaction", JSONObject(storeTransaction))
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
override fun onPurchaseError(error: Map<String, Any?>) {
|
|
227
|
+
notifyListeners("onPurchaseError", JSObject().apply {
|
|
228
|
+
put("error", JSONObject(error))
|
|
229
|
+
})
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
override fun onPurchaseCancelled() {
|
|
233
|
+
notifyListeners("onPurchaseCancelled", JSObject())
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
override fun onRestoreStarted() {
|
|
237
|
+
notifyListeners("onRestoreStarted", JSObject())
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
override fun onRestoreCompleted(customerInfo: Map<String, Any?>) {
|
|
241
|
+
notifyListeners("onRestoreCompleted", JSObject().apply {
|
|
242
|
+
put("customerInfo", JSONObject(customerInfo))
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
override fun onRestoreError(error: Map<String, Any?>) {
|
|
247
|
+
notifyListeners("onRestoreError", JSObject().apply {
|
|
248
|
+
put("error", JSONObject(error))
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
override fun onPurchasePackageInitiated(rcPackage: Map<String, Any?>, requestId: String) {
|
|
253
|
+
notifyListeners("onPurchaseInitiated", JSObject().apply {
|
|
254
|
+
put("package", JSONObject(rcPackage))
|
|
255
|
+
put("requestId", requestId)
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private fun createPurchaseLogicBridge(): HybridPurchaseLogicBridge {
|
|
262
|
+
return HybridPurchaseLogicBridge(
|
|
263
|
+
onPerformPurchase = { eventData ->
|
|
264
|
+
notifyListeners("onPerformPurchaseRequest", JSObject(JSONObject(eventData).toString()))
|
|
265
|
+
},
|
|
266
|
+
onPerformRestore = { eventData ->
|
|
267
|
+
notifyListeners("onPerformRestoreRequest", JSObject(JSONObject(eventData).toString()))
|
|
268
|
+
},
|
|
269
|
+
)
|
|
270
|
+
}
|
|
271
|
+
|
|
154
272
|
@PluginMethod
|
|
155
273
|
fun presentCustomerCenter(call: PluginCall) {
|
|
156
274
|
val currentActivity = activity
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PluginListenerHandle } from '@capacitor/core';
|
|
2
|
-
import type { PurchasesOffering } from '@revenuecat/purchases-typescript-internal-esm';
|
|
2
|
+
import type { CustomerInfo, PurchasesError, PurchasesOffering, PurchasesPackage, PurchasesStoreTransaction } from '@revenuecat/purchases-typescript-internal-esm';
|
|
3
3
|
import { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';
|
|
4
4
|
export interface RevenueCatUIPlugin {
|
|
5
5
|
/**
|
|
@@ -37,6 +37,108 @@ export interface RevenueCatUIPlugin {
|
|
|
37
37
|
*/
|
|
38
38
|
removeAllListeners(): Promise<void>;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Object passed to onPurchaseInitiated that allows the developer to
|
|
42
|
+
* control when (and whether) the purchase flow continues.
|
|
43
|
+
* The developer can store this and call resume() asynchronously
|
|
44
|
+
* (e.g., after an auth flow on a different screen).
|
|
45
|
+
*/
|
|
46
|
+
export interface PurchaseResumable {
|
|
47
|
+
/** Call to proceed with or cancel the purchase. Defaults to true (proceed). */
|
|
48
|
+
resume(shouldProceed?: boolean): void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Callbacks for observing paywall lifecycle events such as purchases,
|
|
52
|
+
* restores, and errors. All callbacks are optional.
|
|
53
|
+
*
|
|
54
|
+
* Pass as `listener` in {@link PresentPaywallOptions} to receive events
|
|
55
|
+
* while the paywall is displayed.
|
|
56
|
+
*/
|
|
57
|
+
export interface PaywallListener {
|
|
58
|
+
/** Called when a purchase begins for a package. */
|
|
59
|
+
onPurchaseStarted?: (args: {
|
|
60
|
+
packageBeingPurchased: PurchasesPackage;
|
|
61
|
+
}) => void;
|
|
62
|
+
/** Called when a purchase completes successfully. */
|
|
63
|
+
onPurchaseCompleted?: (args: {
|
|
64
|
+
customerInfo: CustomerInfo;
|
|
65
|
+
storeTransaction: PurchasesStoreTransaction;
|
|
66
|
+
}) => void;
|
|
67
|
+
/** Called when a purchase fails with an error. */
|
|
68
|
+
onPurchaseError?: (args: {
|
|
69
|
+
error: PurchasesError;
|
|
70
|
+
}) => void;
|
|
71
|
+
/** Called when the user cancels a purchase. */
|
|
72
|
+
onPurchaseCancelled?: () => void;
|
|
73
|
+
/** Called when a restore operation begins. */
|
|
74
|
+
onRestoreStarted?: () => void;
|
|
75
|
+
/** Called when a restore operation completes successfully. */
|
|
76
|
+
onRestoreCompleted?: (args: {
|
|
77
|
+
customerInfo: CustomerInfo;
|
|
78
|
+
}) => void;
|
|
79
|
+
/** Called when a restore operation fails with an error. */
|
|
80
|
+
onRestoreError?: (args: {
|
|
81
|
+
error: PurchasesError;
|
|
82
|
+
}) => void;
|
|
83
|
+
/**
|
|
84
|
+
* Called before the payment sheet is displayed, allowing the app to gate
|
|
85
|
+
* the purchase flow (e.g., require authentication first).
|
|
86
|
+
*
|
|
87
|
+
* The developer receives a {@link PurchaseResumable} that can be stored
|
|
88
|
+
* and called asynchronously. Call `resumable.resume(true)` to proceed
|
|
89
|
+
* with the purchase, or `resumable.resume(false)` to cancel it.
|
|
90
|
+
*
|
|
91
|
+
* If this callback is not provided, the purchase proceeds automatically.
|
|
92
|
+
*/
|
|
93
|
+
onPurchaseInitiated?: (args: {
|
|
94
|
+
packageBeingPurchased: PurchasesPackage;
|
|
95
|
+
resumable: PurchaseResumable;
|
|
96
|
+
}) => void;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Custom purchase and restore handlers for apps that manage their own
|
|
100
|
+
* purchase flow (`purchasesAreCompletedBy: MY_APP`).
|
|
101
|
+
*
|
|
102
|
+
* When provided in {@link PresentPaywallOptions}, the paywall delegates
|
|
103
|
+
* purchase and restore operations to these handlers instead of using
|
|
104
|
+
* RevenueCat's built-in purchase flow.
|
|
105
|
+
*/
|
|
106
|
+
export interface PurchaseLogic {
|
|
107
|
+
/**
|
|
108
|
+
* Called when the user initiates a purchase from the paywall.
|
|
109
|
+
* Perform the purchase using your own payment system and return the result.
|
|
110
|
+
*/
|
|
111
|
+
performPurchase: (args: {
|
|
112
|
+
packageToPurchase: PurchasesPackage;
|
|
113
|
+
}) => Promise<PurchaseLogicResult>;
|
|
114
|
+
/**
|
|
115
|
+
* Called when the user initiates a restore from the paywall.
|
|
116
|
+
* Perform the restore using your own system and return the result.
|
|
117
|
+
*/
|
|
118
|
+
performRestore: () => Promise<PurchaseLogicResult>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The result of a custom purchase or restore operation performed by {@link PurchaseLogic}.
|
|
122
|
+
*/
|
|
123
|
+
export type PurchaseLogicResult = {
|
|
124
|
+
result: PURCHASE_LOGIC_RESULT.SUCCESS;
|
|
125
|
+
} | {
|
|
126
|
+
result: PURCHASE_LOGIC_RESULT.CANCELLATION;
|
|
127
|
+
} | {
|
|
128
|
+
result: PURCHASE_LOGIC_RESULT.ERROR;
|
|
129
|
+
error?: PurchasesError;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Possible outcomes from a custom {@link PurchaseLogic} operation.
|
|
133
|
+
*/
|
|
134
|
+
export declare enum PURCHASE_LOGIC_RESULT {
|
|
135
|
+
/** The purchase or restore completed successfully. */
|
|
136
|
+
SUCCESS = "SUCCESS",
|
|
137
|
+
/** The user cancelled the purchase or restore. */
|
|
138
|
+
CANCELLATION = "CANCELLATION",
|
|
139
|
+
/** The purchase or restore failed with an error. */
|
|
140
|
+
ERROR = "ERROR"
|
|
141
|
+
}
|
|
40
142
|
export interface PresentPaywallOptions {
|
|
41
143
|
/**
|
|
42
144
|
* The offering to present.
|
|
@@ -48,6 +150,16 @@ export interface PresentPaywallOptions {
|
|
|
48
150
|
* Only applicable for original template paywalls, ignored for V2 Paywalls.
|
|
49
151
|
*/
|
|
50
152
|
displayCloseButton?: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Optional listener for paywall lifecycle events such as purchase
|
|
155
|
+
* completion, restoration, and errors.
|
|
156
|
+
*/
|
|
157
|
+
listener?: PaywallListener;
|
|
158
|
+
/**
|
|
159
|
+
* Optional custom purchase/restore logic for when
|
|
160
|
+
* `purchasesAreCompletedBy` is set to `MY_APP`.
|
|
161
|
+
*/
|
|
162
|
+
purchaseLogic?: PurchaseLogic;
|
|
51
163
|
}
|
|
52
164
|
export interface PresentPaywallIfNeededOptions extends PresentPaywallOptions {
|
|
53
165
|
/**
|
package/dist/esm/definitions.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';
|
|
2
|
+
/**
|
|
3
|
+
* Possible outcomes from a custom {@link PurchaseLogic} operation.
|
|
4
|
+
*/
|
|
5
|
+
export var PURCHASE_LOGIC_RESULT;
|
|
6
|
+
(function (PURCHASE_LOGIC_RESULT) {
|
|
7
|
+
/** The purchase or restore completed successfully. */
|
|
8
|
+
PURCHASE_LOGIC_RESULT["SUCCESS"] = "SUCCESS";
|
|
9
|
+
/** The user cancelled the purchase or restore. */
|
|
10
|
+
PURCHASE_LOGIC_RESULT["CANCELLATION"] = "CANCELLATION";
|
|
11
|
+
/** The purchase or restore failed with an error. */
|
|
12
|
+
PURCHASE_LOGIC_RESULT["ERROR"] = "ERROR";
|
|
13
|
+
})(PURCHASE_LOGIC_RESULT || (PURCHASE_LOGIC_RESULT = {}));
|
|
2
14
|
// Using the enum from purchases-typescript-internal-esm instead of defining our own
|
|
3
15
|
export { PAYWALL_RESULT as PaywallResultEnum };
|
|
4
16
|
//# sourceMappingURL=definitions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAqH/E;;GAEG;AACH,MAAM,CAAN,IAAY,qBAOX;AAPD,WAAY,qBAAqB;IAC/B,sDAAsD;IACtD,4CAAmB,CAAA;IACnB,kDAAkD;IAClD,sDAA6B,CAAA;IAC7B,oDAAoD;IACpD,wCAAe,CAAA;AACjB,CAAC,EAPW,qBAAqB,KAArB,qBAAqB,QAOhC;AAoCD,oFAAoF;AACpF,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,CAAC","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\nimport type {\n CustomerInfo,\n PurchasesError,\n PurchasesOffering,\n PurchasesPackage,\n PurchasesStoreTransaction,\n} from '@revenuecat/purchases-typescript-internal-esm';\nimport { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';\n\nexport interface RevenueCatUIPlugin {\n /**\n * Presents a paywall configured in the RevenueCat dashboard.\n * @param options The options for presenting the paywall.\n * @returns A PaywallResult indicating what happened during the paywall presentation.\n */\n presentPaywall(options?: PresentPaywallOptions): Promise<PaywallResult>;\n\n /**\n * Presents a paywall only if the user does not have the specified entitlement.\n * @param options The options for presenting the paywall if needed.\n * @returns A PaywallResult indicating what happened during the paywall presentation.\n */\n presentPaywallIfNeeded(options: PresentPaywallIfNeededOptions): Promise<PaywallResult>;\n\n /**\n * Presents the customer center where users can manage their subscriptions.\n */\n presentCustomerCenter(): Promise<void>;\n\n /**\n * Used for web only. Enables or disables returning mock results instead of rejecting promises with \"not supported\".\n * For testing purposes only.\n * @param options Options for mock web results\n */\n setMockWebResults?(options: { shouldMockWebResults: boolean }): Promise<void>;\n\n /**\n * Listen for when a paywall is displayed or dismissed.\n * @param eventName The event to listen for\n * @param listener The listener to call when the event is triggered\n */\n addListener(eventName: 'paywallDisplayed' | 'paywallDismissed', listener: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Remove all listeners for this plugin.\n */\n removeAllListeners(): Promise<void>;\n}\n\n/**\n * Object passed to onPurchaseInitiated that allows the developer to\n * control when (and whether) the purchase flow continues.\n * The developer can store this and call resume() asynchronously\n * (e.g., after an auth flow on a different screen).\n */\nexport interface PurchaseResumable {\n /** Call to proceed with or cancel the purchase. Defaults to true (proceed). */\n resume(shouldProceed?: boolean): void;\n}\n\n/**\n * Callbacks for observing paywall lifecycle events such as purchases,\n * restores, and errors. All callbacks are optional.\n *\n * Pass as `listener` in {@link PresentPaywallOptions} to receive events\n * while the paywall is displayed.\n */\nexport interface PaywallListener {\n /** Called when a purchase begins for a package. */\n onPurchaseStarted?: (args: { packageBeingPurchased: PurchasesPackage }) => void;\n /** Called when a purchase completes successfully. */\n onPurchaseCompleted?: (args: { customerInfo: CustomerInfo; storeTransaction: PurchasesStoreTransaction }) => void;\n /** Called when a purchase fails with an error. */\n onPurchaseError?: (args: { error: PurchasesError }) => void;\n /** Called when the user cancels a purchase. */\n onPurchaseCancelled?: () => void;\n /** Called when a restore operation begins. */\n onRestoreStarted?: () => void;\n /** Called when a restore operation completes successfully. */\n onRestoreCompleted?: (args: { customerInfo: CustomerInfo }) => void;\n /** Called when a restore operation fails with an error. */\n onRestoreError?: (args: { error: PurchasesError }) => void;\n /**\n * Called before the payment sheet is displayed, allowing the app to gate\n * the purchase flow (e.g., require authentication first).\n *\n * The developer receives a {@link PurchaseResumable} that can be stored\n * and called asynchronously. Call `resumable.resume(true)` to proceed\n * with the purchase, or `resumable.resume(false)` to cancel it.\n *\n * If this callback is not provided, the purchase proceeds automatically.\n */\n onPurchaseInitiated?: (args: { packageBeingPurchased: PurchasesPackage; resumable: PurchaseResumable }) => void;\n}\n\n/**\n * Custom purchase and restore handlers for apps that manage their own\n * purchase flow (`purchasesAreCompletedBy: MY_APP`).\n *\n * When provided in {@link PresentPaywallOptions}, the paywall delegates\n * purchase and restore operations to these handlers instead of using\n * RevenueCat's built-in purchase flow.\n */\nexport interface PurchaseLogic {\n /**\n * Called when the user initiates a purchase from the paywall.\n * Perform the purchase using your own payment system and return the result.\n */\n performPurchase: (args: { packageToPurchase: PurchasesPackage }) => Promise<PurchaseLogicResult>;\n /**\n * Called when the user initiates a restore from the paywall.\n * Perform the restore using your own system and return the result.\n */\n performRestore: () => Promise<PurchaseLogicResult>;\n}\n\n/**\n * The result of a custom purchase or restore operation performed by {@link PurchaseLogic}.\n */\nexport type PurchaseLogicResult =\n | { result: PURCHASE_LOGIC_RESULT.SUCCESS }\n | { result: PURCHASE_LOGIC_RESULT.CANCELLATION }\n | { result: PURCHASE_LOGIC_RESULT.ERROR; error?: PurchasesError };\n\n/**\n * Possible outcomes from a custom {@link PurchaseLogic} operation.\n */\nexport enum PURCHASE_LOGIC_RESULT {\n /** The purchase or restore completed successfully. */\n SUCCESS = 'SUCCESS',\n /** The user cancelled the purchase or restore. */\n CANCELLATION = 'CANCELLATION',\n /** The purchase or restore failed with an error. */\n ERROR = 'ERROR',\n}\n\nexport interface PresentPaywallOptions {\n /**\n * The offering to present.\n * If not provided, the current offering will be used.\n */\n offering?: PurchasesOffering;\n\n /**\n * Whether to display a close button on the paywall.\n * Only applicable for original template paywalls, ignored for V2 Paywalls.\n */\n displayCloseButton?: boolean;\n\n /**\n * Optional listener for paywall lifecycle events such as purchase\n * completion, restoration, and errors.\n */\n listener?: PaywallListener;\n\n /**\n * Optional custom purchase/restore logic for when\n * `purchasesAreCompletedBy` is set to `MY_APP`.\n */\n purchaseLogic?: PurchaseLogic;\n}\n\nexport interface PresentPaywallIfNeededOptions extends PresentPaywallOptions {\n /**\n * The identifier of the entitlement that is required.\n * The paywall will only be presented if the user doesn't have this entitlement.\n */\n requiredEntitlementIdentifier: string;\n}\n\n// Using the enum from purchases-typescript-internal-esm instead of defining our own\nexport { PAYWALL_RESULT as PaywallResultEnum };\n\nexport interface PaywallResult {\n /**\n * The result of the paywall presentation.\n */\n result: PAYWALL_RESULT;\n}\n"]}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,181 @@
|
|
|
1
1
|
import { registerPlugin } from '@capacitor/core';
|
|
2
|
-
|
|
2
|
+
import { PURCHASE_LOGIC_RESULT } from './definitions';
|
|
3
|
+
const nativePlugin = registerPlugin('RevenueCatUI', {
|
|
3
4
|
web: () => import('./web').then((m) => new m.RevenueCatUIWeb()),
|
|
4
5
|
});
|
|
6
|
+
function serializeResultForNative(result) {
|
|
7
|
+
if (result.result === PURCHASE_LOGIC_RESULT.ERROR && 'error' in result && result.error) {
|
|
8
|
+
return {
|
|
9
|
+
result: result.result,
|
|
10
|
+
error: {
|
|
11
|
+
code: result.error.code,
|
|
12
|
+
message: result.error.message,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return { result: result.result };
|
|
17
|
+
}
|
|
18
|
+
async function presentWithListenerSupport(nativeMethod, options, listener, purchaseLogic) {
|
|
19
|
+
const handles = [];
|
|
20
|
+
try {
|
|
21
|
+
// Register PaywallListener event handlers
|
|
22
|
+
if (listener) {
|
|
23
|
+
if (listener.onPurchaseStarted) {
|
|
24
|
+
const cb = listener.onPurchaseStarted;
|
|
25
|
+
handles.push(await nativePlugin.addListener('onPurchaseStarted', (data) => {
|
|
26
|
+
var _a;
|
|
27
|
+
cb({ packageBeingPurchased: (_a = data.packageBeingPurchased) !== null && _a !== void 0 ? _a : data });
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
if (listener.onPurchaseCompleted) {
|
|
31
|
+
const cb = listener.onPurchaseCompleted;
|
|
32
|
+
handles.push(await nativePlugin.addListener('onPurchaseCompleted', (data) => {
|
|
33
|
+
cb({
|
|
34
|
+
customerInfo: data.customerInfo,
|
|
35
|
+
storeTransaction: data.storeTransaction,
|
|
36
|
+
});
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
if (listener.onPurchaseError) {
|
|
40
|
+
const cb = listener.onPurchaseError;
|
|
41
|
+
handles.push(await nativePlugin.addListener('onPurchaseError', (data) => {
|
|
42
|
+
var _a;
|
|
43
|
+
cb({ error: (_a = data.error) !== null && _a !== void 0 ? _a : data });
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
if (listener.onPurchaseCancelled) {
|
|
47
|
+
const cb = listener.onPurchaseCancelled;
|
|
48
|
+
handles.push(await nativePlugin.addListener('onPurchaseCancelled', () => {
|
|
49
|
+
cb();
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
if (listener.onRestoreStarted) {
|
|
53
|
+
const cb = listener.onRestoreStarted;
|
|
54
|
+
handles.push(await nativePlugin.addListener('onRestoreStarted', () => {
|
|
55
|
+
cb();
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
if (listener.onRestoreCompleted) {
|
|
59
|
+
const cb = listener.onRestoreCompleted;
|
|
60
|
+
handles.push(await nativePlugin.addListener('onRestoreCompleted', (data) => {
|
|
61
|
+
var _a;
|
|
62
|
+
cb({ customerInfo: (_a = data.customerInfo) !== null && _a !== void 0 ? _a : data });
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
if (listener.onRestoreError) {
|
|
66
|
+
const cb = listener.onRestoreError;
|
|
67
|
+
handles.push(await nativePlugin.addListener('onRestoreError', (data) => {
|
|
68
|
+
var _a;
|
|
69
|
+
cb({ error: (_a = data.error) !== null && _a !== void 0 ? _a : data });
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Always register onPurchaseInitiated so we auto-resume when the user
|
|
74
|
+
// doesn't provide an onPurchaseInitiated callback — otherwise the
|
|
75
|
+
// purchase flow hangs waiting for a resume that never comes.
|
|
76
|
+
// This must be outside the `if (listener)` block because the native
|
|
77
|
+
// delegate adapter always fires this event (even with purchaseLogic only).
|
|
78
|
+
const onPurchaseInitiatedCb = listener === null || listener === void 0 ? void 0 : listener.onPurchaseInitiated;
|
|
79
|
+
handles.push(await nativePlugin.addListener('onPurchaseInitiated', (data) => {
|
|
80
|
+
var _a;
|
|
81
|
+
const requestId = data.requestId;
|
|
82
|
+
const packageBeingPurchased = (_a = data.package) !== null && _a !== void 0 ? _a : data.packageBeingPurchased;
|
|
83
|
+
if (onPurchaseInitiatedCb) {
|
|
84
|
+
onPurchaseInitiatedCb({
|
|
85
|
+
packageBeingPurchased,
|
|
86
|
+
resumable: {
|
|
87
|
+
resume(shouldProceed = true) {
|
|
88
|
+
nativePlugin.resumePurchaseInitiated({ requestId, shouldProceed });
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// No callback provided — auto-proceed with the purchase.
|
|
95
|
+
nativePlugin.resumePurchaseInitiated({ requestId, shouldProceed: true });
|
|
96
|
+
}
|
|
97
|
+
}));
|
|
98
|
+
// Register PurchaseLogic event handlers
|
|
99
|
+
if (purchaseLogic) {
|
|
100
|
+
handles.push(await nativePlugin.addListener('onPerformPurchaseRequest', async (data) => {
|
|
101
|
+
var _a, _b, _c;
|
|
102
|
+
const requestId = data.requestId;
|
|
103
|
+
const packageToPurchase = (_b = (_a = data.package) !== null && _a !== void 0 ? _a : data.packageBeingPurchased) !== null && _b !== void 0 ? _b : data.packageToPurchase;
|
|
104
|
+
try {
|
|
105
|
+
const result = await purchaseLogic.performPurchase({ packageToPurchase });
|
|
106
|
+
await nativePlugin.resumePurchaseLogicPurchase(Object.assign({ requestId }, serializeResultForNative(result)));
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
await nativePlugin.resumePurchaseLogicPurchase({
|
|
110
|
+
requestId,
|
|
111
|
+
result: PURCHASE_LOGIC_RESULT.ERROR,
|
|
112
|
+
error: { message: (_c = e === null || e === void 0 ? void 0 : e.message) !== null && _c !== void 0 ? _c : 'Unknown error' },
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}));
|
|
116
|
+
handles.push(await nativePlugin.addListener('onPerformRestoreRequest', async (data) => {
|
|
117
|
+
var _a;
|
|
118
|
+
const requestId = data.requestId;
|
|
119
|
+
try {
|
|
120
|
+
const result = await purchaseLogic.performRestore();
|
|
121
|
+
await nativePlugin.resumePurchaseLogicRestore(Object.assign({ requestId }, serializeResultForNative(result)));
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
await nativePlugin.resumePurchaseLogicRestore({
|
|
125
|
+
requestId,
|
|
126
|
+
result: PURCHASE_LOGIC_RESULT.ERROR,
|
|
127
|
+
error: { message: (_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : 'Unknown error' },
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
// Call native with serializable-only options
|
|
133
|
+
const nativeOptions = Object.assign(Object.assign({}, options), { hasPaywallListener: !!listener, hasPurchaseLogic: !!purchaseLogic });
|
|
134
|
+
// Remove non-serializable fields
|
|
135
|
+
delete nativeOptions.listener;
|
|
136
|
+
delete nativeOptions.purchaseLogic;
|
|
137
|
+
return await nativeMethod(nativeOptions);
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
// Clean up all registered listeners
|
|
141
|
+
for (const handle of handles) {
|
|
142
|
+
await handle.remove();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const RevenueCatUI = {
|
|
147
|
+
async presentPaywall(options) {
|
|
148
|
+
const listener = options === null || options === void 0 ? void 0 : options.listener;
|
|
149
|
+
const purchaseLogic = options === null || options === void 0 ? void 0 : options.purchaseLogic;
|
|
150
|
+
if (!listener && !purchaseLogic) {
|
|
151
|
+
return nativePlugin.presentPaywall(options !== null && options !== void 0 ? options : {});
|
|
152
|
+
}
|
|
153
|
+
return presentWithListenerSupport((opts) => nativePlugin.presentPaywall(opts), Object.assign({}, options), listener, purchaseLogic);
|
|
154
|
+
},
|
|
155
|
+
async presentPaywallIfNeeded(options) {
|
|
156
|
+
const listener = options === null || options === void 0 ? void 0 : options.listener;
|
|
157
|
+
const purchaseLogic = options === null || options === void 0 ? void 0 : options.purchaseLogic;
|
|
158
|
+
if (!listener && !purchaseLogic) {
|
|
159
|
+
return nativePlugin.presentPaywallIfNeeded(options);
|
|
160
|
+
}
|
|
161
|
+
return presentWithListenerSupport((opts) => nativePlugin.presentPaywallIfNeeded(opts), Object.assign({}, options), listener, purchaseLogic);
|
|
162
|
+
},
|
|
163
|
+
async presentCustomerCenter() {
|
|
164
|
+
return nativePlugin.presentCustomerCenter();
|
|
165
|
+
},
|
|
166
|
+
setMockWebResults: nativePlugin.setMockWebResults
|
|
167
|
+
? async (options) => {
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
169
|
+
return nativePlugin.setMockWebResults(options);
|
|
170
|
+
}
|
|
171
|
+
: undefined,
|
|
172
|
+
addListener(eventName, listener) {
|
|
173
|
+
return nativePlugin.addListener(eventName, listener);
|
|
174
|
+
},
|
|
175
|
+
removeAllListeners() {
|
|
176
|
+
return nativePlugin.removeAllListeners();
|
|
177
|
+
},
|
|
178
|
+
};
|
|
5
179
|
export * from './definitions';
|
|
6
180
|
export { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';
|
|
7
181
|
export { RevenueCatUI };
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,YAAY,GAAG,cAAc,CAAqB,cAAc,EAAE;IACtE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;CAChE,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { RevenueCatUIPlugin } from './definitions';\n\nconst RevenueCatUI = registerPlugin<RevenueCatUIPlugin>('RevenueCatUI', {\n web: () => import('./web').then((m) => new m.RevenueCatUIWeb()),\n});\n\nexport * from './definitions';\nexport { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';\nexport { RevenueCatUI };\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { registerPlugin } from '@capacitor/core';\nimport type { PluginListenerHandle } from '@capacitor/core';\n\nimport type {\n PaywallListener,\n PaywallResult,\n PresentPaywallIfNeededOptions,\n PresentPaywallOptions,\n PurchaseLogic,\n PurchaseLogicResult,\n RevenueCatUIPlugin,\n} from './definitions';\nimport { PURCHASE_LOGIC_RESULT } from './definitions';\n\n/**\n * Internal native plugin interface with native-only methods and events.\n * This is not exported to consumers.\n */\ninterface RevenueCatUINativePlugin {\n presentPaywall(options: {\n offering?: any;\n displayCloseButton?: boolean;\n hasPaywallListener?: boolean;\n hasPurchaseLogic?: boolean;\n }): Promise<PaywallResult>;\n presentPaywallIfNeeded(options: {\n offering?: any;\n displayCloseButton?: boolean;\n requiredEntitlementIdentifier: string;\n hasPaywallListener?: boolean;\n hasPurchaseLogic?: boolean;\n }): Promise<PaywallResult>;\n presentCustomerCenter(): Promise<void>;\n setMockWebResults?(options: { shouldMockWebResults: boolean }): Promise<void>;\n\n resumePurchaseInitiated(options: { requestId: string; shouldProceed: boolean }): Promise<void>;\n resumePurchaseLogicPurchase(options: {\n requestId: string;\n result: string;\n error?: { code?: string; message?: string };\n }): Promise<void>;\n resumePurchaseLogicRestore(options: {\n requestId: string;\n result: string;\n error?: { code?: string; message?: string };\n }): Promise<void>;\n\n addListener(eventName: string, listener: (data: any) => void): Promise<PluginListenerHandle>;\n removeAllListeners(): Promise<void>;\n}\n\nconst nativePlugin = registerPlugin<RevenueCatUINativePlugin>('RevenueCatUI', {\n web: () => import('./web').then((m) => new m.RevenueCatUIWeb()),\n});\n\nfunction serializeResultForNative(result: PurchaseLogicResult): {\n result: string;\n error?: { code?: string; message?: string };\n} {\n if (result.result === PURCHASE_LOGIC_RESULT.ERROR && 'error' in result && result.error) {\n return {\n result: result.result,\n error: {\n code: result.error.code,\n message: result.error.message,\n },\n };\n }\n return { result: result.result };\n}\n\nasync function presentWithListenerSupport(\n nativeMethod: (options: any) => Promise<PaywallResult>,\n options: any,\n listener?: PaywallListener,\n purchaseLogic?: PurchaseLogic,\n): Promise<PaywallResult> {\n const handles: PluginListenerHandle[] = [];\n\n try {\n // Register PaywallListener event handlers\n if (listener) {\n if (listener.onPurchaseStarted) {\n const cb = listener.onPurchaseStarted;\n handles.push(\n await nativePlugin.addListener('onPurchaseStarted', (data: any) => {\n cb({ packageBeingPurchased: data.packageBeingPurchased ?? data });\n }),\n );\n }\n if (listener.onPurchaseCompleted) {\n const cb = listener.onPurchaseCompleted;\n handles.push(\n await nativePlugin.addListener('onPurchaseCompleted', (data: any) => {\n cb({\n customerInfo: data.customerInfo,\n storeTransaction: data.storeTransaction,\n });\n }),\n );\n }\n if (listener.onPurchaseError) {\n const cb = listener.onPurchaseError;\n handles.push(\n await nativePlugin.addListener('onPurchaseError', (data: any) => {\n cb({ error: data.error ?? data });\n }),\n );\n }\n if (listener.onPurchaseCancelled) {\n const cb = listener.onPurchaseCancelled;\n handles.push(\n await nativePlugin.addListener('onPurchaseCancelled', () => {\n cb();\n }),\n );\n }\n if (listener.onRestoreStarted) {\n const cb = listener.onRestoreStarted;\n handles.push(\n await nativePlugin.addListener('onRestoreStarted', () => {\n cb();\n }),\n );\n }\n if (listener.onRestoreCompleted) {\n const cb = listener.onRestoreCompleted;\n handles.push(\n await nativePlugin.addListener('onRestoreCompleted', (data: any) => {\n cb({ customerInfo: data.customerInfo ?? data });\n }),\n );\n }\n if (listener.onRestoreError) {\n const cb = listener.onRestoreError;\n handles.push(\n await nativePlugin.addListener('onRestoreError', (data: any) => {\n cb({ error: data.error ?? data });\n }),\n );\n }\n }\n\n // Always register onPurchaseInitiated so we auto-resume when the user\n // doesn't provide an onPurchaseInitiated callback — otherwise the\n // purchase flow hangs waiting for a resume that never comes.\n // This must be outside the `if (listener)` block because the native\n // delegate adapter always fires this event (even with purchaseLogic only).\n const onPurchaseInitiatedCb = listener?.onPurchaseInitiated;\n handles.push(\n await nativePlugin.addListener('onPurchaseInitiated', (data: any) => {\n const requestId: string = data.requestId;\n const packageBeingPurchased = data.package ?? data.packageBeingPurchased;\n if (onPurchaseInitiatedCb) {\n onPurchaseInitiatedCb({\n packageBeingPurchased,\n resumable: {\n resume(shouldProceed = true) {\n nativePlugin.resumePurchaseInitiated({ requestId, shouldProceed });\n },\n },\n });\n } else {\n // No callback provided — auto-proceed with the purchase.\n nativePlugin.resumePurchaseInitiated({ requestId, shouldProceed: true });\n }\n }),\n );\n\n // Register PurchaseLogic event handlers\n if (purchaseLogic) {\n handles.push(\n await nativePlugin.addListener('onPerformPurchaseRequest', async (data: any) => {\n const requestId: string = data.requestId;\n const packageToPurchase = data.package ?? data.packageBeingPurchased ?? data.packageToPurchase;\n try {\n const result = await purchaseLogic.performPurchase({ packageToPurchase });\n await nativePlugin.resumePurchaseLogicPurchase({\n requestId,\n ...serializeResultForNative(result),\n });\n } catch (e: any) {\n await nativePlugin.resumePurchaseLogicPurchase({\n requestId,\n result: PURCHASE_LOGIC_RESULT.ERROR,\n error: { message: e?.message ?? 'Unknown error' },\n });\n }\n }),\n );\n handles.push(\n await nativePlugin.addListener('onPerformRestoreRequest', async (data: any) => {\n const requestId: string = data.requestId;\n try {\n const result = await purchaseLogic.performRestore();\n await nativePlugin.resumePurchaseLogicRestore({\n requestId,\n ...serializeResultForNative(result),\n });\n } catch (e: any) {\n await nativePlugin.resumePurchaseLogicRestore({\n requestId,\n result: PURCHASE_LOGIC_RESULT.ERROR,\n error: { message: e?.message ?? 'Unknown error' },\n });\n }\n }),\n );\n }\n\n // Call native with serializable-only options\n const nativeOptions = {\n ...options,\n hasPaywallListener: !!listener,\n hasPurchaseLogic: !!purchaseLogic,\n };\n // Remove non-serializable fields\n delete nativeOptions.listener;\n delete nativeOptions.purchaseLogic;\n\n return await nativeMethod(nativeOptions);\n } finally {\n // Clean up all registered listeners\n for (const handle of handles) {\n await handle.remove();\n }\n }\n}\n\nconst RevenueCatUI: RevenueCatUIPlugin = {\n async presentPaywall(options?: PresentPaywallOptions): Promise<PaywallResult> {\n const listener = options?.listener;\n const purchaseLogic = options?.purchaseLogic;\n\n if (!listener && !purchaseLogic) {\n return nativePlugin.presentPaywall(options ?? {});\n }\n\n return presentWithListenerSupport(\n (opts) => nativePlugin.presentPaywall(opts),\n { ...options },\n listener,\n purchaseLogic,\n );\n },\n\n async presentPaywallIfNeeded(options: PresentPaywallIfNeededOptions): Promise<PaywallResult> {\n const listener = options?.listener;\n const purchaseLogic = options?.purchaseLogic;\n\n if (!listener && !purchaseLogic) {\n return nativePlugin.presentPaywallIfNeeded(options);\n }\n\n return presentWithListenerSupport(\n (opts) => nativePlugin.presentPaywallIfNeeded(opts),\n { ...options },\n listener,\n purchaseLogic,\n );\n },\n\n async presentCustomerCenter(): Promise<void> {\n return nativePlugin.presentCustomerCenter();\n },\n\n setMockWebResults: nativePlugin.setMockWebResults\n ? async (options: { shouldMockWebResults: boolean }): Promise<void> => {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return nativePlugin.setMockWebResults!(options);\n }\n : undefined,\n\n addListener(eventName: 'paywallDisplayed' | 'paywallDismissed', listener: () => void): Promise<PluginListenerHandle> {\n return nativePlugin.addListener(eventName, listener);\n },\n\n removeAllListeners(): Promise<void> {\n return nativePlugin.removeAllListeners();\n },\n};\n\nexport * from './definitions';\nexport { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';\nexport { RevenueCatUI };\n"]}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -11,6 +11,26 @@ export declare class RevenueCatUIWeb extends WebPlugin implements RevenueCatUIPl
|
|
|
11
11
|
presentPaywall(options?: PresentPaywallOptions): Promise<PaywallResult>;
|
|
12
12
|
presentPaywallIfNeeded(options: PresentPaywallIfNeededOptions): Promise<PaywallResult>;
|
|
13
13
|
presentCustomerCenter(): Promise<void>;
|
|
14
|
+
resumePurchaseInitiated(_options: {
|
|
15
|
+
requestId: string;
|
|
16
|
+
shouldProceed: boolean;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
resumePurchaseLogicPurchase(_options: {
|
|
19
|
+
requestId: string;
|
|
20
|
+
result: string;
|
|
21
|
+
error?: {
|
|
22
|
+
code?: string;
|
|
23
|
+
message?: string;
|
|
24
|
+
};
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
resumePurchaseLogicRestore(_options: {
|
|
27
|
+
requestId: string;
|
|
28
|
+
result: string;
|
|
29
|
+
error?: {
|
|
30
|
+
code?: string;
|
|
31
|
+
message?: string;
|
|
32
|
+
};
|
|
33
|
+
}): Promise<void>;
|
|
14
34
|
addListener(eventName: string, listener: (...args: any[]) => void): Promise<PluginListenerHandle>;
|
|
15
35
|
removeAllListeners(): Promise<void>;
|
|
16
36
|
private mockNonReturningFunctionIfEnabled;
|
package/dist/esm/web.js
CHANGED
|
@@ -23,6 +23,18 @@ export class RevenueCatUIWeb extends WebPlugin {
|
|
|
23
23
|
async presentCustomerCenter() {
|
|
24
24
|
return this.mockNonReturningFunctionIfEnabled('presentCustomerCenter');
|
|
25
25
|
}
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
27
|
+
async resumePurchaseInitiated(_options) {
|
|
28
|
+
return this.mockNonReturningFunctionIfEnabled('resumePurchaseInitiated');
|
|
29
|
+
}
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
31
|
+
async resumePurchaseLogicPurchase(_options) {
|
|
32
|
+
return this.mockNonReturningFunctionIfEnabled('resumePurchaseLogicPurchase');
|
|
33
|
+
}
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
35
|
+
async resumePurchaseLogicRestore(_options) {
|
|
36
|
+
return this.mockNonReturningFunctionIfEnabled('resumePurchaseLogicRestore');
|
|
37
|
+
}
|
|
26
38
|
addListener(eventName, listener) {
|
|
27
39
|
if (eventName !== 'paywallDisplayed' && eventName !== 'paywallDismissed') {
|
|
28
40
|
console.warn(`Unsupported event: ${eventName}`);
|