react-native-iap 15.5.3 → 15.5.4

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.
@@ -402,43 +402,32 @@ class HybridRnIap : HybridRnIapSpec() {
402
402
  val skusList = skus.toList()
403
403
 
404
404
  val products: List<ProductCommon> = try {
405
- when (queryType) {
406
- ProductQueryType.All -> {
407
- collectAllQueryProducts(
408
- skusList = skusList,
409
- fetchKind = { kind ->
410
- RnIapLog.payload(
411
- "fetchProducts.native",
412
- mapOf("skus" to skusList, "type" to kind.rawValue)
413
- )
414
- val fetched = openIap.fetchProducts(ProductRequest(skusList, kind)).productsOrEmpty()
415
- RnIapLog.result(
416
- "fetchProducts.native",
417
- fetched.map { mapOf("id" to it.id, "type" to it.type.rawValue) }
418
- )
419
- fetched
420
- },
421
- onFailure = { kind, error ->
422
- RnIapLog.failure("fetchProducts.native[${kind.rawValue}]", error)
423
- },
424
- )
425
- }
426
- else -> {
427
- RnIapLog.payload(
428
- "fetchProducts.native",
429
- mapOf("skus" to skusList, "type" to queryType.rawValue)
430
- )
431
- val fetched = openIap.fetchProducts(ProductRequest(skusList, queryType)).productsOrEmpty()
432
- RnIapLog.result(
433
- "fetchProducts.native",
434
- fetched.map { mapOf("id" to it.id, "type" to it.type.rawValue) }
435
- )
405
+ RnIapLog.payload(
406
+ "fetchProducts.native",
407
+ mapOf("skus" to skusList, "type" to queryType.rawValue)
408
+ )
409
+ // Pass the query type through unchanged: the native module resolves
410
+ // ProductQueryType.All itself, so each sku keeps its real product type
411
+ // instead of being shadowed by a per-type not-found placeholder.
412
+ val fetched = openIap.fetchProducts(ProductRequest(skusList, queryType)).productsOrEmpty()
413
+ RnIapLog.result(
414
+ "fetchProducts.native",
415
+ fetched.map { mapOf("id" to it.id, "type" to it.type.rawValue) }
416
+ )
436
417
 
437
- // Preserve input order for non-All queries
438
- val byId = fetched.associateBy { it.id }
439
- skusList.mapNotNull { byId[it] }
440
- }
418
+ // Match the iOS bridge's result shape: preserve input order,
419
+ // drop duplicate skus, then append any fetched products that
420
+ // were not requested.
421
+ val byId = fetched.associateBy { it.id }
422
+ val seenIds = mutableSetOf<String>()
423
+ val orderedProducts = mutableListOf<ProductCommon>()
424
+ skusList.forEach { sku ->
425
+ byId[sku]?.takeIf { seenIds.add(it.id) }?.let(orderedProducts::add)
426
+ }
427
+ fetched.forEach { product ->
428
+ if (seenIds.add(product.id)) orderedProducts.add(product)
441
429
  }
430
+ orderedProducts
442
431
  } catch (e: OpenIapError) {
443
432
  throw OpenIapException(toErrorJson(e))
444
433
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iap",
3
- "version": "15.5.3",
3
+ "version": "15.5.4",
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",
@@ -1,42 +0,0 @@
1
- package com.margelo.nitro.iap
2
-
3
- import dev.hyo.openiap.ProductCommon
4
- import dev.hyo.openiap.ProductQueryType
5
- import kotlin.coroutines.cancellation.CancellationException
6
- import kotlinx.coroutines.async
7
- import kotlinx.coroutines.coroutineScope
8
-
9
- internal suspend fun collectAllQueryProducts(
10
- skusList: List<String>,
11
- fetchKind: suspend (ProductQueryType) -> List<ProductCommon>,
12
- onFailure: (ProductQueryType, Throwable) -> Unit = { _, _ -> },
13
- ): List<ProductCommon> = coroutineScope {
14
- val byId = linkedMapOf<String, ProductCommon>()
15
- var firstFailure: Throwable? = null
16
-
17
- val queries = listOf(ProductQueryType.InApp, ProductQueryType.Subs).map { kind ->
18
- kind to async {
19
- runCatching {
20
- fetchKind(kind)
21
- }
22
- }
23
- }
24
-
25
- queries.forEach { (kind, query) ->
26
- query.await().onSuccess { fetched ->
27
- fetched.forEach { product ->
28
- byId.putIfAbsent(product.id, product)
29
- }
30
- }.onFailure { error ->
31
- if (error is CancellationException) throw error
32
- onFailure(kind, error)
33
- if (firstFailure == null) firstFailure = error
34
- }
35
- }
36
-
37
- if (byId.isEmpty()) {
38
- firstFailure?.let { throw it }
39
- }
40
-
41
- skusList.mapNotNull { byId[it] }
42
- }