react-native-iap 14.3.4 → 14.3.5

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.
Files changed (76) hide show
  1. package/NitroIap.podspec +1 -1
  2. package/README.md +1 -1
  3. package/android/CMakeLists.txt +4 -0
  4. package/android/build.gradle +2 -2
  5. package/android/src/main/cpp/cpp-adapter.cpp +8 -0
  6. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +93 -51
  7. package/ios/HybridRnIap.swift +38 -30
  8. package/lib/module/hooks/useIAP.js +4 -4
  9. package/lib/module/hooks/useIAP.js.map +1 -1
  10. package/lib/module/index.js +54 -53
  11. package/lib/module/index.js.map +1 -1
  12. package/lib/module/types.js +1 -59
  13. package/lib/module/types.js.map +1 -1
  14. package/lib/module/utils/type-bridge.js +44 -33
  15. package/lib/module/utils/type-bridge.js.map +1 -1
  16. package/lib/typescript/src/hooks/useIAP.d.ts +4 -4
  17. package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
  18. package/lib/typescript/src/index.d.ts +8 -7
  19. package/lib/typescript/src/index.d.ts.map +1 -1
  20. package/lib/typescript/src/specs/RnIap.nitro.d.ts +2 -1
  21. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  22. package/lib/typescript/src/types.d.ts +159 -204
  23. package/lib/typescript/src/types.d.ts.map +1 -1
  24. package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
  25. package/nitrogen/generated/android/NitroIap+autolinking.cmake +9 -4
  26. package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +32 -5
  27. package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +1 -1
  28. package/nitrogen/generated/android/c++/JIapPlatform.hpp +59 -0
  29. package/nitrogen/generated/android/c++/JPurchase.cpp +26 -0
  30. package/nitrogen/generated/android/c++/JPurchase.hpp +80 -0
  31. package/nitrogen/generated/android/c++/JPurchaseAndroid.hpp +140 -0
  32. package/nitrogen/generated/android/c++/JPurchaseIOS.hpp +194 -0
  33. package/nitrogen/generated/android/c++/JPurchaseOfferIOS.hpp +61 -0
  34. package/nitrogen/generated/android/c++/JPurchaseState.hpp +71 -0
  35. package/nitrogen/generated/android/c++/JRequestPurchaseResult.hpp +89 -0
  36. package/nitrogen/generated/android/c++/JVariant_PurchaseAndroid_PurchaseIOS.cpp +26 -0
  37. package/nitrogen/generated/android/c++/JVariant_PurchaseAndroid_PurchaseIOS.hpp +80 -0
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +1 -1
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/IapPlatform.kt +21 -0
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Purchase.kt +42 -0
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseAndroid.kt +77 -0
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseIOS.kt +116 -0
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseOfferIOS.kt +35 -0
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseState.kt +25 -0
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/RequestPurchaseResult.kt +32 -0
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_PurchaseAndroid_PurchaseIOS.kt +42 -0
  47. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.cpp +13 -5
  48. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +186 -25
  49. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +18 -0
  50. package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +20 -2
  51. package/nitrogen/generated/ios/swift/Func_void_RequestPurchaseResult.swift +47 -0
  52. package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +1 -1
  53. package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +7 -7
  54. package/nitrogen/generated/ios/swift/IapPlatform.swift +40 -0
  55. package/nitrogen/generated/ios/swift/Purchase.swift +18 -0
  56. package/nitrogen/generated/ios/swift/PurchaseAndroid.swift +399 -0
  57. package/nitrogen/generated/ios/swift/PurchaseIOS.swift +768 -0
  58. package/nitrogen/generated/ios/swift/PurchaseOfferIOS.swift +57 -0
  59. package/nitrogen/generated/ios/swift/PurchaseState.swift +56 -0
  60. package/nitrogen/generated/ios/swift/RequestPurchaseResult.swift +148 -0
  61. package/nitrogen/generated/ios/swift/Variant_PurchaseAndroid_PurchaseIOS.swift +18 -0
  62. package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +4 -1
  63. package/nitrogen/generated/shared/c++/IapPlatform.hpp +76 -0
  64. package/nitrogen/generated/shared/c++/PurchaseAndroid.hpp +138 -0
  65. package/nitrogen/generated/shared/c++/PurchaseIOS.hpp +193 -0
  66. package/nitrogen/generated/shared/c++/PurchaseOfferIOS.hpp +75 -0
  67. package/nitrogen/generated/shared/c++/PurchaseState.hpp +92 -0
  68. package/nitrogen/generated/shared/c++/RequestPurchaseResult.hpp +78 -0
  69. package/package.json +5 -4
  70. package/plugin/build/withIAP.js +1 -1
  71. package/plugin/src/withIAP.ts +1 -1
  72. package/src/hooks/useIAP.ts +14 -8
  73. package/src/index.ts +73 -74
  74. package/src/specs/RnIap.nitro.ts +4 -1
  75. package/src/types.ts +183 -216
  76. package/src/utils/type-bridge.ts +55 -43
package/src/index.ts CHANGED
@@ -12,14 +12,17 @@ import type {
12
12
  NitroReceiptValidationResultIOS,
13
13
  NitroReceiptValidationResultAndroid,
14
14
  } from './specs/RnIap.nitro';
15
- import {ProductQueryType} from './types';
15
+ import type {
16
+ ProductQueryType,
17
+ RequestPurchaseProps,
18
+ RequestPurchaseResult,
19
+ } from './types';
16
20
  import type {
17
21
  Product,
18
22
  ProductRequest,
19
23
  Purchase,
20
24
  PurchaseAndroid,
21
25
  PurchaseOptions,
22
- PurchaseParams,
23
26
  PurchaseError,
24
27
  ReceiptValidationResultAndroid,
25
28
  ReceiptValidationResultIOS,
@@ -27,6 +30,7 @@ import type {
27
30
  RequestPurchaseIosProps,
28
31
  RequestPurchasePropsByPlatforms,
29
32
  RequestSubscriptionAndroidProps,
33
+ RequestSubscriptionIosProps,
30
34
  RequestSubscriptionPropsByPlatforms,
31
35
  SubscriptionStatusIOS,
32
36
  } from './types';
@@ -50,35 +54,56 @@ export type {
50
54
  export * from './types';
51
55
  export * from './utils/error';
52
56
 
53
- // Internal constants/helpers for bridging legacy Nitro expectations
54
- const NITRO_PRODUCT_TYPE_INAPP = 'inapp';
55
- const NITRO_PRODUCT_TYPE_SUBS = 'subs';
57
+ export type ProductTypeInput = 'inapp' | 'in-app' | 'subs';
58
+
59
+ const LEGACY_INAPP_WARNING =
60
+ "[react-native-iap] `type: 'inapp'` is deprecated and will be removed in v14.4.0. Use 'in-app' instead.";
56
61
 
57
62
  function toNitroProductType(
58
- type?: ProductQueryType | null,
59
- ): typeof NITRO_PRODUCT_TYPE_INAPP | typeof NITRO_PRODUCT_TYPE_SUBS {
60
- return type === ProductQueryType.Subs
61
- ? NITRO_PRODUCT_TYPE_SUBS
62
- : NITRO_PRODUCT_TYPE_INAPP;
63
+ type?: ProductTypeInput | ProductQueryType | null,
64
+ ): 'inapp' | 'subs' {
65
+ if (type === 'subs') {
66
+ return 'subs';
67
+ }
68
+ if (type === 'inapp') {
69
+ console.warn(LEGACY_INAPP_WARNING);
70
+ return 'inapp';
71
+ }
72
+ if (type === 'all') {
73
+ return 'inapp';
74
+ }
75
+ return 'inapp';
63
76
  }
64
77
 
65
78
  function isSubscriptionQuery(type?: ProductQueryType | null): boolean {
66
- return type === ProductQueryType.Subs;
79
+ return type === 'subs';
67
80
  }
68
81
 
69
82
  function normalizeProductQueryType(
70
83
  type?: ProductQueryType | string | null,
71
84
  ): ProductQueryType {
72
- if (type === ProductQueryType.All || type === 'all') {
73
- return ProductQueryType.All;
85
+ if (type === 'all' || type === 'subs' || type === 'in-app') {
86
+ return type;
74
87
  }
75
- if (type === ProductQueryType.Subs || type === 'subs') {
76
- return ProductQueryType.Subs;
77
- }
78
- if (type === ProductQueryType.InApp || type === 'inapp') {
79
- return ProductQueryType.InApp;
88
+
89
+ if (typeof type === 'string') {
90
+ const normalized = type.trim().toLowerCase().replace(/_/g, '-');
91
+
92
+ if (normalized === 'all') {
93
+ return 'all';
94
+ }
95
+ if (normalized === 'subs') {
96
+ return 'subs';
97
+ }
98
+ if (normalized === 'inapp') {
99
+ console.warn(LEGACY_INAPP_WARNING);
100
+ return 'in-app';
101
+ }
102
+ if (normalized === 'in-app') {
103
+ return 'in-app';
104
+ }
80
105
  }
81
- return ProductQueryType.InApp;
106
+ return 'in-app';
82
107
  }
83
108
 
84
109
  export interface EventSubscription {
@@ -174,7 +199,7 @@ export const endConnection = async (): Promise<boolean> => {
174
199
  * Fetch products from the store
175
200
  * @param params - Product request configuration
176
201
  * @param params.skus - Array of product SKUs to fetch
177
- * @param params.type - Optional filter: 'inapp' (default) for products, 'subs' for subscriptions, or 'all' for both.
202
+ * @param params.type - Optional filter: 'in-app' (default) for products, 'subs' for subscriptions, or 'all' for both.
178
203
  * @returns Promise<Product[]> - Array of products from the store
179
204
  *
180
205
  * @example
@@ -188,7 +213,7 @@ export const endConnection = async (): Promise<boolean> => {
188
213
  */
189
214
  export const fetchProducts = async ({
190
215
  skus,
191
- type = ProductQueryType.InApp,
216
+ type = 'in-app',
192
217
  }: ProductRequest): Promise<Product[]> => {
193
218
  try {
194
219
  if (!skus || skus.length === 0) {
@@ -197,10 +222,10 @@ export const fetchProducts = async ({
197
222
 
198
223
  const normalizedType = normalizeProductQueryType(type);
199
224
 
200
- if (normalizedType === ProductQueryType.All) {
225
+ if (normalizedType === 'all') {
201
226
  const [inappNitro, subsNitro] = await Promise.all([
202
- IAP.instance.fetchProducts(skus, NITRO_PRODUCT_TYPE_INAPP),
203
- IAP.instance.fetchProducts(skus, NITRO_PRODUCT_TYPE_SUBS),
227
+ IAP.instance.fetchProducts(skus, 'inapp'),
228
+ IAP.instance.fetchProducts(skus, 'subs'),
204
229
  ]);
205
230
  const allNitro = [...inappNitro, ...subsNitro];
206
231
  const validAll = allNitro.filter(validateNitroProduct);
@@ -237,7 +262,7 @@ export const fetchProducts = async ({
237
262
  * Request a purchase for products or subscriptions
238
263
  * @param params - Purchase request configuration
239
264
  * @param params.request - Platform-specific purchase parameters
240
- * @param params.type - Type of purchase: 'inapp' for products (default) or 'subs' for subscriptions
265
+ * @param params.type - Type of purchase: 'in-app' for products (default) or 'subs' for subscriptions
241
266
  *
242
267
  * @example
243
268
  * ```typescript
@@ -247,7 +272,7 @@ export const fetchProducts = async ({
247
272
  * ios: { sku: productId },
248
273
  * android: { skus: [productId] }
249
274
  * },
250
- * type: 'inapp'
275
+ * type: 'in-app'
251
276
  * });
252
277
  *
253
278
  * // Subscription purchase
@@ -268,49 +293,20 @@ export const fetchProducts = async ({
268
293
  * ⚠️ Important: This is an event-based operation, not promise-based.
269
294
  * Listen for events through purchaseUpdatedListener or purchaseErrorListener.
270
295
  * @param params - Purchase request configuration
271
- * @param params.requestPurchase - Platform-specific purchase parameters (in-app)
272
- * @param params.requestSubscription - Platform-specific subscription parameters (subs)
296
+ * @param params.request - Platform-specific request parameters
273
297
  * @param params.type - Type of purchase (defaults to in-app)
274
298
  */
275
299
  export const requestPurchase = async (
276
- params: PurchaseParams,
277
- ): Promise<void> => {
300
+ params: RequestPurchaseProps,
301
+ ): Promise<RequestPurchaseResult> => {
278
302
  try {
279
- const {requestPurchase: purchaseRequest, requestSubscription} = params;
280
- const normalizedPurchaseRequest = purchaseRequest ?? undefined;
281
- const normalizedSubscriptionRequest = requestSubscription ?? undefined;
282
-
283
- const effectiveType = normalizeProductQueryType(params.type);
284
- const isSubs = isSubscriptionQuery(effectiveType);
285
- let request:
303
+ const normalizedType = normalizeProductQueryType(params.type);
304
+ const isSubs = isSubscriptionQuery(normalizedType);
305
+ const request = params.request as
286
306
  | RequestPurchasePropsByPlatforms
287
307
  | RequestSubscriptionPropsByPlatforms
288
308
  | undefined;
289
309
 
290
- if (isSubs) {
291
- if (
292
- __DEV__ &&
293
- normalizedPurchaseRequest &&
294
- !normalizedSubscriptionRequest
295
- ) {
296
- console.warn(
297
- '[react-native-iap] `requestPurchase` was provided for a subscription request. Did you mean to use `requestSubscription`?',
298
- );
299
- }
300
- request = normalizedSubscriptionRequest ?? normalizedPurchaseRequest;
301
- } else {
302
- if (
303
- __DEV__ &&
304
- normalizedSubscriptionRequest &&
305
- !normalizedPurchaseRequest
306
- ) {
307
- console.warn(
308
- '[react-native-iap] `requestSubscription` was provided for an in-app purchase request. Did you mean to use `requestPurchase`?',
309
- );
310
- }
311
- request = normalizedPurchaseRequest ?? normalizedSubscriptionRequest;
312
- }
313
-
314
310
  if (!request) {
315
311
  throw new Error('Missing purchase request configuration');
316
312
  }
@@ -338,16 +334,19 @@ export const requestPurchase = async (
338
334
  const unifiedRequest: any = {};
339
335
 
340
336
  if (Platform.OS === 'ios' && request.ios) {
341
- const iosReq = request.ios as RequestPurchaseIosProps;
342
- const autoFinishSubs =
343
- isSubs && iosReq.andDangerouslyFinishTransactionAutomatically == null;
344
- unifiedRequest.ios = {
345
- ...iosReq,
346
- // Align with native SwiftUI flow: auto-finish subscriptions by default
347
- ...(autoFinishSubs
348
- ? {andDangerouslyFinishTransactionAutomatically: true}
349
- : {}),
350
- } as RequestPurchaseIosProps;
337
+ if (isSubs) {
338
+ const iosReq = request.ios as RequestSubscriptionIosProps;
339
+ const autoFinishSubs =
340
+ iosReq.andDangerouslyFinishTransactionAutomatically == null;
341
+ unifiedRequest.ios = {
342
+ ...iosReq,
343
+ ...(autoFinishSubs
344
+ ? {andDangerouslyFinishTransactionAutomatically: true}
345
+ : {}),
346
+ } as RequestSubscriptionIosProps;
347
+ } else {
348
+ unifiedRequest.ios = request.ios as RequestPurchaseIosProps;
349
+ }
351
350
  }
352
351
 
353
352
  if (Platform.OS === 'android' && request.android) {
@@ -356,14 +355,14 @@ export const requestPurchase = async (
356
355
  unifiedRequest.android = {
357
356
  ...subsRequest,
358
357
  subscriptionOffers: subsRequest.subscriptionOffers || [],
359
- } as RequestPurchaseAndroidProps;
358
+ } as RequestSubscriptionAndroidProps;
360
359
  } else {
361
- unifiedRequest.android = request.android;
360
+ unifiedRequest.android = request.android as RequestPurchaseAndroidProps;
362
361
  }
363
362
  }
364
363
 
365
364
  // Call unified method - returns void, listen for events instead
366
- await IAP.instance.requestPurchase(unifiedRequest);
365
+ return await IAP.instance.requestPurchase(unifiedRequest);
367
366
  } catch (error) {
368
367
  console.error('Failed to request purchase:', error);
369
368
  throw error;
@@ -1,4 +1,5 @@
1
1
  import type {HybridObject} from 'react-native-nitro-modules';
2
+ import type {RequestPurchaseResult} from '../types';
2
3
 
3
4
  // ╔══════════════════════════════════════════════════════════════════════════╗
4
5
  // ║ PARAMS ║
@@ -307,7 +308,9 @@ export interface RnIap extends HybridObject<{ios: 'swift'; android: 'kotlin'}> {
307
308
  * @param request - Platform-specific purchase request parameters
308
309
  * @returns Promise<void> - Always returns void, listen for events instead
309
310
  */
310
- requestPurchase(request: NitroPurchaseRequest): Promise<void>;
311
+ requestPurchase(
312
+ request: NitroPurchaseRequest,
313
+ ): Promise<RequestPurchaseResult>;
311
314
 
312
315
  /**
313
316
  * Get available purchases (unified method for both platforms)