@pigeonmal/react-native-nitro-fetch 0.1.6

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 (104) hide show
  1. package/NitroFetch.podspec +30 -0
  2. package/android/CMakeLists.txt +70 -0
  3. package/android/build.gradle +130 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  7. package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +72 -0
  8. package/android/src/main/java/com/margelo/nitro/nitrofetch/FetchCache.kt +58 -0
  9. package/android/src/main/java/com/margelo/nitro/nitrofetch/NativeStorage.kt +102 -0
  10. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetch.kt +94 -0
  11. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt +331 -0
  12. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchPackage.kt +22 -0
  13. package/ios/FetchCache.swift +56 -0
  14. package/ios/NativeStorage.swift +61 -0
  15. package/ios/NitroAutoPrefetcher.swift +45 -0
  16. package/ios/NitroBootstrap.mm +27 -0
  17. package/ios/NitroFetch.swift +9 -0
  18. package/ios/NitroFetchClient.swift +230 -0
  19. package/lib/module/NitroFetch.nitro.js +4 -0
  20. package/lib/module/NitroFetch.nitro.js.map +1 -0
  21. package/lib/module/NitroInstances.js +8 -0
  22. package/lib/module/NitroInstances.js.map +1 -0
  23. package/lib/module/fetch.js +522 -0
  24. package/lib/module/fetch.js.map +1 -0
  25. package/lib/module/index.js +12 -0
  26. package/lib/module/index.js.map +1 -0
  27. package/lib/module/package.json +1 -0
  28. package/lib/module/type.js +2 -0
  29. package/lib/module/type.js.map +1 -0
  30. package/lib/typescript/package.json +1 -0
  31. package/lib/typescript/src/NitroFetch.nitro.d.ts +48 -0
  32. package/lib/typescript/src/NitroFetch.nitro.d.ts.map +1 -0
  33. package/lib/typescript/src/NitroInstances.d.ts +5 -0
  34. package/lib/typescript/src/NitroInstances.d.ts.map +1 -0
  35. package/lib/typescript/src/fetch.d.ts +28 -0
  36. package/lib/typescript/src/fetch.d.ts.map +1 -0
  37. package/lib/typescript/src/index.d.ts +6 -0
  38. package/lib/typescript/src/index.d.ts.map +1 -0
  39. package/lib/typescript/src/type.d.ts +4 -0
  40. package/lib/typescript/src/type.d.ts.map +1 -0
  41. package/nitro.json +25 -0
  42. package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.cpp +54 -0
  43. package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.hpp +66 -0
  44. package/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp +96 -0
  45. package/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.hpp +66 -0
  46. package/nitrogen/generated/android/c++/JHybridNitroFetchSpec.cpp +49 -0
  47. package/nitrogen/generated/android/c++/JHybridNitroFetchSpec.hpp +64 -0
  48. package/nitrogen/generated/android/c++/JNitroHeader.hpp +57 -0
  49. package/nitrogen/generated/android/c++/JNitroRequest.hpp +100 -0
  50. package/nitrogen/generated/android/c++/JNitroRequestMethod.hpp +74 -0
  51. package/nitrogen/generated/android/c++/JNitroResponse.hpp +102 -0
  52. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNativeStorageSpec.kt +60 -0
  53. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchClientSpec.kt +60 -0
  54. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchSpec.kt +52 -0
  55. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroHeader.kt +32 -0
  56. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroRequest.kt +47 -0
  57. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroRequestMethod.kt +26 -0
  58. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroResponse.kt +50 -0
  59. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/nitrofetchOnLoad.kt +35 -0
  60. package/nitrogen/generated/android/nitrofetch+autolinking.cmake +85 -0
  61. package/nitrogen/generated/android/nitrofetch+autolinking.gradle +27 -0
  62. package/nitrogen/generated/android/nitrofetchOnLoad.cpp +64 -0
  63. package/nitrogen/generated/android/nitrofetchOnLoad.hpp +25 -0
  64. package/nitrogen/generated/ios/NitroFetch+autolinking.rb +60 -0
  65. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.cpp +90 -0
  66. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp +321 -0
  67. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp +69 -0
  68. package/nitrogen/generated/ios/NitroFetchAutolinking.mm +49 -0
  69. package/nitrogen/generated/ios/NitroFetchAutolinking.swift +55 -0
  70. package/nitrogen/generated/ios/c++/HybridNativeStorageSpecSwift.cpp +11 -0
  71. package/nitrogen/generated/ios/c++/HybridNativeStorageSpecSwift.hpp +85 -0
  72. package/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.cpp +11 -0
  73. package/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp +103 -0
  74. package/nitrogen/generated/ios/c++/HybridNitroFetchSpecSwift.cpp +11 -0
  75. package/nitrogen/generated/ios/c++/HybridNitroFetchSpecSwift.hpp +75 -0
  76. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  77. package/nitrogen/generated/ios/swift/Func_void_NitroResponse.swift +47 -0
  78. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  79. package/nitrogen/generated/ios/swift/HybridNativeStorageSpec.swift +51 -0
  80. package/nitrogen/generated/ios/swift/HybridNativeStorageSpec_cxx.swift +145 -0
  81. package/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec.swift +51 -0
  82. package/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec_cxx.swift +161 -0
  83. package/nitrogen/generated/ios/swift/HybridNitroFetchSpec.swift +49 -0
  84. package/nitrogen/generated/ios/swift/HybridNitroFetchSpec_cxx.swift +126 -0
  85. package/nitrogen/generated/ios/swift/NitroHeader.swift +46 -0
  86. package/nitrogen/generated/ios/swift/NitroRequest.swift +206 -0
  87. package/nitrogen/generated/ios/swift/NitroRequestMethod.swift +60 -0
  88. package/nitrogen/generated/ios/swift/NitroResponse.swift +162 -0
  89. package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.cpp +23 -0
  90. package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.hpp +64 -0
  91. package/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.cpp +23 -0
  92. package/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.hpp +69 -0
  93. package/nitrogen/generated/shared/c++/HybridNitroFetchSpec.cpp +21 -0
  94. package/nitrogen/generated/shared/c++/HybridNitroFetchSpec.hpp +64 -0
  95. package/nitrogen/generated/shared/c++/NitroHeader.hpp +71 -0
  96. package/nitrogen/generated/shared/c++/NitroRequest.hpp +98 -0
  97. package/nitrogen/generated/shared/c++/NitroRequestMethod.hpp +96 -0
  98. package/nitrogen/generated/shared/c++/NitroResponse.hpp +99 -0
  99. package/package.json +162 -0
  100. package/src/NitroFetch.nitro.ts +67 -0
  101. package/src/NitroInstances.ts +14 -0
  102. package/src/fetch.ts +603 -0
  103. package/src/index.tsx +17 -0
  104. package/src/type.ts +3 -0
@@ -0,0 +1,230 @@
1
+ import Foundation
2
+ import NitroModules
3
+
4
+ final class NitroFetchClient: HybridNitroFetchClientSpec {
5
+ func requestSync(req: NitroRequest) throws -> NitroResponse {
6
+ let semaphore = DispatchSemaphore(value: 0)
7
+ var result: Result<NitroResponse, Error>?
8
+
9
+ Task {
10
+ do {
11
+ let response = try await NitroFetchClient.requestStatic(req)
12
+ result = .success(response)
13
+ } catch {
14
+ result = .failure(error)
15
+ }
16
+ semaphore.signal()
17
+ }
18
+
19
+ semaphore.wait()
20
+
21
+ switch result! {
22
+ case .success(let response):
23
+ return response
24
+ case .failure(let error):
25
+ throw error
26
+ }
27
+ }
28
+
29
+ // Async version - returns Promise<NitroResponse>
30
+ func request(req: NitroRequest) throws -> Promise<NitroResponse> {
31
+ let promise = Promise<NitroResponse>.init()
32
+ Task {
33
+ do {
34
+ let response = try await NitroFetchClient.requestStatic(req)
35
+ promise.resolve(withResult: response)
36
+ } catch {
37
+ promise.reject(withError: error)
38
+ }
39
+ }
40
+ return promise
41
+ }
42
+
43
+ func prefetch(req: NitroRequest) throws -> Promise<Void> {
44
+ let promise = Promise<Void>.init()
45
+ Task {
46
+ do {
47
+ try await NitroFetchClient.prefetchStatic(req)
48
+ promise.resolve(withResult: ())
49
+ } catch {
50
+ promise.reject(withError: error)
51
+ }
52
+
53
+ }
54
+ return promise
55
+ }
56
+
57
+ // Shared URLSession for static operations
58
+ private static let session: URLSession = {
59
+ let config = URLSessionConfiguration.default
60
+ config.requestCachePolicy = .useProtocolCachePolicy
61
+ config.urlCache = URLCache(memoryCapacity: 32 * 1024 * 1024,
62
+ diskCapacity: 100 * 1024 * 1024,
63
+ diskPath: "nitrofetch_urlcache")
64
+ return URLSession(configuration: config)
65
+ }()
66
+
67
+ private static func findPrefetchKey(_ req: NitroRequest) -> String? {
68
+ guard let headers = req.headers else { return nil }
69
+ for h in headers {
70
+ if h.key.caseInsensitiveCompare("prefetchKey") == .orderedSame {
71
+ return h.value
72
+ }
73
+ }
74
+ return nil
75
+ }
76
+
77
+ // MARK: - Static API usable from native bootstrap
78
+
79
+
80
+ public class func requestStatic(_ req: NitroRequest) async throws -> NitroResponse {
81
+ if let key = findPrefetchKey(req) {
82
+ // If a prefetched result is fresh, return immediately
83
+ if let cached = FetchCache.getResultIfFresh(key, maxAgeMs: 5_000) {
84
+ var headers = cached.headers ?? []
85
+ headers.append(NitroHeader(key: "nitroPrefetched", value: "true"))
86
+ return NitroResponse(url: cached.url,
87
+ status: cached.status,
88
+ statusText: cached.statusText,
89
+ ok: cached.ok,
90
+ redirected: cached.redirected,
91
+ headers: headers,
92
+ bodyString: cached.bodyString,
93
+ bodyBytes: cached.bodyBytes)
94
+ }
95
+
96
+ // If a prefetch is already pending, await and reuse its result
97
+ if FetchCache.getPending(key) {
98
+ return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<NitroResponse, Error>) in
99
+ FetchCache.addPending(key) { result in
100
+ switch result {
101
+ case .success(let res):
102
+ // Mirror Android: mark response as coming from prefetch
103
+ var headers = res.headers ?? []
104
+ headers.append(NitroHeader(key: "nitroPrefetched", value: "true"))
105
+ let wrapped = NitroResponse(url: res.url,
106
+ status: res.status,
107
+ statusText: res.statusText,
108
+ ok: res.ok,
109
+ redirected: res.redirected,
110
+ headers: headers,
111
+ bodyString: res.bodyString,
112
+ bodyBytes: res.bodyBytes)
113
+ continuation.resume(returning: wrapped)
114
+ case .failure(let err):
115
+ continuation.resume(throwing: err)
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ let (urlRequest, finalURL) = try buildURLRequest(req)
123
+ let (data, response) = try await session.data(for: urlRequest)
124
+ guard let http = response as? HTTPURLResponse else {
125
+ throw NSError(domain: "NitroFetch", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])
126
+ }
127
+
128
+ let headersPairs: [NitroHeader] = http.allHeaderFields.compactMap { k, v in
129
+ guard let key = k as? String else { return nil }
130
+ return NitroHeader(key: key, value: String(describing: v))
131
+ }
132
+
133
+ // Choose bodyString by default (matching Android’s first pass)
134
+ let charset = NitroFetchClient.detectCharset(from: http) ?? String.Encoding.utf8
135
+ let bodyStr = String(data: data, encoding: charset) ?? String(data: data, encoding: .utf8)
136
+
137
+ let res = NitroResponse(
138
+ url: finalURL?.absoluteString ?? http.url?.absoluteString ?? req.url,
139
+ status: Double(http.statusCode),
140
+ statusText: HTTPURLResponse.localizedString(forStatusCode: http.statusCode),
141
+ ok: (200...299).contains(http.statusCode),
142
+ redirected: (finalURL?.absoluteString ?? http.url?.absoluteString ?? req.url) != req.url,
143
+ headers: headersPairs,
144
+ bodyString: bodyStr,
145
+ bodyBytes: nil
146
+ )
147
+
148
+ // Do not write to cache here; only prefetch should populate the cache
149
+
150
+ return res
151
+ }
152
+
153
+ public class func prefetchStatic(_ req: NitroRequest) async throws {
154
+ guard let key = findPrefetchKey(req) else {
155
+ throw NSError(domain: "NitroFetch", code: -2, userInfo: [NSLocalizedDescriptionKey: "prefetch: missing 'prefetchKey' header"])
156
+ }
157
+
158
+ if FetchCache.getResultIfFresh(key, maxAgeMs: 5_000) != nil {
159
+ return // already have a fresh result
160
+ }
161
+
162
+ if FetchCache.getPending(key) {
163
+ return // already pending
164
+ }
165
+
166
+ // Mark pending and start the request
167
+ FetchCache.addPending(key) { _ in /* ignored here */ }
168
+ Task.detached {
169
+ do {
170
+ let (urlRequest, finalURL) = try buildURLRequest(req)
171
+ let (data, response) = try await session.data(for: urlRequest)
172
+ guard let http = response as? HTTPURLResponse else {
173
+ throw NSError(domain: "NitroFetch", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])
174
+ }
175
+ let headersPairs: [NitroHeader] = http.allHeaderFields.compactMap { k, v in
176
+ guard let key = k as? String else { return nil }
177
+ return NitroHeader(key: key, value: String(describing: v))
178
+ }
179
+ let charset = NitroFetchClient.detectCharset(from: http) ?? .utf8
180
+ let bodyStr = String(data: data, encoding: charset) ?? String(data: data, encoding: .utf8)
181
+ let res = NitroResponse(
182
+ url: finalURL?.absoluteString ?? http.url?.absoluteString ?? req.url,
183
+ status: Double(http.statusCode),
184
+ statusText: HTTPURLResponse.localizedString(forStatusCode: http.statusCode),
185
+ ok: (200...299).contains(http.statusCode),
186
+ redirected: (finalURL?.absoluteString ?? http.url?.absoluteString ?? req.url) != req.url,
187
+ headers: headersPairs,
188
+ bodyString: bodyStr,
189
+ bodyBytes: nil
190
+ )
191
+ FetchCache.complete(key, with: .success(res))
192
+ } catch {
193
+ FetchCache.complete(key, with: .failure(error))
194
+ }
195
+ }
196
+ }
197
+
198
+ private static func reqToHttpMethod(_ req: NitroRequest) -> String? {
199
+ return req.method?.stringValue
200
+ }
201
+
202
+ private static func buildURLRequest(_ req: NitroRequest) throws -> (URLRequest, URL?) {
203
+ guard let url = URL(string: req.url) else {
204
+ throw NSError(domain: "NitroFetch", code: -3, userInfo: [NSLocalizedDescriptionKey: "Invalid URL: \(req.url)"])
205
+ }
206
+ var r = URLRequest(url: url)
207
+ if let m = req.method?.rawValue { r.httpMethod = reqToHttpMethod(req) }
208
+ if let headers = req.headers {
209
+ for h in headers { r.addValue(h.value, forHTTPHeaderField: h.key) }
210
+ }
211
+ if let s = req.bodyString {
212
+ r.httpBody = s.data(using: .utf8)
213
+ }
214
+ if let t = req.timeoutMs, t > 0 { r.timeoutInterval = TimeInterval(t) / 1000.0 }
215
+ return (r, nil)
216
+ }
217
+
218
+ private static func detectCharset(from http: HTTPURLResponse) -> String.Encoding? {
219
+ if let ct = http.value(forHTTPHeaderField: "Content-Type")?.lowercased() {
220
+ if let range = ct.range(of: "charset=") {
221
+ let charset = String(ct[range.upperBound...]).trimmingCharacters(in: .whitespaces)
222
+ let mapped = CFStringConvertIANACharSetNameToEncoding(charset as CFString)
223
+ if mapped != kCFStringEncodingInvalidId {
224
+ return String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(mapped))
225
+ }
226
+ }
227
+ }
228
+ return nil
229
+ }
230
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=NitroFetch.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["NitroFetch.nitro.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ import { NitroModules } from 'react-native-nitro-modules';
4
+ // Create singletons once per JS runtime
5
+ export const NitroFetch = NitroModules.createHybridObject('NitroFetch');
6
+ export const NativeStorage = NitroModules.createHybridObject('NativeStorage');
7
+ export const boxedNitroFetch = NitroModules.box(NitroFetch);
8
+ //# sourceMappingURL=NitroInstances.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NitroModules","NitroFetch","createHybridObject","NativeStorage","boxedNitroFetch","box"],"sourceRoot":"../../src","sources":["NitroInstances.ts"],"mappings":";;AAAA,SAASA,YAAY,QAAQ,4BAA4B;AAMzD;AACA,OAAO,MAAMC,UAA0B,GACrCD,YAAY,CAACE,kBAAkB,CAAiB,YAAY,CAAC;AAE/D,OAAO,MAAMC,aAAgC,GAC3CH,YAAY,CAACE,kBAAkB,CAAoB,eAAe,CAAC;AAErE,OAAO,MAAME,eAAe,GAAGJ,YAAY,CAACK,GAAG,CAACJ,UAAU,CAAC","ignoreList":[]}