expo-iap 3.0.0 → 3.0.2-rc.1
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 +7 -0
- package/README.md +11 -1
- package/android/build.gradle +1 -1
- package/bun.lock +137 -340
- package/coverage/clover.xml +358 -0
- package/coverage/coverage-final.json +7 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +176 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/src/ExpoIap.types.ts.html +1396 -0
- package/coverage/lcov-report/src/helpers/index.html +116 -0
- package/coverage/lcov-report/src/helpers/subscription.ts.html +532 -0
- package/coverage/lcov-report/src/index.html +116 -0
- package/coverage/lcov-report/src/index.ts.html +1945 -0
- package/coverage/lcov-report/src/modules/android.ts.html +496 -0
- package/coverage/lcov-report/src/modules/index.html +131 -0
- package/coverage/lcov-report/src/modules/ios.ts.html +1012 -0
- package/coverage/lcov-report/src/types/ExpoIapAndroid.types.ts.html +502 -0
- package/coverage/lcov-report/src/types/index.html +116 -0
- package/coverage/lcov-report/src/useIAP.ts.html +1654 -0
- package/coverage/lcov-report/src/utils/constants.ts.html +127 -0
- package/coverage/lcov-report/src/utils/errorMapping.ts.html +427 -0
- package/coverage/lcov-report/src/utils/index.html +116 -0
- package/coverage/lcov.info +685 -0
- package/ios/ExpoIapModule.swift +24 -21
- package/ios/expoiap.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/expoiap.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/package.json +2 -2
- package/plugin/build/withIAP.js +17 -11
- package/plugin/build/withLocalOpenIAP.js +11 -7
- package/plugin/src/withIAP.ts +20 -16
- package/plugin/src/withLocalOpenIAP.ts +11 -9
- package/plugin/tsconfig.tsbuildinfo +1 -1
package/ios/ExpoIapModule.swift
CHANGED
|
@@ -84,7 +84,7 @@ public class ExpoIapModule: Module {
|
|
|
84
84
|
|
|
85
85
|
// MARK: - Product Management
|
|
86
86
|
|
|
87
|
-
AsyncFunction("fetchProducts") { (params: [String: Any]) async throws -> [[String: Any
|
|
87
|
+
AsyncFunction("fetchProducts") { (params: [String: Any]) async throws -> [[String: Any]] in
|
|
88
88
|
try await ensureConnection()
|
|
89
89
|
logDebug("fetchProducts raw params: \(params)")
|
|
90
90
|
|
|
@@ -144,7 +144,8 @@ public class ExpoIapModule: Module {
|
|
|
144
144
|
for product in products {
|
|
145
145
|
logDebug("Product: \(product.id) - \(product.title) - \(product.displayPrice)")
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
// Ensure non-optional values for Expo bridge
|
|
148
|
+
return OpenIapSerialization.products(products).map { $0.compactMapValues { $0 } }
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
// MARK: - Purchase Operations
|
|
@@ -220,7 +221,7 @@ public class ExpoIapModule: Module {
|
|
|
220
221
|
|
|
221
222
|
// MARK: - Purchase History
|
|
222
223
|
|
|
223
|
-
AsyncFunction("getAvailablePurchases") { (options: [String: Any?]?) async throws -> [[String: Any
|
|
224
|
+
AsyncFunction("getAvailablePurchases") { (options: [String: Any?]?) async throws -> [[String: Any]] in
|
|
224
225
|
try await ensureConnection()
|
|
225
226
|
logDebug("getAvailablePurchases called")
|
|
226
227
|
|
|
@@ -232,11 +233,11 @@ public class ExpoIapModule: Module {
|
|
|
232
233
|
)
|
|
233
234
|
}
|
|
234
235
|
let purchases = try await OpenIapModule.shared.getAvailablePurchases(purchaseOptions)
|
|
235
|
-
return OpenIapSerialization.purchases(purchases)
|
|
236
|
+
return OpenIapSerialization.purchases(purchases).map { $0.compactMapValues { $0 } }
|
|
236
237
|
}
|
|
237
238
|
|
|
238
239
|
// Legacy function for backward compatibility
|
|
239
|
-
AsyncFunction("getAvailableItems") { (alsoPublishToEventListener: Bool, onlyIncludeActiveItems: Bool) async throws -> [[String: Any
|
|
240
|
+
AsyncFunction("getAvailableItems") { (alsoPublishToEventListener: Bool, onlyIncludeActiveItems: Bool) async throws -> [[String: Any]] in
|
|
240
241
|
try await ensureConnection()
|
|
241
242
|
logDebug("getAvailableItems called (legacy)")
|
|
242
243
|
|
|
@@ -245,15 +246,15 @@ public class ExpoIapModule: Module {
|
|
|
245
246
|
onlyIncludeActiveItemsIOS: onlyIncludeActiveItems
|
|
246
247
|
)
|
|
247
248
|
let purchases = try await OpenIapModule.shared.getAvailablePurchases(purchaseOptions)
|
|
248
|
-
return OpenIapSerialization.purchases(purchases)
|
|
249
|
+
return OpenIapSerialization.purchases(purchases).map { $0.compactMapValues { $0 } }
|
|
249
250
|
}
|
|
250
251
|
|
|
251
|
-
AsyncFunction("getPendingTransactionsIOS") { () async throws -> [[String: Any
|
|
252
|
+
AsyncFunction("getPendingTransactionsIOS") { () async throws -> [[String: Any]] in
|
|
252
253
|
try await ensureConnection()
|
|
253
254
|
logDebug("getPendingTransactionsIOS called")
|
|
254
255
|
|
|
255
256
|
let pendingTransactions = try await OpenIapModule.shared.getPendingTransactionsIOS()
|
|
256
|
-
return OpenIapSerialization.purchases(pendingTransactions)
|
|
257
|
+
return OpenIapSerialization.purchases(pendingTransactions).map { $0.compactMapValues { $0 } }
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
AsyncFunction("clearTransactionIOS") { () async throws -> Bool in
|
|
@@ -285,21 +286,22 @@ public class ExpoIapModule: Module {
|
|
|
285
286
|
return try await OpenIapModule.shared.getReceiptDataIOS() ?? ""
|
|
286
287
|
}
|
|
287
288
|
|
|
288
|
-
AsyncFunction("validateReceiptIOS") { (sku: String) async throws -> [String: Any
|
|
289
|
+
AsyncFunction("validateReceiptIOS") { (sku: String) async throws -> [String: Any] in
|
|
289
290
|
try await ensureConnection()
|
|
290
291
|
logDebug("validateReceiptIOS called for sku: \(sku)")
|
|
291
292
|
do {
|
|
292
293
|
// Use OpenIapReceiptValidationProps to keep naming parity with OpenIAP
|
|
293
294
|
let props = OpenIapReceiptValidationProps(sku: sku)
|
|
294
295
|
let result = try await OpenIapModule.shared.validateReceiptIOS(props)
|
|
295
|
-
|
|
296
|
+
let dict: [String: Any?] = [
|
|
296
297
|
"isValid": result.isValid,
|
|
297
298
|
"receiptData": result.receiptData,
|
|
298
299
|
"jwsRepresentation": result.jwsRepresentation,
|
|
299
300
|
// Populate unified purchaseToken for iOS as alias of JWS
|
|
300
301
|
"purchaseToken": result.jwsRepresentation,
|
|
301
|
-
"latestTransaction": result.latestTransaction.map { OpenIapSerialization.purchase($0) },
|
|
302
|
+
"latestTransaction": result.latestTransaction.map { OpenIapSerialization.purchase($0).compactMapValues { $0 } },
|
|
302
303
|
]
|
|
304
|
+
return dict.compactMapValues { $0 }
|
|
303
305
|
} catch {
|
|
304
306
|
throw OpenIapError.make(code: OpenIapError.E_RECEIPT_FAILED)
|
|
305
307
|
}
|
|
@@ -314,11 +316,12 @@ public class ExpoIapModule: Module {
|
|
|
314
316
|
return true
|
|
315
317
|
}
|
|
316
318
|
|
|
317
|
-
AsyncFunction("showManageSubscriptionsIOS") { () async throws -> [[String: Any
|
|
319
|
+
AsyncFunction("showManageSubscriptionsIOS") { () async throws -> [[String: Any]] in
|
|
318
320
|
try await ensureConnection()
|
|
319
321
|
logDebug("showManageSubscriptionsIOS called")
|
|
322
|
+
// OpenIAP 1.1.9 returns already-serialized dictionaries here.
|
|
320
323
|
let purchases = try await OpenIapModule.shared.showManageSubscriptionsIOS()
|
|
321
|
-
return
|
|
324
|
+
return purchases.map { $0.compactMapValues { $0 } }
|
|
322
325
|
}
|
|
323
326
|
|
|
324
327
|
AsyncFunction("deepLinkToSubscriptionsIOS") { () async throws in
|
|
@@ -339,7 +342,7 @@ public class ExpoIapModule: Module {
|
|
|
339
342
|
return try await OpenIapModule.shared.beginRefundRequestIOS(sku: sku)
|
|
340
343
|
}
|
|
341
344
|
|
|
342
|
-
AsyncFunction("getPromotedProductIOS") { () async throws -> [String: Any
|
|
345
|
+
AsyncFunction("getPromotedProductIOS") { () async throws -> [String: Any]? in
|
|
343
346
|
try await ensureConnection()
|
|
344
347
|
logDebug("getPromotedProductIOS called")
|
|
345
348
|
|
|
@@ -347,7 +350,7 @@ public class ExpoIapModule: Module {
|
|
|
347
350
|
// Fetch full product info by SKU to conform to OpenIapProduct
|
|
348
351
|
let request = OpenIapProductRequest(skus: [promoted.productIdentifier], type: .all)
|
|
349
352
|
let products = try await OpenIapModule.shared.fetchProducts(request)
|
|
350
|
-
let serialized = OpenIapSerialization.products(products)
|
|
353
|
+
let serialized = OpenIapSerialization.products(products).map { $0.compactMapValues { $0 } }
|
|
351
354
|
return serialized.first
|
|
352
355
|
}
|
|
353
356
|
return nil
|
|
@@ -384,7 +387,7 @@ public class ExpoIapModule: Module {
|
|
|
384
387
|
return await OpenIapModule.shared.isEligibleForIntroOfferIOS(groupID: groupID)
|
|
385
388
|
}
|
|
386
389
|
|
|
387
|
-
AsyncFunction("subscriptionStatusIOS") { (sku: String) async throws -> [[String: Any
|
|
390
|
+
AsyncFunction("subscriptionStatusIOS") { (sku: String) async throws -> [[String: Any]]? in
|
|
388
391
|
try await ensureConnection()
|
|
389
392
|
logDebug("subscriptionStatusIOS called for sku: \(sku)")
|
|
390
393
|
|
|
@@ -405,18 +408,18 @@ public class ExpoIapModule: Module {
|
|
|
405
408
|
dict["renewalInfo"] = renewalInfo
|
|
406
409
|
}
|
|
407
410
|
|
|
408
|
-
return dict
|
|
411
|
+
return dict.compactMapValues { $0 }
|
|
409
412
|
}
|
|
410
413
|
}
|
|
411
414
|
return nil
|
|
412
415
|
}
|
|
413
416
|
|
|
414
|
-
AsyncFunction("currentEntitlementIOS") { (sku: String) async throws -> [String: Any
|
|
417
|
+
AsyncFunction("currentEntitlementIOS") { (sku: String) async throws -> [String: Any]? in
|
|
415
418
|
try await ensureConnection()
|
|
416
419
|
logDebug("currentEntitlementIOS called for sku: \(sku)")
|
|
417
420
|
do {
|
|
418
421
|
if let entitlement = try await OpenIapModule.shared.currentEntitlementIOS(sku: sku) {
|
|
419
|
-
return OpenIapSerialization.purchase(entitlement)
|
|
422
|
+
return OpenIapSerialization.purchase(entitlement).compactMapValues { $0 }
|
|
420
423
|
}
|
|
421
424
|
return nil
|
|
422
425
|
} catch {
|
|
@@ -424,12 +427,12 @@ public class ExpoIapModule: Module {
|
|
|
424
427
|
}
|
|
425
428
|
}
|
|
426
429
|
|
|
427
|
-
AsyncFunction("latestTransactionIOS") { (sku: String) async throws -> [String: Any
|
|
430
|
+
AsyncFunction("latestTransactionIOS") { (sku: String) async throws -> [String: Any]? in
|
|
428
431
|
try await ensureConnection()
|
|
429
432
|
logDebug("latestTransactionIOS called for sku: \(sku)")
|
|
430
433
|
do {
|
|
431
434
|
if let transaction = try await OpenIapModule.shared.latestTransactionIOS(sku: sku) {
|
|
432
|
-
return OpenIapSerialization.purchase(transaction)
|
|
435
|
+
return OpenIapSerialization.purchase(transaction).compactMapValues { $0 }
|
|
433
436
|
}
|
|
434
437
|
return nil
|
|
435
438
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-iap",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2-rc.1",
|
|
4
4
|
"description": "In App Purchase module in Expo",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"lint:ci": "bun run lint:tsc && bun run lint:eslint && bun run lint:prettier && bun run lint:kt",
|
|
16
16
|
"test": "jest",
|
|
17
17
|
"test:coverage": "jest --coverage",
|
|
18
|
-
"prepare": "expo-module prepare && husky install",
|
|
18
|
+
"prepare": "expo-module prepare && sh -c 'command -v husky >/dev/null 2>&1 && husky install || { echo \"husky not installed; skipping\"; exit 0; }'",
|
|
19
19
|
"expo-module": "expo-module",
|
|
20
20
|
"open:ios": "xed example/ios",
|
|
21
21
|
"open:android": "open -a \"Android Studio\" example/android",
|
package/plugin/build/withIAP.js
CHANGED
|
@@ -65,21 +65,26 @@ const addLineToGradle = (content, anchor, lineToAdd, offset = 1) => {
|
|
|
65
65
|
};
|
|
66
66
|
const modifyAppBuildGradle = (gradle, language) => {
|
|
67
67
|
let modified = gradle;
|
|
68
|
-
//
|
|
68
|
+
// Ensure OpenIAP dependency exists at desired version in app-level build.gradle(.kts)
|
|
69
69
|
const impl = (ga, v) => language === 'kotlin'
|
|
70
70
|
? ` implementation("${ga}:${v}")`
|
|
71
71
|
: ` implementation "${ga}:${v}"`;
|
|
72
72
|
// Pin OpenIAP Google library to 1.1.0
|
|
73
73
|
const openiapDep = impl('io.github.hyochan.openiap:openiap-google', '1.1.0');
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
// Remove any existing openiap-google lines (any version, groovy/kotlin, implementation/api)
|
|
75
|
+
const openiapAnyLine = /^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*\)?\s*$/gm;
|
|
76
|
+
const hadExisting = openiapAnyLine.test(modified);
|
|
77
|
+
if (hadExisting) {
|
|
78
|
+
modified = modified.replace(openiapAnyLine, '').replace(/\n{3,}/g, '\n\n');
|
|
79
|
+
}
|
|
80
|
+
// Ensure the desired dependency line is present
|
|
81
|
+
if (!new RegExp(String.raw `io\.github\.hyochan\.openiap:openiap-google:1\.1\.0`).test(modified)) {
|
|
82
|
+
// Insert just after the opening `dependencies {` line
|
|
83
|
+
modified = addLineToGradle(modified, /dependencies\s*{/, openiapDep, 1);
|
|
84
|
+
logOnce(hadExisting
|
|
85
|
+
? '🛠️ expo-iap: Replaced OpenIAP dependency with 1.1.0'
|
|
86
|
+
: '🛠️ expo-iap: Added OpenIAP dependency (1.1.0) to build.gradle');
|
|
79
87
|
}
|
|
80
|
-
// Log only once and only if we actually added dependencies
|
|
81
|
-
if (hasAddedDependency)
|
|
82
|
-
logOnce('🛠️ expo-iap: Added OpenIAP dependency to build.gradle');
|
|
83
88
|
return modified;
|
|
84
89
|
};
|
|
85
90
|
const withIapAndroid = (config, props) => {
|
|
@@ -141,11 +146,12 @@ const withIapIOS = (config) => {
|
|
|
141
146
|
};
|
|
142
147
|
const withIap = (config, options) => {
|
|
143
148
|
try {
|
|
144
|
-
|
|
149
|
+
// Respect explicit flag; fall back to presence of localPath only when flag is unset
|
|
150
|
+
const isLocalDev = options?.enableLocalDev ?? !!options?.localPath;
|
|
145
151
|
// Apply Android modifications (skip adding deps when linking local module)
|
|
146
152
|
let result = withIapAndroid(config, { addDeps: !isLocalDev });
|
|
147
153
|
// iOS: choose one path to avoid overlap
|
|
148
|
-
if (
|
|
154
|
+
if (isLocalDev) {
|
|
149
155
|
if (!options?.localPath) {
|
|
150
156
|
config_plugins_1.WarningAggregator.addWarningIOS('expo-iap', 'enableLocalDev is true but no localPath provided. Skipping local OpenIAP integration.');
|
|
151
157
|
}
|
|
@@ -177,10 +177,12 @@ const withLocalOpenIAP = (config, props) => {
|
|
|
177
177
|
}
|
|
178
178
|
const gradle = config.modResults;
|
|
179
179
|
const dependencyLine = ` implementation project(':openiap-google')`;
|
|
180
|
-
// Remove any previously
|
|
180
|
+
// Remove any previously added Maven deps for openiap-google to avoid duplicate classes
|
|
181
181
|
const removalPatterns = [
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
// Groovy DSL: implementation "io.github.hyochan.openiap:openiap-google:x.y.z" or api "..."
|
|
183
|
+
/^\s*(?:implementation|api)\s+["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*$/gm,
|
|
184
|
+
// Kotlin DSL: implementation("io.github.hyochan.openiap:openiap-google:x.y.z") or api("...")
|
|
185
|
+
/^\s*(?:implementation|api)\s*\(\s*["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*\)\s*$/gm,
|
|
184
186
|
];
|
|
185
187
|
let contents = gradle.contents;
|
|
186
188
|
let removedAny = false;
|
|
@@ -192,7 +194,7 @@ const withLocalOpenIAP = (config, props) => {
|
|
|
192
194
|
}
|
|
193
195
|
if (removedAny) {
|
|
194
196
|
gradle.contents = contents;
|
|
195
|
-
console.log('🧹 Removed
|
|
197
|
+
console.log('🧹 Removed Maven openiap-google to use local :openiap-google');
|
|
196
198
|
}
|
|
197
199
|
if (!gradle.contents.includes(dependencyLine)) {
|
|
198
200
|
const anchor = /dependencies\s*\{/m;
|
|
@@ -216,8 +218,10 @@ const withLocalOpenIAP = (config, props) => {
|
|
|
216
218
|
if (fs.existsSync(appBuildGradle)) {
|
|
217
219
|
let contents = fs.readFileSync(appBuildGradle, 'utf8');
|
|
218
220
|
const patterns = [
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
// Groovy DSL
|
|
222
|
+
/^\s*(?:implementation|api)\s+["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*$/gm,
|
|
223
|
+
// Kotlin DSL
|
|
224
|
+
/^\s*(?:implementation|api)\s*\(\s*["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*\)\s*$/gm,
|
|
221
225
|
];
|
|
222
226
|
let changed = false;
|
|
223
227
|
for (const p of patterns) {
|
|
@@ -228,7 +232,7 @@ const withLocalOpenIAP = (config, props) => {
|
|
|
228
232
|
}
|
|
229
233
|
if (changed) {
|
|
230
234
|
fs.writeFileSync(appBuildGradle, contents);
|
|
231
|
-
console.log('🧹 expo-iap: Cleaned
|
|
235
|
+
console.log('🧹 expo-iap: Cleaned Maven openiap-google for local :openiap-google');
|
|
232
236
|
}
|
|
233
237
|
}
|
|
234
238
|
}
|
package/plugin/src/withIAP.ts
CHANGED
|
@@ -49,7 +49,7 @@ const modifyAppBuildGradle = (
|
|
|
49
49
|
): string => {
|
|
50
50
|
let modified = gradle;
|
|
51
51
|
|
|
52
|
-
//
|
|
52
|
+
// Ensure OpenIAP dependency exists at desired version in app-level build.gradle(.kts)
|
|
53
53
|
const impl = (ga: string, v: string) =>
|
|
54
54
|
language === 'kotlin'
|
|
55
55
|
? ` implementation("${ga}:${v}")`
|
|
@@ -57,21 +57,24 @@ const modifyAppBuildGradle = (
|
|
|
57
57
|
// Pin OpenIAP Google library to 1.1.0
|
|
58
58
|
const openiapDep = impl('io.github.hyochan.openiap:openiap-google', '1.1.0');
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (!hasGA('io.github.hyochan.openiap:openiap-google')) {
|
|
68
|
-
modified = addLineToGradle(modified, /dependencies\s*{/, openiapDep, 0);
|
|
69
|
-
hasAddedDependency = true;
|
|
60
|
+
// Remove any existing openiap-google lines (any version, groovy/kotlin, implementation/api)
|
|
61
|
+
const openiapAnyLine =
|
|
62
|
+
/^\s*(?:implementation|api)\s*\(?\s*["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*\)?\s*$/gm;
|
|
63
|
+
const hadExisting = openiapAnyLine.test(modified);
|
|
64
|
+
if (hadExisting) {
|
|
65
|
+
modified = modified.replace(openiapAnyLine, '').replace(/\n{3,}/g, '\n\n');
|
|
70
66
|
}
|
|
71
67
|
|
|
72
|
-
//
|
|
73
|
-
if (
|
|
74
|
-
|
|
68
|
+
// Ensure the desired dependency line is present
|
|
69
|
+
if (!new RegExp(String.raw`io\.github\.hyochan\.openiap:openiap-google:1\.1\.0`).test(modified)) {
|
|
70
|
+
// Insert just after the opening `dependencies {` line
|
|
71
|
+
modified = addLineToGradle(modified, /dependencies\s*{/, openiapDep, 1);
|
|
72
|
+
logOnce(
|
|
73
|
+
hadExisting
|
|
74
|
+
? '🛠️ expo-iap: Replaced OpenIAP dependency with 1.1.0'
|
|
75
|
+
: '🛠️ expo-iap: Added OpenIAP dependency (1.1.0) to build.gradle',
|
|
76
|
+
);
|
|
77
|
+
}
|
|
75
78
|
|
|
76
79
|
return modified;
|
|
77
80
|
};
|
|
@@ -173,12 +176,13 @@ const withIap: ConfigPlugin<ExpoIapPluginOptions | void> = (
|
|
|
173
176
|
options,
|
|
174
177
|
) => {
|
|
175
178
|
try {
|
|
176
|
-
|
|
179
|
+
// Respect explicit flag; fall back to presence of localPath only when flag is unset
|
|
180
|
+
const isLocalDev = options?.enableLocalDev ?? !!options?.localPath;
|
|
177
181
|
// Apply Android modifications (skip adding deps when linking local module)
|
|
178
182
|
let result = withIapAndroid(config, {addDeps: !isLocalDev});
|
|
179
183
|
|
|
180
184
|
// iOS: choose one path to avoid overlap
|
|
181
|
-
if (
|
|
185
|
+
if (isLocalDev) {
|
|
182
186
|
if (!options?.localPath) {
|
|
183
187
|
WarningAggregator.addWarningIOS(
|
|
184
188
|
'expo-iap',
|
|
@@ -196,10 +196,12 @@ const withLocalOpenIAP: ConfigPlugin<{localPath?: LocalPathOption} | void> = (
|
|
|
196
196
|
const gradle = config.modResults;
|
|
197
197
|
const dependencyLine = ` implementation project(':openiap-google')`;
|
|
198
198
|
|
|
199
|
-
// Remove any previously
|
|
199
|
+
// Remove any previously added Maven deps for openiap-google to avoid duplicate classes
|
|
200
200
|
const removalPatterns = [
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
// Groovy DSL: implementation "io.github.hyochan.openiap:openiap-google:x.y.z" or api "..."
|
|
202
|
+
/^\s*(?:implementation|api)\s+["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*$/gm,
|
|
203
|
+
// Kotlin DSL: implementation("io.github.hyochan.openiap:openiap-google:x.y.z") or api("...")
|
|
204
|
+
/^\s*(?:implementation|api)\s*\(\s*["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*\)\s*$/gm,
|
|
203
205
|
];
|
|
204
206
|
let contents = gradle.contents;
|
|
205
207
|
let removedAny = false;
|
|
@@ -211,9 +213,7 @@ const withLocalOpenIAP: ConfigPlugin<{localPath?: LocalPathOption} | void> = (
|
|
|
211
213
|
}
|
|
212
214
|
if (removedAny) {
|
|
213
215
|
gradle.contents = contents;
|
|
214
|
-
console.log(
|
|
215
|
-
'🧹 Removed external Play Billing/GMS deps to use local :openiap-google',
|
|
216
|
-
);
|
|
216
|
+
console.log('🧹 Removed Maven openiap-google to use local :openiap-google');
|
|
217
217
|
}
|
|
218
218
|
if (!gradle.contents.includes(dependencyLine)) {
|
|
219
219
|
const anchor = /dependencies\s*\{/m;
|
|
@@ -244,8 +244,10 @@ const withLocalOpenIAP: ConfigPlugin<{localPath?: LocalPathOption} | void> = (
|
|
|
244
244
|
if (fs.existsSync(appBuildGradle)) {
|
|
245
245
|
let contents = fs.readFileSync(appBuildGradle, 'utf8');
|
|
246
246
|
const patterns = [
|
|
247
|
-
|
|
248
|
-
|
|
247
|
+
// Groovy DSL
|
|
248
|
+
/^\s*(?:implementation|api)\s+["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*$/gm,
|
|
249
|
+
// Kotlin DSL
|
|
250
|
+
/^\s*(?:implementation|api)\s*\(\s*["']io\.github\.hyochan\.openiap:openiap-google:[^"']+["']\s*\)\s*$/gm,
|
|
249
251
|
];
|
|
250
252
|
let changed = false;
|
|
251
253
|
for (const p of patterns) {
|
|
@@ -257,7 +259,7 @@ const withLocalOpenIAP: ConfigPlugin<{localPath?: LocalPathOption} | void> = (
|
|
|
257
259
|
if (changed) {
|
|
258
260
|
fs.writeFileSync(appBuildGradle, contents);
|
|
259
261
|
console.log(
|
|
260
|
-
'🧹 expo-iap: Cleaned
|
|
262
|
+
'🧹 expo-iap: Cleaned Maven openiap-google for local :openiap-google',
|
|
261
263
|
);
|
|
262
264
|
}
|
|
263
265
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/
|
|
1
|
+
{"root":["./src/withiap.ts","./src/withlocalopeniap.ts"],"version":"5.9.2"}
|