From 548bbc8b748da5ab4c525142a1a2556fc5fb7359 Mon Sep 17 00:00:00 2001 From: riteshshukla04 Date: Wed, 1 Oct 2025 23:41:05 +0530 Subject: [PATCH 1/2] Add Network Metrics --- .../margelo/nitro/nitrofetch/NitroFetch.kt | 7 + .../nitro/nitrofetch/NitroFetchClient.kt | 45 ++++++ example/src/App.tsx | 7 + ios/NitroFetchClient.swift | 14 ++ .../android/c++/JEffectiveConnectionType.hpp | 74 ++++++++++ .../c++/JHybridNitroFetchClientSpec.cpp | 13 ++ .../c++/JHybridNitroFetchClientSpec.hpp | 1 + .../android/c++/JNetworkQualityEstimate.hpp | 71 +++++++++ .../nitrofetch/EffectiveConnectionType.kt | 26 ++++ .../nitrofetch/HybridNitroFetchClientSpec.kt | 4 + .../nitrofetch/NetworkQualityEstimate.kt | 41 ++++++ .../android/nitrofetch+autolinking.cmake | 11 +- .../ios/NitroFetch-Swift-Cxx-Bridge.hpp | 30 ++++ .../ios/NitroFetch-Swift-Cxx-Umbrella.hpp | 6 + .../c++/HybridNitroFetchClientSpecSwift.hpp | 14 ++ .../ios/swift/EffectiveConnectionType.swift | 60 ++++++++ .../swift/HybridNitroFetchClientSpec.swift | 1 + .../HybridNitroFetchClientSpec_cxx.swift | 12 ++ .../ios/swift/NetworkQualityEstimate.swift | 139 ++++++++++++++++++ .../shared/c++/EffectiveConnectionType.hpp | 96 ++++++++++++ .../shared/c++/HybridNitroFetchClientSpec.cpp | 1 + .../shared/c++/HybridNitroFetchClientSpec.hpp | 4 + .../shared/c++/NetworkQualityEstimate.hpp | 85 +++++++++++ src/NitroFetch.nitro.ts | 20 +++ src/fetch.ts | 16 ++ src/index.tsx | 3 + 26 files changed, 794 insertions(+), 7 deletions(-) create mode 100644 nitrogen/generated/android/c++/JEffectiveConnectionType.hpp create mode 100644 nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp create mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/EffectiveConnectionType.kt create mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NetworkQualityEstimate.kt create mode 100644 nitrogen/generated/ios/swift/EffectiveConnectionType.swift create mode 100644 nitrogen/generated/ios/swift/NetworkQualityEstimate.swift create mode 100644 nitrogen/generated/shared/c++/EffectiveConnectionType.hpp create mode 100644 nitrogen/generated/shared/c++/NetworkQualityEstimate.hpp diff --git a/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetch.kt b/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetch.kt index 89170c6..8d74810 100644 --- a/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetch.kt +++ b/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetch.kt @@ -44,6 +44,7 @@ class NitroFetch : HybridNitroFetchSpec() { val nativeProvider = providers.firstOrNull { it.name.contains("Native", ignoreCase = true) } val cacheDir = File(app.cacheDir, "nitrofetch_cronet_cache").apply { mkdirs() } + val builder = (nativeProvider?.createBuilder() ?: CronetEngine.Builder(app)) .enableHttp2(true) .enableQuic(true) @@ -51,6 +52,12 @@ class NitroFetch : HybridNitroFetchSpec() { .setStoragePath(cacheDir.absolutePath) .enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, 50 * 1024 * 1024) .setUserAgent("NitroFetch/0.1") + .enableNetworkQualityEstimator(true) + + // Note: NQE experimental options can be configured via setExperimentalOptions() if needed: + // val nqeOptions = """{"NetworkQualityEstimator":{"effective_connection_type_algorithm":"TransportRTTAndDownstreamThroughput"}}""" + // builder.setExperimentalOptions(nqeOptions) + // This requires Cronet 119+ or embedded Cronet with the method available // --- Optional debugging knobs (uncomment temporarily) --- diff --git a/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt b/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt index 9f3d63a..401c599 100644 --- a/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt +++ b/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt @@ -252,5 +252,50 @@ class NitroFetchClient(private val engine: CronetEngine, private val executor: E return promise } + override fun getNetworkQualityEstimate(): NetworkQualityEstimate { + try { + // Note: NQE values are based on observations from actual network requests. + // Values update as the app makes network calls and Cronet learns about network conditions. + + // Get RTT estimates (in milliseconds, -1 if unknown) + val httpRttMs = engine.httpRttMs + val transportRttMs = engine.transportRttMs + + // Get throughput estimates (in kbps, -1 if unknown) + val downstreamKbps = engine.downstreamThroughputKbps + + // Get effective connection type + val effectiveConnectionType = when (engine.effectiveConnectionType) { + CronetEngine.EFFECTIVE_CONNECTION_TYPE_UNKNOWN -> EffectiveConnectionType.UNKNOWN + CronetEngine.EFFECTIVE_CONNECTION_TYPE_OFFLINE -> EffectiveConnectionType.OFFLINE + CronetEngine.EFFECTIVE_CONNECTION_TYPE_SLOW_2G -> EffectiveConnectionType.SLOW_2G + CronetEngine.EFFECTIVE_CONNECTION_TYPE_2G -> EffectiveConnectionType._2G + CronetEngine.EFFECTIVE_CONNECTION_TYPE_3G -> EffectiveConnectionType._3G + CronetEngine.EFFECTIVE_CONNECTION_TYPE_4G -> EffectiveConnectionType._4G + else -> EffectiveConnectionType.UNKNOWN + } + + Log.i("NitroFetchClient", "NQESnapshot - httpRtt: ${httpRttMs}ms, transportRtt: ${transportRttMs}ms, downstream: ${downstreamKbps}kbps, effectiveType: ${effectiveConnectionType}") + + return NetworkQualityEstimate( + downstreamThroughputKbps = if (downstreamKbps != -1) downstreamKbps.toDouble() else null, + upstreamThroughputKbps = null, // Cronet doesn't provide upstream throughput + httpRttMs = if (httpRttMs != -1) httpRttMs.toDouble() else null, + transportRttMs = if (transportRttMs != -1) transportRttMs.toDouble() else null, + effectiveConnectionType = effectiveConnectionType + ) + } catch (e: Exception) { + Log.e("NitroFetchClient", "Error getting network quality estimate", e) + // Return empty estimate on error + return NetworkQualityEstimate( + downstreamThroughputKbps = null, + upstreamThroughputKbps = null, + httpRttMs = null, + transportRttMs = null, + effectiveConnectionType = EffectiveConnectionType.UNKNOWN + ) + } + } + } diff --git a/example/src/App.tsx b/example/src/App.tsx index 8b2470f..c5490b1 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -14,6 +14,7 @@ import { prefetch, prefetchOnAppStart, removeAllFromAutoprefetch, + getNetworkQualityEstimate, } from 'react-native-nitro-fetch'; type Row = { @@ -185,6 +186,12 @@ export default function App() { const loadPrices = React.useCallback(async () => { console.log('Loading crypto prices from coingecko start'); + try{ + const networkQuality = await getNetworkQualityEstimate(); + console.log('Network quality:', networkQuality); + } catch (e: any) { + console.error('Error getting network quality:', e); + } const ids = [ 'bitcoin', 'ethereum', diff --git a/ios/NitroFetchClient.swift b/ios/NitroFetchClient.swift index 91c731e..1a6534e 100644 --- a/ios/NitroFetchClient.swift +++ b/ios/NitroFetchClient.swift @@ -29,6 +29,20 @@ final class NitroFetchClient: HybridNitroFetchClientSpec { return promise } + func getNetworkQualityEstimate() throws -> NetworkQualityEstimate { + // NQE is not supported on iOS yet - requires Cronet integration + NSLog("[NitroFetch] Network Quality Estimator (NQE) is not supported on iOS yet. It will be available once iOS uses Cronet.") + + // Return empty estimate + return NetworkQualityEstimate( + downstreamThroughputKbps: nil, + upstreamThroughputKbps: nil, + httpRttMs: nil, + transportRttMs: nil, + effectiveConnectionType: "unknown" + ) + } + // Shared URLSession for static operations private static let session: URLSession = { let config = URLSessionConfiguration.default diff --git a/nitrogen/generated/android/c++/JEffectiveConnectionType.hpp b/nitrogen/generated/android/c++/JEffectiveConnectionType.hpp new file mode 100644 index 0000000..65a6107 --- /dev/null +++ b/nitrogen/generated/android/c++/JEffectiveConnectionType.hpp @@ -0,0 +1,74 @@ +/// +/// JEffectiveConnectionType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "EffectiveConnectionType.hpp" + +namespace margelo::nitro::nitrofetch { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "EffectiveConnectionType" and the the Kotlin enum "EffectiveConnectionType". + */ + struct JEffectiveConnectionType final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitrofetch/EffectiveConnectionType;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum EffectiveConnectionType. + */ + [[maybe_unused]] + [[nodiscard]] + EffectiveConnectionType toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldOrdinal = clazz->getField("value"); + int ordinal = this->getFieldValue(fieldOrdinal); + return static_cast(ordinal); + } + + public: + /** + * Create a Java/Kotlin-based enum with the given C++ enum's value. + */ + [[maybe_unused]] + static jni::alias_ref fromCpp(EffectiveConnectionType value) { + static const auto clazz = javaClassStatic(); + static const auto fieldUNKNOWN = clazz->getStaticField("UNKNOWN"); + static const auto fieldOFFLINE = clazz->getStaticField("OFFLINE"); + static const auto fieldSLOW_2G = clazz->getStaticField("SLOW_2G"); + static const auto field_2G = clazz->getStaticField("_2G"); + static const auto field_3G = clazz->getStaticField("_3G"); + static const auto field_4G = clazz->getStaticField("_4G"); + static const auto fieldWIFI = clazz->getStaticField("WIFI"); + + switch (value) { + case EffectiveConnectionType::UNKNOWN: + return clazz->getStaticFieldValue(fieldUNKNOWN); + case EffectiveConnectionType::OFFLINE: + return clazz->getStaticFieldValue(fieldOFFLINE); + case EffectiveConnectionType::SLOW_2G: + return clazz->getStaticFieldValue(fieldSLOW_2G); + case EffectiveConnectionType::_2G: + return clazz->getStaticFieldValue(field_2G); + case EffectiveConnectionType::_3G: + return clazz->getStaticFieldValue(field_3G); + case EffectiveConnectionType::_4G: + return clazz->getStaticFieldValue(field_4G); + case EffectiveConnectionType::WIFI: + return clazz->getStaticFieldValue(fieldWIFI); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::nitrofetch diff --git a/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp b/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp index 3351207..714a75e 100644 --- a/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp +++ b/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp @@ -11,6 +11,10 @@ namespace margelo::nitro::nitrofetch { struct NitroResponse; } // Forward declaration of `NitroHeader` to properly resolve imports. namespace margelo::nitro::nitrofetch { struct NitroHeader; } +// Forward declaration of `NetworkQualityEstimate` to properly resolve imports. +namespace margelo::nitro::nitrofetch { struct NetworkQualityEstimate; } +// Forward declaration of `EffectiveConnectionType` to properly resolve imports. +namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } // Forward declaration of `NitroRequest` to properly resolve imports. namespace margelo::nitro::nitrofetch { struct NitroRequest; } // Forward declaration of `NitroRequestMethod` to properly resolve imports. @@ -25,6 +29,10 @@ namespace margelo::nitro::nitrofetch { enum class NitroRequestMethod; } #include #include "JNitroHeader.hpp" #include +#include "NetworkQualityEstimate.hpp" +#include "JNetworkQualityEstimate.hpp" +#include "EffectiveConnectionType.hpp" +#include "JEffectiveConnectionType.hpp" #include "NitroRequest.hpp" #include "JNitroRequest.hpp" #include "NitroRequestMethod.hpp" @@ -87,5 +95,10 @@ namespace margelo::nitro::nitrofetch { return __promise; }(); } + NetworkQualityEstimate JHybridNitroFetchClientSpec::getNetworkQualityEstimate() { + static const auto method = javaClassStatic()->getMethod()>("getNetworkQualityEstimate"); + auto __result = method(_javaPart); + return __result->toCpp(); + } } // namespace margelo::nitro::nitrofetch diff --git a/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.hpp b/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.hpp index b06ff39..c65b1f6 100644 --- a/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.hpp +++ b/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.hpp @@ -55,6 +55,7 @@ namespace margelo::nitro::nitrofetch { // Methods std::shared_ptr> request(const NitroRequest& req) override; std::shared_ptr> prefetch(const NitroRequest& req) override; + NetworkQualityEstimate getNetworkQualityEstimate() override; private: friend HybridBase; diff --git a/nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp b/nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp new file mode 100644 index 0000000..d5366e0 --- /dev/null +++ b/nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp @@ -0,0 +1,71 @@ +/// +/// JNetworkQualityEstimate.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "NetworkQualityEstimate.hpp" + +#include "EffectiveConnectionType.hpp" +#include "JEffectiveConnectionType.hpp" +#include + +namespace margelo::nitro::nitrofetch { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "NetworkQualityEstimate" and the the Kotlin data class "NetworkQualityEstimate". + */ + struct JNetworkQualityEstimate final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitrofetch/NetworkQualityEstimate;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct NetworkQualityEstimate by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + NetworkQualityEstimate toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldDownstreamThroughputKbps = clazz->getField("downstreamThroughputKbps"); + jni::local_ref downstreamThroughputKbps = this->getFieldValue(fieldDownstreamThroughputKbps); + static const auto fieldUpstreamThroughputKbps = clazz->getField("upstreamThroughputKbps"); + jni::local_ref upstreamThroughputKbps = this->getFieldValue(fieldUpstreamThroughputKbps); + static const auto fieldHttpRttMs = clazz->getField("httpRttMs"); + jni::local_ref httpRttMs = this->getFieldValue(fieldHttpRttMs); + static const auto fieldTransportRttMs = clazz->getField("transportRttMs"); + jni::local_ref transportRttMs = this->getFieldValue(fieldTransportRttMs); + static const auto fieldEffectiveConnectionType = clazz->getField("effectiveConnectionType"); + jni::local_ref effectiveConnectionType = this->getFieldValue(fieldEffectiveConnectionType); + return NetworkQualityEstimate( + downstreamThroughputKbps != nullptr ? std::make_optional(downstreamThroughputKbps->value()) : std::nullopt, + upstreamThroughputKbps != nullptr ? std::make_optional(upstreamThroughputKbps->value()) : std::nullopt, + httpRttMs != nullptr ? std::make_optional(httpRttMs->value()) : std::nullopt, + transportRttMs != nullptr ? std::make_optional(transportRttMs->value()) : std::nullopt, + effectiveConnectionType != nullptr ? std::make_optional(effectiveConnectionType->toCpp()) : std::nullopt + ); + } + + public: + /** + * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java. + */ + [[maybe_unused]] + static jni::local_ref fromCpp(const NetworkQualityEstimate& value) { + return newInstance( + value.downstreamThroughputKbps.has_value() ? jni::JDouble::valueOf(value.downstreamThroughputKbps.value()) : nullptr, + value.upstreamThroughputKbps.has_value() ? jni::JDouble::valueOf(value.upstreamThroughputKbps.value()) : nullptr, + value.httpRttMs.has_value() ? jni::JDouble::valueOf(value.httpRttMs.value()) : nullptr, + value.transportRttMs.has_value() ? jni::JDouble::valueOf(value.transportRttMs.value()) : nullptr, + value.effectiveConnectionType.has_value() ? JEffectiveConnectionType::fromCpp(value.effectiveConnectionType.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::nitrofetch diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/EffectiveConnectionType.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/EffectiveConnectionType.kt new file mode 100644 index 0000000..4a2c97f --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/EffectiveConnectionType.kt @@ -0,0 +1,26 @@ +/// +/// EffectiveConnectionType.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.nitrofetch + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "EffectiveConnectionType". + */ +@DoNotStrip +@Keep +enum class EffectiveConnectionType(@DoNotStrip @Keep val value: Int) { + UNKNOWN(0), + OFFLINE(1), + SLOW_2G(2), + _2G(3), + _3G(4), + _4G(5), + WIFI(6); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchClientSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchClientSpec.kt index c6a8cee..7cb4083 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchClientSpec.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchClientSpec.kt @@ -47,6 +47,10 @@ abstract class HybridNitroFetchClientSpec: HybridObject() { @DoNotStrip @Keep abstract fun prefetch(req: NitroRequest): Promise + + @DoNotStrip + @Keep + abstract fun getNetworkQualityEstimate(): NetworkQualityEstimate private external fun initHybrid(): HybridData diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NetworkQualityEstimate.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NetworkQualityEstimate.kt new file mode 100644 index 0000000..a936d29 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NetworkQualityEstimate.kt @@ -0,0 +1,41 @@ +/// +/// NetworkQualityEstimate.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.nitrofetch + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "NetworkQualityEstimate". + */ +@DoNotStrip +@Keep +data class NetworkQualityEstimate + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val downstreamThroughputKbps: Double?, + @DoNotStrip + @Keep + val upstreamThroughputKbps: Double?, + @DoNotStrip + @Keep + val httpRttMs: Double?, + @DoNotStrip + @Keep + val transportRttMs: Double?, + @DoNotStrip + @Keep + val effectiveConnectionType: EffectiveConnectionType? + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/nitrofetch+autolinking.cmake b/nitrogen/generated/android/nitrofetch+autolinking.cmake index 1512532..e44f071 100644 --- a/nitrogen/generated/android/nitrofetch+autolinking.cmake +++ b/nitrogen/generated/android/nitrofetch+autolinking.cmake @@ -13,12 +13,6 @@ # include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/nitrofetch+autolinking.cmake) # ``` -# Define a flag to check if we are building properly -add_definitions(-DBUILDING_NITROFETCH_WITH_GENERATED_CMAKE_PROJECT) - -# Enable Raw Props parsing in react-native (for Nitro Views) -add_definitions(-DRN_SERIALIZABLE_STATE) - # Add all headers that were generated by Nitrogen include_directories( "../nitrogen/generated/shared/c++" @@ -40,9 +34,12 @@ target_sources( ../nitrogen/generated/android/c++/JHybridNitroFetchSpec.cpp ) +# Define a flag to check if we are building properly +add_definitions(-DBUILDING_NITROFETCH_WITH_GENERATED_CMAKE_PROJECT) + # From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake # Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake -target_compile_definitions( + target_compile_definitions( nitrofetch PRIVATE -DFOLLY_NO_CONFIG=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 diff --git a/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp b/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp index cc4a79d..6834399 100644 --- a/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp +++ b/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp @@ -8,10 +8,14 @@ #pragma once // Forward declarations of C++ defined types +// Forward declaration of `EffectiveConnectionType` to properly resolve imports. +namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } // Forward declaration of `HybridNitroFetchClientSpec` to properly resolve imports. namespace margelo::nitro::nitrofetch { class HybridNitroFetchClientSpec; } // Forward declaration of `HybridNitroFetchSpec` to properly resolve imports. namespace margelo::nitro::nitrofetch { class HybridNitroFetchSpec; } +// Forward declaration of `NetworkQualityEstimate` to properly resolve imports. +namespace margelo::nitro::nitrofetch { struct NetworkQualityEstimate; } // Forward declaration of `NitroHeader` to properly resolve imports. namespace margelo::nitro::nitrofetch { struct NitroHeader; } // Forward declaration of `NitroRequestMethod` to properly resolve imports. @@ -26,8 +30,10 @@ namespace NitroFetch { class HybridNitroFetchClientSpec_cxx; } namespace NitroFetch { class HybridNitroFetchSpec_cxx; } // Include C++ defined types +#include "EffectiveConnectionType.hpp" #include "HybridNitroFetchClientSpec.hpp" #include "HybridNitroFetchSpec.hpp" +#include "NetworkQualityEstimate.hpp" #include "NitroHeader.hpp" #include "NitroRequestMethod.hpp" #include "NitroResponse.hpp" @@ -223,6 +229,21 @@ namespace margelo::nitro::nitrofetch::bridge::swift { return Func_void_Wrapper(std::move(value)); } + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_EffectiveConnectionType_ = std::optional; + inline std::optional create_std__optional_EffectiveConnectionType_(const EffectiveConnectionType& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_EffectiveConnectionType_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline EffectiveConnectionType get_std__optional_EffectiveConnectionType_(const std::optional& optional) noexcept { + return *optional; + } + // pragma MARK: std::shared_ptr /** * Specialized version of `std::shared_ptr`. @@ -253,6 +274,15 @@ namespace margelo::nitro::nitrofetch::bridge::swift { return Result>>::withError(error); } + // pragma MARK: Result + using Result_NetworkQualityEstimate_ = Result; + inline Result_NetworkQualityEstimate_ create_Result_NetworkQualityEstimate_(const NetworkQualityEstimate& value) noexcept { + return Result::withValue(value); + } + inline Result_NetworkQualityEstimate_ create_Result_NetworkQualityEstimate_(const std::exception_ptr& error) noexcept { + return Result::withError(error); + } + // pragma MARK: std::shared_ptr /** * Specialized version of `std::shared_ptr`. diff --git a/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp b/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp index cccdc32..634d0fd 100644 --- a/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp +++ b/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp @@ -8,10 +8,14 @@ #pragma once // Forward declarations of C++ defined types +// Forward declaration of `EffectiveConnectionType` to properly resolve imports. +namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } // Forward declaration of `HybridNitroFetchClientSpec` to properly resolve imports. namespace margelo::nitro::nitrofetch { class HybridNitroFetchClientSpec; } // Forward declaration of `HybridNitroFetchSpec` to properly resolve imports. namespace margelo::nitro::nitrofetch { class HybridNitroFetchSpec; } +// Forward declaration of `NetworkQualityEstimate` to properly resolve imports. +namespace margelo::nitro::nitrofetch { struct NetworkQualityEstimate; } // Forward declaration of `NitroHeader` to properly resolve imports. namespace margelo::nitro::nitrofetch { struct NitroHeader; } // Forward declaration of `NitroRequestMethod` to properly resolve imports. @@ -22,8 +26,10 @@ namespace margelo::nitro::nitrofetch { struct NitroRequest; } namespace margelo::nitro::nitrofetch { struct NitroResponse; } // Include C++ defined types +#include "EffectiveConnectionType.hpp" #include "HybridNitroFetchClientSpec.hpp" #include "HybridNitroFetchSpec.hpp" +#include "NetworkQualityEstimate.hpp" #include "NitroHeader.hpp" #include "NitroRequest.hpp" #include "NitroRequestMethod.hpp" diff --git a/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp index 7e0882b..80f3568 100644 --- a/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp +++ b/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp @@ -20,6 +20,10 @@ namespace margelo::nitro::nitrofetch { struct NitroHeader; } namespace margelo::nitro::nitrofetch { struct NitroRequest; } // Forward declaration of `NitroRequestMethod` to properly resolve imports. namespace margelo::nitro::nitrofetch { enum class NitroRequestMethod; } +// Forward declaration of `NetworkQualityEstimate` to properly resolve imports. +namespace margelo::nitro::nitrofetch { struct NetworkQualityEstimate; } +// Forward declaration of `EffectiveConnectionType` to properly resolve imports. +namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } #include "NitroResponse.hpp" #include @@ -29,6 +33,8 @@ namespace margelo::nitro::nitrofetch { enum class NitroRequestMethod; } #include #include "NitroRequest.hpp" #include "NitroRequestMethod.hpp" +#include "NetworkQualityEstimate.hpp" +#include "EffectiveConnectionType.hpp" #include "NitroFetch-Swift-Cxx-Umbrella.hpp" @@ -87,6 +93,14 @@ namespace margelo::nitro::nitrofetch { auto __value = std::move(__result.value()); return __value; } + inline NetworkQualityEstimate getNetworkQualityEstimate() override { + auto __result = _swiftPart.getNetworkQualityEstimate(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } private: NitroFetch::HybridNitroFetchClientSpec_cxx _swiftPart; diff --git a/nitrogen/generated/ios/swift/EffectiveConnectionType.swift b/nitrogen/generated/ios/swift/EffectiveConnectionType.swift new file mode 100644 index 0000000..0f0f8b6 --- /dev/null +++ b/nitrogen/generated/ios/swift/EffectiveConnectionType.swift @@ -0,0 +1,60 @@ +/// +/// EffectiveConnectionType.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `EffectiveConnectionType`, backed by a C++ enum. + */ +public typealias EffectiveConnectionType = margelo.nitro.nitrofetch.EffectiveConnectionType + +public extension EffectiveConnectionType { + /** + * Get a EffectiveConnectionType for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "unknown": + self = .unknown + case "offline": + self = .offline + case "slow-2G": + self = .slow2g + case "2G": + self = .2g + case "3G": + self = .3g + case "4G": + self = .4g + case "wifi": + self = .wifi + default: + return nil + } + } + + /** + * Get the String value this EffectiveConnectionType represents. + */ + var stringValue: String { + switch self { + case .unknown: + return "unknown" + case .offline: + return "offline" + case .slow2g: + return "slow-2G" + case .2g: + return "2G" + case .3g: + return "3G" + case .4g: + return "4G" + case .wifi: + return "wifi" + } + } +} diff --git a/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec.swift b/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec.swift index 1548ec5..aae5ea4 100644 --- a/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec.swift +++ b/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec.swift @@ -16,6 +16,7 @@ public protocol HybridNitroFetchClientSpec_protocol: HybridObject { // Methods func request(req: NitroRequest) throws -> Promise func prefetch(req: NitroRequest) throws -> Promise + func getNetworkQualityEstimate() throws -> NetworkQualityEstimate } /// See ``HybridNitroFetchClientSpec`` diff --git a/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec_cxx.swift index 2cc0866..ffc6798 100644 --- a/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec_cxx.swift +++ b/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec_cxx.swift @@ -146,4 +146,16 @@ open class HybridNitroFetchClientSpec_cxx { return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr) } } + + @inline(__always) + public final func getNetworkQualityEstimate() -> bridge.Result_NetworkQualityEstimate_ { + do { + let __result = try self.__implementation.getNetworkQualityEstimate() + let __resultCpp = __result + return bridge.create_Result_NetworkQualityEstimate_(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_NetworkQualityEstimate_(__exceptionPtr) + } + } } diff --git a/nitrogen/generated/ios/swift/NetworkQualityEstimate.swift b/nitrogen/generated/ios/swift/NetworkQualityEstimate.swift new file mode 100644 index 0000000..1edefa6 --- /dev/null +++ b/nitrogen/generated/ios/swift/NetworkQualityEstimate.swift @@ -0,0 +1,139 @@ +/// +/// NetworkQualityEstimate.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `NetworkQualityEstimate`, backed by a C++ struct. + */ +public typealias NetworkQualityEstimate = margelo.nitro.nitrofetch.NetworkQualityEstimate + +public extension NetworkQualityEstimate { + private typealias bridge = margelo.nitro.nitrofetch.bridge.swift + + /** + * Create a new instance of `NetworkQualityEstimate`. + */ + init(downstreamThroughputKbps: Double?, upstreamThroughputKbps: Double?, httpRttMs: Double?, transportRttMs: Double?, effectiveConnectionType: EffectiveConnectionType?) { + self.init({ () -> bridge.std__optional_double_ in + if let __unwrappedValue = downstreamThroughputKbps { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = upstreamThroughputKbps { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = httpRttMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = transportRttMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_EffectiveConnectionType_ in + if let __unwrappedValue = effectiveConnectionType { + return bridge.create_std__optional_EffectiveConnectionType_(__unwrappedValue) + } else { + return .init() + } + }()) + } + + var downstreamThroughputKbps: Double? { + @inline(__always) + get { + return self.__downstreamThroughputKbps.value + } + @inline(__always) + set { + self.__downstreamThroughputKbps = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var upstreamThroughputKbps: Double? { + @inline(__always) + get { + return self.__upstreamThroughputKbps.value + } + @inline(__always) + set { + self.__upstreamThroughputKbps = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var httpRttMs: Double? { + @inline(__always) + get { + return self.__httpRttMs.value + } + @inline(__always) + set { + self.__httpRttMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var transportRttMs: Double? { + @inline(__always) + get { + return self.__transportRttMs.value + } + @inline(__always) + set { + self.__transportRttMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var effectiveConnectionType: EffectiveConnectionType? { + @inline(__always) + get { + return self.__effectiveConnectionType.value + } + @inline(__always) + set { + self.__effectiveConnectionType = { () -> bridge.std__optional_EffectiveConnectionType_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_EffectiveConnectionType_(__unwrappedValue) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/shared/c++/EffectiveConnectionType.hpp b/nitrogen/generated/shared/c++/EffectiveConnectionType.hpp new file mode 100644 index 0000000..67ca032 --- /dev/null +++ b/nitrogen/generated/shared/c++/EffectiveConnectionType.hpp @@ -0,0 +1,96 @@ +/// +/// EffectiveConnectionType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +namespace margelo::nitro::nitrofetch { + + /** + * An enum which can be represented as a JavaScript union (EffectiveConnectionType). + */ + enum class EffectiveConnectionType { + UNKNOWN SWIFT_NAME(unknown) = 0, + OFFLINE SWIFT_NAME(offline) = 1, + SLOW_2G SWIFT_NAME(slow2g) = 2, + _2G SWIFT_NAME(2g) = 3, + _3G SWIFT_NAME(3g) = 4, + _4G SWIFT_NAME(4g) = 5, + WIFI SWIFT_NAME(wifi) = 6, + } CLOSED_ENUM; + +} // namespace margelo::nitro::nitrofetch + +namespace margelo::nitro { + + // C++ EffectiveConnectionType <> JS EffectiveConnectionType (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::nitrofetch::EffectiveConnectionType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("unknown"): return margelo::nitro::nitrofetch::EffectiveConnectionType::UNKNOWN; + case hashString("offline"): return margelo::nitro::nitrofetch::EffectiveConnectionType::OFFLINE; + case hashString("slow-2G"): return margelo::nitro::nitrofetch::EffectiveConnectionType::SLOW_2G; + case hashString("2G"): return margelo::nitro::nitrofetch::EffectiveConnectionType::_2G; + case hashString("3G"): return margelo::nitro::nitrofetch::EffectiveConnectionType::_3G; + case hashString("4G"): return margelo::nitro::nitrofetch::EffectiveConnectionType::_4G; + case hashString("wifi"): return margelo::nitro::nitrofetch::EffectiveConnectionType::WIFI; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum EffectiveConnectionType - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitrofetch::EffectiveConnectionType arg) { + switch (arg) { + case margelo::nitro::nitrofetch::EffectiveConnectionType::UNKNOWN: return JSIConverter::toJSI(runtime, "unknown"); + case margelo::nitro::nitrofetch::EffectiveConnectionType::OFFLINE: return JSIConverter::toJSI(runtime, "offline"); + case margelo::nitro::nitrofetch::EffectiveConnectionType::SLOW_2G: return JSIConverter::toJSI(runtime, "slow-2G"); + case margelo::nitro::nitrofetch::EffectiveConnectionType::_2G: return JSIConverter::toJSI(runtime, "2G"); + case margelo::nitro::nitrofetch::EffectiveConnectionType::_3G: return JSIConverter::toJSI(runtime, "3G"); + case margelo::nitro::nitrofetch::EffectiveConnectionType::_4G: return JSIConverter::toJSI(runtime, "4G"); + case margelo::nitro::nitrofetch::EffectiveConnectionType::WIFI: return JSIConverter::toJSI(runtime, "wifi"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert EffectiveConnectionType to JS - invalid value: " + + std::to_string(static_cast(arg)) + "!"); + } + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isString()) { + return false; + } + std::string unionValue = JSIConverter::fromJSI(runtime, value); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("unknown"): + case hashString("offline"): + case hashString("slow-2G"): + case hashString("2G"): + case hashString("3G"): + case hashString("4G"): + case hashString("wifi"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.cpp b/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.cpp index 1540766..08c1509 100644 --- a/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.cpp +++ b/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.cpp @@ -16,6 +16,7 @@ namespace margelo::nitro::nitrofetch { registerHybrids(this, [](Prototype& prototype) { prototype.registerHybridMethod("request", &HybridNitroFetchClientSpec::request); prototype.registerHybridMethod("prefetch", &HybridNitroFetchClientSpec::prefetch); + prototype.registerHybridMethod("getNetworkQualityEstimate", &HybridNitroFetchClientSpec::getNetworkQualityEstimate); }); } diff --git a/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.hpp b/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.hpp index 936fff5..0f73050 100644 --- a/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.hpp +++ b/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.hpp @@ -17,10 +17,13 @@ namespace margelo::nitro::nitrofetch { struct NitroResponse; } // Forward declaration of `NitroRequest` to properly resolve imports. namespace margelo::nitro::nitrofetch { struct NitroRequest; } +// Forward declaration of `NetworkQualityEstimate` to properly resolve imports. +namespace margelo::nitro::nitrofetch { struct NetworkQualityEstimate; } #include "NitroResponse.hpp" #include #include "NitroRequest.hpp" +#include "NetworkQualityEstimate.hpp" namespace margelo::nitro::nitrofetch { @@ -55,6 +58,7 @@ namespace margelo::nitro::nitrofetch { // Methods virtual std::shared_ptr> request(const NitroRequest& req) = 0; virtual std::shared_ptr> prefetch(const NitroRequest& req) = 0; + virtual NetworkQualityEstimate getNetworkQualityEstimate() = 0; protected: // Hybrid Setup diff --git a/nitrogen/generated/shared/c++/NetworkQualityEstimate.hpp b/nitrogen/generated/shared/c++/NetworkQualityEstimate.hpp new file mode 100644 index 0000000..66084d1 --- /dev/null +++ b/nitrogen/generated/shared/c++/NetworkQualityEstimate.hpp @@ -0,0 +1,85 @@ +/// +/// NetworkQualityEstimate.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `EffectiveConnectionType` to properly resolve imports. +namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } + +#include +#include "EffectiveConnectionType.hpp" + +namespace margelo::nitro::nitrofetch { + + /** + * A struct which can be represented as a JavaScript object (NetworkQualityEstimate). + */ + struct NetworkQualityEstimate { + public: + std::optional downstreamThroughputKbps SWIFT_PRIVATE; + std::optional upstreamThroughputKbps SWIFT_PRIVATE; + std::optional httpRttMs SWIFT_PRIVATE; + std::optional transportRttMs SWIFT_PRIVATE; + std::optional effectiveConnectionType SWIFT_PRIVATE; + + public: + NetworkQualityEstimate() = default; + explicit NetworkQualityEstimate(std::optional downstreamThroughputKbps, std::optional upstreamThroughputKbps, std::optional httpRttMs, std::optional transportRttMs, std::optional effectiveConnectionType): downstreamThroughputKbps(downstreamThroughputKbps), upstreamThroughputKbps(upstreamThroughputKbps), httpRttMs(httpRttMs), transportRttMs(transportRttMs), effectiveConnectionType(effectiveConnectionType) {} + }; + +} // namespace margelo::nitro::nitrofetch + +namespace margelo::nitro { + + // C++ NetworkQualityEstimate <> JS NetworkQualityEstimate (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::nitrofetch::NetworkQualityEstimate fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::nitrofetch::NetworkQualityEstimate( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "downstreamThroughputKbps")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "upstreamThroughputKbps")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "httpRttMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "transportRttMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "effectiveConnectionType")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::nitrofetch::NetworkQualityEstimate& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "downstreamThroughputKbps", JSIConverter>::toJSI(runtime, arg.downstreamThroughputKbps)); + obj.setProperty(runtime, "upstreamThroughputKbps", JSIConverter>::toJSI(runtime, arg.upstreamThroughputKbps)); + obj.setProperty(runtime, "httpRttMs", JSIConverter>::toJSI(runtime, arg.httpRttMs)); + obj.setProperty(runtime, "transportRttMs", JSIConverter>::toJSI(runtime, arg.transportRttMs)); + obj.setProperty(runtime, "effectiveConnectionType", JSIConverter>::toJSI(runtime, arg.effectiveConnectionType)); + return obj; + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "downstreamThroughputKbps"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "upstreamThroughputKbps"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "httpRttMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "transportRttMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "effectiveConnectionType"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/src/NitroFetch.nitro.ts b/src/NitroFetch.nitro.ts index b44cbff..e68fe8e 100644 --- a/src/NitroFetch.nitro.ts +++ b/src/NitroFetch.nitro.ts @@ -39,12 +39,32 @@ export interface NitroResponse { bodyBytes?: string; //will be ArrayBuffer in future } +export enum EffectiveConnectionType { + UNKNOWN = 'unknown', + OFFLINE = 'offline', + SLOW_2G = 'slow-2G', + TWO_G = '2G', + THREE_G = '3G', + FOUR_G = '4G', + WIFI = 'wifi', +} + +export interface NetworkQualityEstimate { + downstreamThroughputKbps?: number; + upstreamThroughputKbps?: number; + httpRttMs?: number; + transportRttMs?: number; + effectiveConnectionType?: EffectiveConnectionType; +} + export interface NitroFetchClient extends HybridObject<{ ios: 'swift'; android: 'kotlin'; }> { // Client-binded request that uses the env configured at creation. request(req: NitroRequest): Promise; // Start a prefetch for a given request; expects a header `prefetchKey`. prefetch(req: NitroRequest): Promise; + // Get network quality estimate from Cronet (Android only, uses Network Quality Estimator) + getNetworkQualityEstimate(): NetworkQualityEstimate; } export interface NitroFetch diff --git a/src/fetch.ts b/src/fetch.ts index a9e67ec..d09ca0d 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -294,6 +294,22 @@ export async function removeAllFromAutoprefetch(): Promise { } } +// Get network quality estimate from Cronet's Network Quality Estimator +export function getNetworkQualityEstimate() { + const hasNative = typeof (NitroFetchHybrid as any)?.createClient === 'function'; + if (!hasNative) { + throw new Error('NitroFetch native module not available'); + } + + // Create a fresh client to get the latest network quality estimate + const freshClient = NitroFetchHybrid.createClient(); + if (!freshClient || typeof (freshClient as any).getNetworkQualityEstimate !== 'function') { + throw new Error('getNetworkQualityEstimate not supported'); + } + + return freshClient.getNetworkQualityEstimate(); +} + // Optional off-thread processing using react-native-worklets-core export type NitroWorkletMapper = (payload: { url: string; diff --git a/src/index.tsx b/src/index.tsx index 6b911d2..d0ff81e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,8 +5,11 @@ export { prefetchOnAppStart, removeFromAutoPrefetch, removeAllFromAutoprefetch, + getNetworkQualityEstimate, } from './fetch'; export type { NitroRequest, NitroResponse } from './fetch'; +export type { NetworkQualityEstimate } from './NitroFetch.nitro'; +export { EffectiveConnectionType } from './NitroFetch.nitro'; export { NitroFetch } from './NitroInstances'; import './fetch'; From 11c00025fdc7dc952c5239172dad1da9a73c60d6 Mon Sep 17 00:00:00 2001 From: riteshshukla04 Date: Thu, 2 Oct 2025 00:19:37 +0530 Subject: [PATCH 2/2] Add Network Metrics --- .../nitro/nitrofetch/NitroFetchClient.kt | 16 ++-- example/ios/Podfile.lock | 4 +- .../android/c++/JEffectiveConnectionType.hpp | 74 -------------- .../c++/JHybridNitroFetchClientSpec.cpp | 4 - .../android/c++/JNetworkQualityEstimate.hpp | 11 +-- .../nitrofetch/EffectiveConnectionType.kt | 26 ----- .../nitrofetch/NetworkQualityEstimate.kt | 2 +- .../ios/NitroFetch-Swift-Cxx-Bridge.hpp | 18 ---- .../ios/NitroFetch-Swift-Cxx-Umbrella.hpp | 3 - .../c++/HybridNitroFetchClientSpecSwift.hpp | 3 - .../ios/swift/EffectiveConnectionType.swift | 60 ------------ .../ios/swift/NetworkQualityEstimate.swift | 21 ++-- .../shared/c++/EffectiveConnectionType.hpp | 96 ------------------- .../shared/c++/NetworkQualityEstimate.hpp | 15 ++- src/NitroFetch.nitro.ts | 12 +-- src/index.tsx | 1 - 16 files changed, 38 insertions(+), 328 deletions(-) delete mode 100644 nitrogen/generated/android/c++/JEffectiveConnectionType.hpp delete mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/EffectiveConnectionType.kt delete mode 100644 nitrogen/generated/ios/swift/EffectiveConnectionType.swift delete mode 100644 nitrogen/generated/shared/c++/EffectiveConnectionType.hpp diff --git a/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt b/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt index 401c599..2b751da 100644 --- a/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt +++ b/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt @@ -266,13 +266,13 @@ class NitroFetchClient(private val engine: CronetEngine, private val executor: E // Get effective connection type val effectiveConnectionType = when (engine.effectiveConnectionType) { - CronetEngine.EFFECTIVE_CONNECTION_TYPE_UNKNOWN -> EffectiveConnectionType.UNKNOWN - CronetEngine.EFFECTIVE_CONNECTION_TYPE_OFFLINE -> EffectiveConnectionType.OFFLINE - CronetEngine.EFFECTIVE_CONNECTION_TYPE_SLOW_2G -> EffectiveConnectionType.SLOW_2G - CronetEngine.EFFECTIVE_CONNECTION_TYPE_2G -> EffectiveConnectionType._2G - CronetEngine.EFFECTIVE_CONNECTION_TYPE_3G -> EffectiveConnectionType._3G - CronetEngine.EFFECTIVE_CONNECTION_TYPE_4G -> EffectiveConnectionType._4G - else -> EffectiveConnectionType.UNKNOWN + CronetEngine.EFFECTIVE_CONNECTION_TYPE_UNKNOWN -> "unknown" + CronetEngine.EFFECTIVE_CONNECTION_TYPE_OFFLINE -> "offline" + CronetEngine.EFFECTIVE_CONNECTION_TYPE_SLOW_2G -> "slow-2G" + CronetEngine.EFFECTIVE_CONNECTION_TYPE_2G -> "2G" + CronetEngine.EFFECTIVE_CONNECTION_TYPE_3G -> "3G" + CronetEngine.EFFECTIVE_CONNECTION_TYPE_4G -> "4G" + else -> "unknown" } Log.i("NitroFetchClient", "NQESnapshot - httpRtt: ${httpRttMs}ms, transportRtt: ${transportRttMs}ms, downstream: ${downstreamKbps}kbps, effectiveType: ${effectiveConnectionType}") @@ -292,7 +292,7 @@ class NitroFetchClient(private val engine: CronetEngine, private val executor: E upstreamThroughputKbps = null, httpRttMs = null, transportRttMs = null, - effectiveConnectionType = EffectiveConnectionType.UNKNOWN + effectiveConnectionType = "unknown" ) } } diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index e52777e..17cd235 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -8,7 +8,7 @@ PODS: - hermes-engine (0.81.0): - hermes-engine/Pre-built (= 0.81.0) - hermes-engine/Pre-built (0.81.0) - - NitroFetch (0.1.1): + - NitroFetch (0.1.3): - boost - DoubleConversion - fast_float @@ -2644,7 +2644,7 @@ SPEC CHECKSUMS: fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: e7491a2038f2618c8cd444ed411a6deb350a3742 - NitroFetch: 3653fb32c838befe759159a7b22e83a89344b191 + NitroFetch: d99e3c3dad9f70317525c4fad230dff507857720 NitroModules: 33aca4acd8fd5c2a29dc99976680cd99e7263573 RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 RCTDeprecation: 0735ab4f6b3ec93a7f98187b5da74d7916e2cf4c diff --git a/nitrogen/generated/android/c++/JEffectiveConnectionType.hpp b/nitrogen/generated/android/c++/JEffectiveConnectionType.hpp deleted file mode 100644 index 65a6107..0000000 --- a/nitrogen/generated/android/c++/JEffectiveConnectionType.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/// -/// JEffectiveConnectionType.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2025 Marc Rousavy @ Margelo -/// - -#pragma once - -#include -#include "EffectiveConnectionType.hpp" - -namespace margelo::nitro::nitrofetch { - - using namespace facebook; - - /** - * The C++ JNI bridge between the C++ enum "EffectiveConnectionType" and the the Kotlin enum "EffectiveConnectionType". - */ - struct JEffectiveConnectionType final: public jni::JavaClass { - public: - static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitrofetch/EffectiveConnectionType;"; - - public: - /** - * Convert this Java/Kotlin-based enum to the C++ enum EffectiveConnectionType. - */ - [[maybe_unused]] - [[nodiscard]] - EffectiveConnectionType toCpp() const { - static const auto clazz = javaClassStatic(); - static const auto fieldOrdinal = clazz->getField("value"); - int ordinal = this->getFieldValue(fieldOrdinal); - return static_cast(ordinal); - } - - public: - /** - * Create a Java/Kotlin-based enum with the given C++ enum's value. - */ - [[maybe_unused]] - static jni::alias_ref fromCpp(EffectiveConnectionType value) { - static const auto clazz = javaClassStatic(); - static const auto fieldUNKNOWN = clazz->getStaticField("UNKNOWN"); - static const auto fieldOFFLINE = clazz->getStaticField("OFFLINE"); - static const auto fieldSLOW_2G = clazz->getStaticField("SLOW_2G"); - static const auto field_2G = clazz->getStaticField("_2G"); - static const auto field_3G = clazz->getStaticField("_3G"); - static const auto field_4G = clazz->getStaticField("_4G"); - static const auto fieldWIFI = clazz->getStaticField("WIFI"); - - switch (value) { - case EffectiveConnectionType::UNKNOWN: - return clazz->getStaticFieldValue(fieldUNKNOWN); - case EffectiveConnectionType::OFFLINE: - return clazz->getStaticFieldValue(fieldOFFLINE); - case EffectiveConnectionType::SLOW_2G: - return clazz->getStaticFieldValue(fieldSLOW_2G); - case EffectiveConnectionType::_2G: - return clazz->getStaticFieldValue(field_2G); - case EffectiveConnectionType::_3G: - return clazz->getStaticFieldValue(field_3G); - case EffectiveConnectionType::_4G: - return clazz->getStaticFieldValue(field_4G); - case EffectiveConnectionType::WIFI: - return clazz->getStaticFieldValue(fieldWIFI); - default: - std::string stringValue = std::to_string(static_cast(value)); - throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); - } - } - }; - -} // namespace margelo::nitro::nitrofetch diff --git a/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp b/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp index 714a75e..df4485c 100644 --- a/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp +++ b/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp @@ -13,8 +13,6 @@ namespace margelo::nitro::nitrofetch { struct NitroResponse; } namespace margelo::nitro::nitrofetch { struct NitroHeader; } // Forward declaration of `NetworkQualityEstimate` to properly resolve imports. namespace margelo::nitro::nitrofetch { struct NetworkQualityEstimate; } -// Forward declaration of `EffectiveConnectionType` to properly resolve imports. -namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } // Forward declaration of `NitroRequest` to properly resolve imports. namespace margelo::nitro::nitrofetch { struct NitroRequest; } // Forward declaration of `NitroRequestMethod` to properly resolve imports. @@ -31,8 +29,6 @@ namespace margelo::nitro::nitrofetch { enum class NitroRequestMethod; } #include #include "NetworkQualityEstimate.hpp" #include "JNetworkQualityEstimate.hpp" -#include "EffectiveConnectionType.hpp" -#include "JEffectiveConnectionType.hpp" #include "NitroRequest.hpp" #include "JNitroRequest.hpp" #include "NitroRequestMethod.hpp" diff --git a/nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp b/nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp index d5366e0..b9cd94b 100644 --- a/nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp +++ b/nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp @@ -10,9 +10,8 @@ #include #include "NetworkQualityEstimate.hpp" -#include "EffectiveConnectionType.hpp" -#include "JEffectiveConnectionType.hpp" #include +#include namespace margelo::nitro::nitrofetch { @@ -41,14 +40,14 @@ namespace margelo::nitro::nitrofetch { jni::local_ref httpRttMs = this->getFieldValue(fieldHttpRttMs); static const auto fieldTransportRttMs = clazz->getField("transportRttMs"); jni::local_ref transportRttMs = this->getFieldValue(fieldTransportRttMs); - static const auto fieldEffectiveConnectionType = clazz->getField("effectiveConnectionType"); - jni::local_ref effectiveConnectionType = this->getFieldValue(fieldEffectiveConnectionType); + static const auto fieldEffectiveConnectionType = clazz->getField("effectiveConnectionType"); + jni::local_ref effectiveConnectionType = this->getFieldValue(fieldEffectiveConnectionType); return NetworkQualityEstimate( downstreamThroughputKbps != nullptr ? std::make_optional(downstreamThroughputKbps->value()) : std::nullopt, upstreamThroughputKbps != nullptr ? std::make_optional(upstreamThroughputKbps->value()) : std::nullopt, httpRttMs != nullptr ? std::make_optional(httpRttMs->value()) : std::nullopt, transportRttMs != nullptr ? std::make_optional(transportRttMs->value()) : std::nullopt, - effectiveConnectionType != nullptr ? std::make_optional(effectiveConnectionType->toCpp()) : std::nullopt + effectiveConnectionType != nullptr ? std::make_optional(effectiveConnectionType->toStdString()) : std::nullopt ); } @@ -63,7 +62,7 @@ namespace margelo::nitro::nitrofetch { value.upstreamThroughputKbps.has_value() ? jni::JDouble::valueOf(value.upstreamThroughputKbps.value()) : nullptr, value.httpRttMs.has_value() ? jni::JDouble::valueOf(value.httpRttMs.value()) : nullptr, value.transportRttMs.has_value() ? jni::JDouble::valueOf(value.transportRttMs.value()) : nullptr, - value.effectiveConnectionType.has_value() ? JEffectiveConnectionType::fromCpp(value.effectiveConnectionType.value()) : nullptr + value.effectiveConnectionType.has_value() ? jni::make_jstring(value.effectiveConnectionType.value()) : nullptr ); } }; diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/EffectiveConnectionType.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/EffectiveConnectionType.kt deleted file mode 100644 index 4a2c97f..0000000 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/EffectiveConnectionType.kt +++ /dev/null @@ -1,26 +0,0 @@ -/// -/// EffectiveConnectionType.kt -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2025 Marc Rousavy @ Margelo -/// - -package com.margelo.nitro.nitrofetch - -import androidx.annotation.Keep -import com.facebook.proguard.annotations.DoNotStrip - -/** - * Represents the JavaScript enum/union "EffectiveConnectionType". - */ -@DoNotStrip -@Keep -enum class EffectiveConnectionType(@DoNotStrip @Keep val value: Int) { - UNKNOWN(0), - OFFLINE(1), - SLOW_2G(2), - _2G(3), - _3G(4), - _4G(5), - WIFI(6); -} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NetworkQualityEstimate.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NetworkQualityEstimate.kt index a936d29..6687802 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NetworkQualityEstimate.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NetworkQualityEstimate.kt @@ -35,7 +35,7 @@ data class NetworkQualityEstimate val transportRttMs: Double?, @DoNotStrip @Keep - val effectiveConnectionType: EffectiveConnectionType? + val effectiveConnectionType: String? ) { /* main constructor */ } diff --git a/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp b/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp index 6834399..2434016 100644 --- a/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp +++ b/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp @@ -8,8 +8,6 @@ #pragma once // Forward declarations of C++ defined types -// Forward declaration of `EffectiveConnectionType` to properly resolve imports. -namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } // Forward declaration of `HybridNitroFetchClientSpec` to properly resolve imports. namespace margelo::nitro::nitrofetch { class HybridNitroFetchClientSpec; } // Forward declaration of `HybridNitroFetchSpec` to properly resolve imports. @@ -30,7 +28,6 @@ namespace NitroFetch { class HybridNitroFetchClientSpec_cxx; } namespace NitroFetch { class HybridNitroFetchSpec_cxx; } // Include C++ defined types -#include "EffectiveConnectionType.hpp" #include "HybridNitroFetchClientSpec.hpp" #include "HybridNitroFetchSpec.hpp" #include "NetworkQualityEstimate.hpp" @@ -229,21 +226,6 @@ namespace margelo::nitro::nitrofetch::bridge::swift { return Func_void_Wrapper(std::move(value)); } - // pragma MARK: std::optional - /** - * Specialized version of `std::optional`. - */ - using std__optional_EffectiveConnectionType_ = std::optional; - inline std::optional create_std__optional_EffectiveConnectionType_(const EffectiveConnectionType& value) noexcept { - return std::optional(value); - } - inline bool has_value_std__optional_EffectiveConnectionType_(const std::optional& optional) noexcept { - return optional.has_value(); - } - inline EffectiveConnectionType get_std__optional_EffectiveConnectionType_(const std::optional& optional) noexcept { - return *optional; - } - // pragma MARK: std::shared_ptr /** * Specialized version of `std::shared_ptr`. diff --git a/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp b/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp index 634d0fd..2cb3a02 100644 --- a/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp +++ b/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp @@ -8,8 +8,6 @@ #pragma once // Forward declarations of C++ defined types -// Forward declaration of `EffectiveConnectionType` to properly resolve imports. -namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } // Forward declaration of `HybridNitroFetchClientSpec` to properly resolve imports. namespace margelo::nitro::nitrofetch { class HybridNitroFetchClientSpec; } // Forward declaration of `HybridNitroFetchSpec` to properly resolve imports. @@ -26,7 +24,6 @@ namespace margelo::nitro::nitrofetch { struct NitroRequest; } namespace margelo::nitro::nitrofetch { struct NitroResponse; } // Include C++ defined types -#include "EffectiveConnectionType.hpp" #include "HybridNitroFetchClientSpec.hpp" #include "HybridNitroFetchSpec.hpp" #include "NetworkQualityEstimate.hpp" diff --git a/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp index 80f3568..5bf989b 100644 --- a/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp +++ b/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp @@ -22,8 +22,6 @@ namespace margelo::nitro::nitrofetch { struct NitroRequest; } namespace margelo::nitro::nitrofetch { enum class NitroRequestMethod; } // Forward declaration of `NetworkQualityEstimate` to properly resolve imports. namespace margelo::nitro::nitrofetch { struct NetworkQualityEstimate; } -// Forward declaration of `EffectiveConnectionType` to properly resolve imports. -namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } #include "NitroResponse.hpp" #include @@ -34,7 +32,6 @@ namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } #include "NitroRequest.hpp" #include "NitroRequestMethod.hpp" #include "NetworkQualityEstimate.hpp" -#include "EffectiveConnectionType.hpp" #include "NitroFetch-Swift-Cxx-Umbrella.hpp" diff --git a/nitrogen/generated/ios/swift/EffectiveConnectionType.swift b/nitrogen/generated/ios/swift/EffectiveConnectionType.swift deleted file mode 100644 index 0f0f8b6..0000000 --- a/nitrogen/generated/ios/swift/EffectiveConnectionType.swift +++ /dev/null @@ -1,60 +0,0 @@ -/// -/// EffectiveConnectionType.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2025 Marc Rousavy @ Margelo -/// - -/** - * Represents the JS union `EffectiveConnectionType`, backed by a C++ enum. - */ -public typealias EffectiveConnectionType = margelo.nitro.nitrofetch.EffectiveConnectionType - -public extension EffectiveConnectionType { - /** - * Get a EffectiveConnectionType for the given String value, or - * return `nil` if the given value was invalid/unknown. - */ - init?(fromString string: String) { - switch string { - case "unknown": - self = .unknown - case "offline": - self = .offline - case "slow-2G": - self = .slow2g - case "2G": - self = .2g - case "3G": - self = .3g - case "4G": - self = .4g - case "wifi": - self = .wifi - default: - return nil - } - } - - /** - * Get the String value this EffectiveConnectionType represents. - */ - var stringValue: String { - switch self { - case .unknown: - return "unknown" - case .offline: - return "offline" - case .slow2g: - return "slow-2G" - case .2g: - return "2G" - case .3g: - return "3G" - case .4g: - return "4G" - case .wifi: - return "wifi" - } - } -} diff --git a/nitrogen/generated/ios/swift/NetworkQualityEstimate.swift b/nitrogen/generated/ios/swift/NetworkQualityEstimate.swift index 1edefa6..1ebb1dd 100644 --- a/nitrogen/generated/ios/swift/NetworkQualityEstimate.swift +++ b/nitrogen/generated/ios/swift/NetworkQualityEstimate.swift @@ -18,7 +18,7 @@ public extension NetworkQualityEstimate { /** * Create a new instance of `NetworkQualityEstimate`. */ - init(downstreamThroughputKbps: Double?, upstreamThroughputKbps: Double?, httpRttMs: Double?, transportRttMs: Double?, effectiveConnectionType: EffectiveConnectionType?) { + init(downstreamThroughputKbps: Double?, upstreamThroughputKbps: Double?, httpRttMs: Double?, transportRttMs: Double?, effectiveConnectionType: String?) { self.init({ () -> bridge.std__optional_double_ in if let __unwrappedValue = downstreamThroughputKbps { return bridge.create_std__optional_double_(__unwrappedValue) @@ -43,9 +43,9 @@ public extension NetworkQualityEstimate { } else { return .init() } - }(), { () -> bridge.std__optional_EffectiveConnectionType_ in + }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = effectiveConnectionType { - return bridge.create_std__optional_EffectiveConnectionType_(__unwrappedValue) + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } @@ -120,16 +120,23 @@ public extension NetworkQualityEstimate { } } - var effectiveConnectionType: EffectiveConnectionType? { + var effectiveConnectionType: String? { @inline(__always) get { - return self.__effectiveConnectionType.value + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__effectiveConnectionType) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__effectiveConnectionType) + return String(__unwrapped) + } else { + return nil + } + }() } @inline(__always) set { - self.__effectiveConnectionType = { () -> bridge.std__optional_EffectiveConnectionType_ in + self.__effectiveConnectionType = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { - return bridge.create_std__optional_EffectiveConnectionType_(__unwrappedValue) + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } diff --git a/nitrogen/generated/shared/c++/EffectiveConnectionType.hpp b/nitrogen/generated/shared/c++/EffectiveConnectionType.hpp deleted file mode 100644 index 67ca032..0000000 --- a/nitrogen/generated/shared/c++/EffectiveConnectionType.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/// -/// EffectiveConnectionType.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2025 Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -namespace margelo::nitro::nitrofetch { - - /** - * An enum which can be represented as a JavaScript union (EffectiveConnectionType). - */ - enum class EffectiveConnectionType { - UNKNOWN SWIFT_NAME(unknown) = 0, - OFFLINE SWIFT_NAME(offline) = 1, - SLOW_2G SWIFT_NAME(slow2g) = 2, - _2G SWIFT_NAME(2g) = 3, - _3G SWIFT_NAME(3g) = 4, - _4G SWIFT_NAME(4g) = 5, - WIFI SWIFT_NAME(wifi) = 6, - } CLOSED_ENUM; - -} // namespace margelo::nitro::nitrofetch - -namespace margelo::nitro { - - // C++ EffectiveConnectionType <> JS EffectiveConnectionType (union) - template <> - struct JSIConverter final { - static inline margelo::nitro::nitrofetch::EffectiveConnectionType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - std::string unionValue = JSIConverter::fromJSI(runtime, arg); - switch (hashString(unionValue.c_str(), unionValue.size())) { - case hashString("unknown"): return margelo::nitro::nitrofetch::EffectiveConnectionType::UNKNOWN; - case hashString("offline"): return margelo::nitro::nitrofetch::EffectiveConnectionType::OFFLINE; - case hashString("slow-2G"): return margelo::nitro::nitrofetch::EffectiveConnectionType::SLOW_2G; - case hashString("2G"): return margelo::nitro::nitrofetch::EffectiveConnectionType::_2G; - case hashString("3G"): return margelo::nitro::nitrofetch::EffectiveConnectionType::_3G; - case hashString("4G"): return margelo::nitro::nitrofetch::EffectiveConnectionType::_4G; - case hashString("wifi"): return margelo::nitro::nitrofetch::EffectiveConnectionType::WIFI; - default: [[unlikely]] - throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum EffectiveConnectionType - invalid value!"); - } - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitrofetch::EffectiveConnectionType arg) { - switch (arg) { - case margelo::nitro::nitrofetch::EffectiveConnectionType::UNKNOWN: return JSIConverter::toJSI(runtime, "unknown"); - case margelo::nitro::nitrofetch::EffectiveConnectionType::OFFLINE: return JSIConverter::toJSI(runtime, "offline"); - case margelo::nitro::nitrofetch::EffectiveConnectionType::SLOW_2G: return JSIConverter::toJSI(runtime, "slow-2G"); - case margelo::nitro::nitrofetch::EffectiveConnectionType::_2G: return JSIConverter::toJSI(runtime, "2G"); - case margelo::nitro::nitrofetch::EffectiveConnectionType::_3G: return JSIConverter::toJSI(runtime, "3G"); - case margelo::nitro::nitrofetch::EffectiveConnectionType::_4G: return JSIConverter::toJSI(runtime, "4G"); - case margelo::nitro::nitrofetch::EffectiveConnectionType::WIFI: return JSIConverter::toJSI(runtime, "wifi"); - default: [[unlikely]] - throw std::invalid_argument("Cannot convert EffectiveConnectionType to JS - invalid value: " - + std::to_string(static_cast(arg)) + "!"); - } - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isString()) { - return false; - } - std::string unionValue = JSIConverter::fromJSI(runtime, value); - switch (hashString(unionValue.c_str(), unionValue.size())) { - case hashString("unknown"): - case hashString("offline"): - case hashString("slow-2G"): - case hashString("2G"): - case hashString("3G"): - case hashString("4G"): - case hashString("wifi"): - return true; - default: - return false; - } - } - }; - -} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/NetworkQualityEstimate.hpp b/nitrogen/generated/shared/c++/NetworkQualityEstimate.hpp index 66084d1..cd1fd8b 100644 --- a/nitrogen/generated/shared/c++/NetworkQualityEstimate.hpp +++ b/nitrogen/generated/shared/c++/NetworkQualityEstimate.hpp @@ -18,11 +18,10 @@ #error NitroModules cannot be found! Are you sure you installed NitroModules properly? #endif -// Forward declaration of `EffectiveConnectionType` to properly resolve imports. -namespace margelo::nitro::nitrofetch { enum class EffectiveConnectionType; } + #include -#include "EffectiveConnectionType.hpp" +#include namespace margelo::nitro::nitrofetch { @@ -35,11 +34,11 @@ namespace margelo::nitro::nitrofetch { std::optional upstreamThroughputKbps SWIFT_PRIVATE; std::optional httpRttMs SWIFT_PRIVATE; std::optional transportRttMs SWIFT_PRIVATE; - std::optional effectiveConnectionType SWIFT_PRIVATE; + std::optional effectiveConnectionType SWIFT_PRIVATE; public: NetworkQualityEstimate() = default; - explicit NetworkQualityEstimate(std::optional downstreamThroughputKbps, std::optional upstreamThroughputKbps, std::optional httpRttMs, std::optional transportRttMs, std::optional effectiveConnectionType): downstreamThroughputKbps(downstreamThroughputKbps), upstreamThroughputKbps(upstreamThroughputKbps), httpRttMs(httpRttMs), transportRttMs(transportRttMs), effectiveConnectionType(effectiveConnectionType) {} + explicit NetworkQualityEstimate(std::optional downstreamThroughputKbps, std::optional upstreamThroughputKbps, std::optional httpRttMs, std::optional transportRttMs, std::optional effectiveConnectionType): downstreamThroughputKbps(downstreamThroughputKbps), upstreamThroughputKbps(upstreamThroughputKbps), httpRttMs(httpRttMs), transportRttMs(transportRttMs), effectiveConnectionType(effectiveConnectionType) {} }; } // namespace margelo::nitro::nitrofetch @@ -56,7 +55,7 @@ namespace margelo::nitro { JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "upstreamThroughputKbps")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "httpRttMs")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "transportRttMs")), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "effectiveConnectionType")) + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "effectiveConnectionType")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::nitrofetch::NetworkQualityEstimate& arg) { @@ -65,7 +64,7 @@ namespace margelo::nitro { obj.setProperty(runtime, "upstreamThroughputKbps", JSIConverter>::toJSI(runtime, arg.upstreamThroughputKbps)); obj.setProperty(runtime, "httpRttMs", JSIConverter>::toJSI(runtime, arg.httpRttMs)); obj.setProperty(runtime, "transportRttMs", JSIConverter>::toJSI(runtime, arg.transportRttMs)); - obj.setProperty(runtime, "effectiveConnectionType", JSIConverter>::toJSI(runtime, arg.effectiveConnectionType)); + obj.setProperty(runtime, "effectiveConnectionType", JSIConverter>::toJSI(runtime, arg.effectiveConnectionType)); return obj; } static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { @@ -77,7 +76,7 @@ namespace margelo::nitro { if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "upstreamThroughputKbps"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "httpRttMs"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "transportRttMs"))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "effectiveConnectionType"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "effectiveConnectionType"))) return false; return true; } }; diff --git a/src/NitroFetch.nitro.ts b/src/NitroFetch.nitro.ts index e68fe8e..f0a91e5 100644 --- a/src/NitroFetch.nitro.ts +++ b/src/NitroFetch.nitro.ts @@ -39,22 +39,12 @@ export interface NitroResponse { bodyBytes?: string; //will be ArrayBuffer in future } -export enum EffectiveConnectionType { - UNKNOWN = 'unknown', - OFFLINE = 'offline', - SLOW_2G = 'slow-2G', - TWO_G = '2G', - THREE_G = '3G', - FOUR_G = '4G', - WIFI = 'wifi', -} - export interface NetworkQualityEstimate { downstreamThroughputKbps?: number; upstreamThroughputKbps?: number; httpRttMs?: number; transportRttMs?: number; - effectiveConnectionType?: EffectiveConnectionType; + effectiveConnectionType?: string; } export interface NitroFetchClient diff --git a/src/index.tsx b/src/index.tsx index d0ff81e..47fed65 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -9,7 +9,6 @@ export { } from './fetch'; export type { NitroRequest, NitroResponse } from './fetch'; export type { NetworkQualityEstimate } from './NitroFetch.nitro'; -export { EffectiveConnectionType } from './NitroFetch.nitro'; export { NitroFetch } from './NitroInstances'; import './fetch';