react-native-purchases
Version:
React Native in-app purchases and subscriptions made easy. Supports iOS and Android.
847 lines • 116 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PurchasesAdTracker = exports.AdRevenuePrecision = exports.AdFormat = exports.AdMediatorName = exports.WebPurchaseRedemptionResultType = exports.STOREKIT_VERSION = exports.LOG_LEVEL = exports.REFUND_REQUEST_STATUS = exports.BILLING_FEATURE = exports.PURCHASES_ARE_COMPLETED_BY_TYPE = exports.PURCHASE_TYPE = void 0;
var react_native_1 = require("react-native");
var purchases_typescript_internal_1 = require("@revenuecat/purchases-typescript-internal");
var environment_1 = require("./utils/environment");
var nativeModule_1 = require("./browser/nativeModule");
// This export is kept to keep backwards compatibility to any possible users using this file directly
var purchases_typescript_internal_2 = require("@revenuecat/purchases-typescript-internal");
Object.defineProperty(exports, "PURCHASE_TYPE", { enumerable: true, get: function () { return purchases_typescript_internal_2.PURCHASE_TYPE; } });
Object.defineProperty(exports, "PURCHASES_ARE_COMPLETED_BY_TYPE", { enumerable: true, get: function () { return purchases_typescript_internal_2.PURCHASES_ARE_COMPLETED_BY_TYPE; } });
Object.defineProperty(exports, "BILLING_FEATURE", { enumerable: true, get: function () { return purchases_typescript_internal_2.BILLING_FEATURE; } });
Object.defineProperty(exports, "REFUND_REQUEST_STATUS", { enumerable: true, get: function () { return purchases_typescript_internal_2.REFUND_REQUEST_STATUS; } });
Object.defineProperty(exports, "LOG_LEVEL", { enumerable: true, get: function () { return purchases_typescript_internal_2.LOG_LEVEL; } });
Object.defineProperty(exports, "STOREKIT_VERSION", { enumerable: true, get: function () { return purchases_typescript_internal_2.STOREKIT_VERSION; } });
Object.defineProperty(exports, "WebPurchaseRedemptionResultType", { enumerable: true, get: function () { return purchases_typescript_internal_2.WebPurchaseRedemptionResultType; } });
var react_native_2 = require("react-native");
var NATIVE_MODULE_ERROR = "[RevenueCat] Native module (RNPurchases) not found. This can happen if:\n\n" +
"- You are running in an environment where native modules are unavailable\n" +
"- The native module failed to initialize\n" +
"- The package is not properly linked\n\n" +
"To fix this:\n" +
"- If using Expo Go, the SDK works in preview mode but native modules are not available. " +
"For full functionality, create a development build: https://docs.expo.dev/develop/development-builds/create-a-build/\n" +
"- If using bare React Native, run 'pod install' and rebuild the app\n" +
"- Check that you have rebuilt the app after installing the package\n";
// Get the native module or use the browser implementation
var usingBrowserMode = (0, environment_1.shouldUseBrowserMode)();
var RNPurchases = usingBrowserMode ? nativeModule_1.browserNativeModuleRNPurchases : react_native_1.NativeModules.RNPurchases;
// Only create event emitter if native module is available to avoid crash on import
var eventEmitter = !usingBrowserMode && RNPurchases ? new react_native_1.NativeEventEmitter(RNPurchases) : null;
// Helper function to check if native module is available - provides better error message than "Cannot read property X of null"
function throwIfNativeModuleNotAvailable() {
if (!RNPurchases) {
throw new Error(NATIVE_MODULE_ERROR);
}
}
var customerInfoUpdateListeners = [];
var shouldPurchasePromoProductListeners = [];
var customLogHandler;
var trackedEventListeners = [];
/**
* Predefined mediator name constants. Use these or pass any string for unlisted networks.
* @beta
*/
exports.AdMediatorName = {
adMob: "AdMob",
appLovin: "AppLovin",
};
/**
* Predefined ad format constants. Use these or pass any string for unlisted formats.
* @beta
*/
exports.AdFormat = {
other: "other",
banner: "banner",
interstitial: "interstitial",
rewarded: "rewarded",
rewardedInterstitial: "rewarded_interstitial",
nativeAd: "native",
appOpen: "app_open",
};
/**
* Predefined precision constants for ad revenue. Use these or pass any string for unlisted values.
* @beta
*/
exports.AdRevenuePrecision = {
exact: "exact",
publisherDefined: "publisher_defined",
estimated: "estimated",
unknown: "unknown",
};
var debugEventListeners = [];
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.addListener("Purchases-CustomerInfoUpdated", function (customerInfo) {
customerInfoUpdateListeners.forEach(function (listener) { return listener(customerInfo); });
});
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.addListener("Purchases-ShouldPurchasePromoProduct", function (_a) {
var callbackID = _a.callbackID;
shouldPurchasePromoProductListeners.forEach(function (listener) {
return listener(function () { return RNPurchases.makeDeferredPurchase(callbackID); });
});
});
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.addListener("Purchases-LogHandlerEvent", function (_a) {
var logLevel = _a.logLevel, message = _a.message;
if (customLogHandler) {
var logLevelEnum = purchases_typescript_internal_1.LOG_LEVEL[logLevel];
customLogHandler(logLevelEnum, message);
}
});
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.addListener("Purchases-TrackedEvent", function (eventDictionary) {
trackedEventListeners.forEach(function (listener) { return listener({ eventDictionary: eventDictionary }); });
});
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.addListener("Purchases-DebugEvent", function (eventDictionary) {
debugEventListeners.forEach(function (listener) { return listener({ eventDictionary: eventDictionary }); });
});
function throwIfNotConfigured() {
return __awaiter(this, void 0, void 0, function () {
var isConfigured;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.isConfigured()];
case 1:
isConfigured = _a.sent();
if (!isConfigured) {
throw new purchases_typescript_internal_1.UninitializedPurchasesError();
}
return [2 /*return*/];
}
});
});
}
var Purchases = /** @class */ (function () {
function Purchases() {
}
/**
* Sets up Purchases with your API key and an app user id.
* @param {String} apiKey RevenueCat API Key. Needs to be a String
* @param {String?} appUserID An optional unique id for identifying the user. Needs to be a string.
* @param {PurchasesAreCompletedBy} [purchasesAreCompletedBy=PURCHASES_ARE_COMPLETED_BY_TYPE.REVENUECAT] Set this to an instance of PurchasesAreCompletedByMyApp if you have your own IAP implementation and want to use only RevenueCat's backend. Default is PURCHASES_ARE_COMPLETED_BY_TYPE.REVENUECAT.
* @param {STOREKIT_VERSION} [storeKitVersion=DEFAULT] iOS-only. Defaults to STOREKIT_2. StoreKit 2 is only available on iOS 16+. StoreKit 1 will be used for previous iOS versions regardless of this setting.
* @param {ENTITLEMENT_VERIFICATION_MODE} [entitlementVerificationMode=ENTITLEMENT_VERIFICATION_MODE.DISABLED] Sets the entitlement verifciation mode to use. For more details, check https://rev.cat/trusted-entitlements
* @param {boolean} [useAmazon=false] An optional boolean. Android-only. Set this to true to enable Amazon on compatible devices.
* @param {String?} userDefaultsSuiteName An optional string. iOS-only, will be ignored for Android.
* Set this if you would like the RevenueCat SDK to store its preferences in a different NSUserDefaults suite, otherwise it will use standardUserDefaults.
* Default is null, which will make the SDK use standardUserDefaults.
* @param {boolean} [pendingTransactionsForPrepaidPlansEnabled=false] An optional boolean. Android-only. Set this to true to enable pending transactions for prepaid subscriptions in Google Play.
* @param {boolean} [diagnosticsEnabled=false] An optional boolean. Set this to true to enable SDK diagnostics.
* @param {boolean} [automaticDeviceIdentifierCollectionEnabled=true] An optional boolean. Set this to true to allow the collection of identifiers when setting the identifier for an attribution network.
* @param {String?} [preferredUILocaleOverride] An optional string. Set this to the preferred UI locale to use for RevenueCat UI components.
*
* @warning If you use purchasesAreCompletedBy=PurchasesAreCompletedByMyApp, you must also provide a value for storeKitVersion.
*/
Purchases.configure = function (_a) {
var apiKey = _a.apiKey, _b = _a.appUserID, appUserID = _b === void 0 ? null : _b, _c = _a.purchasesAreCompletedBy, purchasesAreCompletedBy = _c === void 0 ? purchases_typescript_internal_1.PURCHASES_ARE_COMPLETED_BY_TYPE.REVENUECAT : _c, userDefaultsSuiteName = _a.userDefaultsSuiteName, _d = _a.storeKitVersion, storeKitVersion = _d === void 0 ? purchases_typescript_internal_1.STOREKIT_VERSION.DEFAULT : _d, _e = _a.useAmazon, useAmazon = _e === void 0 ? false : _e, _f = _a.shouldShowInAppMessagesAutomatically, shouldShowInAppMessagesAutomatically = _f === void 0 ? true : _f, _g = _a.entitlementVerificationMode, entitlementVerificationMode = _g === void 0 ? purchases_typescript_internal_1.ENTITLEMENT_VERIFICATION_MODE.DISABLED : _g, _h = _a.pendingTransactionsForPrepaidPlansEnabled, pendingTransactionsForPrepaidPlansEnabled = _h === void 0 ? false : _h, _j = _a.diagnosticsEnabled, diagnosticsEnabled = _j === void 0 ? false : _j, _k = _a.automaticDeviceIdentifierCollectionEnabled, automaticDeviceIdentifierCollectionEnabled = _k === void 0 ? true : _k, preferredUILocaleOverride = _a.preferredUILocaleOverride;
throwIfNativeModuleNotAvailable();
if (!customLogHandler) {
this.setLogHandler(function (logLevel, message) {
switch (logLevel) {
case purchases_typescript_internal_1.LOG_LEVEL.DEBUG:
// tslint:disable-next-line:no-console
console.debug("[RevenueCat] ".concat(message));
break;
case purchases_typescript_internal_1.LOG_LEVEL.INFO:
// tslint:disable-next-line:no-console
console.info("[RevenueCat] ".concat(message));
break;
case purchases_typescript_internal_1.LOG_LEVEL.WARN:
// tslint:disable-next-line:no-console
console.warn("[RevenueCat] ".concat(message));
break;
case purchases_typescript_internal_1.LOG_LEVEL.ERROR:
// tslint:disable-next-line:no-console
console.error("[RevenueCat] ".concat(message));
break;
default:
// tslint:disable-next-line:no-console
console.log("[RevenueCat] ".concat(message));
}
});
}
if (apiKey === undefined || typeof apiKey !== "string") {
throw new Error('Invalid API key. It must be called with an Object: configure({apiKey: "key"})');
}
if (appUserID !== null &&
typeof appUserID !== "undefined" &&
typeof appUserID !== "string") {
throw new Error("appUserID needs to be a string");
}
var purchasesCompletedByToUse = purchases_typescript_internal_1.PURCHASES_ARE_COMPLETED_BY_TYPE.REVENUECAT;
var storeKitVersionToUse = storeKitVersion;
if (Purchases.isPurchasesAreCompletedByMyApp(purchasesAreCompletedBy)) {
purchasesCompletedByToUse = purchases_typescript_internal_1.PURCHASES_ARE_COMPLETED_BY_TYPE.MY_APP;
storeKitVersionToUse = purchasesAreCompletedBy.storeKitVersion;
if (storeKitVersion !== purchases_typescript_internal_1.STOREKIT_VERSION.DEFAULT &&
storeKitVersionToUse !== storeKitVersion) {
// Typically, console messages aren't used in TS libraries, but in this case it's worth calling out the difference in
// StoreKit versions, and since the difference isn't possible farther down the call chain, we should go ahead
// and log it here.
// tslint:disable-next-line:no-console
console.warn("Warning: The storeKitVersion in purchasesAreCompletedBy does not match the function's storeKitVersion parameter. We will use the value found in purchasesAreCompletedBy.");
}
if (storeKitVersionToUse === purchases_typescript_internal_1.STOREKIT_VERSION.DEFAULT) {
// tslint:disable-next-line:no-console
console.warn("Warning: You should provide the specific StoreKit version you're using in your implementation when configuring PURCHASES_ARE_COMPLETED_BY_TYPE.MY_APP, and not rely on the DEFAULT.");
}
}
RNPurchases.setupPurchases(apiKey, appUserID, purchasesCompletedByToUse, userDefaultsSuiteName, storeKitVersionToUse, useAmazon, shouldShowInAppMessagesAutomatically, entitlementVerificationMode, pendingTransactionsForPrepaidPlansEnabled, diagnosticsEnabled, automaticDeviceIdentifierCollectionEnabled, preferredUILocaleOverride);
};
/**
* @deprecated, configure behavior through the RevenueCat dashboard (app.revenuecat.com) instead.
* If an user tries to purchase a product that is active on the current app store account,
* we will treat it as a restore and alias the new ID with the previous id.
* If you have configured the Legacy restore behavior in the RevenueCat dashboard
* and are currently setting this to true, keep this setting active.
* @param {boolean} allowSharing Set this to true if you are passing in an appUserID but it is anonymous,
* this is true by default if you didn't pass an appUserID
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet.
*/
Purchases.setAllowSharingStoreAccount = function (allowSharing) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
RNPurchases.setAllowSharingStoreAccount(allowSharing);
return [2 /*return*/];
}
});
});
};
/**
* iOS only.
* @param {boolean} simulatesAskToBuyInSandbox Set this property to true *only* when testing the ask-to-buy / SCA
* purchases flow. More information: http://errors.rev.cat/ask-to-buy
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet.
*/
Purchases.setSimulatesAskToBuyInSandbox = function (simulatesAskToBuyInSandbox) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (react_native_2.Platform.OS === "ios") {
RNPurchases.setSimulatesAskToBuyInSandbox(simulatesAskToBuyInSandbox);
}
return [2 /*return*/];
});
});
};
/**
* Sets a function to be called on updated customer info
* @param {CustomerInfoUpdateListener} customerInfoUpdateListener CustomerInfo update listener
*/
Purchases.addCustomerInfoUpdateListener = function (customerInfoUpdateListener) {
if (typeof customerInfoUpdateListener !== "function") {
throw new Error("addCustomerInfoUpdateListener needs a function");
}
customerInfoUpdateListeners.push(customerInfoUpdateListener);
};
/**
* Removes a given CustomerInfoUpdateListener
* @param {CustomerInfoUpdateListener} listenerToRemove CustomerInfoUpdateListener reference of the listener to remove
* @returns {boolean} True if listener was removed, false otherwise
*/
Purchases.removeCustomerInfoUpdateListener = function (listenerToRemove) {
if (customerInfoUpdateListeners.includes(listenerToRemove)) {
customerInfoUpdateListeners = customerInfoUpdateListeners.filter(function (listener) { return listenerToRemove !== listener; });
return true;
}
return false;
};
/**
* Sets a function to be called on purchases initiated on the Apple App Store. This is only used in iOS.
* @param {ShouldPurchasePromoProductListener} shouldPurchasePromoProductListener Called when a user initiates a
* promotional in-app purchase from the App Store. If your app is able to handle a purchase at the current time, run
* the deferredPurchase function. If the app is not in a state to make a purchase: cache the deferredPurchase, then
* call the deferredPurchase when the app is ready to make the promotional purchase.
* If the purchase should never be made, you don't need to ever call the deferredPurchase and the app will not
* proceed with promotional purchases.
*/
Purchases.addShouldPurchasePromoProductListener = function (shouldPurchasePromoProductListener) {
if (typeof shouldPurchasePromoProductListener !== "function") {
throw new Error("addShouldPurchasePromoProductListener needs a function");
}
shouldPurchasePromoProductListeners.push(shouldPurchasePromoProductListener);
};
/**
* Removes a given ShouldPurchasePromoProductListener
* @param {ShouldPurchasePromoProductListener} listenerToRemove ShouldPurchasePromoProductListener reference of
* the listener to remove
* @returns {boolean} True if listener was removed, false otherwise
*/
Purchases.removeShouldPurchasePromoProductListener = function (listenerToRemove) {
if (shouldPurchasePromoProductListeners.includes(listenerToRemove)) {
shouldPurchasePromoProductListeners =
shouldPurchasePromoProductListeners.filter(function (listener) { return listenerToRemove !== listener; });
return true;
}
return false;
};
/**
* Gets the map of entitlements -> offerings -> products
* @returns {Promise<PurchasesOfferings>} Promise of entitlements structure. The promise will be rejected if configure
* has not been called yet.
*/
Purchases.getOfferings = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.getOfferings()];
}
});
});
};
/**
* Retrieves a current offering for a placement identifier, use this to access offerings defined by targeting
* placements configured in the RevenueCat dashboard.
* @param {String} placementIdentifier The placement identifier to fetch a current offeringn for
* @returns {Promise<PurchasesOffering | null>} Promise of an optional offering. The promise will be rejected if configure
* has not been called yet.
*/
Purchases.getCurrentOfferingForPlacement = function (placementIdentifier) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.getCurrentOfferingForPlacement(placementIdentifier)];
}
});
});
};
/**
* Syncs subscriber attributes and then fetches the configured offerings for this user. This method is intended to
* be called when using Targeting Rules with Custom Attributes. Any subscriber attributes should be set before
* calling this method to ensure the returned offerings are applied with the latest subscriber attributes.
* @returns {Promise<PurchasesOfferings>} Promise of entitlements structure. The promise will be rejected if configure
* has not been called yet.
*/
Purchases.syncAttributesAndOfferingsIfNeeded = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.syncAttributesAndOfferingsIfNeeded()];
}
});
});
};
/**
* Sets attribution data from Appstack's attribution params, then syncs subscriber attributes and fetches
* fresh offerings so that Appstack-based targeting is applied before the promise resolves.
*
* Pass the object received from the Appstack Attribution SDK's `getAttributionParams()` directly.
* The SDK extracts relevant attribution info and sets the appropriate subscriber attributes.
*
* @param {object} data The attribution params from the Appstack Attribution SDK.
* @returns {Promise<PurchasesOfferings>} Promise of offerings targeted with Appstack data.
*/
Purchases.setAppstackAttributionParams = function (data) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.setAppstackAttributionParams(data)];
}
});
});
};
/**
* Fetch the product info
* @param {String[]} productIdentifiers Array of product identifiers
* @param {String} type Optional type of products to fetch, can be SUBSCRIPTION or NON_SUBSCRIPTION. SUBSCRIPTION by default
* @returns {Promise<PurchasesStoreProduct[]>} A promise containing an array of products. The promise will be rejected
* if the products are not properly configured in RevenueCat or if there is another error retrieving them.
* Rejections return an error code, and a userInfo object with more information. The promise will also be rejected
* if configure has not been called yet.
*/
Purchases.getProducts = function (productIdentifiers_1) {
return __awaiter(this, arguments, void 0, function (productIdentifiers, type) {
if (type === void 0) { type = purchases_typescript_internal_1.PRODUCT_CATEGORY.SUBSCRIPTION; }
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.getProductInfo(productIdentifiers, type)];
}
});
});
};
/**
* Make a purchase
*
* @param {String} productIdentifier The product identifier of the product you want to purchase
* @param {UpgradeInfo} upgradeInfo Android only. Optional UpgradeInfo you wish to upgrade from containing the oldSKU
* and the optional prorationMode.
* @param {String} type Optional type of product, can be inapp or subs. Subs by default
* @deprecated, use purchaseStoreProduct instead
*/
Purchases.purchaseProduct = function (productIdentifier_1, upgradeInfo_1) {
return __awaiter(this, arguments, void 0, function (productIdentifier, upgradeInfo, type) {
if (type === void 0) { type = purchases_typescript_internal_1.PURCHASE_TYPE.SUBS; }
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.purchaseProduct(productIdentifier, upgradeInfo, type, null, null, null).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* Make a purchase
*
* @param {PurchasesStoreProduct} product The product you want to purchase
* @param {GoogleProductChangeInfo | StoreProductChangeInfo} productChangeInfo Android only. Optional product change info you
* wish to upgrade from containing the oldProductIdentifier and the optional prorationMode or replacementMode.
* @param {boolean} googleIsPersonalizedPrice Android and Google only. Optional boolean indicates personalized pricing on products available for purchase in the EU.
* For compliance with EU regulations. User will see "This price has been customized for you" in the purchase dialog when true.
* See https://developer.android.com/google/play/billing/integrate#personalized-price for more info.
* @returns {Promise<{ productIdentifier: string, customerInfo:CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code,
* a boolean indicating if the user cancelled the purchase, and an object with more information. The promise will
* also be rejected if configure has not been called yet.
*/
Purchases.purchaseStoreProduct = function (product, productChangeInfo, googleIsPersonalizedPrice) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.purchaseProduct(product.identifier, productChangeInfo, product.productCategory, null, googleIsPersonalizedPrice == null
? null
: { isPersonalizedPrice: googleIsPersonalizedPrice }, product.presentedOfferingContext).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* iOS only. Purchase a product applying a given discount.
*
* @param {PurchasesStoreProduct} product The product you want to purchase
* @param {PurchasesPromotionalOffer} discount Discount to apply to this package. Retrieve this discount using getPromotionalOffer.
* @param {boolean} googleIsPersonalizedPrice Android and Google only. Optional boolean indicates personalized pricing on products available for purchase in the EU.
* For compliance with EU regulations. User will see "This price has been customize for you" in the purchase dialog when true.
* See https://developer.android.com/google/play/billing/integrate#personalized-price for more info.
* @returns {Promise<{ productIdentifier: string, customerInfo:CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code,
* a boolean indicating if the user cancelled the purchase, and an object with more information. The promise will be
* rejected if configure has not been called yet.
*/
Purchases.purchaseDiscountedProduct = function (product, discount) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
if (typeof discount === "undefined" || discount == null) {
throw new Error("A discount is required");
}
return [2 /*return*/, RNPurchases.purchaseProduct(product.identifier, null, null, discount.timestamp.toString(), null, product.presentedOfferingContext).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* Make a purchase
*
* @param {PurchasesPackage} aPackage The Package you wish to purchase. You can get the Packages by calling getOfferings
* @param {UpgradeInfo} upgradeInfo DEPRECATED. Use productChangeInfo.
* @param {GoogleProductChangeInfo | StoreProductChangeInfo} productChangeInfo Android only. Optional product change info you
* wish to upgrade from containing the oldProductIdentifier and the optional prorationMode or replacementMode.
* @param {boolean} googleIsPersonalizedPrice Android and Google only. Optional boolean indicates personalized pricing on products available for purchase in the EU.
* For compliance with EU regulations. User will see "This price has been customized for you" in the purchase dialog when true.
* See https://developer.android.com/google/play/billing/integrate#personalized-price for more info.
* @returns {Promise<{ productIdentifier: string, customerInfo: CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code, a boolean indicating if the
* user cancelled the purchase, and an object with more information. The promise will be also be rejected if configure
* has not been called yet.
*/
Purchases.purchasePackage = function (aPackage, upgradeInfo, productChangeInfo, googleIsPersonalizedPrice) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.purchasePackage(aPackage.identifier, aPackage.presentedOfferingContext, productChangeInfo || upgradeInfo, null, googleIsPersonalizedPrice == null
? null
: { isPersonalizedPrice: googleIsPersonalizedPrice }).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* Google only. Make a purchase of a subscriptionOption
*
* @param {SubscriptionOption} subscriptionOption The SubscriptionOption you wish to purchase. You can get the SubscriptionOption from StoreProducts by calling getOfferings
* @param {GoogleProductChangeInfo | StoreProductChangeInfo} productChangeInfo Android only. Optional product change info you
* wish to upgrade from containing the oldProductIdentifier and the optional prorationMode or replacementMode.
* @param {boolean} googleIsPersonalizedPrice Android and Google only. Optional boolean indicates personalized pricing on products available for purchase in the EU.
* For compliance with EU regulations. User will see "This price has been customized for you" in the purchase dialog when true.
* See https://developer.android.com/google/play/billing/integrate#personalized-price for more info.
* @returns {Promise<{ productIdentifier: string, customerInfo: CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code, a boolean indicating if the
* user cancelled the purchase, and an object with more information. The promise will be also be rejected if configure
* has not been called yet.
*/
Purchases.purchaseSubscriptionOption = function (subscriptionOption, productChangeInfo, googleIsPersonalizedPrice) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [4 /*yield*/, Purchases.throwIfIOSPlatform()];
case 2:
_a.sent();
return [2 /*return*/, RNPurchases.purchaseSubscriptionOption(subscriptionOption.productId, subscriptionOption.id, productChangeInfo, null, googleIsPersonalizedPrice == null
? null
: { isPersonalizedPrice: googleIsPersonalizedPrice }, subscriptionOption.presentedOfferingContext).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* iOS only. Purchase a package applying a given discount.
*
* @param {PurchasesPackage} aPackage The Package you wish to purchase. You can get the Packages by calling getOfferings
* @param {PurchasesPromotionalOffer} discount Discount to apply to this package. Retrieve this discount using getPromotionalOffer.
* @returns {Promise<{ productIdentifier: string, customerInfo: CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code, a boolean indicating if the
* user cancelled the purchase, and an object with more information. The promise will be also be rejected if configure
* has not been called yet.
*/
Purchases.purchaseDiscountedPackage = function (aPackage, discount) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
if (typeof discount === "undefined" || discount == null) {
throw new Error("A discount is required");
}
return [2 /*return*/, RNPurchases.purchasePackage(aPackage.identifier, aPackage.presentedOfferingContext, null, discount.timestamp.toString(), null).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* Restores a user's previous purchases and links their appUserIDs to any user's also using those purchases.
* @returns {Promise<CustomerInfo>} A promise of a customer info object. Rejections return an error code, and an
* userInfo object with more information. The promise will be also be rejected if configure has not been called yet.
*/
Purchases.restorePurchases = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.restorePurchases()];
}
});
});
};
/**
* Get the appUserID
* @returns {Promise<string>} The app user id in a promise
*/
Purchases.getAppUserID = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.getAppUserID()];
}
});
});
};
/**
* Gets the storefront for the current store account.
* @returns {Promise<Storefront | null>} The storefront for the current store account, or null if the storefront is not available.
*/
Purchases.getStorefront = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.getStorefront()];
}
});
});
};
/**
* This function will logIn the current user with an appUserID. Typically this would be used after a log in
* to identify a user without calling configure.
* @param {String} appUserID The appUserID that should be linked to the currently user
* @returns {Promise<LogInResult>} A promise of an object that contains the customerInfo after logging in, as well
* as a boolean indicating whether the user has just been created for the first time in the RevenueCat backend. The
* promise will be rejected if configure has not been called yet or if there's an issue logging in.
*/
Purchases.logIn = function (appUserID) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
// noinspection SuspiciousTypeOfGuard
if (typeof appUserID !== "string") {
throw new Error("appUserID needs to be a string");
}
return [2 /*return*/, RNPurchases.logIn(appUserID)];
}
});
});
};
/**
* Logs out the Purchases client clearing the saved appUserID. This will generate a random user id and save it in the cache.
* @returns {Promise<CustomerInfo>} A promise of a customer info object. Rejections return an error code,
* and a userInfo object with more information. The promise will be rejected if configure has not been called yet or if
* there's an issue logging out.
*/
Purchases.logOut = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.logOut()];
}
});
});
};
/**
* Enables/Disables debugs logs
* @param {boolean} enabled Enable or not debug logs
* @deprecated, use setLogLevel instead
*/
Purchases.setDebugLogsEnabled = function (enabled) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
RNPurchases.setDebugLogsEnabled(enabled);
return [2 /*return*/];
});
});
};
/**
* Used to set the log level. Useful for debugging issues with the lovely team @RevenueCat.
* The default is {LOG_LEVEL.INFO} in release builds and {LOG_LEVEL.DEBUG} in debug builds.
* @param {LOG_LEVEL} level
*/
Purchases.setLogLevel = function (level) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
RNPurchases.setLogLevel(level);
return [2 /*return*/];
});
});
};
/**
* Set a custom log handler for redirecting logs to your own logging system.
* By default, this sends info, warning, and error messages.
* If you wish to receive Debug level messages, see [setLogLevel].
* @param {LogHandler} logHandler It will get called for each log event.
* Use this function to redirect the log to your own logging system
*/
Purchases.setLogHandler = function (logHandler) {
customLogHandler = logHandler;
if (usingBrowserMode) {
RNPurchases.setLogHandler(logHandler);
}
else {
RNPurchases.setLogHandler();
}
};
/**
* Sets a function to be called when a feature event is tracked by RevenueCatUI.
* This is a debug API for monitoring paywall and customer center events not meant for public use.
* Currently only works on Android and iOS.
* @internal
* @param {TrackedEventListener} trackedEventListener TrackedEvent listener
*/
Purchases.addTrackedEventListener = function (trackedEventListener) {
return __awaiter(this, void 0, void 0, function () {
var isFirstListener;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
if (react_native_2.Platform.OS === "android" || react_native_2.Platform.OS === "ios") {
if (typeof trackedEventListener !== "function") {
throw new Error("addTrackedEventListener needs a function");
}
isFirstListener = trackedEventListeners.length === 0;
trackedEventListeners.push(trackedEventListener);
if (isFirstListener && !usingBrowserMode) {
RNPurchases.setTrackedEventListener();
}
}
return [2 /*return*/];
}
});
});
};
/**
* Removes a given TrackedEventListener.
* This is a debug API not meant for public use.
* @internal
* @param trackedEventListener TrackedEvent listener to remove
*/
Purchases.removeTrackedEventListener = function (trackedEventListener) {
trackedEventListeners = trackedEventListeners.filter(function (listener) { return listener !== trackedEventListener; });
};
/**
* Sets a function to be called when a debug event is tracked by RevenueCat.
* This is a debug API for monitoring debug events not meant for public use.
* Currently only works on Android.
* @internal
* @param {DebugEventListener} debugEventListener DebugEvent listener
*/
Purchases.addDebugEventListener = function (debugEventListener) {
return __awaiter(this, void 0, void 0, function () {
var isFirstListener;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
if (react_native_2.Platform.OS === "android") {
if (typeof debugEventListener !== "function") {
throw new Error("addDebugEventListener needs a function");
}
isFirstListener = debugEventListeners.length === 0;
debugEventListeners.push(debugEventListener);
if (isFirstListener && !usingBrowserMode) {
RNPurchases.setDebugEventListener();
}
}
return [2 /*return*/];
}
});
});
};
/**
* Removes a given DebugEventListener.
* This is a debug API not meant for public use.
* @internal
* @param debugEventListener DebugEventListener listener to remove
*/
Purchases.removeDebugEventListener = function (debugEventListener) {
debugEventListeners = debugEventListeners.filter(function (listener) { return listener !== debugEventListener; });
};
/**
* Gets current customer info
* @returns {Promise<CustomerInfo>} A promise of a customer info object. Rejections return an error code, and an
* userInfo object with more information. The promise will be rejected if configure has not been called yet or if
* there's an issue getting the customer information.
*/
Purchases.getCustomerInfo = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
return [2 /*return*/, RNPurchases.getCustomerInfo()];
}
});
});
};
/**
* This method will send all the purchases to the RevenueCat backend. Call this when using your own implementation
* for subscriptions anytime a sync is needed, like after a successful purchase.
*
* @deprecated Use {@link syncPurchasesForResult} instead, which returns the updated CustomerInfo.
* @warning This function should only be called if you're not calling purchaseProduct/purchaseStoreProduct/purchasePackage/purchaseSubscriptionOption.
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet or if there's an error
* syncing purchases.
*/
Purchases.syncPurchases = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, throwIfNotConfigured()];
case 1:
_a.sent();
RNPurchases.syncPurchases();
return