react-native-iap 16.0.2 → 16.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.
Files changed (50) hide show
  1. package/README.md +4 -32
  2. package/android/gradle.properties +3 -3
  3. package/android/src/main/cpp/cpp-adapter.cpp +4 -1
  4. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +6 -6
  5. package/android/src/main/java/com/margelo/nitro/iap/NitroIapPackage.java +2 -6
  6. package/lib/module/hooks/useIAP.js +12 -4
  7. package/lib/module/hooks/useIAP.js.map +1 -1
  8. package/lib/module/index.js +2 -4
  9. package/lib/module/index.js.map +1 -1
  10. package/lib/module/utils/type-bridge.js.map +1 -1
  11. package/lib/typescript/src/hooks/useIAP.d.ts +1 -3
  12. package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
  13. package/lib/typescript/src/index.d.ts +9 -11
  14. package/lib/typescript/src/index.d.ts.map +1 -1
  15. package/lib/typescript/src/index.kepler.d.ts +7 -7
  16. package/lib/typescript/src/index.kepler.d.ts.map +1 -1
  17. package/lib/typescript/src/specs/RnIap.nitro.d.ts +1 -1
  18. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  19. package/lib/typescript/src/utils/available-purchases.d.ts +1 -1
  20. package/lib/typescript/src/utils/available-purchases.d.ts.map +1 -1
  21. package/lib/typescript/src/utils/error.d.ts +1 -1
  22. package/lib/typescript/src/utils/error.d.ts.map +1 -1
  23. package/lib/typescript/src/utils/errorMapping.d.ts +1 -1
  24. package/lib/typescript/src/utils/errorMapping.d.ts.map +1 -1
  25. package/lib/typescript/src/utils/purchase.d.ts +1 -1
  26. package/lib/typescript/src/utils/purchase.d.ts.map +1 -1
  27. package/lib/typescript/src/utils/type-bridge.d.ts +2 -2
  28. package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
  29. package/lib/typescript/src/utils.d.ts +1 -1
  30. package/lib/typescript/src/utils.d.ts.map +1 -1
  31. package/lib/typescript/src/vega-adapter.d.ts +1 -1
  32. package/lib/typescript/src/vega-adapter.d.ts.map +1 -1
  33. package/lib/typescript/src/vega.d.ts +1 -1
  34. package/lib/typescript/src/vega.d.ts.map +1 -1
  35. package/lib/typescript/src/vega.kepler.d.ts +1 -1
  36. package/lib/typescript/src/vega.kepler.d.ts.map +1 -1
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_DeveloperProvidedBillingDetailsAndroid.kt +0 -2
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_NitroProduct.kt +0 -2
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_NitroPurchase.kt +0 -2
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_NitroPurchaseResult.kt +0 -2
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_UserChoiceBillingDetails.kt +0 -2
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +2 -0
  43. package/openiap-versions.json +1 -1
  44. package/package.json +34 -37
  45. package/src/hooks/useIAP.ts +50 -31
  46. package/src/index.ts +15 -20
  47. package/src/utils/type-bridge.ts +0 -2
  48. package/lib/module/types/react-test-renderer.d.js +0 -2
  49. package/lib/module/types/react-test-renderer.d.js.map +0 -1
  50. package/src/types/react-test-renderer.d.ts +0 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iap",
3
- "version": "16.0.2",
3
+ "version": "16.1.0",
4
4
  "description": "React Native In-App Purchases module for iOS and Android using Nitro",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -47,11 +47,11 @@
47
47
  "typecheck:lib": "yarn tsc --noEmit",
48
48
  "clean": "rm -rf android/build node_modules/**/android/build lib nitrogen/generated",
49
49
  "lint": "eslint --ext .ts,.tsx,.js,.jsx src",
50
- "lint:eslint": "eslint --fix 'src/**/*.{ts,tsx}'",
50
+ "lint:eslint": "eslint --no-warn-ignored --fix 'src/**/*.{ts,tsx}'",
51
51
  "lint:prettier": "prettier --write \"**/*.{md,js,jsx,ts,tsx}\"",
52
52
  "lint:tsc": "tsc -p tsconfig.json --noEmit --skipLibCheck",
53
53
  "lint:ci": "yarn lint:tsc && yarn lint:eslint && yarn lint:prettier",
54
- "prepare": "npx tsx scripts/check-nitro-versions.ts && bob build && yarn nitrogen",
54
+ "prepare": "tsx scripts/check-nitro-versions.ts && bob build && yarn nitrogen",
55
55
  "nitrogen": "node --stack-size=65536 node_modules/nitrogen/lib/index.js",
56
56
  "specs": "yarn nitrogen --logLevel=\"debug\"",
57
57
  "test": "jest --coverage",
@@ -61,7 +61,7 @@
61
61
  "test:ci": "jest --maxWorkers=2 --coverage",
62
62
  "test:ci:example": "yarn workspace rn-iap-example test --coverage",
63
63
  "verify:consumer-install": "node ../../scripts/verify-npm-consumer-install.mjs --package . --package-name react-native-iap --required openiap-versions.json --required lib/module/index.js --required lib/typescript/src/index.d.ts --required android/build.gradle --required NitroIap.podspec --required nitro.json",
64
- "prepare:husky": "husky install",
64
+ "prepare:husky": "husky",
65
65
  "precommit": "lint-staged",
66
66
  "ci:check": "./scripts/ci-check.sh",
67
67
  "generate:types": "node scripts/update-types.mjs",
@@ -87,39 +87,40 @@
87
87
  "registry": "https://registry.npmjs.org/"
88
88
  },
89
89
  "devDependencies": {
90
- "@babel/plugin-proposal-private-methods": "^7.18.6",
91
- "@commitlint/cli": "^19.8.1",
92
- "@commitlint/config-conventional": "^19.8.1",
93
- "@react-native/eslint-config": "0.81.0",
94
- "@testing-library/react": "^16.3.0",
95
- "@testing-library/react-hooks": "^8.0.1",
96
- "@types/jest": "^29.5.12",
97
- "@types/node": "^24.4.0",
98
- "@types/react": "^19.1.12",
99
- "babel-jest": "^30.1.1",
100
- "eslint": "^8.57.0",
101
- "eslint-config-expo": "^9.2.0",
102
- "eslint-config-prettier": "^9.1.0",
103
- "eslint-plugin-prettier": "^5.2.1",
104
- "expo": "^53.0.20",
105
- "husky": "^8.0.3",
106
- "jest": "^30.1.1",
107
- "lint-staged": "^15.2.0",
108
- "nitrogen": "^0.36.1",
109
- "prettier": "^3.3.3",
110
- "react": "19.1.0",
111
- "react-native": "0.81.1",
112
- "react-native-builder-bob": "^0.38.4",
113
- "react-native-nitro-modules": "^0.36.1",
114
- "react-test-renderer": "^19.1.1",
115
- "typescript": "^5.9.2"
90
+ "@babel/core": "^7.29.7",
91
+ "@commitlint/cli": "^21.2.1",
92
+ "@commitlint/config-conventional": "^21.2.0",
93
+ "@react-native/babel-preset": "0.86.2",
94
+ "@react-native/jest-preset": "0.86.2",
95
+ "@types/jest": "^29.5.14",
96
+ "@types/node": "^26.2.0",
97
+ "@types/react": "^19.2.18",
98
+ "babel-jest": "^29.7.0",
99
+ "eslint": "^9.39.5",
100
+ "eslint-config-expo": "^57.0.1",
101
+ "eslint-config-prettier": "^10.1.8",
102
+ "eslint-plugin-prettier": "^5.5.6",
103
+ "expo": "^57.0.11",
104
+ "globals": "^17.9.0",
105
+ "husky": "^9.1.7",
106
+ "jest": "^29.7.0",
107
+ "lint-staged": "^17.3.0",
108
+ "nitrogen": "^0.36.5",
109
+ "prettier": "^3.9.6",
110
+ "react": "19.2.8",
111
+ "react-native": "0.86.2",
112
+ "react-native-builder-bob": "^0.43.0",
113
+ "react-native-nitro-modules": "^0.36.5",
114
+ "test-renderer": "^1.2.0",
115
+ "tsx": "^4.23.11",
116
+ "typescript": "^5.9.3"
116
117
  },
117
118
  "peerDependencies": {
118
- "@amazon-devices/keplerscript-appstore-iap-lib": "~2.12.13",
119
+ "@amazon-devices/keplerscript-appstore-iap-lib": "~2.13.0",
119
120
  "@amazon-devices/package-manager-lib": "~1.0.1767254401",
120
121
  "react": "*",
121
122
  "react-native": "*",
122
- "react-native-nitro-modules": "^0.36.1"
123
+ "react-native-nitro-modules": "^0.36.5"
123
124
  },
124
125
  "peerDependenciesMeta": {
125
126
  "@amazon-devices/keplerscript-appstore-iap-lib": {
@@ -132,10 +133,6 @@
132
133
  "workspaces": [
133
134
  "example"
134
135
  ],
135
- "eslintIgnore": [
136
- "node_modules/",
137
- "lib/"
138
- ],
139
136
  "react-native-builder-bob": {
140
137
  "source": "src",
141
138
  "output": "lib",
@@ -176,6 +173,6 @@
176
173
  },
177
174
  "packageManager": "yarn@3.6.1",
178
175
  "resolutions": {
179
- "nitrogen@^0.36.1": "patch:nitrogen@npm%3A0.36.1#./.yarn/patches/nitrogen-npm-0.36.1-abe3b64156.patch"
176
+ "nitrogen@^0.36.5": "patch:nitrogen@npm%3A0.36.5#./.yarn/patches/nitrogen-npm-0.36.5-array-equatable.patch"
180
177
  }
181
178
  }
@@ -47,8 +47,6 @@ import type {
47
47
  VerifyPurchaseWithProviderProps,
48
48
  VerifyPurchaseWithProviderResult,
49
49
  PurchaseOptions,
50
- } from '../types';
51
- import type {
52
50
  ActiveSubscription,
53
51
  Product,
54
52
  Purchase,
@@ -57,8 +55,8 @@ import type {
57
55
  ProductSubscription,
58
56
  MutationField,
59
57
  QueryField,
58
+ MutationFinishTransactionArgs,
60
59
  } from '../types';
61
- import type {MutationFinishTransactionArgs} from '../types';
62
60
 
63
61
  // Types for event subscriptions
64
62
  interface EventSubscription {
@@ -354,7 +352,8 @@ export function useIAP(options?: UseIapOptions): UseIap {
354
352
  }>({});
355
353
 
356
354
  // Track if component is mounted to prevent listener leaks on early unmount
357
- const isMountedRef = useRef<boolean>(true);
355
+ const isMountedRef = useRef<boolean>(false);
356
+ const initializationGenerationRef = useRef(0);
358
357
 
359
358
  const subscriptionsRefState = useRef<ProductSubscription[]>([]);
360
359
 
@@ -693,37 +692,56 @@ export function useIAP(options?: UseIapOptions): UseIap {
693
692
  subscriptionsRef.current.subscriptionBillingIssue = undefined;
694
693
  }, []);
695
694
 
696
- const initIapWithSubscriptions = useCallback(async (): Promise<void> => {
697
- const config = buildAndroidConfig();
698
-
699
- try {
700
- const result = await initConnection(config);
701
-
702
- if (!isMountedRef.current) {
695
+ const initIapWithSubscriptions = useCallback(
696
+ async (generation: number): Promise<void> => {
697
+ if (
698
+ !isMountedRef.current ||
699
+ initializationGenerationRef.current !== generation
700
+ ) {
703
701
  return;
704
702
  }
705
703
 
706
- if (!result) {
707
- cleanupListeners();
708
- setConnected(false);
709
- RnIapConsole.warn('[useIAP] initConnection returned false');
710
- return;
711
- }
704
+ const config = buildAndroidConfig();
712
705
 
713
- // Android retains events emitted during connection setup in bounded
714
- // native queues; registration flushes that backlog after Nitro is ready.
715
- // Other platforms preserve the existing post-init listener ordering.
716
- registerListeners();
717
- setConnected(true);
718
- } catch (error) {
719
- RnIapConsole.error('initConnection failed:', error);
720
- cleanupListeners();
721
- if (isMountedRef.current) {
722
- setConnected(false);
706
+ try {
707
+ const result = await initConnection(config);
708
+
709
+ if (
710
+ !isMountedRef.current ||
711
+ initializationGenerationRef.current !== generation
712
+ ) {
713
+ return;
714
+ }
715
+
716
+ if (!result) {
717
+ cleanupListeners();
718
+ setConnected(false);
719
+ RnIapConsole.warn('[useIAP] initConnection returned false');
720
+ return;
721
+ }
722
+
723
+ // Android retains events emitted during connection setup in bounded
724
+ // native queues; registration flushes that backlog after Nitro is ready.
725
+ // Other platforms preserve the existing post-init listener ordering.
726
+ registerListeners();
727
+ setConnected(true);
728
+ } catch (error) {
729
+ if (
730
+ !isMountedRef.current ||
731
+ initializationGenerationRef.current !== generation
732
+ ) {
733
+ return;
734
+ }
735
+ RnIapConsole.error('initConnection failed:', error);
736
+ cleanupListeners();
737
+ if (isMountedRef.current) {
738
+ setConnected(false);
739
+ }
740
+ invokeOnError(error);
723
741
  }
724
- invokeOnError(error);
725
- }
726
- }, [buildAndroidConfig, registerListeners, cleanupListeners, invokeOnError]);
742
+ },
743
+ [buildAndroidConfig, registerListeners, cleanupListeners, invokeOnError],
744
+ );
727
745
 
728
746
  const reconnect = useCallback(async (): Promise<boolean> => {
729
747
  const config = buildAndroidConfig();
@@ -755,8 +773,9 @@ export function useIAP(options?: UseIapOptions): UseIap {
755
773
  }, [buildAndroidConfig, registerListeners, cleanupListeners, invokeOnError]);
756
774
 
757
775
  useEffect(() => {
776
+ const generation = ++initializationGenerationRef.current;
758
777
  isMountedRef.current = true;
759
- initIapWithSubscriptions();
778
+ void Promise.resolve().then(() => initIapWithSubscriptions(generation));
760
779
 
761
780
  return () => {
762
781
  isMountedRef.current = false;
package/src/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  // External dependencies
2
2
  import {Platform} from 'react-native';
3
- // Side-effect import ensures Nitro installs its dispatcher before IAP is used (no-op in tests)
4
- import 'react-native-nitro-modules';
3
+ // Importing NitroModules installs its dispatcher before IAP is used (no-op in tests).
5
4
  import {NitroModules} from 'react-native-nitro-modules';
6
5
 
7
6
  // Internal modules
@@ -16,9 +15,21 @@ import type {
16
15
  } from './specs/RnIap.nitro';
17
16
  import {ErrorCode} from './types';
18
17
  import type {
18
+ AppTransaction,
19
19
  AndroidSubscriptionOfferInput,
20
+ ActiveSubscription,
21
+ BillingChoiceInfoAndroid,
22
+ BillingProgramAndroid,
23
+ BillingProgramInformationDialogParamsAndroid,
24
+ BillingProgramReportingDetailsAndroid,
25
+ BillingResultAndroid,
26
+ DeveloperBillingTypeAndroid,
27
+ DeveloperProvidedBillingDetailsAndroid,
20
28
  DiscountOfferInputIOS,
21
29
  FetchProductsResult,
30
+ GetBillingChoiceInfoParamsAndroid,
31
+ InAppMessageParamsAndroid,
32
+ InAppMessageResultAndroid,
22
33
  MutationField,
23
34
  Product,
24
35
  ProductIOS,
@@ -29,7 +40,6 @@ import type {
29
40
  PurchaseUpdatedListenerOptions,
30
41
  PurchaseIOS,
31
42
  QueryField,
32
- AppTransaction,
33
43
  VerifyPurchaseResultAndroid,
34
44
  VerifyPurchaseResultIOS,
35
45
  RequestPurchaseAndroidProps,
@@ -38,8 +48,6 @@ import type {
38
48
  RequestSubscriptionAndroidProps,
39
49
  RequestSubscriptionIosProps,
40
50
  RequestSubscriptionPropsByPlatforms,
41
- ActiveSubscription,
42
- DeveloperProvidedBillingDetailsAndroid,
43
51
  UserChoiceBillingDetails,
44
52
  } from './types';
45
53
  import {
@@ -69,20 +77,8 @@ import {getVegaIapModule, isVegaOS} from './vega';
69
77
  // Billing Programs API (Android 8.2.0+)
70
78
  // ------------------------------
71
79
 
72
- // Note: BillingProgramAndroid, ExternalLinkLaunchModeAndroid, and ExternalLinkTypeAndroid
80
+ // BillingProgramAndroid, ExternalLinkLaunchModeAndroid, and ExternalLinkTypeAndroid
73
81
  // are exported from './types' (auto-generated from openiap-gql).
74
- // Import them here for use in this file's interfaces and functions.
75
- import type {
76
- BillingChoiceInfoAndroid,
77
- BillingProgramAndroid,
78
- BillingProgramInformationDialogParamsAndroid,
79
- BillingProgramReportingDetailsAndroid,
80
- BillingResultAndroid,
81
- DeveloperBillingTypeAndroid,
82
- GetBillingChoiceInfoParamsAndroid,
83
- InAppMessageParamsAndroid,
84
- InAppMessageResultAndroid,
85
- } from './types';
86
82
 
87
83
  // Export all types
88
84
  export type {
@@ -888,8 +884,7 @@ export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
888
884
 
889
885
  if (normalizedType === 'all') {
890
886
  const converted = (await fetchAndConvert('all')) as (
891
- | Product
892
- | ProductSubscription
887
+ Product | ProductSubscription
893
888
  )[];
894
889
 
895
890
  RnIapConsole.debug(
@@ -19,8 +19,6 @@ import type {
19
19
  ProductTypeIOS,
20
20
  PurchaseState,
21
21
  SubscriptionPeriodIOS,
22
- } from '../types';
23
- import type {
24
22
  Product,
25
23
  ProductSubscription,
26
24
  Purchase,
@@ -1,2 +0,0 @@
1
- "use strict";
2
- //# sourceMappingURL=react-test-renderer.d.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":[],"sourceRoot":"../../../src","sources":["types/react-test-renderer.d.ts"],"mappings":"","ignoreList":[]}
@@ -1,7 +0,0 @@
1
- declare module 'react-test-renderer' {
2
- export function act(
3
- callback: () => void | Promise<void>,
4
- ): void | Promise<void>;
5
- const TestRenderer: any;
6
- export default TestRenderer;
7
- }