react-native-nitro-fetch 0.3.0-beta.1 → 0.3.0

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 (51) hide show
  1. package/NitroFetch.podspec +8 -0
  2. package/android/build.gradle +3 -0
  3. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt +46 -2
  4. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchPackage.kt +2 -2
  5. package/ios/NitroFetchClient.swift +36 -1
  6. package/lib/module/CurlGenerator.js +28 -0
  7. package/lib/module/CurlGenerator.js.map +1 -0
  8. package/lib/module/Headers.js +95 -0
  9. package/lib/module/Headers.js.map +1 -0
  10. package/lib/module/HermesProfiler.js +28 -0
  11. package/lib/module/HermesProfiler.js.map +1 -0
  12. package/lib/module/NetworkInspector.js +184 -0
  13. package/lib/module/NetworkInspector.js.map +1 -0
  14. package/lib/module/Request.js +120 -0
  15. package/lib/module/Request.js.map +1 -0
  16. package/lib/module/Response.js +236 -0
  17. package/lib/module/Response.js.map +1 -0
  18. package/lib/module/fetch.js +143 -56
  19. package/lib/module/fetch.js.map +1 -1
  20. package/lib/module/index.js +6 -0
  21. package/lib/module/index.js.map +1 -1
  22. package/lib/module/utf8.js +29 -0
  23. package/lib/module/utf8.js.map +1 -0
  24. package/lib/typescript/src/CurlGenerator.d.ts +13 -0
  25. package/lib/typescript/src/CurlGenerator.d.ts.map +1 -0
  26. package/lib/typescript/src/Headers.d.ts +19 -0
  27. package/lib/typescript/src/Headers.d.ts.map +1 -0
  28. package/lib/typescript/src/HermesProfiler.d.ts +6 -0
  29. package/lib/typescript/src/HermesProfiler.d.ts.map +1 -0
  30. package/lib/typescript/src/NetworkInspector.d.ts +96 -0
  31. package/lib/typescript/src/NetworkInspector.d.ts.map +1 -0
  32. package/lib/typescript/src/Request.d.ts +48 -0
  33. package/lib/typescript/src/Request.d.ts.map +1 -0
  34. package/lib/typescript/src/Response.d.ts +56 -0
  35. package/lib/typescript/src/Response.d.ts.map +1 -0
  36. package/lib/typescript/src/fetch.d.ts +11 -3
  37. package/lib/typescript/src/fetch.d.ts.map +1 -1
  38. package/lib/typescript/src/index.d.ts +13 -1
  39. package/lib/typescript/src/index.d.ts.map +1 -1
  40. package/lib/typescript/src/utf8.d.ts +3 -0
  41. package/lib/typescript/src/utf8.d.ts.map +1 -0
  42. package/package.json +1 -1
  43. package/src/CurlGenerator.ts +44 -0
  44. package/src/Headers.ts +127 -0
  45. package/src/HermesProfiler.ts +37 -0
  46. package/src/NetworkInspector.ts +278 -0
  47. package/src/Request.ts +187 -0
  48. package/src/Response.ts +335 -0
  49. package/src/fetch.ts +186 -75
  50. package/src/index.tsx +22 -1
  51. package/src/utf8.ts +40 -0
@@ -26,5 +26,13 @@ Pod::Spec.new do |s|
26
26
  load 'nitrogen/generated/ios/NitroFetch+autolinking.rb'
27
27
  add_nitrogen_files(s)
28
28
 
29
+ if ENV['NITROFETCH_TRACING'] == '1'
30
+ current_xcconfig = s.attributes_hash['pod_target_xcconfig'] || {}
31
+ existing = current_xcconfig['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] || '$(inherited)'
32
+ s.pod_target_xcconfig = current_xcconfig.merge({
33
+ 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => "#{existing} NITROFETCH_TRACING"
34
+ })
35
+ end
36
+
29
37
  install_modules_dependencies(s)
30
38
  end
@@ -39,6 +39,9 @@ android {
39
39
  minSdkVersion getExtOrIntegerDefault("minSdkVersion")
40
40
  targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
41
41
 
42
+ def enableTracing = (getExtOrDefault("enableTracing") ?: "false").toString().toBoolean()
43
+ buildConfigField "boolean", "NITRO_FETCH_TRACING", enableTracing.toString()
44
+
42
45
  externalNativeBuild {
43
46
  cmake {
44
47
  cppFlags "-frtti -fexceptions -Wall -fstack-protector-all"
@@ -1,6 +1,7 @@
1
1
  package com.margelo.nitro.nitrofetch
2
2
 
3
3
  import android.net.Uri
4
+ import android.os.Trace
4
5
  import android.util.Log
5
6
  import com.facebook.proguard.annotations.DoNotStrip
6
7
  import com.margelo.nitro.NitroModules
@@ -71,12 +72,44 @@ class NitroFetchClient(private val engine: CronetEngine, private val executor: E
71
72
  onFail: (Throwable) -> Unit
72
73
  ): UrlRequest {
73
74
  val url = req.url
75
+ val shouldFollowRedirects = req.followRedirects ?: true
76
+ val traceLabel = if (BuildConfig.NITRO_FETCH_TRACING) {
77
+ "NitroFetch ${req.method?.name ?: "GET"} ${Uri.parse(url).path ?: url}"
78
+ } else ""
79
+ val traceCookie = if (BuildConfig.NITRO_FETCH_TRACING) url.hashCode() else 0
80
+ if (BuildConfig.NITRO_FETCH_TRACING) {
81
+ Trace.beginAsyncSection(traceLabel, traceCookie)
82
+ }
74
83
  val callback = object : UrlRequest.Callback() {
75
84
  private val buffer = ByteBuffer.allocateDirect(16 * 1024)
76
85
  private val out = java.io.ByteArrayOutputStream()
86
+ private var redirectStopped = false
77
87
 
78
88
  override fun onRedirectReceived(request: UrlRequest, info: UrlResponseInfo, newLocationUrl: String) {
79
- request.followRedirect()
89
+ if (shouldFollowRedirects) {
90
+ request.followRedirect()
91
+ } else {
92
+ // Return the redirect response as-is without following
93
+ redirectStopped = true
94
+ request.cancel()
95
+ try {
96
+ val headersArr = info.allHeadersAsList.map { NitroHeader(it.key, it.value) }.toTypedArray()
97
+ val status = info.httpStatusCode
98
+ val res = NitroResponse(
99
+ url = info.url,
100
+ status = status.toDouble(),
101
+ statusText = info.httpStatusText ?: "",
102
+ ok = false,
103
+ redirected = false,
104
+ headers = headersArr,
105
+ bodyString = "",
106
+ bodyBytes = null
107
+ )
108
+ onSuccess(res)
109
+ } catch (t: Throwable) {
110
+ onFail(t)
111
+ }
112
+ }
80
113
  }
81
114
 
82
115
  override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) {
@@ -94,6 +127,9 @@ class NitroFetchClient(private val engine: CronetEngine, private val executor: E
94
127
  }
95
128
 
96
129
  override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) {
130
+ if (BuildConfig.NITRO_FETCH_TRACING) {
131
+ Trace.endAsyncSection(traceLabel, traceCookie)
132
+ }
97
133
  try {
98
134
  val headersArr: Array<NitroHeader> =
99
135
  info.allHeadersAsList.map { NitroHeader(it.key, it.value) }.toTypedArray()
@@ -127,11 +163,19 @@ class NitroFetchClient(private val engine: CronetEngine, private val executor: E
127
163
  }
128
164
 
129
165
  override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) {
166
+ if (BuildConfig.NITRO_FETCH_TRACING) {
167
+ Trace.endAsyncSection(traceLabel, traceCookie)
168
+ }
130
169
  onFail(RuntimeException("Cronet failed: ${error.message}", error))
131
170
  }
132
171
 
133
172
  override fun onCanceled(request: UrlRequest, info: UrlResponseInfo?) {
134
- onFail(RuntimeException("Cronet canceled"))
173
+ if (BuildConfig.NITRO_FETCH_TRACING) {
174
+ Trace.endAsyncSection(traceLabel, traceCookie)
175
+ }
176
+ if (!redirectStopped) {
177
+ onFail(RuntimeException("Cronet canceled"))
178
+ }
135
179
  }
136
180
  }
137
181
 
@@ -1,11 +1,11 @@
1
1
  package com.margelo.nitro.nitrofetch
2
2
 
3
- import com.facebook.react.TurboReactPackage
3
+ import com.facebook.react.BaseReactPackage
4
4
  import com.facebook.react.bridge.NativeModule
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.module.model.ReactModuleInfoProvider
7
7
 
8
- class NitroFetchPackage : TurboReactPackage() {
8
+ class NitroFetchPackage : BaseReactPackage() {
9
9
  override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
10
10
  return null
11
11
  }
@@ -1,5 +1,10 @@
1
1
  import Foundation
2
2
  import NitroModules
3
+ import os
4
+
5
+ #if NITROFETCH_TRACING
6
+ private let fetchLog = OSLog(subsystem: "com.margelo.nitrofetch", category: "network")
7
+ #endif
3
8
 
4
9
  final class NitroFetchClient: HybridNitroFetchClientSpec {
5
10
 
@@ -154,7 +159,18 @@ final class NitroFetchClient: HybridNitroFetchClientSpec {
154
159
  }
155
160
 
156
161
  let (urlRequest, finalURL) = try await buildURLRequest(req)
157
- let (data, response) = try await session.data(for: urlRequest)
162
+ let shouldFollowRedirects = req.followRedirects ?? true
163
+ let delegate: URLSessionTaskDelegate? = shouldFollowRedirects ? nil : NoRedirectDelegate()
164
+
165
+ #if NITROFETCH_TRACING
166
+ let signpostID = OSSignpostID(log: fetchLog)
167
+ let traceMethod = req.method?.stringValue ?? "GET"
168
+ let tracePath = URL(string: req.url)?.path ?? req.url
169
+ os_signpost(.begin, log: fetchLog, name: "NitroFetch", signpostID: signpostID,
170
+ "%{public}s %{public}s", traceMethod, tracePath)
171
+ #endif
172
+
173
+ let (data, response) = try await session.data(for: urlRequest, delegate: delegate)
158
174
  guard let http = response as? HTTPURLResponse else {
159
175
  throw NSError(domain: "NitroFetch", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])
160
176
  }
@@ -181,6 +197,11 @@ final class NitroFetchClient: HybridNitroFetchClientSpec {
181
197
 
182
198
  // Do not write to cache here; only prefetch should populate the cache
183
199
 
200
+ #if NITROFETCH_TRACING
201
+ os_signpost(.end, log: fetchLog, name: "NitroFetch", signpostID: signpostID,
202
+ "status=%d bytes=%d", http.statusCode, data.count)
203
+ #endif
204
+
184
205
  return res
185
206
  }
186
207
 
@@ -310,3 +331,17 @@ final class NitroFetchClient: HybridNitroFetchClientSpec {
310
331
  return nil
311
332
  }
312
333
  }
334
+
335
+ /// Delegate that prevents URLSession from following HTTP redirects.
336
+ /// When the completion handler receives `nil`, the 3xx response is returned as-is.
337
+ final class NoRedirectDelegate: NSObject, URLSessionTaskDelegate {
338
+ func urlSession(
339
+ _ session: URLSession,
340
+ task: URLSessionTask,
341
+ willPerformHTTPRedirection response: HTTPURLResponse,
342
+ newRequest request: URLRequest,
343
+ completionHandler: @escaping @Sendable (URLRequest?) -> Void
344
+ ) {
345
+ completionHandler(nil)
346
+ }
347
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ function shellEscape(str) {
4
+ if (/^[a-zA-Z0-9._\-/:=@,+]+$/.test(str)) return str;
5
+ return "'" + str.replace(/'/g, "'\\''") + "'";
6
+ }
7
+ export function generateCurl(options) {
8
+ const parts = ['curl'];
9
+ if (options.method && options.method !== 'GET') {
10
+ parts.push('-X', shellEscape(options.method));
11
+ }
12
+ if (options.headers) {
13
+ for (const h of options.headers) {
14
+ if (h.key.toLowerCase() === 'prefetchkey') continue;
15
+ parts.push('-H', shellEscape(`${h.key}: ${h.value}`));
16
+ }
17
+ }
18
+ if (options.body) {
19
+ const maxLen = 10_000;
20
+ const truncated = options.body.length > maxLen ? options.body.slice(0, maxLen) + '...[truncated]' : options.body;
21
+ parts.push('-d', shellEscape(truncated));
22
+ }
23
+ if (options.verbose) parts.push('-v');
24
+ if (options.compressed) parts.push('--compressed');
25
+ parts.push(shellEscape(options.url));
26
+ return parts.join(' ');
27
+ }
28
+ //# sourceMappingURL=CurlGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["shellEscape","str","test","replace","generateCurl","options","parts","method","push","headers","h","key","toLowerCase","value","body","maxLen","truncated","length","slice","verbose","compressed","url","join"],"sourceRoot":"../../src","sources":["CurlGenerator.ts"],"mappings":";;AASA,SAASA,WAAWA,CAACC,GAAW,EAAU;EACxC,IAAI,0BAA0B,CAACC,IAAI,CAACD,GAAG,CAAC,EAAE,OAAOA,GAAG;EACpD,OAAO,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,GAAG;AAC/C;AAEA,OAAO,SAASC,YAAYA,CAACC,OAAoB,EAAU;EACzD,MAAMC,KAAe,GAAG,CAAC,MAAM,CAAC;EAEhC,IAAID,OAAO,CAACE,MAAM,IAAIF,OAAO,CAACE,MAAM,KAAK,KAAK,EAAE;IAC9CD,KAAK,CAACE,IAAI,CAAC,IAAI,EAAER,WAAW,CAACK,OAAO,CAACE,MAAM,CAAC,CAAC;EAC/C;EAEA,IAAIF,OAAO,CAACI,OAAO,EAAE;IACnB,KAAK,MAAMC,CAAC,IAAIL,OAAO,CAACI,OAAO,EAAE;MAC/B,IAAIC,CAAC,CAACC,GAAG,CAACC,WAAW,CAAC,CAAC,KAAK,aAAa,EAAE;MAC3CN,KAAK,CAACE,IAAI,CAAC,IAAI,EAAER,WAAW,CAAC,GAAGU,CAAC,CAACC,GAAG,KAAKD,CAAC,CAACG,KAAK,EAAE,CAAC,CAAC;IACvD;EACF;EAEA,IAAIR,OAAO,CAACS,IAAI,EAAE;IAChB,MAAMC,MAAM,GAAG,MAAM;IACrB,MAAMC,SAAS,GACbX,OAAO,CAACS,IAAI,CAACG,MAAM,GAAGF,MAAM,GACxBV,OAAO,CAACS,IAAI,CAACI,KAAK,CAAC,CAAC,EAAEH,MAAM,CAAC,GAAG,gBAAgB,GAChDV,OAAO,CAACS,IAAI;IAClBR,KAAK,CAACE,IAAI,CAAC,IAAI,EAAER,WAAW,CAACgB,SAAS,CAAC,CAAC;EAC1C;EAEA,IAAIX,OAAO,CAACc,OAAO,EAAEb,KAAK,CAACE,IAAI,CAAC,IAAI,CAAC;EACrC,IAAIH,OAAO,CAACe,UAAU,EAAEd,KAAK,CAACE,IAAI,CAAC,cAAc,CAAC;EAElDF,KAAK,CAACE,IAAI,CAACR,WAAW,CAACK,OAAO,CAACgB,GAAG,CAAC,CAAC;EAEpC,OAAOf,KAAK,CAACgB,IAAI,CAAC,GAAG,CAAC;AACxB","ignoreList":[]}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+
3
+ function normalizeName(name) {
4
+ return name.toLowerCase();
5
+ }
6
+ export class NitroHeaders {
7
+ constructor(init) {
8
+ this._map = new Map();
9
+ if (!init) return;
10
+ if (init instanceof NitroHeaders) {
11
+ init._map.forEach((values, key) => {
12
+ this._map.set(key, [...values]);
13
+ });
14
+ } else if (typeof Headers !== 'undefined' && init instanceof Headers) {
15
+ init.forEach((value, key) => {
16
+ this._map.set(normalizeName(key), [value]);
17
+ });
18
+ } else if (Array.isArray(init)) {
19
+ for (const entry of init) {
20
+ if (Array.isArray(entry) && entry.length >= 2) {
21
+ // [string, string] tuple
22
+ const key = normalizeName(String(entry[0]));
23
+ const value = String(entry[1]);
24
+ const existing = this._map.get(key);
25
+ if (existing) existing.push(value);else this._map.set(key, [value]);
26
+ } else if (entry && typeof entry === 'object' && 'key' in entry && 'value' in entry) {
27
+ // NitroHeader object
28
+ const key = normalizeName(entry.key);
29
+ const value = entry.value;
30
+ const existing = this._map.get(key);
31
+ if (existing) existing.push(value);else this._map.set(key, [value]);
32
+ }
33
+ }
34
+ } else if (typeof init === 'object' && init !== null) {
35
+ const keys = Object.keys(init);
36
+ for (let i = 0; i < keys.length; i++) {
37
+ const k = keys[i];
38
+ const v = init[k];
39
+ if (v !== undefined) {
40
+ this._map.set(normalizeName(k), [String(v)]);
41
+ }
42
+ }
43
+ }
44
+ }
45
+ append(name, value) {
46
+ const key = normalizeName(name);
47
+ const existing = this._map.get(key);
48
+ if (existing) existing.push(value);else this._map.set(key, [value]);
49
+ }
50
+ delete(name) {
51
+ this._map.delete(normalizeName(name));
52
+ }
53
+ get(name) {
54
+ const values = this._map.get(normalizeName(name));
55
+ if (!values || values.length === 0) return null;
56
+ return values.join(', ');
57
+ }
58
+ getSetCookie() {
59
+ return this._map.get('set-cookie') ?? [];
60
+ }
61
+ has(name) {
62
+ return this._map.has(normalizeName(name));
63
+ }
64
+ set(name, value) {
65
+ this._map.set(normalizeName(name), [value]);
66
+ }
67
+ forEach(callback) {
68
+ const sortedKeys = Array.from(this._map.keys()).sort();
69
+ for (const key of sortedKeys) {
70
+ callback(this._map.get(key).join(', '), key, this);
71
+ }
72
+ }
73
+ *entries() {
74
+ const sortedKeys = Array.from(this._map.keys()).sort();
75
+ for (const key of sortedKeys) {
76
+ yield [key, this._map.get(key).join(', ')];
77
+ }
78
+ }
79
+ *keys() {
80
+ const sortedKeys = Array.from(this._map.keys()).sort();
81
+ for (const key of sortedKeys) {
82
+ yield key;
83
+ }
84
+ }
85
+ *values() {
86
+ const sortedKeys = Array.from(this._map.keys()).sort();
87
+ for (const key of sortedKeys) {
88
+ yield this._map.get(key).join(', ');
89
+ }
90
+ }
91
+ [Symbol.iterator]() {
92
+ return this.entries();
93
+ }
94
+ }
95
+ //# sourceMappingURL=Headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["normalizeName","name","toLowerCase","NitroHeaders","constructor","init","_map","Map","forEach","values","key","set","Headers","value","Array","isArray","entry","length","String","existing","get","push","keys","Object","i","k","v","undefined","append","delete","join","getSetCookie","has","callback","sortedKeys","from","sort","entries","Symbol","iterator"],"sourceRoot":"../../src","sources":["Headers.ts"],"mappings":";;AAUA,SAASA,aAAaA,CAACC,IAAY,EAAU;EAC3C,OAAOA,IAAI,CAACC,WAAW,CAAC,CAAC;AAC3B;AAEA,OAAO,MAAMC,YAAY,CAAC;EAGxBC,WAAWA,CAACC,IAAuB,EAAE;IACnC,IAAI,CAACC,IAAI,GAAG,IAAIC,GAAG,CAAC,CAAC;IACrB,IAAI,CAACF,IAAI,EAAE;IAEX,IAAIA,IAAI,YAAYF,YAAY,EAAE;MAChCE,IAAI,CAACC,IAAI,CAACE,OAAO,CAAC,CAACC,MAAM,EAAEC,GAAG,KAAK;QACjC,IAAI,CAACJ,IAAI,CAACK,GAAG,CAACD,GAAG,EAAE,CAAC,GAAGD,MAAM,CAAC,CAAC;MACjC,CAAC,CAAC;IACJ,CAAC,MAAM,IAAI,OAAOG,OAAO,KAAK,WAAW,IAAIP,IAAI,YAAYO,OAAO,EAAE;MACpEP,IAAI,CAACG,OAAO,CAAC,CAACK,KAAK,EAAEH,GAAG,KAAK;QAC3B,IAAI,CAACJ,IAAI,CAACK,GAAG,CAACX,aAAa,CAACU,GAAG,CAAC,EAAE,CAACG,KAAK,CAAC,CAAC;MAC5C,CAAC,CAAC;IACJ,CAAC,MAAM,IAAIC,KAAK,CAACC,OAAO,CAACV,IAAI,CAAC,EAAE;MAC9B,KAAK,MAAMW,KAAK,IAAIX,IAAI,EAAE;QACxB,IAAIS,KAAK,CAACC,OAAO,CAACC,KAAK,CAAC,IAAIA,KAAK,CAACC,MAAM,IAAI,CAAC,EAAE;UAC7C;UACA,MAAMP,GAAG,GAAGV,aAAa,CAACkB,MAAM,CAACF,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;UAC3C,MAAMH,KAAK,GAAGK,MAAM,CAACF,KAAK,CAAC,CAAC,CAAC,CAAC;UAC9B,MAAMG,QAAQ,GAAG,IAAI,CAACb,IAAI,CAACc,GAAG,CAACV,GAAG,CAAC;UACnC,IAAIS,QAAQ,EAAEA,QAAQ,CAACE,IAAI,CAACR,KAAK,CAAC,CAAC,KAC9B,IAAI,CAACP,IAAI,CAACK,GAAG,CAACD,GAAG,EAAE,CAACG,KAAK,CAAC,CAAC;QAClC,CAAC,MAAM,IACLG,KAAK,IACL,OAAOA,KAAK,KAAK,QAAQ,IACzB,KAAK,IAAIA,KAAK,IACd,OAAO,IAAIA,KAAK,EAChB;UACA;UACA,MAAMN,GAAG,GAAGV,aAAa,CAAEgB,KAAK,CAAiBN,GAAG,CAAC;UACrD,MAAMG,KAAK,GAAIG,KAAK,CAAiBH,KAAK;UAC1C,MAAMM,QAAQ,GAAG,IAAI,CAACb,IAAI,CAACc,GAAG,CAACV,GAAG,CAAC;UACnC,IAAIS,QAAQ,EAAEA,QAAQ,CAACE,IAAI,CAACR,KAAK,CAAC,CAAC,KAC9B,IAAI,CAACP,IAAI,CAACK,GAAG,CAACD,GAAG,EAAE,CAACG,KAAK,CAAC,CAAC;QAClC;MACF;IACF,CAAC,MAAM,IAAI,OAAOR,IAAI,KAAK,QAAQ,IAAIA,IAAI,KAAK,IAAI,EAAE;MACpD,MAAMiB,IAAI,GAAGC,MAAM,CAACD,IAAI,CAACjB,IAA8B,CAAC;MACxD,KAAK,IAAImB,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGF,IAAI,CAACL,MAAM,EAAEO,CAAC,EAAE,EAAE;QACpC,MAAMC,CAAC,GAAGH,IAAI,CAACE,CAAC,CAAE;QAClB,MAAME,CAAC,GAAIrB,IAAI,CAA4BoB,CAAC,CAAC;QAC7C,IAAIC,CAAC,KAAKC,SAAS,EAAE;UACnB,IAAI,CAACrB,IAAI,CAACK,GAAG,CAACX,aAAa,CAACyB,CAAC,CAAC,EAAE,CAACP,MAAM,CAACQ,CAAC,CAAC,CAAC,CAAC;QAC9C;MACF;IACF;EACF;EAEAE,MAAMA,CAAC3B,IAAY,EAAEY,KAAa,EAAQ;IACxC,MAAMH,GAAG,GAAGV,aAAa,CAACC,IAAI,CAAC;IAC/B,MAAMkB,QAAQ,GAAG,IAAI,CAACb,IAAI,CAACc,GAAG,CAACV,GAAG,CAAC;IACnC,IAAIS,QAAQ,EAAEA,QAAQ,CAACE,IAAI,CAACR,KAAK,CAAC,CAAC,KAC9B,IAAI,CAACP,IAAI,CAACK,GAAG,CAACD,GAAG,EAAE,CAACG,KAAK,CAAC,CAAC;EAClC;EAEAgB,MAAMA,CAAC5B,IAAY,EAAQ;IACzB,IAAI,CAACK,IAAI,CAACuB,MAAM,CAAC7B,aAAa,CAACC,IAAI,CAAC,CAAC;EACvC;EAEAmB,GAAGA,CAACnB,IAAY,EAAiB;IAC/B,MAAMQ,MAAM,GAAG,IAAI,CAACH,IAAI,CAACc,GAAG,CAACpB,aAAa,CAACC,IAAI,CAAC,CAAC;IACjD,IAAI,CAACQ,MAAM,IAAIA,MAAM,CAACQ,MAAM,KAAK,CAAC,EAAE,OAAO,IAAI;IAC/C,OAAOR,MAAM,CAACqB,IAAI,CAAC,IAAI,CAAC;EAC1B;EAEAC,YAAYA,CAAA,EAAa;IACvB,OAAO,IAAI,CAACzB,IAAI,CAACc,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE;EAC1C;EAEAY,GAAGA,CAAC/B,IAAY,EAAW;IACzB,OAAO,IAAI,CAACK,IAAI,CAAC0B,GAAG,CAAChC,aAAa,CAACC,IAAI,CAAC,CAAC;EAC3C;EAEAU,GAAGA,CAACV,IAAY,EAAEY,KAAa,EAAQ;IACrC,IAAI,CAACP,IAAI,CAACK,GAAG,CAACX,aAAa,CAACC,IAAI,CAAC,EAAE,CAACY,KAAK,CAAC,CAAC;EAC7C;EAEAL,OAAOA,CACLyB,QAAqE,EAC/D;IACN,MAAMC,UAAU,GAAGpB,KAAK,CAACqB,IAAI,CAAC,IAAI,CAAC7B,IAAI,CAACgB,IAAI,CAAC,CAAC,CAAC,CAACc,IAAI,CAAC,CAAC;IACtD,KAAK,MAAM1B,GAAG,IAAIwB,UAAU,EAAE;MAC5BD,QAAQ,CAAC,IAAI,CAAC3B,IAAI,CAACc,GAAG,CAACV,GAAG,CAAC,CAAEoB,IAAI,CAAC,IAAI,CAAC,EAAEpB,GAAG,EAAE,IAAI,CAAC;IACrD;EACF;EAEA,CAAC2B,OAAOA,CAAA,EAAuC;IAC7C,MAAMH,UAAU,GAAGpB,KAAK,CAACqB,IAAI,CAAC,IAAI,CAAC7B,IAAI,CAACgB,IAAI,CAAC,CAAC,CAAC,CAACc,IAAI,CAAC,CAAC;IACtD,KAAK,MAAM1B,GAAG,IAAIwB,UAAU,EAAE;MAC5B,MAAM,CAACxB,GAAG,EAAE,IAAI,CAACJ,IAAI,CAACc,GAAG,CAACV,GAAG,CAAC,CAAEoB,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C;EACF;EAEA,CAACR,IAAIA,CAAA,EAA6B;IAChC,MAAMY,UAAU,GAAGpB,KAAK,CAACqB,IAAI,CAAC,IAAI,CAAC7B,IAAI,CAACgB,IAAI,CAAC,CAAC,CAAC,CAACc,IAAI,CAAC,CAAC;IACtD,KAAK,MAAM1B,GAAG,IAAIwB,UAAU,EAAE;MAC5B,MAAMxB,GAAG;IACX;EACF;EAEA,CAACD,MAAMA,CAAA,EAA6B;IAClC,MAAMyB,UAAU,GAAGpB,KAAK,CAACqB,IAAI,CAAC,IAAI,CAAC7B,IAAI,CAACgB,IAAI,CAAC,CAAC,CAAC,CAACc,IAAI,CAAC,CAAC;IACtD,KAAK,MAAM1B,GAAG,IAAIwB,UAAU,EAAE;MAC5B,MAAM,IAAI,CAAC5B,IAAI,CAACc,GAAG,CAACV,GAAG,CAAC,CAAEoB,IAAI,CAAC,IAAI,CAAC;IACtC;EACF;EAEA,CAACQ,MAAM,CAACC,QAAQ,IAAwC;IACtD,OAAO,IAAI,CAACF,OAAO,CAAC,CAAC;EACvB;AACF","ignoreList":[]}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ export async function profileFetch(fn, outputPath) {
4
+ const hermes = global.HermesInternal;
5
+ if (!hermes) {
6
+ const result = await fn();
7
+ return {
8
+ result
9
+ };
10
+ }
11
+ const path = outputPath ?? `/tmp/nitrofetch-profile-${Date.now()}.cpuprofile`;
12
+ hermes.enableSamplingProfiler();
13
+ try {
14
+ const result = await fn();
15
+ return {
16
+ result,
17
+ profilePath: path
18
+ };
19
+ } finally {
20
+ hermes.disableSamplingProfiler();
21
+ try {
22
+ hermes.dumpSamplingProfiler(path);
23
+ } catch {
24
+ // Profile dump may fail on some platforms
25
+ }
26
+ }
27
+ }
28
+ //# sourceMappingURL=HermesProfiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["profileFetch","fn","outputPath","hermes","global","HermesInternal","result","path","Date","now","enableSamplingProfiler","profilePath","disableSamplingProfiler","dumpSamplingProfiler"],"sourceRoot":"../../src","sources":["HermesProfiler.ts"],"mappings":";;AAaA,OAAO,eAAeA,YAAYA,CAChCC,EAAoB,EACpBC,UAAmB,EACQ;EAC3B,MAAMC,MAAM,GAAGC,MAAM,CAACC,cAAc;EACpC,IAAI,CAACF,MAAM,EAAE;IACX,MAAMG,MAAM,GAAG,MAAML,EAAE,CAAC,CAAC;IACzB,OAAO;MAAEK;IAAO,CAAC;EACnB;EAEA,MAAMC,IAAI,GAAGL,UAAU,IAAI,2BAA2BM,IAAI,CAACC,GAAG,CAAC,CAAC,aAAa;EAC7EN,MAAM,CAACO,sBAAsB,CAAC,CAAC;EAC/B,IAAI;IACF,MAAMJ,MAAM,GAAG,MAAML,EAAE,CAAC,CAAC;IACzB,OAAO;MAAEK,MAAM;MAAEK,WAAW,EAAEJ;IAAK,CAAC;EACtC,CAAC,SAAS;IACRJ,MAAM,CAACS,uBAAuB,CAAC,CAAC;IAChC,IAAI;MACFT,MAAM,CAACU,oBAAoB,CAACN,IAAI,CAAC;IACnC,CAAC,CAAC,MAAM;MACN;IAAA;EAEJ;AACF","ignoreList":[]}
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+
3
+ import { generateCurl } from "./CurlGenerator.js";
4
+ class NetworkInspectorImpl {
5
+ _enabled = false;
6
+ _entries = [];
7
+ _maxEntries = 500;
8
+ _maxBodyCapture = 4096;
9
+ _listeners = new Set();
10
+ enable(options) {
11
+ this._enabled = true;
12
+ if (options?.maxEntries != null) this._maxEntries = options.maxEntries;
13
+ if (options?.maxBodyCapture != null) this._maxBodyCapture = options.maxBodyCapture;
14
+ }
15
+ disable() {
16
+ this._enabled = false;
17
+ }
18
+ isEnabled() {
19
+ return this._enabled;
20
+ }
21
+ getEntries() {
22
+ return this._entries;
23
+ }
24
+ getHttpEntries() {
25
+ return this._entries.filter(e => e.type === 'http');
26
+ }
27
+ getWebSocketEntries() {
28
+ return this._entries.filter(e => e.type === 'websocket');
29
+ }
30
+ getEntry(id) {
31
+ return this._entries.find(e => e.id === id);
32
+ }
33
+ clear() {
34
+ this._entries = [];
35
+ }
36
+ onEntry(callback) {
37
+ this._listeners.add(callback);
38
+ return () => {
39
+ this._listeners.delete(callback);
40
+ };
41
+ }
42
+ _notify(entry) {
43
+ for (const cb of this._listeners) {
44
+ try {
45
+ cb(entry);
46
+ } catch {
47
+ // swallow listener errors
48
+ }
49
+ }
50
+ }
51
+ _trimEntries() {
52
+ if (this._entries.length > this._maxEntries) {
53
+ this._entries.shift();
54
+ }
55
+ }
56
+
57
+ // --- HTTP recording ---
58
+
59
+ _recordStart(id, url, method, headers, body) {
60
+ if (!this._enabled) return;
61
+ const bodySize = body ? body.length : 0;
62
+ const entry = {
63
+ id,
64
+ type: 'http',
65
+ url,
66
+ method,
67
+ requestHeaders: headers.map(h => ({
68
+ key: h.key,
69
+ value: h.value
70
+ })),
71
+ requestBody: body ? body.slice(0, this._maxBodyCapture) : undefined,
72
+ requestBodySize: bodySize,
73
+ status: 0,
74
+ statusText: '',
75
+ responseHeaders: [],
76
+ responseBodySize: 0,
77
+ startTime: performance.now(),
78
+ endTime: 0,
79
+ duration: 0,
80
+ curl: generateCurl({
81
+ url,
82
+ method,
83
+ headers,
84
+ body
85
+ })
86
+ };
87
+ this._entries.push(entry);
88
+ this._trimEntries();
89
+ }
90
+ _recordEnd(id, status, statusText, headers, bodySize, error, responseBody) {
91
+ if (!this._enabled) return;
92
+ const entry = this._entries.find(e => e.id === id && e.type === 'http');
93
+ if (!entry) return;
94
+ entry.status = status;
95
+ entry.statusText = statusText;
96
+ entry.responseHeaders = headers.map(h => ({
97
+ key: h.key,
98
+ value: h.value
99
+ }));
100
+ entry.responseBodySize = bodySize;
101
+ entry.endTime = performance.now();
102
+ entry.duration = entry.endTime - entry.startTime;
103
+ if (error) entry.error = error;
104
+ if (responseBody != null) {
105
+ entry.responseBody = responseBody.slice(0, this._maxBodyCapture);
106
+ }
107
+ this._notify(entry);
108
+ }
109
+
110
+ // --- WebSocket recording ---
111
+
112
+ _recordWsOpen(id, url, protocols, headers) {
113
+ if (!this._enabled) return;
114
+ const entry = {
115
+ id,
116
+ type: 'websocket',
117
+ url,
118
+ protocols,
119
+ requestHeaders: headers.map(h => ({
120
+ key: h.key,
121
+ value: h.value
122
+ })),
123
+ startTime: performance.now(),
124
+ endTime: 0,
125
+ duration: 0,
126
+ readyState: 'CONNECTING',
127
+ messages: [],
128
+ messagesSent: 0,
129
+ messagesReceived: 0,
130
+ bytesSent: 0,
131
+ bytesReceived: 0
132
+ };
133
+ this._entries.push(entry);
134
+ this._trimEntries();
135
+ this._notify(entry);
136
+ }
137
+ _recordWsConnected(id) {
138
+ if (!this._enabled) return;
139
+ const entry = this._entries.find(e => e.id === id && e.type === 'websocket');
140
+ if (!entry) return;
141
+ entry.readyState = 'OPEN';
142
+ this._notify(entry);
143
+ }
144
+ _recordWsMessage(id, direction, data, size, isBinary) {
145
+ if (!this._enabled) return;
146
+ const entry = this._entries.find(e => e.id === id && e.type === 'websocket');
147
+ if (!entry) return;
148
+ entry.messages.push({
149
+ direction,
150
+ data: data.slice(0, this._maxBodyCapture),
151
+ size,
152
+ isBinary,
153
+ timestamp: performance.now()
154
+ });
155
+ if (direction === 'sent') {
156
+ entry.messagesSent++;
157
+ entry.bytesSent += size;
158
+ } else {
159
+ entry.messagesReceived++;
160
+ entry.bytesReceived += size;
161
+ }
162
+ this._notify(entry);
163
+ }
164
+ _recordWsClose(id, code, reason) {
165
+ if (!this._enabled) return;
166
+ const entry = this._entries.find(e => e.id === id && e.type === 'websocket');
167
+ if (!entry) return;
168
+ entry.readyState = 'CLOSED';
169
+ entry.closeCode = code;
170
+ entry.closeReason = reason;
171
+ entry.endTime = performance.now();
172
+ entry.duration = entry.endTime - entry.startTime;
173
+ this._notify(entry);
174
+ }
175
+ _recordWsError(id, error) {
176
+ if (!this._enabled) return;
177
+ const entry = this._entries.find(e => e.id === id && e.type === 'websocket');
178
+ if (!entry) return;
179
+ entry.error = error;
180
+ this._notify(entry);
181
+ }
182
+ }
183
+ export const NetworkInspector = new NetworkInspectorImpl();
184
+ //# sourceMappingURL=NetworkInspector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["generateCurl","NetworkInspectorImpl","_enabled","_entries","_maxEntries","_maxBodyCapture","_listeners","Set","enable","options","maxEntries","maxBodyCapture","disable","isEnabled","getEntries","getHttpEntries","filter","e","type","getWebSocketEntries","getEntry","id","find","clear","onEntry","callback","add","delete","_notify","entry","cb","_trimEntries","length","shift","_recordStart","url","method","headers","body","bodySize","requestHeaders","map","h","key","value","requestBody","slice","undefined","requestBodySize","status","statusText","responseHeaders","responseBodySize","startTime","performance","now","endTime","duration","curl","push","_recordEnd","error","responseBody","_recordWsOpen","protocols","readyState","messages","messagesSent","messagesReceived","bytesSent","bytesReceived","_recordWsConnected","_recordWsMessage","direction","data","size","isBinary","timestamp","_recordWsClose","code","reason","closeCode","closeReason","_recordWsError","NetworkInspector"],"sourceRoot":"../../src","sources":["NetworkInspector.ts"],"mappings":"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","ignoreList":[]}