@entitlehub/react-native 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/index.cjs +121 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +95 -0
- package/package.json +50 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-07-18
|
|
4
|
+
|
|
5
|
+
Initial release.
|
|
6
|
+
|
|
7
|
+
- `configureEntitleHub`, `purchaseProduct` (native sheet → validate → entitlements),
|
|
8
|
+
`restorePurchases`, `getCustomerInfo`, `isEntitled`, `getOfferings`, `getProducts`, `logIn`,
|
|
9
|
+
`addCustomerInfoUpdateListener`.
|
|
10
|
+
- Wraps `expo-iap` (peer) for the store purchase and `@entitlehub/sdk` for the entitlement layer.
|
|
11
|
+
Publishable-key only; receipts validated server-side by EntitleHub.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 EntitleHub
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# @entitlehub/react-native
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@entitlehub/react-native)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
EntitleHub for **React Native & Expo** — one call to purchase and unlock entitlements. It opens the
|
|
7
|
+
native store sheet (via [`expo-iap`](https://github.com/hyochan/expo-iap)), validates the receipt
|
|
8
|
+
with EntitleHub server-side, and hands you the updated entitlements. The RevenueCat developer
|
|
9
|
+
experience, on EntitleHub.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx expo install expo-iap
|
|
13
|
+
npm install @entitlehub/react-native @entitlehub/sdk
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Use
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import {
|
|
20
|
+
configureEntitleHub, purchaseProduct, getCustomerInfo, restorePurchases, isEntitled,
|
|
21
|
+
} from "@entitlehub/react-native";
|
|
22
|
+
|
|
23
|
+
// once, after your own login:
|
|
24
|
+
await configureEntitleHub({ apiKey: "pk_live_…", appUserId: user.id });
|
|
25
|
+
|
|
26
|
+
// gate a feature:
|
|
27
|
+
if (await isEntitled("pro")) unlockPro();
|
|
28
|
+
|
|
29
|
+
// buy — opens the native sheet, validates, returns entitlements:
|
|
30
|
+
const info = await purchaseProduct("app_pro_monthly", { isSubscription: true });
|
|
31
|
+
if (info.isActive("pro")) unlockPro();
|
|
32
|
+
|
|
33
|
+
// restore:
|
|
34
|
+
const restored = await restorePurchases();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| Function | What it does |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `configureEntitleHub({ apiKey, appUserId, baseUrl? })` | Configure + open the store connection. |
|
|
40
|
+
| `purchaseProduct(productId, { isSubscription? })` | Native purchase → validate with EntitleHub → returns `CustomerInfo`. |
|
|
41
|
+
| `restorePurchases()` | Re-validate the store's purchases, return `CustomerInfo`. |
|
|
42
|
+
| `getCustomerInfo()` / `isEntitled(id)` | Read entitlements. |
|
|
43
|
+
| `getOfferings()` / `getProducts(ids)` | Catalog metadata / live store prices. |
|
|
44
|
+
| `logIn(appUserId)` | Switch the acting user. |
|
|
45
|
+
| `addCustomerInfoUpdateListener(fn)` | React to entitlement changes. |
|
|
46
|
+
|
|
47
|
+
Only your **publishable** key (`pk_`) ships in the app. EntitleHub validates the Apple/Google
|
|
48
|
+
receipt server-side, so a forged one is rejected — no secret key on the device.
|
|
49
|
+
|
|
50
|
+
## How it works
|
|
51
|
+
|
|
52
|
+
`purchaseProduct` calls `expo-iap` to open the StoreKit / Play Billing sheet, then reports the
|
|
53
|
+
resulting receipt to EntitleHub: the iOS StoreKit 2 JWS, or the Android purchase token. EntitleHub
|
|
54
|
+
verifies it (Apple root CA / Google Play API), writes the entitlement grant, and returns the
|
|
55
|
+
customer info. Renewals/refunds stay current via
|
|
56
|
+
[server-to-server notifications](https://entitlehub.com/docs/store-credentials).
|
|
57
|
+
|
|
58
|
+
Full guide: **[entitlehub.com/docs/purchases](https://entitlehub.com/docs/purchases)**.
|
|
59
|
+
|
|
60
|
+
> Requires a development build (Expo Go has no in-app-purchase native module). The entitlement layer
|
|
61
|
+
> is [`@entitlehub/sdk`](https://www.npmjs.com/package/@entitlehub/sdk); this package adds the
|
|
62
|
+
> purchase flow on top.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
addCustomerInfoUpdateListener: () => addCustomerInfoUpdateListener,
|
|
24
|
+
configureEntitleHub: () => configureEntitleHub,
|
|
25
|
+
getCustomerInfo: () => getCustomerInfo,
|
|
26
|
+
getOfferings: () => getOfferings,
|
|
27
|
+
getProducts: () => getProducts,
|
|
28
|
+
isEntitled: () => isEntitled,
|
|
29
|
+
logIn: () => logIn,
|
|
30
|
+
purchaseProduct: () => purchaseProduct,
|
|
31
|
+
restorePurchases: () => restorePurchases
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(index_exports);
|
|
34
|
+
var import_sdk = require("@entitlehub/sdk");
|
|
35
|
+
var _iap;
|
|
36
|
+
function iap() {
|
|
37
|
+
if (_iap) return _iap;
|
|
38
|
+
try {
|
|
39
|
+
_iap = require("expo-iap");
|
|
40
|
+
} catch {
|
|
41
|
+
throw new Error("@entitlehub/react-native needs 'expo-iap'. Install it with: npx expo install expo-iap");
|
|
42
|
+
}
|
|
43
|
+
return _iap;
|
|
44
|
+
}
|
|
45
|
+
var client;
|
|
46
|
+
function eh() {
|
|
47
|
+
if (!client) throw new Error("Call configureEntitleHub({ apiKey, appUserId }) before using EntitleHub.");
|
|
48
|
+
return client;
|
|
49
|
+
}
|
|
50
|
+
async function configureEntitleHub(opts) {
|
|
51
|
+
client = new import_sdk.EntitleHub({ apiKey: opts.apiKey, appUserId: opts.appUserId, baseUrl: opts.baseUrl });
|
|
52
|
+
try {
|
|
53
|
+
await iap().initConnection();
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function logIn(appUserId) {
|
|
58
|
+
return eh().logIn(appUserId);
|
|
59
|
+
}
|
|
60
|
+
async function getCustomerInfo() {
|
|
61
|
+
return eh().getCustomerInfo();
|
|
62
|
+
}
|
|
63
|
+
async function isEntitled(entitlementId) {
|
|
64
|
+
return eh().isEntitled(entitlementId);
|
|
65
|
+
}
|
|
66
|
+
async function getOfferings() {
|
|
67
|
+
return eh().getOfferings();
|
|
68
|
+
}
|
|
69
|
+
async function getProducts(productIds) {
|
|
70
|
+
return iap().getProducts(productIds);
|
|
71
|
+
}
|
|
72
|
+
async function purchaseProduct(productId, opts = {}) {
|
|
73
|
+
const I = iap();
|
|
74
|
+
const result = await I.requestPurchase({ sku: productId, skus: [productId] });
|
|
75
|
+
const purchase = Array.isArray(result) ? result[0] : result;
|
|
76
|
+
if (!purchase) throw new Error("purchase-cancelled");
|
|
77
|
+
const info = await reportToEntitleHub(purchase, productId, opts.isSubscription);
|
|
78
|
+
try {
|
|
79
|
+
await I.finishTransaction({ purchase, isConsumable: false });
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
return info;
|
|
83
|
+
}
|
|
84
|
+
async function restorePurchases() {
|
|
85
|
+
const I = iap();
|
|
86
|
+
const purchases = await I.getAvailablePurchases() || [];
|
|
87
|
+
for (const p of purchases) {
|
|
88
|
+
await reportToEntitleHub(p, p.productId ?? p.id ?? p.sku, true).catch(() => {
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return eh().getCustomerInfo({ fetchPolicy: "network-only" });
|
|
92
|
+
}
|
|
93
|
+
function addCustomerInfoUpdateListener(fn) {
|
|
94
|
+
return eh().addCustomerInfoUpdateListener(fn);
|
|
95
|
+
}
|
|
96
|
+
async function reportToEntitleHub(purchase, productId, isSubscription) {
|
|
97
|
+
const jws = purchase?.jwsRepresentationIos ?? purchase?.jwsRepresentation ?? purchase?.verificationResultIos;
|
|
98
|
+
if (jws) return eh().reportPurchase({ signedTransaction: jws });
|
|
99
|
+
const token = purchase?.purchaseTokenAndroid ?? purchase?.purchaseToken;
|
|
100
|
+
if (token) {
|
|
101
|
+
return eh().reportPurchase({
|
|
102
|
+
store: "play",
|
|
103
|
+
storeProductId: productId,
|
|
104
|
+
purchaseToken: token,
|
|
105
|
+
isSubscription: Boolean(isSubscription)
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
throw new Error("Could not read a receipt from the purchase (no iOS JWS or Android purchase token).");
|
|
109
|
+
}
|
|
110
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
111
|
+
0 && (module.exports = {
|
|
112
|
+
addCustomerInfoUpdateListener,
|
|
113
|
+
configureEntitleHub,
|
|
114
|
+
getCustomerInfo,
|
|
115
|
+
getOfferings,
|
|
116
|
+
getProducts,
|
|
117
|
+
isEntitled,
|
|
118
|
+
logIn,
|
|
119
|
+
purchaseProduct,
|
|
120
|
+
restorePurchases
|
|
121
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CustomerInfo, Offerings } from '@entitlehub/sdk';
|
|
2
|
+
export { CustomerInfo, Offerings } from '@entitlehub/sdk';
|
|
3
|
+
|
|
4
|
+
interface ConfigureOptions {
|
|
5
|
+
/** Your EntitleHub publishable key (pk_live_… / pk_test_…). Client-safe. */
|
|
6
|
+
apiKey: string;
|
|
7
|
+
/** Your own stable user id. */
|
|
8
|
+
appUserId: string;
|
|
9
|
+
/** Override the API base (self-host). */
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Configure EntitleHub and open the store connection. Call once at startup (after your own login). */
|
|
13
|
+
declare function configureEntitleHub(opts: ConfigureOptions): Promise<void>;
|
|
14
|
+
/** Switch the acting user after your own login. Returns their entitlements. */
|
|
15
|
+
declare function logIn(appUserId: string): Promise<CustomerInfo>;
|
|
16
|
+
/** The current user's entitlements (cached; RC-style CustomerInfo). */
|
|
17
|
+
declare function getCustomerInfo(): Promise<CustomerInfo>;
|
|
18
|
+
/** Convenience: is the user entitled right now? */
|
|
19
|
+
declare function isEntitled(entitlementId: string): Promise<boolean>;
|
|
20
|
+
/** Your EntitleHub catalog (entitlements + products) for building a paywall. */
|
|
21
|
+
declare function getOfferings(): Promise<Offerings>;
|
|
22
|
+
/** Live store products (prices, localized titles) for the given ids, from the native store. */
|
|
23
|
+
declare function getProducts(productIds: string[]): Promise<any[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Buy a product in one call: open the native purchase sheet, validate the receipt with EntitleHub,
|
|
26
|
+
* and return the updated entitlements. Purchase + entitlement sync, the RevenueCat way.
|
|
27
|
+
* Throws "purchase-cancelled" if the user backs out.
|
|
28
|
+
*/
|
|
29
|
+
declare function purchaseProduct(productId: string, opts?: {
|
|
30
|
+
isSubscription?: boolean;
|
|
31
|
+
}): Promise<CustomerInfo>;
|
|
32
|
+
/** Restore the user's purchases: re-validate each with EntitleHub, then return entitlements. */
|
|
33
|
+
declare function restorePurchases(): Promise<CustomerInfo>;
|
|
34
|
+
/** Subscribe to entitlement changes (e.g. after a purchase). Returns an unsubscribe function. */
|
|
35
|
+
declare function addCustomerInfoUpdateListener(fn: (info: CustomerInfo) => void): () => void;
|
|
36
|
+
|
|
37
|
+
export { type ConfigureOptions, addCustomerInfoUpdateListener, configureEntitleHub, getCustomerInfo, getOfferings, getProducts, isEntitled, logIn, purchaseProduct, restorePurchases };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CustomerInfo, Offerings } from '@entitlehub/sdk';
|
|
2
|
+
export { CustomerInfo, Offerings } from '@entitlehub/sdk';
|
|
3
|
+
|
|
4
|
+
interface ConfigureOptions {
|
|
5
|
+
/** Your EntitleHub publishable key (pk_live_… / pk_test_…). Client-safe. */
|
|
6
|
+
apiKey: string;
|
|
7
|
+
/** Your own stable user id. */
|
|
8
|
+
appUserId: string;
|
|
9
|
+
/** Override the API base (self-host). */
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Configure EntitleHub and open the store connection. Call once at startup (after your own login). */
|
|
13
|
+
declare function configureEntitleHub(opts: ConfigureOptions): Promise<void>;
|
|
14
|
+
/** Switch the acting user after your own login. Returns their entitlements. */
|
|
15
|
+
declare function logIn(appUserId: string): Promise<CustomerInfo>;
|
|
16
|
+
/** The current user's entitlements (cached; RC-style CustomerInfo). */
|
|
17
|
+
declare function getCustomerInfo(): Promise<CustomerInfo>;
|
|
18
|
+
/** Convenience: is the user entitled right now? */
|
|
19
|
+
declare function isEntitled(entitlementId: string): Promise<boolean>;
|
|
20
|
+
/** Your EntitleHub catalog (entitlements + products) for building a paywall. */
|
|
21
|
+
declare function getOfferings(): Promise<Offerings>;
|
|
22
|
+
/** Live store products (prices, localized titles) for the given ids, from the native store. */
|
|
23
|
+
declare function getProducts(productIds: string[]): Promise<any[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Buy a product in one call: open the native purchase sheet, validate the receipt with EntitleHub,
|
|
26
|
+
* and return the updated entitlements. Purchase + entitlement sync, the RevenueCat way.
|
|
27
|
+
* Throws "purchase-cancelled" if the user backs out.
|
|
28
|
+
*/
|
|
29
|
+
declare function purchaseProduct(productId: string, opts?: {
|
|
30
|
+
isSubscription?: boolean;
|
|
31
|
+
}): Promise<CustomerInfo>;
|
|
32
|
+
/** Restore the user's purchases: re-validate each with EntitleHub, then return entitlements. */
|
|
33
|
+
declare function restorePurchases(): Promise<CustomerInfo>;
|
|
34
|
+
/** Subscribe to entitlement changes (e.g. after a purchase). Returns an unsubscribe function. */
|
|
35
|
+
declare function addCustomerInfoUpdateListener(fn: (info: CustomerInfo) => void): () => void;
|
|
36
|
+
|
|
37
|
+
export { type ConfigureOptions, addCustomerInfoUpdateListener, configureEntitleHub, getCustomerInfo, getOfferings, getProducts, isEntitled, logIn, purchaseProduct, restorePurchases };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import { EntitleHub } from "@entitlehub/sdk";
|
|
10
|
+
var _iap;
|
|
11
|
+
function iap() {
|
|
12
|
+
if (_iap) return _iap;
|
|
13
|
+
try {
|
|
14
|
+
_iap = __require("expo-iap");
|
|
15
|
+
} catch {
|
|
16
|
+
throw new Error("@entitlehub/react-native needs 'expo-iap'. Install it with: npx expo install expo-iap");
|
|
17
|
+
}
|
|
18
|
+
return _iap;
|
|
19
|
+
}
|
|
20
|
+
var client;
|
|
21
|
+
function eh() {
|
|
22
|
+
if (!client) throw new Error("Call configureEntitleHub({ apiKey, appUserId }) before using EntitleHub.");
|
|
23
|
+
return client;
|
|
24
|
+
}
|
|
25
|
+
async function configureEntitleHub(opts) {
|
|
26
|
+
client = new EntitleHub({ apiKey: opts.apiKey, appUserId: opts.appUserId, baseUrl: opts.baseUrl });
|
|
27
|
+
try {
|
|
28
|
+
await iap().initConnection();
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function logIn(appUserId) {
|
|
33
|
+
return eh().logIn(appUserId);
|
|
34
|
+
}
|
|
35
|
+
async function getCustomerInfo() {
|
|
36
|
+
return eh().getCustomerInfo();
|
|
37
|
+
}
|
|
38
|
+
async function isEntitled(entitlementId) {
|
|
39
|
+
return eh().isEntitled(entitlementId);
|
|
40
|
+
}
|
|
41
|
+
async function getOfferings() {
|
|
42
|
+
return eh().getOfferings();
|
|
43
|
+
}
|
|
44
|
+
async function getProducts(productIds) {
|
|
45
|
+
return iap().getProducts(productIds);
|
|
46
|
+
}
|
|
47
|
+
async function purchaseProduct(productId, opts = {}) {
|
|
48
|
+
const I = iap();
|
|
49
|
+
const result = await I.requestPurchase({ sku: productId, skus: [productId] });
|
|
50
|
+
const purchase = Array.isArray(result) ? result[0] : result;
|
|
51
|
+
if (!purchase) throw new Error("purchase-cancelled");
|
|
52
|
+
const info = await reportToEntitleHub(purchase, productId, opts.isSubscription);
|
|
53
|
+
try {
|
|
54
|
+
await I.finishTransaction({ purchase, isConsumable: false });
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
return info;
|
|
58
|
+
}
|
|
59
|
+
async function restorePurchases() {
|
|
60
|
+
const I = iap();
|
|
61
|
+
const purchases = await I.getAvailablePurchases() || [];
|
|
62
|
+
for (const p of purchases) {
|
|
63
|
+
await reportToEntitleHub(p, p.productId ?? p.id ?? p.sku, true).catch(() => {
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return eh().getCustomerInfo({ fetchPolicy: "network-only" });
|
|
67
|
+
}
|
|
68
|
+
function addCustomerInfoUpdateListener(fn) {
|
|
69
|
+
return eh().addCustomerInfoUpdateListener(fn);
|
|
70
|
+
}
|
|
71
|
+
async function reportToEntitleHub(purchase, productId, isSubscription) {
|
|
72
|
+
const jws = purchase?.jwsRepresentationIos ?? purchase?.jwsRepresentation ?? purchase?.verificationResultIos;
|
|
73
|
+
if (jws) return eh().reportPurchase({ signedTransaction: jws });
|
|
74
|
+
const token = purchase?.purchaseTokenAndroid ?? purchase?.purchaseToken;
|
|
75
|
+
if (token) {
|
|
76
|
+
return eh().reportPurchase({
|
|
77
|
+
store: "play",
|
|
78
|
+
storeProductId: productId,
|
|
79
|
+
purchaseToken: token,
|
|
80
|
+
isSubscription: Boolean(isSubscription)
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
throw new Error("Could not read a receipt from the purchase (no iOS JWS or Android purchase token).");
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
addCustomerInfoUpdateListener,
|
|
87
|
+
configureEntitleHub,
|
|
88
|
+
getCustomerInfo,
|
|
89
|
+
getOfferings,
|
|
90
|
+
getProducts,
|
|
91
|
+
isEntitled,
|
|
92
|
+
logIn,
|
|
93
|
+
purchaseProduct,
|
|
94
|
+
restorePurchases
|
|
95
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@entitlehub/react-native",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "EntitleHub for React Native & Expo — one call to purchase and unlock entitlements. Wraps expo-iap for the native store sheet and validates receipts via EntitleHub.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"entitlehub",
|
|
7
|
+
"react-native",
|
|
8
|
+
"expo",
|
|
9
|
+
"in-app-purchase",
|
|
10
|
+
"iap",
|
|
11
|
+
"subscriptions",
|
|
12
|
+
"storekit",
|
|
13
|
+
"play-billing",
|
|
14
|
+
"entitlements"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://entitlehub.com/docs/purchases",
|
|
17
|
+
"repository": { "type": "git", "url": "git+https://github.com/DanCue44/entitlehub-sdk.git", "directory": "react-native" },
|
|
18
|
+
"bugs": { "url": "https://github.com/DanCue44/entitlehub-sdk/issues" },
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"publishConfig": { "access": "public" },
|
|
21
|
+
"type": "module",
|
|
22
|
+
"main": "./dist/index.cjs",
|
|
23
|
+
"module": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js",
|
|
29
|
+
"require": "./dist/index.cjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": ["dist", "README.md", "CHANGELOG.md", "LICENSE"],
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"prepublishOnly": "npm run build"
|
|
38
|
+
},
|
|
39
|
+
"engines": { "node": ">=18" },
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@entitlehub/sdk": ">=0.2.0",
|
|
42
|
+
"expo-iap": "*",
|
|
43
|
+
"react": ">=17"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@entitlehub/sdk": "file:../sdk",
|
|
47
|
+
"tsup": "^8.0.0",
|
|
48
|
+
"typescript": "^5.9.3"
|
|
49
|
+
}
|
|
50
|
+
}
|