expo-iap 3.1.20 → 3.1.22
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/README.md +1 -1
- package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +12 -4
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/bun.lockb +0 -0
- package/coverage/clover.xml +2 -2
- package/coverage/coverage-final.json +1 -1
- package/coverage/lcov-report/index.html +1 -1
- package/coverage/lcov-report/src/index.html +1 -1
- package/coverage/lcov-report/src/index.ts.html +3 -3
- package/coverage/lcov-report/src/modules/android.ts.html +1 -1
- package/coverage/lcov-report/src/modules/index.html +1 -1
- package/coverage/lcov-report/src/modules/ios.ts.html +1 -1
- package/coverage/lcov-report/src/utils/debug.ts.html +1 -1
- package/coverage/lcov-report/src/utils/errorMapping.ts.html +1 -1
- package/coverage/lcov-report/src/utils/index.html +1 -1
- package/openiap-versions.json +1 -1
- package/package.json +1 -1
- package/plugin/build/withIAP.js +45 -33
- package/plugin/build/withLocalOpenIAP.js +12 -6
- package/plugin/src/withIAP.ts +57 -37
- package/plugin/src/withLocalOpenIAP.ts +16 -6
- package/src/index.ts +2 -2
package/openiap-versions.json
CHANGED
package/package.json
CHANGED
package/plugin/build/withIAP.js
CHANGED
|
@@ -72,19 +72,23 @@ const modifyAppBuildGradle = (gradle, language, isHorizonEnabled) => {
|
|
|
72
72
|
let modified = gradle;
|
|
73
73
|
// Determine which flavor to use based on isHorizonEnabled
|
|
74
74
|
const flavor = isHorizonEnabled ? 'horizon' : 'play';
|
|
75
|
+
// Use openiap-google-horizon artifact when horizon is enabled
|
|
76
|
+
const artifactId = isHorizonEnabled
|
|
77
|
+
? 'openiap-google-horizon'
|
|
78
|
+
: 'openiap-google';
|
|
75
79
|
// Ensure OpenIAP dependency exists at desired version in app-level build.gradle(.kts)
|
|
76
80
|
const impl = (ga, v) => language === 'kotlin'
|
|
77
81
|
? ` implementation("${ga}:${v}")`
|
|
78
82
|
: ` implementation "${ga}:${v}"`;
|
|
79
|
-
const openiapDep = impl(
|
|
80
|
-
// Remove any existing openiap-google lines (any version, groovy/kotlin, implementation/api)
|
|
81
|
-
const openiapAnyLine = /^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google
|
|
83
|
+
const openiapDep = impl(`io.github.hyochan.openiap:${artifactId}`, OPENIAP_ANDROID_VERSION);
|
|
84
|
+
// Remove any existing openiap-google or openiap-google-horizon lines (any version, groovy/kotlin, implementation/api)
|
|
85
|
+
const openiapAnyLine = /^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google(?:-horizon)?:[^"']+["']\s*\)?\s*$/gm;
|
|
82
86
|
const hadExisting = openiapAnyLine.test(modified);
|
|
83
87
|
if (hadExisting) {
|
|
84
88
|
modified = modified.replace(openiapAnyLine, '').replace(/\n{3,}/g, '\n\n');
|
|
85
89
|
}
|
|
86
90
|
// Ensure the desired dependency line is present
|
|
87
|
-
if (!new RegExp(String.raw `io\.github\.hyochan\.openiap
|
|
91
|
+
if (!new RegExp(String.raw `io\.github\.hyochan\.openiap:${artifactId}:${OPENIAP_ANDROID_VERSION}`).test(modified)) {
|
|
88
92
|
// Insert just after the opening `dependencies {` line
|
|
89
93
|
modified = addLineToGradle(modified, /dependencies\s*{/, openiapDep, 1);
|
|
90
94
|
logOnce(hadExisting
|
|
@@ -124,6 +128,20 @@ const withIapAndroid = (config, props) => {
|
|
|
124
128
|
return config;
|
|
125
129
|
});
|
|
126
130
|
}
|
|
131
|
+
// Set horizonEnabled property in gradle.properties so expo-iap module can pick it up
|
|
132
|
+
config = (0, config_plugins_1.withGradleProperties)(config, (config) => {
|
|
133
|
+
const horizonValue = props?.isHorizonEnabled ?? false;
|
|
134
|
+
// Remove any existing horizonEnabled entries
|
|
135
|
+
config.modResults = config.modResults.filter((item) => item.type !== 'property' || item.key !== 'horizonEnabled');
|
|
136
|
+
// Add the horizonEnabled property
|
|
137
|
+
config.modResults.push({
|
|
138
|
+
type: 'property',
|
|
139
|
+
key: 'horizonEnabled',
|
|
140
|
+
value: String(horizonValue),
|
|
141
|
+
});
|
|
142
|
+
logOnce(`✅ Set horizonEnabled=${horizonValue} in gradle.properties`);
|
|
143
|
+
return config;
|
|
144
|
+
});
|
|
127
145
|
// Note: missingDimensionStrategy for local dev is handled in withLocalOpenIAP
|
|
128
146
|
config = (0, config_plugins_1.withAndroidManifest)(config, (config) => {
|
|
129
147
|
const manifest = config.modResults;
|
|
@@ -153,20 +171,22 @@ const withIapAndroid = (config, props) => {
|
|
|
153
171
|
application['meta-data'] = [];
|
|
154
172
|
}
|
|
155
173
|
const metaData = application['meta-data'];
|
|
174
|
+
// Use the correct meta-data name for Horizon Platform SDK
|
|
175
|
+
const horizonMetaDataName = 'com.meta.horizon.platform.ovr.OCULUS_APP_ID';
|
|
156
176
|
const horizonAppIdMeta = {
|
|
157
177
|
$: {
|
|
158
|
-
'android:name':
|
|
178
|
+
'android:name': horizonMetaDataName,
|
|
159
179
|
'android:value': props.horizonAppId,
|
|
160
180
|
},
|
|
161
181
|
};
|
|
162
|
-
const existingIndex = metaData.findIndex((m) => m.$['android:name'] ===
|
|
182
|
+
const existingIndex = metaData.findIndex((m) => m.$['android:name'] === horizonMetaDataName);
|
|
163
183
|
if (existingIndex !== -1) {
|
|
164
184
|
metaData[existingIndex] = horizonAppIdMeta;
|
|
165
|
-
logOnce(`✅ Updated
|
|
185
|
+
logOnce(`✅ Updated ${horizonMetaDataName} to ${props.horizonAppId} in AndroidManifest.xml`);
|
|
166
186
|
}
|
|
167
187
|
else {
|
|
168
188
|
metaData.push(horizonAppIdMeta);
|
|
169
|
-
logOnce(`✅ Added
|
|
189
|
+
logOnce(`✅ Added ${horizonMetaDataName}: ${props.horizonAppId} to AndroidManifest.xml`);
|
|
170
190
|
}
|
|
171
191
|
}
|
|
172
192
|
return config;
|
|
@@ -179,31 +199,23 @@ const withIapIOS = (config, options) => {
|
|
|
179
199
|
if (options) {
|
|
180
200
|
config = (0, withIosAlternativeBilling_1.withIosAlternativeBilling)(config, options);
|
|
181
201
|
}
|
|
182
|
-
return (0, config_plugins_1.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (localPodRegex.test(content)) {
|
|
200
|
-
content = content.replace(localPodRegex, '').replace(/\n{3,}/g, '\n\n');
|
|
201
|
-
logOnce('🧹 expo-iap: Removed local OpenIAP pod from Podfile');
|
|
202
|
-
}
|
|
203
|
-
fs.writeFileSync(podfilePath, content);
|
|
204
|
-
return config;
|
|
205
|
-
},
|
|
206
|
-
]);
|
|
202
|
+
return (0, config_plugins_1.withPodfile)(config, (config) => {
|
|
203
|
+
let content = config.modResults.contents;
|
|
204
|
+
// 1) Ensure CocoaPods CDN source is present at the very top
|
|
205
|
+
const cdnLine = `source 'https://cdn.cocoapods.org/'`;
|
|
206
|
+
if (!content.includes(cdnLine)) {
|
|
207
|
+
content = `${cdnLine}\n\n${content}`;
|
|
208
|
+
logOnce('📦 expo-iap: Added CocoaPods CDN source to Podfile');
|
|
209
|
+
}
|
|
210
|
+
// 2) Remove any lingering local OpenIAP pod injection
|
|
211
|
+
const localPodRegex = /^\s*pod\s+'openiap'\s*,\s*:path\s*=>\s*['"][^'"]+['"][^\n]*$/gm;
|
|
212
|
+
if (localPodRegex.test(content)) {
|
|
213
|
+
content = content.replace(localPodRegex, '').replace(/\n{3,}/g, '\n\n');
|
|
214
|
+
logOnce('🧹 expo-iap: Removed local OpenIAP pod from Podfile');
|
|
215
|
+
}
|
|
216
|
+
config.modResults.contents = content;
|
|
217
|
+
return config;
|
|
218
|
+
});
|
|
207
219
|
};
|
|
208
220
|
const withIap = (config, options) => {
|
|
209
221
|
try {
|
|
@@ -70,7 +70,7 @@ const withLocalOpenIAP = (config, props) => {
|
|
|
70
70
|
}
|
|
71
71
|
return null;
|
|
72
72
|
};
|
|
73
|
-
// iOS: inject local pod path
|
|
73
|
+
// iOS: inject local pod path with wrapper podspec
|
|
74
74
|
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
75
75
|
'ios',
|
|
76
76
|
async (config) => {
|
|
@@ -88,18 +88,23 @@ const withLocalOpenIAP = (config, props) => {
|
|
|
88
88
|
console.warn(`⚠️ Podfile not found at ${podfilePath}. Skipping.`);
|
|
89
89
|
return config;
|
|
90
90
|
}
|
|
91
|
+
logOnce(`✅ Using local OpenIAP from: ${iosPath}`);
|
|
91
92
|
let podfileContent = fs.readFileSync(podfilePath, 'utf8');
|
|
93
|
+
// Check if local OpenIAP pod is already configured
|
|
92
94
|
if (podfileContent.includes("pod 'openiap',")) {
|
|
93
95
|
logOnce('✅ Local OpenIAP pod already configured');
|
|
94
96
|
return config;
|
|
95
97
|
}
|
|
96
98
|
const targetRegex = /target\s+['"][\w]+['"]\s+do\s*\n\s*use_expo_modules!/;
|
|
99
|
+
const relativePath = path
|
|
100
|
+
.relative(platformProjectRoot, iosPath)
|
|
101
|
+
.replace(/\\/g, '/');
|
|
97
102
|
if (targetRegex.test(podfileContent)) {
|
|
98
103
|
podfileContent = podfileContent.replace(targetRegex, (match) => {
|
|
99
104
|
return `${match}
|
|
100
|
-
|
|
105
|
+
|
|
101
106
|
# Local OpenIAP pod for development (added by expo-iap plugin)
|
|
102
|
-
pod 'openiap', :path => '${
|
|
107
|
+
pod 'openiap', :path => '${relativePath}'`;
|
|
103
108
|
});
|
|
104
109
|
fs.writeFileSync(podfilePath, podfileContent);
|
|
105
110
|
logOnce(`✅ Added local OpenIAP pod at: ${iosPath}`);
|
|
@@ -195,11 +200,12 @@ const withLocalOpenIAP = (config, props) => {
|
|
|
195
200
|
const flavor = props?.isHorizonEnabled ? 'horizon' : 'play';
|
|
196
201
|
const strategyLine = ` missingDimensionStrategy "platform", "${flavor}"`;
|
|
197
202
|
let contents = gradle.contents;
|
|
198
|
-
// Remove Maven deps (
|
|
199
|
-
|
|
203
|
+
// Remove Maven deps (both openiap-google and openiap-google-horizon)
|
|
204
|
+
// to avoid duplicate classes with local module
|
|
205
|
+
const mavenPattern = /^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google(?:-horizon)?:[^"']+["']\s*\)?\s*$/gm;
|
|
200
206
|
if (mavenPattern.test(contents)) {
|
|
201
207
|
contents = contents.replace(mavenPattern, '\n');
|
|
202
|
-
logOnce('🧹 Removed Maven openiap-google (using local module)');
|
|
208
|
+
logOnce('🧹 Removed Maven openiap-google* dependencies (using local module)');
|
|
203
209
|
}
|
|
204
210
|
// Add missingDimensionStrategy (required for flavored module)
|
|
205
211
|
// Remove any existing platform strategies first to avoid duplicates
|
package/plugin/src/withIAP.ts
CHANGED
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
WarningAggregator,
|
|
5
5
|
withAndroidManifest,
|
|
6
6
|
withAppBuildGradle,
|
|
7
|
-
|
|
7
|
+
withGradleProperties,
|
|
8
|
+
withPodfile,
|
|
8
9
|
} from 'expo/config-plugins';
|
|
9
10
|
import * as fs from 'fs';
|
|
10
11
|
import * as path from 'path';
|
|
@@ -64,19 +65,24 @@ const modifyAppBuildGradle = (
|
|
|
64
65
|
// Determine which flavor to use based on isHorizonEnabled
|
|
65
66
|
const flavor = isHorizonEnabled ? 'horizon' : 'play';
|
|
66
67
|
|
|
68
|
+
// Use openiap-google-horizon artifact when horizon is enabled
|
|
69
|
+
const artifactId = isHorizonEnabled
|
|
70
|
+
? 'openiap-google-horizon'
|
|
71
|
+
: 'openiap-google';
|
|
72
|
+
|
|
67
73
|
// Ensure OpenIAP dependency exists at desired version in app-level build.gradle(.kts)
|
|
68
74
|
const impl = (ga: string, v: string) =>
|
|
69
75
|
language === 'kotlin'
|
|
70
76
|
? ` implementation("${ga}:${v}")`
|
|
71
77
|
: ` implementation "${ga}:${v}"`;
|
|
72
78
|
const openiapDep = impl(
|
|
73
|
-
|
|
79
|
+
`io.github.hyochan.openiap:${artifactId}`,
|
|
74
80
|
OPENIAP_ANDROID_VERSION,
|
|
75
81
|
);
|
|
76
82
|
|
|
77
|
-
// Remove any existing openiap-google lines (any version, groovy/kotlin, implementation/api)
|
|
83
|
+
// Remove any existing openiap-google or openiap-google-horizon lines (any version, groovy/kotlin, implementation/api)
|
|
78
84
|
const openiapAnyLine =
|
|
79
|
-
/^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google
|
|
85
|
+
/^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google(?:-horizon)?:[^"']+["']\s*\)?\s*$/gm;
|
|
80
86
|
const hadExisting = openiapAnyLine.test(modified);
|
|
81
87
|
if (hadExisting) {
|
|
82
88
|
modified = modified.replace(openiapAnyLine, '').replace(/\n{3,}/g, '\n\n');
|
|
@@ -85,7 +91,7 @@ const modifyAppBuildGradle = (
|
|
|
85
91
|
// Ensure the desired dependency line is present
|
|
86
92
|
if (
|
|
87
93
|
!new RegExp(
|
|
88
|
-
String.raw`io\.github\.hyochan\.openiap
|
|
94
|
+
String.raw`io\.github\.hyochan\.openiap:${artifactId}:${OPENIAP_ANDROID_VERSION}`,
|
|
89
95
|
).test(modified)
|
|
90
96
|
) {
|
|
91
97
|
// Insert just after the opening `dependencies {` line
|
|
@@ -155,6 +161,27 @@ const withIapAndroid: ConfigPlugin<
|
|
|
155
161
|
});
|
|
156
162
|
}
|
|
157
163
|
|
|
164
|
+
// Set horizonEnabled property in gradle.properties so expo-iap module can pick it up
|
|
165
|
+
config = withGradleProperties(config, (config) => {
|
|
166
|
+
const horizonValue = props?.isHorizonEnabled ?? false;
|
|
167
|
+
|
|
168
|
+
// Remove any existing horizonEnabled entries
|
|
169
|
+
config.modResults = config.modResults.filter(
|
|
170
|
+
(item) => item.type !== 'property' || item.key !== 'horizonEnabled',
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// Add the horizonEnabled property
|
|
174
|
+
config.modResults.push({
|
|
175
|
+
type: 'property',
|
|
176
|
+
key: 'horizonEnabled',
|
|
177
|
+
value: String(horizonValue),
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
logOnce(`✅ Set horizonEnabled=${horizonValue} in gradle.properties`);
|
|
181
|
+
|
|
182
|
+
return config;
|
|
183
|
+
});
|
|
184
|
+
|
|
158
185
|
// Note: missingDimensionStrategy for local dev is handled in withLocalOpenIAP
|
|
159
186
|
|
|
160
187
|
config = withAndroidManifest(config, (config) => {
|
|
@@ -195,26 +222,29 @@ const withIapAndroid: ConfigPlugin<
|
|
|
195
222
|
}
|
|
196
223
|
|
|
197
224
|
const metaData = application['meta-data'];
|
|
225
|
+
|
|
226
|
+
// Use the correct meta-data name for Horizon Platform SDK
|
|
227
|
+
const horizonMetaDataName = 'com.meta.horizon.platform.ovr.OCULUS_APP_ID';
|
|
198
228
|
const horizonAppIdMeta = {
|
|
199
229
|
$: {
|
|
200
|
-
'android:name':
|
|
230
|
+
'android:name': horizonMetaDataName,
|
|
201
231
|
'android:value': props.horizonAppId,
|
|
202
232
|
},
|
|
203
233
|
};
|
|
204
234
|
|
|
205
235
|
const existingIndex = metaData.findIndex(
|
|
206
|
-
(m) => m.$['android:name'] ===
|
|
236
|
+
(m) => m.$['android:name'] === horizonMetaDataName,
|
|
207
237
|
);
|
|
208
238
|
|
|
209
239
|
if (existingIndex !== -1) {
|
|
210
240
|
metaData[existingIndex] = horizonAppIdMeta;
|
|
211
241
|
logOnce(
|
|
212
|
-
`✅ Updated
|
|
242
|
+
`✅ Updated ${horizonMetaDataName} to ${props.horizonAppId} in AndroidManifest.xml`,
|
|
213
243
|
);
|
|
214
244
|
} else {
|
|
215
245
|
metaData.push(horizonAppIdMeta);
|
|
216
246
|
logOnce(
|
|
217
|
-
`✅ Added
|
|
247
|
+
`✅ Added ${horizonMetaDataName}: ${props.horizonAppId} to AndroidManifest.xml`,
|
|
218
248
|
);
|
|
219
249
|
}
|
|
220
250
|
}
|
|
@@ -235,37 +265,27 @@ const withIapIOS: ConfigPlugin<IOSAlternativeBillingConfig | undefined> = (
|
|
|
235
265
|
config = withIosAlternativeBilling(config, options);
|
|
236
266
|
}
|
|
237
267
|
|
|
238
|
-
return
|
|
239
|
-
|
|
240
|
-
async (config) => {
|
|
241
|
-
const {platformProjectRoot} = config.modRequest;
|
|
242
|
-
const podfilePath = path.join(platformProjectRoot, 'Podfile');
|
|
268
|
+
return withPodfile(config, (config) => {
|
|
269
|
+
let content = config.modResults.contents;
|
|
243
270
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
// 1) Ensure CocoaPods CDN source is present at the very top
|
|
251
|
-
const cdnLine = `source 'https://cdn.cocoapods.org/'`;
|
|
252
|
-
if (!content.includes(cdnLine)) {
|
|
253
|
-
content = `${cdnLine}\n\n${content}`;
|
|
254
|
-
logOnce('📦 expo-iap: Added CocoaPods CDN source to Podfile');
|
|
255
|
-
}
|
|
271
|
+
// 1) Ensure CocoaPods CDN source is present at the very top
|
|
272
|
+
const cdnLine = `source 'https://cdn.cocoapods.org/'`;
|
|
273
|
+
if (!content.includes(cdnLine)) {
|
|
274
|
+
content = `${cdnLine}\n\n${content}`;
|
|
275
|
+
logOnce('📦 expo-iap: Added CocoaPods CDN source to Podfile');
|
|
276
|
+
}
|
|
256
277
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
278
|
+
// 2) Remove any lingering local OpenIAP pod injection
|
|
279
|
+
const localPodRegex =
|
|
280
|
+
/^\s*pod\s+'openiap'\s*,\s*:path\s*=>\s*['"][^'"]+['"][^\n]*$/gm;
|
|
281
|
+
if (localPodRegex.test(content)) {
|
|
282
|
+
content = content.replace(localPodRegex, '').replace(/\n{3,}/g, '\n\n');
|
|
283
|
+
logOnce('🧹 expo-iap: Removed local OpenIAP pod from Podfile');
|
|
284
|
+
}
|
|
264
285
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
]);
|
|
286
|
+
config.modResults.contents = content;
|
|
287
|
+
return config;
|
|
288
|
+
});
|
|
269
289
|
};
|
|
270
290
|
|
|
271
291
|
export interface ExpoIapPluginOptions {
|
|
@@ -61,7 +61,7 @@ const withLocalOpenIAP: ConfigPlugin<
|
|
|
61
61
|
return null;
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
// iOS: inject local pod path
|
|
64
|
+
// iOS: inject local pod path with wrapper podspec
|
|
65
65
|
config = withDangerousMod(config, [
|
|
66
66
|
'ios',
|
|
67
67
|
async (config) => {
|
|
@@ -82,8 +82,12 @@ const withLocalOpenIAP: ConfigPlugin<
|
|
|
82
82
|
console.warn(`⚠️ Podfile not found at ${podfilePath}. Skipping.`);
|
|
83
83
|
return config;
|
|
84
84
|
}
|
|
85
|
+
|
|
86
|
+
logOnce(`✅ Using local OpenIAP from: ${iosPath}`);
|
|
87
|
+
|
|
85
88
|
let podfileContent = fs.readFileSync(podfilePath, 'utf8');
|
|
86
89
|
|
|
90
|
+
// Check if local OpenIAP pod is already configured
|
|
87
91
|
if (podfileContent.includes("pod 'openiap',")) {
|
|
88
92
|
logOnce('✅ Local OpenIAP pod already configured');
|
|
89
93
|
return config;
|
|
@@ -91,13 +95,16 @@ const withLocalOpenIAP: ConfigPlugin<
|
|
|
91
95
|
|
|
92
96
|
const targetRegex =
|
|
93
97
|
/target\s+['"][\w]+['"]\s+do\s*\n\s*use_expo_modules!/;
|
|
98
|
+
const relativePath = path
|
|
99
|
+
.relative(platformProjectRoot, iosPath)
|
|
100
|
+
.replace(/\\/g, '/');
|
|
94
101
|
|
|
95
102
|
if (targetRegex.test(podfileContent)) {
|
|
96
103
|
podfileContent = podfileContent.replace(targetRegex, (match) => {
|
|
97
104
|
return `${match}
|
|
98
|
-
|
|
105
|
+
|
|
99
106
|
# Local OpenIAP pod for development (added by expo-iap plugin)
|
|
100
|
-
pod 'openiap', :path => '${
|
|
107
|
+
pod 'openiap', :path => '${relativePath}'`;
|
|
101
108
|
});
|
|
102
109
|
fs.writeFileSync(podfilePath, podfileContent);
|
|
103
110
|
logOnce(`✅ Added local OpenIAP pod at: ${iosPath}`);
|
|
@@ -224,12 +231,15 @@ const withLocalOpenIAP: ConfigPlugin<
|
|
|
224
231
|
|
|
225
232
|
let contents = gradle.contents;
|
|
226
233
|
|
|
227
|
-
// Remove Maven deps (
|
|
234
|
+
// Remove Maven deps (both openiap-google and openiap-google-horizon)
|
|
235
|
+
// to avoid duplicate classes with local module
|
|
228
236
|
const mavenPattern =
|
|
229
|
-
/^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google
|
|
237
|
+
/^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google(?:-horizon)?:[^"']+["']\s*\)?\s*$/gm;
|
|
230
238
|
if (mavenPattern.test(contents)) {
|
|
231
239
|
contents = contents.replace(mavenPattern, '\n');
|
|
232
|
-
logOnce(
|
|
240
|
+
logOnce(
|
|
241
|
+
'🧹 Removed Maven openiap-google* dependencies (using local module)',
|
|
242
|
+
);
|
|
233
243
|
}
|
|
234
244
|
|
|
235
245
|
// Add missingDimensionStrategy (required for flavored module)
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// External dependencies
|
|
2
|
-
import {
|
|
2
|
+
import {requireNativeModule} from 'expo-modules-core';
|
|
3
3
|
import {Platform} from 'react-native';
|
|
4
4
|
|
|
5
5
|
// Internal modules
|
|
@@ -80,7 +80,7 @@ type ExpoIapEmitter = {
|
|
|
80
80
|
|
|
81
81
|
// Ensure the emitter has proper EventEmitter interface
|
|
82
82
|
export const emitter = (ExpoIapModule ||
|
|
83
|
-
|
|
83
|
+
requireNativeModule('ExpoIap')) as ExpoIapEmitter;
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* TODO(v3.1.0): Remove legacy 'inapp' alias once downstream apps migrate to 'in-app'.
|