react-native-iap 14.2.2 → 14.2.3
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/NitroIap.podspec +4 -1
- package/README.md +10 -0
- package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +5 -1
- package/app.plugin.js +1 -1
- package/lib/module/helpers/subscription.js.map +1 -1
- package/lib/module/hooks/useIAP.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/react-test-renderer.d.js +2 -0
- package/lib/module/types/react-test-renderer.d.js.map +1 -0
- package/lib/module/utils/error.js.map +1 -1
- package/lib/module/utils/errorMapping.js.map +1 -1
- package/lib/module/utils/type-bridge.js.map +1 -1
- package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
- package/lib/typescript/src/helpers/subscription.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/utils/error.d.ts.map +1 -1
- package/lib/typescript/src/utils/errorMapping.d.ts.map +1 -1
- package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
- package/package.json +1 -9
- package/plugin/src/withIAP.ts +59 -59
- package/src/helpers/subscription.ts +21 -21
- package/src/hooks/useIAP.ts +193 -193
- package/src/index.ts +346 -344
- package/src/specs/RnIap.nitro.ts +160 -157
- package/src/types/react-test-renderer.d.ts +7 -0
- package/src/types.ts +294 -294
- package/src/utils/error.ts +19 -19
- package/src/utils/errorMapping.ts +13 -13
- package/src/utils/type-bridge.ts +94 -93
package/plugin/src/withIAP.ts
CHANGED
|
@@ -3,131 +3,131 @@ import {
|
|
|
3
3
|
WarningAggregator,
|
|
4
4
|
withAndroidManifest,
|
|
5
5
|
withAppBuildGradle,
|
|
6
|
-
} from 'expo/config-plugins'
|
|
7
|
-
import type {
|
|
6
|
+
} from 'expo/config-plugins';
|
|
7
|
+
import type {ConfigPlugin} from 'expo/config-plugins';
|
|
8
8
|
|
|
9
|
-
const pkg = require('../../package.json')
|
|
9
|
+
const pkg = require('../../package.json');
|
|
10
10
|
|
|
11
11
|
// Global flag to prevent duplicate logs
|
|
12
|
-
let hasLoggedPluginExecution = false
|
|
12
|
+
let hasLoggedPluginExecution = false;
|
|
13
13
|
|
|
14
14
|
const addLineToGradle = (
|
|
15
15
|
content: string,
|
|
16
16
|
anchor: RegExp | string,
|
|
17
17
|
lineToAdd: string,
|
|
18
|
-
offset: number = 1
|
|
18
|
+
offset: number = 1,
|
|
19
19
|
): string => {
|
|
20
|
-
const lines = content.split('\n')
|
|
21
|
-
const index = lines.findIndex((line) => line.match(anchor))
|
|
20
|
+
const lines = content.split('\n');
|
|
21
|
+
const index = lines.findIndex((line) => line.match(anchor));
|
|
22
22
|
if (index === -1) {
|
|
23
23
|
console.warn(
|
|
24
|
-
`Anchor "${anchor}" not found in build.gradle. Appending to end
|
|
25
|
-
)
|
|
26
|
-
lines.push(lineToAdd)
|
|
24
|
+
`Anchor "${anchor}" not found in build.gradle. Appending to end.`,
|
|
25
|
+
);
|
|
26
|
+
lines.push(lineToAdd);
|
|
27
27
|
} else {
|
|
28
|
-
lines.splice(index + offset, 0, lineToAdd)
|
|
28
|
+
lines.splice(index + offset, 0, lineToAdd);
|
|
29
29
|
}
|
|
30
|
-
return lines.join('\n')
|
|
31
|
-
}
|
|
30
|
+
return lines.join('\n');
|
|
31
|
+
};
|
|
32
32
|
|
|
33
33
|
export const modifyProjectBuildGradle = (gradle: string): string => {
|
|
34
34
|
// Add supportLibVersion to project build.gradle if not present
|
|
35
35
|
if (!gradle.includes('supportLibVersion')) {
|
|
36
|
-
const lines = gradle.split('\n')
|
|
37
|
-
const extIndex = lines.findIndex((line) => line.trim() === 'ext {')
|
|
36
|
+
const lines = gradle.split('\n');
|
|
37
|
+
const extIndex = lines.findIndex((line) => line.trim() === 'ext {');
|
|
38
38
|
if (extIndex !== -1) {
|
|
39
39
|
// Insert supportLibVersion right after 'ext {' with proper indentation
|
|
40
|
-
lines.splice(extIndex + 1, 0, 'supportLibVersion = "28.0.0"')
|
|
41
|
-
return lines.join('\n')
|
|
40
|
+
lines.splice(extIndex + 1, 0, 'supportLibVersion = "28.0.0"');
|
|
41
|
+
return lines.join('\n');
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
return gradle
|
|
45
|
-
}
|
|
44
|
+
return gradle;
|
|
45
|
+
};
|
|
46
46
|
|
|
47
47
|
const modifyAppBuildGradle = (gradle: string): string => {
|
|
48
|
-
let modified = gradle
|
|
48
|
+
let modified = gradle;
|
|
49
49
|
|
|
50
50
|
// Add billing library dependencies to app-level build.gradle
|
|
51
|
-
const billingDep = ` implementation "com.android.billingclient:billing-ktx:8.0.0"
|
|
52
|
-
const gmsDep = ` implementation "com.google.android.gms:play-services-base:18.1.0"
|
|
51
|
+
const billingDep = ` implementation "com.android.billingclient:billing-ktx:8.0.0"`;
|
|
52
|
+
const gmsDep = ` implementation "com.google.android.gms:play-services-base:18.1.0"`;
|
|
53
53
|
|
|
54
|
-
let hasAddedDependency = false
|
|
54
|
+
let hasAddedDependency = false;
|
|
55
55
|
|
|
56
56
|
if (!modified.includes(billingDep)) {
|
|
57
|
-
modified = addLineToGradle(modified, /dependencies\s*{/, billingDep)
|
|
58
|
-
hasAddedDependency = true
|
|
57
|
+
modified = addLineToGradle(modified, /dependencies\s*{/, billingDep);
|
|
58
|
+
hasAddedDependency = true;
|
|
59
59
|
}
|
|
60
60
|
if (!modified.includes(gmsDep)) {
|
|
61
|
-
modified = addLineToGradle(modified, /dependencies\s*{/, gmsDep, 1)
|
|
62
|
-
hasAddedDependency = true
|
|
61
|
+
modified = addLineToGradle(modified, /dependencies\s*{/, gmsDep, 1);
|
|
62
|
+
hasAddedDependency = true;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Log only once and only if we actually added dependencies
|
|
66
66
|
if (hasAddedDependency && !hasLoggedPluginExecution) {
|
|
67
67
|
console.log(
|
|
68
|
-
'🛠️ react-native-iap: Added billing dependencies to build.gradle'
|
|
69
|
-
)
|
|
68
|
+
'🛠️ react-native-iap: Added billing dependencies to build.gradle',
|
|
69
|
+
);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
return modified
|
|
73
|
-
}
|
|
72
|
+
return modified;
|
|
73
|
+
};
|
|
74
74
|
|
|
75
75
|
const withIapAndroid: ConfigPlugin = (config) => {
|
|
76
76
|
// Add IAP dependencies to app build.gradle
|
|
77
77
|
config = withAppBuildGradle(config, (config) => {
|
|
78
78
|
config.modResults.contents = modifyAppBuildGradle(
|
|
79
|
-
config.modResults.contents
|
|
80
|
-
)
|
|
81
|
-
return config
|
|
82
|
-
})
|
|
79
|
+
config.modResults.contents,
|
|
80
|
+
);
|
|
81
|
+
return config;
|
|
82
|
+
});
|
|
83
83
|
|
|
84
84
|
config = withAndroidManifest(config, (config) => {
|
|
85
|
-
const manifest = config.modResults
|
|
85
|
+
const manifest = config.modResults;
|
|
86
86
|
if (!manifest.manifest['uses-permission']) {
|
|
87
|
-
manifest.manifest['uses-permission'] = []
|
|
87
|
+
manifest.manifest['uses-permission'] = [];
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
const permissions = manifest.manifest['uses-permission']
|
|
91
|
-
const billingPerm = {
|
|
90
|
+
const permissions = manifest.manifest['uses-permission'];
|
|
91
|
+
const billingPerm = {$: {'android:name': 'com.android.vending.BILLING'}};
|
|
92
92
|
|
|
93
93
|
const alreadyExists = permissions.some(
|
|
94
|
-
(p) => p.$['android:name'] === 'com.android.vending.BILLING'
|
|
95
|
-
)
|
|
94
|
+
(p) => p.$['android:name'] === 'com.android.vending.BILLING',
|
|
95
|
+
);
|
|
96
96
|
if (!alreadyExists) {
|
|
97
|
-
permissions.push(billingPerm)
|
|
97
|
+
permissions.push(billingPerm);
|
|
98
98
|
if (!hasLoggedPluginExecution) {
|
|
99
99
|
console.log(
|
|
100
|
-
'✅ Added com.android.vending.BILLING to AndroidManifest.xml'
|
|
101
|
-
)
|
|
100
|
+
'✅ Added com.android.vending.BILLING to AndroidManifest.xml',
|
|
101
|
+
);
|
|
102
102
|
}
|
|
103
103
|
} else {
|
|
104
104
|
if (!hasLoggedPluginExecution) {
|
|
105
105
|
console.log(
|
|
106
|
-
'ℹ️ com.android.vending.BILLING already exists in AndroidManifest.xml'
|
|
107
|
-
)
|
|
106
|
+
'ℹ️ com.android.vending.BILLING already exists in AndroidManifest.xml',
|
|
107
|
+
);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
return config
|
|
112
|
-
})
|
|
111
|
+
return config;
|
|
112
|
+
});
|
|
113
113
|
|
|
114
|
-
return config
|
|
115
|
-
}
|
|
114
|
+
return config;
|
|
115
|
+
};
|
|
116
116
|
|
|
117
117
|
const withIAP: ConfigPlugin = (config, _props) => {
|
|
118
118
|
try {
|
|
119
|
-
const result = withIapAndroid(config)
|
|
119
|
+
const result = withIapAndroid(config);
|
|
120
120
|
// Set flag after first execution to prevent duplicate logs
|
|
121
|
-
hasLoggedPluginExecution = true
|
|
122
|
-
return result
|
|
121
|
+
hasLoggedPluginExecution = true;
|
|
122
|
+
return result;
|
|
123
123
|
} catch (error) {
|
|
124
124
|
WarningAggregator.addWarningAndroid(
|
|
125
125
|
'react-native-iap',
|
|
126
|
-
`react-native-iap plugin encountered an error: ${error}
|
|
127
|
-
)
|
|
128
|
-
console.error('react-native-iap plugin error:', error)
|
|
129
|
-
return config
|
|
126
|
+
`react-native-iap plugin encountered an error: ${error}`,
|
|
127
|
+
);
|
|
128
|
+
console.error('react-native-iap plugin error:', error);
|
|
129
|
+
return config;
|
|
130
130
|
}
|
|
131
|
-
}
|
|
131
|
+
};
|
|
132
132
|
|
|
133
|
-
export default createRunOncePlugin(withIAP, pkg.name, pkg.version)
|
|
133
|
+
export default createRunOncePlugin(withIAP, pkg.name, pkg.version);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
1
|
+
import {getAvailablePurchases} from '../';
|
|
2
|
+
import type {ActiveSubscription, PurchaseIOS, PurchaseAndroid} from '../types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Get active subscriptions
|
|
@@ -7,24 +7,24 @@ import type { ActiveSubscription, PurchaseIOS, PurchaseAndroid } from '../types'
|
|
|
7
7
|
* @returns Promise<ActiveSubscription[]> - Array of active subscriptions
|
|
8
8
|
*/
|
|
9
9
|
export const getActiveSubscriptions = async (
|
|
10
|
-
subscriptionIds?: string[]
|
|
10
|
+
subscriptionIds?: string[],
|
|
11
11
|
): Promise<ActiveSubscription[]> => {
|
|
12
12
|
try {
|
|
13
13
|
// Get available purchases and filter for subscriptions
|
|
14
|
-
const purchases = await getAvailablePurchases()
|
|
14
|
+
const purchases = await getAvailablePurchases();
|
|
15
15
|
|
|
16
16
|
// Filter for subscriptions and map to ActiveSubscription format
|
|
17
17
|
const subscriptions = purchases
|
|
18
18
|
.filter((purchase) => {
|
|
19
19
|
// Filter by subscription IDs if provided
|
|
20
20
|
if (subscriptionIds && subscriptionIds.length > 0) {
|
|
21
|
-
return subscriptionIds.includes(purchase.productId)
|
|
21
|
+
return subscriptionIds.includes(purchase.productId);
|
|
22
22
|
}
|
|
23
|
-
return true
|
|
23
|
+
return true;
|
|
24
24
|
})
|
|
25
25
|
.map((purchase): ActiveSubscription => {
|
|
26
|
-
const iosPurchase = purchase as PurchaseIOS
|
|
27
|
-
const androidPurchase = purchase as PurchaseAndroid
|
|
26
|
+
const iosPurchase = purchase as PurchaseIOS;
|
|
27
|
+
const androidPurchase = purchase as PurchaseAndroid;
|
|
28
28
|
return {
|
|
29
29
|
productId: purchase.productId,
|
|
30
30
|
isActive: true, // If it's in availablePurchases, it's active
|
|
@@ -48,18 +48,18 @@ export const getActiveSubscriptions = async (
|
|
|
48
48
|
daysUntilExpirationIOS: iosPurchase.expirationDateIOS
|
|
49
49
|
? Math.ceil(
|
|
50
50
|
(iosPurchase.expirationDateIOS - Date.now()) /
|
|
51
|
-
(1000 * 60 * 60 * 24)
|
|
51
|
+
(1000 * 60 * 60 * 24),
|
|
52
52
|
)
|
|
53
53
|
: undefined,
|
|
54
|
-
}
|
|
55
|
-
})
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
56
|
|
|
57
|
-
return subscriptions
|
|
57
|
+
return subscriptions;
|
|
58
58
|
} catch (error) {
|
|
59
|
-
console.error('Failed to get active subscriptions:', error)
|
|
60
|
-
throw error
|
|
59
|
+
console.error('Failed to get active subscriptions:', error);
|
|
60
|
+
throw error;
|
|
61
61
|
}
|
|
62
|
-
}
|
|
62
|
+
};
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* Check if there are any active subscriptions
|
|
@@ -67,13 +67,13 @@ export const getActiveSubscriptions = async (
|
|
|
67
67
|
* @returns Promise<boolean> - True if there are active subscriptions
|
|
68
68
|
*/
|
|
69
69
|
export const hasActiveSubscriptions = async (
|
|
70
|
-
subscriptionIds?: string[]
|
|
70
|
+
subscriptionIds?: string[],
|
|
71
71
|
): Promise<boolean> => {
|
|
72
72
|
try {
|
|
73
|
-
const activeSubscriptions = await getActiveSubscriptions(subscriptionIds)
|
|
74
|
-
return activeSubscriptions.length > 0
|
|
73
|
+
const activeSubscriptions = await getActiveSubscriptions(subscriptionIds);
|
|
74
|
+
return activeSubscriptions.length > 0;
|
|
75
75
|
} catch (error) {
|
|
76
|
-
console.error('Failed to check active subscriptions:', error)
|
|
77
|
-
return false
|
|
76
|
+
console.error('Failed to check active subscriptions:', error);
|
|
77
|
+
return false;
|
|
78
78
|
}
|
|
79
|
-
}
|
|
79
|
+
};
|