@pigeonmal/react-native-nitro-fetch 0.1.9 → 0.2.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.
Files changed (89) hide show
  1. package/NitroFetch.podspec +30 -30
  2. package/android/CMakeLists.txt +70 -70
  3. package/android/build.gradle +128 -129
  4. package/android/cronet-release/build.gradle +2 -0
  5. package/android/cronet-release/cronet-release.aar +0 -0
  6. package/android/gradle.properties +5 -5
  7. package/android/src/main/AndroidManifest.xml +2 -2
  8. package/android/src/main/cpp/cpp-adapter.cpp +6 -6
  9. package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +72 -72
  10. package/android/src/main/java/com/margelo/nitro/nitrofetch/FetchCache.kt +57 -57
  11. package/android/src/main/java/com/margelo/nitro/nitrofetch/NativeStorage.kt +102 -102
  12. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetch.kt +95 -95
  13. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt +317 -317
  14. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchPackage.kt +22 -22
  15. package/ios/FetchCache.swift +56 -56
  16. package/ios/NativeStorage.swift +61 -61
  17. package/ios/NitroAutoPrefetcher.swift +45 -45
  18. package/ios/NitroBootstrap.mm +27 -27
  19. package/ios/NitroFetch.swift +9 -9
  20. package/ios/NitroFetchClient.swift +230 -230
  21. package/lib/module/NitroFetch.nitro.js.map +1 -1
  22. package/lib/module/NitroInstances.js.map +1 -1
  23. package/lib/module/fetch.js.map +1 -1
  24. package/lib/module/index.js.map +1 -1
  25. package/lib/module/type.js.map +1 -1
  26. package/nitro.json +25 -25
  27. package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.cpp +1 -1
  28. package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.hpp +1 -1
  29. package/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp +1 -1
  30. package/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.hpp +1 -1
  31. package/nitrogen/generated/android/c++/JHybridNitroFetchSpec.cpp +1 -1
  32. package/nitrogen/generated/android/c++/JHybridNitroFetchSpec.hpp +1 -1
  33. package/nitrogen/generated/android/c++/JNitroHeader.hpp +1 -1
  34. package/nitrogen/generated/android/c++/JNitroRequest.hpp +1 -1
  35. package/nitrogen/generated/android/c++/JNitroRequestMethod.hpp +1 -1
  36. package/nitrogen/generated/android/c++/JNitroResponse.hpp +1 -1
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNativeStorageSpec.kt +1 -1
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchClientSpec.kt +1 -1
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchSpec.kt +1 -1
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroHeader.kt +1 -1
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroRequest.kt +1 -1
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroRequestMethod.kt +1 -1
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroResponse.kt +1 -1
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/nitrofetchOnLoad.kt +1 -1
  45. package/nitrogen/generated/android/nitrofetch+autolinking.cmake +1 -1
  46. package/nitrogen/generated/android/nitrofetch+autolinking.gradle +1 -1
  47. package/nitrogen/generated/android/nitrofetchOnLoad.cpp +1 -1
  48. package/nitrogen/generated/android/nitrofetchOnLoad.hpp +1 -1
  49. package/nitrogen/generated/ios/NitroFetch+autolinking.rb +1 -1
  50. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.cpp +1 -1
  51. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp +1 -1
  52. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp +1 -1
  53. package/nitrogen/generated/ios/NitroFetchAutolinking.mm +1 -1
  54. package/nitrogen/generated/ios/NitroFetchAutolinking.swift +1 -1
  55. package/nitrogen/generated/ios/c++/HybridNativeStorageSpecSwift.cpp +1 -1
  56. package/nitrogen/generated/ios/c++/HybridNativeStorageSpecSwift.hpp +1 -1
  57. package/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.cpp +1 -1
  58. package/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp +1 -1
  59. package/nitrogen/generated/ios/c++/HybridNitroFetchSpecSwift.cpp +1 -1
  60. package/nitrogen/generated/ios/c++/HybridNitroFetchSpecSwift.hpp +1 -1
  61. package/nitrogen/generated/ios/swift/Func_void.swift +1 -1
  62. package/nitrogen/generated/ios/swift/Func_void_NitroResponse.swift +1 -1
  63. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -1
  64. package/nitrogen/generated/ios/swift/HybridNativeStorageSpec.swift +1 -1
  65. package/nitrogen/generated/ios/swift/HybridNativeStorageSpec_cxx.swift +1 -1
  66. package/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec.swift +1 -1
  67. package/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec_cxx.swift +1 -1
  68. package/nitrogen/generated/ios/swift/HybridNitroFetchSpec.swift +1 -1
  69. package/nitrogen/generated/ios/swift/HybridNitroFetchSpec_cxx.swift +1 -1
  70. package/nitrogen/generated/ios/swift/NitroHeader.swift +1 -1
  71. package/nitrogen/generated/ios/swift/NitroRequest.swift +1 -1
  72. package/nitrogen/generated/ios/swift/NitroRequestMethod.swift +1 -1
  73. package/nitrogen/generated/ios/swift/NitroResponse.swift +1 -1
  74. package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.cpp +1 -1
  75. package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.hpp +1 -1
  76. package/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.cpp +1 -1
  77. package/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.hpp +1 -1
  78. package/nitrogen/generated/shared/c++/HybridNitroFetchSpec.cpp +1 -1
  79. package/nitrogen/generated/shared/c++/HybridNitroFetchSpec.hpp +1 -1
  80. package/nitrogen/generated/shared/c++/NitroHeader.hpp +1 -1
  81. package/nitrogen/generated/shared/c++/NitroRequest.hpp +1 -1
  82. package/nitrogen/generated/shared/c++/NitroRequestMethod.hpp +1 -1
  83. package/nitrogen/generated/shared/c++/NitroResponse.hpp +1 -1
  84. package/package.json +163 -162
  85. package/src/NitroFetch.nitro.ts +67 -67
  86. package/src/NitroInstances.ts +14 -14
  87. package/src/fetch.ts +603 -603
  88. package/src/index.tsx +17 -17
  89. package/src/type.ts +3 -3
@@ -1,22 +1,22 @@
1
- package com.margelo.nitro.nitrofetch
2
-
3
- import com.facebook.react.TurboReactPackage
4
- import com.facebook.react.bridge.NativeModule
5
- import com.facebook.react.bridge.ReactApplicationContext
6
- import com.facebook.react.module.model.ReactModuleInfoProvider
7
-
8
- class NitroFetchPackage : TurboReactPackage() {
9
- override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
10
- return null
11
- }
12
-
13
- override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
14
- return ReactModuleInfoProvider { HashMap() }
15
- }
16
-
17
- companion object {
18
- init {
19
- System.loadLibrary("nitrofetch")
20
- }
21
- }
22
- }
1
+ package com.margelo.nitro.nitrofetch
2
+
3
+ import com.facebook.react.TurboReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfoProvider
7
+
8
+ class NitroFetchPackage : TurboReactPackage() {
9
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
10
+ return null
11
+ }
12
+
13
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
14
+ return ReactModuleInfoProvider { HashMap() }
15
+ }
16
+
17
+ companion object {
18
+ init {
19
+ System.loadLibrary("nitrofetch")
20
+ }
21
+ }
22
+ }
@@ -1,56 +1,56 @@
1
- import Foundation
2
-
3
- final class FetchCache {
4
- struct CachedEntry {
5
- let response: NitroResponse
6
- let timestampMs: Int64
7
- }
8
-
9
- private static let queue = DispatchQueue(label: "nitrofetch.cache", attributes: .concurrent)
10
- private static var pending: [String: [(Result<NitroResponse, Error>) -> Void]] = [:]
11
- private static var results: [String: CachedEntry] = [:]
12
-
13
- static func getPending(_ key: String) -> Bool {
14
- var has = false
15
- queue.sync { has = pending[key] != nil }
16
- return has
17
- }
18
-
19
- static func addPending(_ key: String, completion: @escaping (Result<NitroResponse, Error>) -> Void) {
20
- queue.async(flags: .barrier) {
21
- var arr = pending[key] ?? []
22
- arr.append(completion)
23
- pending[key] = arr
24
- }
25
- }
26
-
27
- static func complete(_ key: String, with result: Result<NitroResponse, Error>) {
28
- var callbacks: [(Result<NitroResponse, Error>) -> Void] = []
29
- queue.sync {
30
- callbacks = pending[key] ?? []
31
- }
32
- queue.async(flags: .barrier) {
33
- pending.removeValue(forKey: key)
34
- if case let .success(resp) = result {
35
- results[key] = CachedEntry(response: resp, timestampMs: Int64(Date().timeIntervalSince1970 * 1000))
36
- }
37
- }
38
- callbacks.forEach { $0(result) }
39
- }
40
-
41
- static func getResultIfFresh(_ key: String, maxAgeMs: Int64) -> NitroResponse? {
42
- var out: NitroResponse?
43
- queue.sync {
44
- if let entry = results[key] {
45
- let age = Int64(Date().timeIntervalSince1970 * 1000) - entry.timestampMs
46
- if age <= maxAgeMs {
47
- out = entry.response
48
- } else {
49
- results.removeValue(forKey: key)
50
- }
51
- }
52
- }
53
- return out
54
- }
55
- }
56
-
1
+ import Foundation
2
+
3
+ final class FetchCache {
4
+ struct CachedEntry {
5
+ let response: NitroResponse
6
+ let timestampMs: Int64
7
+ }
8
+
9
+ private static let queue = DispatchQueue(label: "nitrofetch.cache", attributes: .concurrent)
10
+ private static var pending: [String: [(Result<NitroResponse, Error>) -> Void]] = [:]
11
+ private static var results: [String: CachedEntry] = [:]
12
+
13
+ static func getPending(_ key: String) -> Bool {
14
+ var has = false
15
+ queue.sync { has = pending[key] != nil }
16
+ return has
17
+ }
18
+
19
+ static func addPending(_ key: String, completion: @escaping (Result<NitroResponse, Error>) -> Void) {
20
+ queue.async(flags: .barrier) {
21
+ var arr = pending[key] ?? []
22
+ arr.append(completion)
23
+ pending[key] = arr
24
+ }
25
+ }
26
+
27
+ static func complete(_ key: String, with result: Result<NitroResponse, Error>) {
28
+ var callbacks: [(Result<NitroResponse, Error>) -> Void] = []
29
+ queue.sync {
30
+ callbacks = pending[key] ?? []
31
+ }
32
+ queue.async(flags: .barrier) {
33
+ pending.removeValue(forKey: key)
34
+ if case let .success(resp) = result {
35
+ results[key] = CachedEntry(response: resp, timestampMs: Int64(Date().timeIntervalSince1970 * 1000))
36
+ }
37
+ }
38
+ callbacks.forEach { $0(result) }
39
+ }
40
+
41
+ static func getResultIfFresh(_ key: String, maxAgeMs: Int64) -> NitroResponse? {
42
+ var out: NitroResponse?
43
+ queue.sync {
44
+ if let entry = results[key] {
45
+ let age = Int64(Date().timeIntervalSince1970 * 1000) - entry.timestampMs
46
+ if age <= maxAgeMs {
47
+ out = entry.response
48
+ } else {
49
+ results.removeValue(forKey: key)
50
+ }
51
+ }
52
+ }
53
+ return out
54
+ }
55
+ }
56
+
@@ -1,61 +1,61 @@
1
- //
2
- // NativeStorage.swift
3
- // Pods
4
- //
5
- // Created by Ritesh Shukla on 08/11/25.
6
- //
7
-
8
- import Foundation
9
-
10
-
11
- final class NativeStorage: HybridNativeStorageSpec {
12
-
13
- private static let suiteName = "nitro_fetch_storage"
14
-
15
- private let userDefaults: UserDefaults
16
-
17
- public override init() {
18
- // Use a named suite for better isolation, fallback to standard if creation fails
19
- if let suite = UserDefaults(suiteName: NativeStorage.suiteName) {
20
- self.userDefaults = suite
21
- } else {
22
- self.userDefaults = UserDefaults.standard
23
- }
24
- super.init()
25
- }
26
-
27
- /// Retrieves a string value for the given key.
28
- ///
29
- /// - Parameter key: The key to look up in storage
30
- /// - Returns: The stored string value, or empty string if key doesn't exist
31
- /// - Throws: RuntimeError if the operation fails
32
- func getString(key: String) throws -> String {
33
- guard let value = userDefaults.string(forKey: key) else {
34
- return ""
35
- }
36
- return value
37
- }
38
-
39
- /// Stores a string value with the given key.
40
- ///
41
- /// - Parameters:
42
- /// - key: The key to store the value under
43
- /// - value: The string value to store
44
- /// - Throws: RuntimeError if the write operation fails
45
- func setString(key: String, value: String) throws {
46
- userDefaults.set(value, forKey: key)
47
- // Synchronize to ensure immediate persistence
48
- userDefaults.synchronize()
49
- }
50
-
51
- /// Deletes the value associated with the given key.
52
- /// If the key doesn't exist, this is a no-op.
53
- ///
54
- /// - Parameter key: The key to delete from storage
55
- /// - Throws: RuntimeError if the delete operation fails
56
- func removeString(key: String) throws {
57
- userDefaults.removeObject(forKey: key)
58
- // Synchronize to ensure immediate persistence
59
- userDefaults.synchronize()
60
- }
61
- }
1
+ //
2
+ // NativeStorage.swift
3
+ // Pods
4
+ //
5
+ // Created by Ritesh Shukla on 08/11/25.
6
+ //
7
+
8
+ import Foundation
9
+
10
+
11
+ final class NativeStorage: HybridNativeStorageSpec {
12
+
13
+ private static let suiteName = "nitro_fetch_storage"
14
+
15
+ private let userDefaults: UserDefaults
16
+
17
+ public override init() {
18
+ // Use a named suite for better isolation, fallback to standard if creation fails
19
+ if let suite = UserDefaults(suiteName: NativeStorage.suiteName) {
20
+ self.userDefaults = suite
21
+ } else {
22
+ self.userDefaults = UserDefaults.standard
23
+ }
24
+ super.init()
25
+ }
26
+
27
+ /// Retrieves a string value for the given key.
28
+ ///
29
+ /// - Parameter key: The key to look up in storage
30
+ /// - Returns: The stored string value, or empty string if key doesn't exist
31
+ /// - Throws: RuntimeError if the operation fails
32
+ func getString(key: String) throws -> String {
33
+ guard let value = userDefaults.string(forKey: key) else {
34
+ return ""
35
+ }
36
+ return value
37
+ }
38
+
39
+ /// Stores a string value with the given key.
40
+ ///
41
+ /// - Parameters:
42
+ /// - key: The key to store the value under
43
+ /// - value: The string value to store
44
+ /// - Throws: RuntimeError if the write operation fails
45
+ func setString(key: String, value: String) throws {
46
+ userDefaults.set(value, forKey: key)
47
+ // Synchronize to ensure immediate persistence
48
+ userDefaults.synchronize()
49
+ }
50
+
51
+ /// Deletes the value associated with the given key.
52
+ /// If the key doesn't exist, this is a no-op.
53
+ ///
54
+ /// - Parameter key: The key to delete from storage
55
+ /// - Throws: RuntimeError if the delete operation fails
56
+ func removeString(key: String) throws {
57
+ userDefaults.removeObject(forKey: key)
58
+ // Synchronize to ensure immediate persistence
59
+ userDefaults.synchronize()
60
+ }
61
+ }
@@ -1,45 +1,45 @@
1
- import Foundation
2
-
3
- @objc(NitroAutoPrefetcher)
4
- public final class NitroAutoPrefetcher: NSObject {
5
- private static var initialized = false
6
- private static let queueKey = "nitrofetch_autoprefetch_queue"
7
- private static let suiteName = "nitro_fetch_storage"
8
-
9
- @objc
10
- public static func prefetchOnStart() {
11
- if initialized { return }
12
- initialized = true
13
-
14
- // Read from UserDefaults
15
- let userDefaults = UserDefaults(suiteName: suiteName) ?? UserDefaults.standard
16
- guard let raw = userDefaults.string(forKey: queueKey), !raw.isEmpty else { return }
17
- guard let data = raw.data(using: .utf8) else { return }
18
- guard let arr = try? JSONSerialization.jsonObject(with: data, options: []) as? [Any] else { return }
19
-
20
- for item in arr {
21
- guard let obj = item as? [String: Any] else { continue }
22
- guard let url = obj["url"] as? String, !url.isEmpty else { continue }
23
- guard let prefetchKey = obj["prefetchKey"] as? String, !prefetchKey.isEmpty else { continue }
24
- let headersDict = (obj["headers"] as? [String: Any]) ?? [:]
25
- var headers: [NitroHeader] = headersDict.map { (k, v) in NitroHeader(key: String(describing: k), value: String(describing: v)) }
26
- headers.append(NitroHeader(key: "prefetchKey", value: prefetchKey))
27
- let req = NitroRequest(url: url,
28
- method: nil,
29
- headers: headers,
30
- bodyString: nil,
31
- bodyBytes: nil,
32
- timeoutMs: nil,
33
- followRedirects: true)
34
- Task {
35
- do { try await NitroFetchClient.prefetchStatic(req) } catch { /* ignore – best effort */ }
36
- }
37
- }
38
- }
39
- }
40
-
41
- // Expose a C-ABI symbol the ObjC++ file can call
42
- @_cdecl("NitroStartSwift")
43
- public func NitroStartSwift() {
44
- NitroAutoPrefetcher.prefetchOnStart()
45
- }
1
+ import Foundation
2
+
3
+ @objc(NitroAutoPrefetcher)
4
+ public final class NitroAutoPrefetcher: NSObject {
5
+ private static var initialized = false
6
+ private static let queueKey = "nitrofetch_autoprefetch_queue"
7
+ private static let suiteName = "nitro_fetch_storage"
8
+
9
+ @objc
10
+ public static func prefetchOnStart() {
11
+ if initialized { return }
12
+ initialized = true
13
+
14
+ // Read from UserDefaults
15
+ let userDefaults = UserDefaults(suiteName: suiteName) ?? UserDefaults.standard
16
+ guard let raw = userDefaults.string(forKey: queueKey), !raw.isEmpty else { return }
17
+ guard let data = raw.data(using: .utf8) else { return }
18
+ guard let arr = try? JSONSerialization.jsonObject(with: data, options: []) as? [Any] else { return }
19
+
20
+ for item in arr {
21
+ guard let obj = item as? [String: Any] else { continue }
22
+ guard let url = obj["url"] as? String, !url.isEmpty else { continue }
23
+ guard let prefetchKey = obj["prefetchKey"] as? String, !prefetchKey.isEmpty else { continue }
24
+ let headersDict = (obj["headers"] as? [String: Any]) ?? [:]
25
+ var headers: [NitroHeader] = headersDict.map { (k, v) in NitroHeader(key: String(describing: k), value: String(describing: v)) }
26
+ headers.append(NitroHeader(key: "prefetchKey", value: prefetchKey))
27
+ let req = NitroRequest(url: url,
28
+ method: nil,
29
+ headers: headers,
30
+ bodyString: nil,
31
+ bodyBytes: nil,
32
+ timeoutMs: nil,
33
+ followRedirects: true)
34
+ Task {
35
+ do { try await NitroFetchClient.prefetchStatic(req) } catch { /* ignore – best effort */ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ // Expose a C-ABI symbol the ObjC++ file can call
42
+ @_cdecl("NitroStartSwift")
43
+ public func NitroStartSwift() {
44
+ NitroAutoPrefetcher.prefetchOnStart()
45
+ }
@@ -1,27 +1,27 @@
1
- #import <Foundation/Foundation.h>
2
- #if __has_include(<UIKit/UIKit.h>)
3
- #import <UIKit/UIKit.h>
4
- #endif
5
-
6
- // No need to import the Swift header if you don’t want to.
7
- // Just declare the C entry point:
8
- extern "C" void NitroStartSwift(void);
9
-
10
- @interface NitroFetchBootstrapper : NSObject @end
11
- @implementation NitroFetchBootstrapper
12
-
13
- + (void)load {
14
- #if __has_include(<UIKit/UIKit.h>)
15
- if (NSClassFromString(@"UIApplication")) {
16
- [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification
17
- object:nil queue:nil
18
- usingBlock:^(__unused NSNotification *note) {
19
- NitroStartSwift(); // <-- call the C symbol
20
- }];
21
- dispatch_async(dispatch_get_main_queue(), ^{
22
- NitroStartSwift();
23
- });
24
- }
25
- #endif
26
- }
27
- @end
1
+ #import <Foundation/Foundation.h>
2
+ #if __has_include(<UIKit/UIKit.h>)
3
+ #import <UIKit/UIKit.h>
4
+ #endif
5
+
6
+ // No need to import the Swift header if you don’t want to.
7
+ // Just declare the C entry point:
8
+ extern "C" void NitroStartSwift(void);
9
+
10
+ @interface NitroFetchBootstrapper : NSObject @end
11
+ @implementation NitroFetchBootstrapper
12
+
13
+ + (void)load {
14
+ #if __has_include(<UIKit/UIKit.h>)
15
+ if (NSClassFromString(@"UIApplication")) {
16
+ [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification
17
+ object:nil queue:nil
18
+ usingBlock:^(__unused NSNotification *note) {
19
+ NitroStartSwift(); // <-- call the C symbol
20
+ }];
21
+ dispatch_async(dispatch_get_main_queue(), ^{
22
+ NitroStartSwift();
23
+ });
24
+ }
25
+ #endif
26
+ }
27
+ @end
@@ -1,9 +1,9 @@
1
- import Foundation
2
-
3
- final class NitroFetch: HybridNitroFetchSpec {
4
- func createClient() throws -> (any HybridNitroFetchClientSpec) {
5
- return NitroFetchClient()
6
- }
7
-
8
- }
9
-
1
+ import Foundation
2
+
3
+ final class NitroFetch: HybridNitroFetchSpec {
4
+ func createClient() throws -> (any HybridNitroFetchClientSpec) {
5
+ return NitroFetchClient()
6
+ }
7
+
8
+ }
9
+