react-native-nitro-fetch 1.3.1 → 1.3.3

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 (40) hide show
  1. package/NitroFetch.podspec +1 -3
  2. package/README.md +38 -0
  3. package/android/build.gradle +12 -0
  4. package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +148 -55
  5. package/android/src/main/java/com/margelo/nitro/nitrofetch/DevToolsReporterImpl.kt +27 -36
  6. package/ios/NitroAutoPrefetcher.swift +149 -53
  7. package/ios/NitroDevToolsReporter.mm +37 -31
  8. package/lib/module/CurlGenerator.js.map +2 -1
  9. package/lib/module/Headers.js.map +2 -1
  10. package/lib/module/HermesProfiler.js.map +1 -1
  11. package/lib/module/NetworkInspector.js +1 -1
  12. package/lib/module/NetworkInspector.js.map +2 -1
  13. package/lib/module/NitroCronet.nitro.js.map +2 -1
  14. package/lib/module/NitroFetch.nitro.js.map +1 -2
  15. package/lib/module/NitroInstances.js.map +2 -1
  16. package/lib/module/Response.js.map +1 -2
  17. package/lib/module/fetch.js +8 -10
  18. package/lib/module/fetch.js.map +2 -1
  19. package/lib/module/index.js.map +2 -2
  20. package/lib/module/index.web.js +2 -1
  21. package/lib/module/tokenRefresh.js.map +2 -1
  22. package/lib/module/utf8.js.map +1 -2
  23. package/lib/typescript/src/fetch.d.ts.map +1 -1
  24. package/lib/typescript/src/tokenRefresh.d.ts +14 -0
  25. package/lib/typescript/src/tokenRefresh.d.ts.map +1 -1
  26. package/package.json +1 -1
  27. package/src/CurlGenerator.js +23 -26
  28. package/src/Headers.js +108 -116
  29. package/src/HermesProfiler.js +16 -18
  30. package/src/NetworkInspector.js +171 -179
  31. package/src/NitroInstances.js +2 -1
  32. package/src/Request.js +167 -164
  33. package/src/Response.js +244 -242
  34. package/src/fetch.js +708 -693
  35. package/src/fetch.ts +15 -16
  36. package/src/index.js +17 -2
  37. package/src/index.web.js +69 -67
  38. package/src/tokenRefresh.js +75 -77
  39. package/src/tokenRefresh.ts +16 -0
  40. package/src/utf8.js +28 -27
@@ -22,9 +22,7 @@ Pod::Spec.new do |s|
22
22
 
23
23
  s.dependency 'React-jsi'
24
24
  s.dependency 'React-callinvoker'
25
- s.dependency 'React-RCTNetwork'
26
-
27
- # Expose the DevTools reporter Obj-C facade to Swift via the pod's umbrella module.
25
+
28
26
  s.public_header_files = [
29
27
  "ios/NitroDevToolsReporter.h",
30
28
  "ios/NitroAutoPrefetcher.h",
package/README.md CHANGED
@@ -134,8 +134,46 @@ registerTokenRefresh({
134
134
  - Default `responseType` is `'json'`. Use **`mappings`** to copy fields from the JSON body into header names (dot paths supported, e.g. `data.token`).
135
135
  - Use **`compositeHeaders`** to build a header from a template and multiple JSON paths (`{{placeholder}}` in the template).
136
136
  - For a plain-text body, set `responseType: 'text'` and use **`textHeader`** / optional **`textTemplate`** (with `{{value}}`).
137
+ - To inject into the prefetch's **JSON body** or **form-data** (the `fetch` path only), use **`bodyMappings`** / **`formDataMappings`** (see below).
137
138
 
139
+ **Example: header + JSON body + form-data mappings**
138
140
 
141
+ One config can fan the same refreshed value into all three destinations. Each mapping only applies to a prefetch whose body it matches — `bodyMappings` won't synthesize a JSON body on a GET/form request, and `formDataMappings` won't make a request multipart.
142
+
143
+ ```ts
144
+ import { registerTokenRefresh } from 'react-native-nitro-fetch'
145
+
146
+ // Refresh endpoint returns e.g. { "data": { "accessToken": "abc123" } }
147
+ registerTokenRefresh({
148
+ target: 'fetch',
149
+ url: 'https://api.example.com/oauth/token',
150
+ method: 'POST',
151
+ responseType: 'json',
152
+
153
+ // 1) header mapping → sets a request header
154
+ mappings: [
155
+ { jsonPath: 'data.accessToken', header: 'Authorization', valueTemplate: 'Bearer {{value}}' },
156
+ ],
157
+
158
+ // 2) JSON-body mapping → sets a (nested) dot-path key in the prefetch's JSON body
159
+ bodyMappings: [
160
+ { jsonPath: 'data.accessToken', bodyPath: 'auth.token' },
161
+ ],
162
+
163
+ // 3) form-data mapping → replaces/appends a multipart field by name
164
+ formDataMappings: [
165
+ { jsonPath: 'data.accessToken', field: 'token' },
166
+ ],
167
+
168
+ onFailure: 'useStoredHeaders',
169
+ })
170
+ ```
171
+
172
+ Result, per prefetch:
173
+ - a JSON prefetch of `{ "deviceId": "d-1" }` → `Authorization: Bearer abc123` **and** body `{ "deviceId": "d-1", "auth": { "token": "abc123" } }`
174
+ - a form-data prefetch → `Authorization: Bearer abc123` **and** a `token=abc123` part
175
+
176
+ > For `responseType: 'text'`, the body/form equivalents of `textHeader` are **`bodyTextPath`** / **`formDataTextField`**.
139
177
 
140
178
  **Example: token refresh + WebSocket prewarm**
141
179
 
@@ -85,6 +85,18 @@ android {
85
85
  release {
86
86
  minifyEnabled false
87
87
  }
88
+
89
+ // Reverting due to build failure
90
+ // // The app's RN-managed `debugOptimized` build type (added by the React Native
91
+ // // gradle plugin, app-only) falls back to this library's `release` variant, where
92
+ // // BuildConfig.DEBUG is false — which constant-folds out the native DevTools/CDP
93
+ // // network reporting in NitroFetchClient.kt. Define a matching debuggable variant
94
+ // // so debugOptimized links a BuildConfig.DEBUG=true build and requests surface in
95
+ // // the React Native DevTools Network panel.
96
+ // debugOptimized {
97
+ // initWith debug
98
+ // matchingFallbacks += ["release"]
99
+ // }
88
100
  }
89
101
 
90
102
  lintOptions {
@@ -65,20 +65,14 @@ object AutoPrefetcher {
65
65
  }
66
66
 
67
67
  if (initialized) {
68
- // late path — kick a single immediate prefetch with cached token headers
68
+ // late path — kick a single immediate prefetch with cached tokens
69
69
  try {
70
70
  val prefs = context.applicationContext
71
71
  .getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
72
- val cacheRaw = NitroFetchSecureAtRest.getDecryptedForPrefs(prefs, KEY_TOKEN_CACHE)
73
- val tokenHeaders: Map<String, String> = if (!cacheRaw.isNullOrEmpty()) {
74
- try {
75
- val co = JSONObject(cacheRaw)
76
- co.keys().asSequence().associateWith { k -> co.optString(k, "") }
77
- } catch (_: Throwable) { emptyMap() }
78
- } else emptyMap()
72
+ val tokens = deserializeCache(NitroFetchSecureAtRest.getDecryptedForPrefs(prefs, KEY_TOKEN_CACHE))
79
73
 
80
74
  val single = JSONArray().apply { put(entry) }
81
- startPrefetches(single, tokenHeaders)
75
+ startPrefetches(single, tokens)
82
76
  } catch (_: Throwable) {}
83
77
  }
84
78
  }
@@ -105,13 +99,11 @@ object AutoPrefetcher {
105
99
 
106
100
  val refreshed = callTokenRefreshSync(refreshConfig)
107
101
 
108
- val tokenHeaders: Map<String, String> = if (refreshed != null) {
109
- android.util.Log.d("NitroFetch", "[TokenRefresh] ✅ Success — got ${refreshed.size} header(s)")
110
- refreshed.forEach { (k, v) -> android.util.Log.d("NitroFetch", "[TokenRefresh] $k: $v") }
111
- // Cache fresh token headers for useStoredHeaders fallback on next cold start
112
- val cacheJson = JSONObject()
113
- refreshed.forEach { (k, v) -> cacheJson.put(k, v) }
114
- NitroFetchSecureAtRest.putEncrypted(prefs, KEY_TOKEN_CACHE, cacheJson.toString())
102
+ val tokens: TokenRefreshResult = if (refreshed != null) {
103
+ android.util.Log.d("NitroFetch", "[TokenRefresh] ✅ Success — got ${refreshed.headers.size} header(s)")
104
+ refreshed.headers.forEach { (k, v) -> android.util.Log.d("NitroFetch", "[TokenRefresh] $k: $v") }
105
+ // Cache fresh tokens for useStoredHeaders fallback on next cold start
106
+ NitroFetchSecureAtRest.putEncrypted(prefs, KEY_TOKEN_CACHE, serializeCache(refreshed))
115
107
  refreshed
116
108
  } else {
117
109
  android.util.Log.d("NitroFetch", "[TokenRefresh] ❌ Refresh failed — onFailure: $onFailure")
@@ -119,36 +111,28 @@ object AutoPrefetcher {
119
111
  android.util.Log.d("NitroFetch", "[TokenRefresh] Skipping all prefetches")
120
112
  return@Thread
121
113
  }
122
- // Use last cached token headers (or empty map if none cached yet)
123
- val cacheRaw = NitroFetchSecureAtRest.getDecryptedForPrefs(prefs, KEY_TOKEN_CACHE)
124
- val cached = if (cacheRaw != null) {
125
- try {
126
- val co = JSONObject(cacheRaw)
127
- co.keys().asSequence().associateWith { k -> co.optString(k, "") }
128
- } catch (_: Throwable) { emptyMap() }
129
- } else {
130
- emptyMap()
131
- }
132
- android.util.Log.d("NitroFetch", "[TokenRefresh] Using cached headers (${cached.size} header(s))")
114
+ // Use last cached tokens (or empty if none cached yet)
115
+ val cached = deserializeCache(NitroFetchSecureAtRest.getDecryptedForPrefs(prefs, KEY_TOKEN_CACHE))
116
+ android.util.Log.d("NitroFetch", "[TokenRefresh] Using cached headers (${cached.headers.size} header(s))")
133
117
  cached
134
118
  }
135
119
 
136
120
  android.util.Log.d("NitroFetch", "[TokenRefresh] Injecting token headers into ${arr.length()} prefetch URL(s)")
137
- startPrefetches(arr, tokenHeaders)
121
+ startPrefetches(arr, tokens)
138
122
  } catch (_: Throwable) {
139
123
  // Best-effort — never crash the app
140
124
  }
141
125
  }.start()
142
126
  } else {
143
127
  // No token refresh config — proceed on current thread (Cronet is async)
144
- startPrefetches(arr, emptyMap())
128
+ startPrefetches(arr, TokenRefreshResult.EMPTY)
145
129
  }
146
130
  } catch (_: Throwable) {
147
131
  // ignore – prefetch-on-start is best-effort
148
132
  }
149
133
  }
150
134
 
151
- private fun startPrefetches(arr: JSONArray, tokenHeaders: Map<String, String>) {
135
+ private fun startPrefetches(arr: JSONArray, tokens: TokenRefreshResult) {
152
136
  for (i in 0 until arr.length()) {
153
137
  val o = arr.optJSONObject(i) ?: continue
154
138
  val url = o.optString("url", null) ?: continue
@@ -160,12 +144,12 @@ object AutoPrefetcher {
160
144
  headersObj.keys().forEachRemaining { k ->
161
145
  merged[k] = headersObj.optString(k, "")
162
146
  }
163
- tokenHeaders.forEach { (k, v) -> merged[k] = v }
147
+ tokens.headers.forEach { (k, v) -> merged[k] = v }
164
148
  merged["prefetchKey"] = prefetchKey
165
149
 
166
150
  android.util.Log.d("NitroFetch", "[TokenRefresh] Prefetching $url with ${merged.size} header(s)")
167
151
  merged.forEach { (k, v) -> android.util.Log.d("NitroFetch", "[TokenRefresh] $k: $v") }
168
- val req = buildNitroRequestFromEntry(url, merged, o)
152
+ val req = buildNitroRequestFromEntry(url, merged, o, tokens)
169
153
 
170
154
  if (FetchCache.getPending(prefetchKey) != null) continue
171
155
  val entryTtlMs = if (o.has("prefetchCacheTtlMs") && !o.isNull("prefetchCacheTtlMs")) {
@@ -237,6 +221,7 @@ object AutoPrefetcher {
237
221
  url: String,
238
222
  mergedHeaders: Map<String, String>,
239
223
  entry: JSONObject?,
224
+ tokens: TokenRefreshResult = TokenRefreshResult.EMPTY,
240
225
  ): NitroRequest {
241
226
  val headerObjs = mergedHeaders.map { (k, v) -> NitroHeader(k, v) }.toTypedArray()
242
227
 
@@ -244,9 +229,10 @@ object AutoPrefetcher {
244
229
  val method: NitroRequestMethod? = methodStr?.let {
245
230
  runCatching { NitroRequestMethod.valueOf(it) }.getOrNull()
246
231
  }
247
- val bodyString = entry
232
+ val rawBodyString = entry
248
233
  ?.takeIf { it.has("bodyString") && !it.isNull("bodyString") }
249
234
  ?.optString("bodyString")
235
+ val bodyString = injectBodyFields(rawBodyString, tokens.bodyFields)
250
236
  val bodyBytes = entry
251
237
  ?.takeIf { it.has("bodyBytes") && !it.isNull("bodyBytes") }
252
238
  ?.optString("bodyBytes")
@@ -261,8 +247,8 @@ object AutoPrefetcher {
261
247
  ?.optDouble("prefetchCacheTtlMs")
262
248
 
263
249
  val formArr = entry?.optJSONArray("bodyFormData")
264
- val bodyFormData: Array<NitroFormDataPart>? = formArr?.let { ja ->
265
- Array(ja.length()) { i ->
250
+ val baseParts: List<NitroFormDataPart> = formArr?.let { ja ->
251
+ List(ja.length()) { i ->
266
252
  val p = ja.optJSONObject(i) ?: JSONObject()
267
253
  NitroFormDataPart(
268
254
  name = p.optString("name", ""),
@@ -272,7 +258,9 @@ object AutoPrefetcher {
272
258
  mimeType = if (p.has("mimeType") && !p.isNull("mimeType")) p.optString("mimeType") else null
273
259
  )
274
260
  }
275
- }
261
+ } ?: emptyList()
262
+ val bodyFormData: Array<NitroFormDataPart>? =
263
+ injectFormFields(baseParts, tokens.formFields)?.toTypedArray()
276
264
 
277
265
  return NitroRequest(
278
266
  url = url,
@@ -290,7 +278,17 @@ object AutoPrefetcher {
290
278
 
291
279
  // MARK: - Token refresh (synchronous, runs on background thread)
292
280
 
293
- private fun callTokenRefreshSync(config: JSONObject): Map<String, String>? {
281
+ private data class TokenRefreshResult(
282
+ val headers: Map<String, String>,
283
+ val bodyFields: Map<String, String>,
284
+ val formFields: Map<String, String>,
285
+ ) {
286
+ companion object {
287
+ val EMPTY = TokenRefreshResult(emptyMap(), emptyMap(), emptyMap())
288
+ }
289
+ }
290
+
291
+ private fun callTokenRefreshSync(config: JSONObject): TokenRefreshResult? {
294
292
  return try {
295
293
  val urlStr = config.optString("url", null) ?: return null
296
294
  val method = config.optString("method", "POST")
@@ -338,33 +336,31 @@ object AutoPrefetcher {
338
336
  body: String,
339
337
  responseType: String,
340
338
  config: JSONObject
341
- ): Map<String, String> {
342
- val result = mutableMapOf<String, String>()
339
+ ): TokenRefreshResult {
340
+ val headers = mutableMapOf<String, String>()
341
+ val bodyFields = mutableMapOf<String, String>()
342
+ val formFields = mutableMapOf<String, String>()
343
343
 
344
344
  if (responseType == "text") {
345
345
  val textHeader = config.optString("textHeader", null)
346
346
  if (textHeader != null) {
347
347
  val textTemplate = config.optString("textTemplate", null)
348
- result[textHeader] = textTemplate?.replace("{{value}}", body) ?: body
348
+ headers[textHeader] = textTemplate?.replace("{{value}}", body) ?: body
349
349
  }
350
- return result
350
+ config.optString("bodyTextPath", null)?.let { bodyFields[it] = body }
351
+ config.optString("formDataTextField", null)?.let { formFields[it] = body }
352
+ return TokenRefreshResult(headers, bodyFields, formFields)
351
353
  }
352
354
 
353
355
  // JSON
354
- val json = try { JSONObject(body) } catch (_: Throwable) { return result }
355
-
356
- val mappings = config.optJSONArray("mappings")
357
- if (mappings != null) {
358
- for (i in 0 until mappings.length()) {
359
- val m = mappings.optJSONObject(i) ?: continue
360
- val jsonPath = m.optString("jsonPath", null) ?: continue
361
- val header = m.optString("header", null) ?: continue
362
- val value = getNestedField(json, jsonPath) ?: continue
363
- val tmpl = m.optString("valueTemplate", null)
364
- result[header] = tmpl?.replace("{{value}}", value) ?: value
365
- }
356
+ val json = try { JSONObject(body) } catch (_: Throwable) {
357
+ return TokenRefreshResult(headers, bodyFields, formFields)
366
358
  }
367
359
 
360
+ collectMappings(json, config.optJSONArray("mappings"), "header", headers)
361
+ collectMappings(json, config.optJSONArray("bodyMappings"), "bodyPath", bodyFields)
362
+ collectMappings(json, config.optJSONArray("formDataMappings"), "field", formFields)
363
+
368
364
  val compositeHeaders = config.optJSONArray("compositeHeaders")
369
365
  if (compositeHeaders != null) {
370
366
  for (i in 0 until compositeHeaders.length()) {
@@ -377,11 +373,29 @@ object AutoPrefetcher {
377
373
  val val2 = getNestedField(json, paths.optString(ph, ""))
378
374
  built = built.replace("{{$ph}}", val2 ?: "")
379
375
  }
380
- result[header] = built
376
+ headers[header] = built
381
377
  }
382
378
  }
383
379
 
384
- return result
380
+ return TokenRefreshResult(headers, bodyFields, formFields)
381
+ }
382
+
383
+ // jsonPath -> value (optionally templated), keyed by the mapping's `destKey` field.
384
+ private fun collectMappings(
385
+ json: JSONObject,
386
+ arr: JSONArray?,
387
+ destKey: String,
388
+ into: MutableMap<String, String>,
389
+ ) {
390
+ if (arr == null) return
391
+ for (i in 0 until arr.length()) {
392
+ val m = arr.optJSONObject(i) ?: continue
393
+ val jsonPath = m.optString("jsonPath", null) ?: continue
394
+ val dest = m.optString(destKey, null) ?: continue
395
+ val value = getNestedField(json, jsonPath) ?: continue
396
+ val tmpl = m.optString("valueTemplate", null)
397
+ into[dest] = tmpl?.replace("{{value}}", value) ?: value
398
+ }
385
399
  }
386
400
 
387
401
  private fun getNestedField(obj: JSONObject, dotPath: String): String? {
@@ -393,4 +407,83 @@ object AutoPrefetcher {
393
407
  }
394
408
  return current.toString()
395
409
  }
410
+
411
+ private fun setNestedField(root: JSONObject, dotPath: String, value: String) {
412
+ val parts = dotPath.split(".")
413
+ var current = root
414
+ for (i in 0 until parts.size - 1) {
415
+ val key = parts[i]
416
+ val existing = current.optJSONObject(key)
417
+ current = existing ?: JSONObject().also { current.put(key, it) }
418
+ }
419
+ current.put(parts.last(), value)
420
+ }
421
+
422
+ private fun injectBodyFields(rawBody: String?, fields: Map<String, String>): String? {
423
+ if (fields.isEmpty()) return rawBody
424
+ // Don't synthesize a JSON body where there wasn't one (e.g. a GET or a
425
+ // form-data request) — only rewrite an existing JSON body.
426
+ if (rawBody.isNullOrEmpty()) return rawBody
427
+ val root = try {
428
+ JSONObject(rawBody)
429
+ } catch (_: Throwable) {
430
+ return rawBody
431
+ }
432
+ fields.forEach { (path, value) -> setNestedField(root, path, value) }
433
+ return root.toString()
434
+ }
435
+
436
+ private fun injectFormFields(
437
+ parts: List<NitroFormDataPart>,
438
+ fields: Map<String, String>,
439
+ ): List<NitroFormDataPart>? {
440
+ if (fields.isEmpty()) return parts.ifEmpty { null }
441
+ // Don't synthesize a multipart body where there wasn't one.
442
+ if (parts.isEmpty()) return null
443
+ val result = parts.toMutableList()
444
+ fields.forEach { (name, value) ->
445
+ val idx = result.indexOfFirst { it.name == name }
446
+ if (idx >= 0) {
447
+ val old = result[idx]
448
+ result[idx] = NitroFormDataPart(
449
+ name = old.name, value = value,
450
+ fileUri = null, fileName = old.fileName, mimeType = old.mimeType
451
+ )
452
+ } else {
453
+ result.add(NitroFormDataPart(name, value, null, null, null))
454
+ }
455
+ }
456
+ return result
457
+ }
458
+
459
+ private fun mapToJson(map: Map<String, String>): JSONObject {
460
+ val o = JSONObject()
461
+ map.forEach { (k, v) -> o.put(k, v) }
462
+ return o
463
+ }
464
+
465
+ private fun jsonToMap(obj: JSONObject?): Map<String, String> {
466
+ if (obj == null) return emptyMap()
467
+ return obj.keys().asSequence().associateWith { k -> obj.optString(k, "") }
468
+ }
469
+
470
+ private fun serializeCache(result: TokenRefreshResult): String =
471
+ JSONObject().apply {
472
+ put("headers", mapToJson(result.headers))
473
+ put("bodyFields", mapToJson(result.bodyFields))
474
+ put("formFields", mapToJson(result.formFields))
475
+ }.toString()
476
+
477
+ private fun deserializeCache(raw: String?): TokenRefreshResult {
478
+ if (raw.isNullOrEmpty()) return TokenRefreshResult.EMPTY
479
+ val o = try { JSONObject(raw) } catch (_: Throwable) { return TokenRefreshResult.EMPTY }
480
+ if (!o.has("headers") && !o.has("bodyFields") && !o.has("formFields")) {
481
+ return TokenRefreshResult(jsonToMap(o), emptyMap(), emptyMap())
482
+ }
483
+ return TokenRefreshResult(
484
+ headers = jsonToMap(o.optJSONObject("headers")),
485
+ bodyFields = jsonToMap(o.optJSONObject("bodyFields")),
486
+ formFields = jsonToMap(o.optJSONObject("formFields")),
487
+ )
488
+ }
396
489
  }
@@ -1,67 +1,58 @@
1
1
  package com.margelo.nitro.nitrofetch
2
2
 
3
- /**
4
- * Direct-dispatch backend for [DevToolsReporter]. Loaded reflectively from the facade
5
- * via `Class.forName`, so a missing `InspectorNetworkReporter` only prevents *this* class
6
- * from loading — the facade itself stays intact and degrades to a no-op.
7
- *
8
- * Once loaded, every call here is a plain JVM static invoke. No reflection, no boxing,
9
- * no method-handle lookups. The `@Suppress` annotations bypass RN's `internal` visibility
10
- * (RN has no public surface here) — this is the documented integration point.
11
- */
12
- @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
3
+ import java.lang.reflect.Method
4
+
5
+
13
6
  internal class DevToolsReporterImpl : DevToolsReporter.Impl {
14
- override fun isDebuggingEnabled(): Boolean =
15
- com.facebook.react.modules.network.InspectorNetworkReporter.isDebuggingEnabled()
7
+ private val cls = Class.forName("com.facebook.react.modules.network.InspectorNetworkReporter")
8
+
9
+ private fun m(name: String): Method = cls.methods.first { it.name == name }
10
+
11
+ // All targets are `public static final` on the reporter object — invoke with a null receiver.
12
+ private val mIsDebuggingEnabled = m("isDebuggingEnabled")
13
+ private val mReportRequestStart = m("reportRequestStart")
14
+ private val mReportConnectionTiming = m("reportConnectionTiming")
15
+ private val mReportResponseStart = m("reportResponseStart")
16
+ private val mReportDataReceivedImpl = m("reportDataReceivedImpl")
17
+ private val mReportResponseEnd = m("reportResponseEnd")
18
+ private val mReportRequestFailed = m("reportRequestFailed")
19
+ private val mMaybeStoreResponseBody = m("maybeStoreResponseBody")
20
+ private val mMaybeStoreResponseBodyIncremental = m("maybeStoreResponseBodyIncremental")
21
+
22
+ override fun isDebuggingEnabled(): Boolean = mIsDebuggingEnabled.invoke(null) as Boolean
16
23
 
17
24
  override fun reportRequestStart(
18
25
  requestId: String, url: String, method: String,
19
26
  headers: Map<String, String>, body: String, encodedDataLength: Long
20
27
  ) {
21
- com.facebook.react.modules.network.InspectorNetworkReporter.reportRequestStart(
22
- requestId, url, method, headers, body, encodedDataLength
23
- )
24
- com.facebook.react.modules.network.InspectorNetworkReporter.reportConnectionTiming(
25
- requestId, headers
26
- )
28
+ mReportRequestStart.invoke(null, requestId, url, method, headers, body, encodedDataLength)
29
+ mReportConnectionTiming.invoke(null, requestId, headers)
27
30
  }
28
31
 
29
32
  override fun reportResponseStart(
30
33
  requestId: String, url: String, statusCode: Int,
31
34
  headers: Map<String, String>, expectedDataLength: Long
32
35
  ) {
33
- com.facebook.react.modules.network.InspectorNetworkReporter.reportResponseStart(
34
- requestId, url, statusCode, headers, expectedDataLength
35
- )
36
+ mReportResponseStart.invoke(null, requestId, url, statusCode, headers, expectedDataLength)
36
37
  }
37
38
 
38
39
  override fun reportDataReceived(requestId: String, length: Int) {
39
- com.facebook.react.modules.network.InspectorNetworkReporter.reportDataReceivedImpl(
40
- requestId, length
41
- )
40
+ mReportDataReceivedImpl.invoke(null, requestId, length)
42
41
  }
43
42
 
44
43
  override fun reportResponseEnd(requestId: String, encodedDataLength: Long) {
45
- com.facebook.react.modules.network.InspectorNetworkReporter.reportResponseEnd(
46
- requestId, encodedDataLength
47
- )
44
+ mReportResponseEnd.invoke(null, requestId, encodedDataLength)
48
45
  }
49
46
 
50
47
  override fun reportRequestFailed(requestId: String, cancelled: Boolean) {
51
- com.facebook.react.modules.network.InspectorNetworkReporter.reportRequestFailed(
52
- requestId, cancelled
53
- )
48
+ mReportRequestFailed.invoke(null, requestId, cancelled)
54
49
  }
55
50
 
56
51
  override fun storeResponseBody(requestId: String, body: String, base64Encoded: Boolean) {
57
- com.facebook.react.modules.network.InspectorNetworkReporter.maybeStoreResponseBody(
58
- requestId, body, base64Encoded
59
- )
52
+ mMaybeStoreResponseBody.invoke(null, requestId, body, base64Encoded)
60
53
  }
61
54
 
62
55
  override fun storeResponseBodyIncremental(requestId: String, data: String) {
63
- com.facebook.react.modules.network.InspectorNetworkReporter.maybeStoreResponseBodyIncremental(
64
- requestId, data
65
- )
56
+ mMaybeStoreResponseBodyIncremental.invoke(null, requestId, data)
66
57
  }
67
58
  }