react-native-nitro-fetch 0.3.0-beta.1 → 1.0.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.
- package/NitroFetch.podspec +8 -0
- package/android/build.gradle +3 -0
- package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt +46 -2
- package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchPackage.kt +2 -2
- package/app.plugin.js +1 -0
- package/expo/plugins/dist/index.d.ts +2 -0
- package/expo/plugins/dist/index.js +11 -0
- package/expo/plugins/dist/withAndroid.d.ts +2 -0
- package/expo/plugins/dist/withAndroid.js +21 -0
- package/ios/FetchCache.swift +14 -7
- package/ios/NitroFetchClient.swift +36 -1
- package/lib/module/CurlGenerator.js +28 -0
- package/lib/module/CurlGenerator.js.map +1 -0
- package/lib/module/Headers.js +95 -0
- package/lib/module/Headers.js.map +1 -0
- package/lib/module/HermesProfiler.js +28 -0
- package/lib/module/HermesProfiler.js.map +1 -0
- package/lib/module/NetworkInspector.js +184 -0
- package/lib/module/NetworkInspector.js.map +1 -0
- package/lib/module/Request.js +120 -0
- package/lib/module/Request.js.map +1 -0
- package/lib/module/Response.js +236 -0
- package/lib/module/Response.js.map +1 -0
- package/lib/module/fetch.js +143 -56
- package/lib/module/fetch.js.map +1 -1
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/utf8.js +29 -0
- package/lib/module/utf8.js.map +1 -0
- package/lib/typescript/expo/plugins/src/index.d.ts +3 -0
- package/lib/typescript/expo/plugins/src/index.d.ts.map +1 -0
- package/lib/typescript/expo/plugins/src/withAndroid.d.ts +3 -0
- package/lib/typescript/expo/plugins/src/withAndroid.d.ts.map +1 -0
- package/lib/typescript/src/CurlGenerator.d.ts +13 -0
- package/lib/typescript/src/CurlGenerator.d.ts.map +1 -0
- package/lib/typescript/src/Headers.d.ts +19 -0
- package/lib/typescript/src/Headers.d.ts.map +1 -0
- package/lib/typescript/src/HermesProfiler.d.ts +6 -0
- package/lib/typescript/src/HermesProfiler.d.ts.map +1 -0
- package/lib/typescript/src/NetworkInspector.d.ts +96 -0
- package/lib/typescript/src/NetworkInspector.d.ts.map +1 -0
- package/lib/typescript/src/Request.d.ts +48 -0
- package/lib/typescript/src/Request.d.ts.map +1 -0
- package/lib/typescript/src/Response.d.ts +56 -0
- package/lib/typescript/src/Response.d.ts.map +1 -0
- package/lib/typescript/src/fetch.d.ts +11 -3
- package/lib/typescript/src/fetch.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +13 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utf8.d.ts +3 -0
- package/lib/typescript/src/utf8.d.ts.map +1 -0
- package/package.json +11 -5
- package/src/CurlGenerator.ts +44 -0
- package/src/Headers.ts +127 -0
- package/src/HermesProfiler.ts +37 -0
- package/src/NetworkInspector.ts +278 -0
- package/src/Request.ts +187 -0
- package/src/Response.ts +335 -0
- package/src/fetch.ts +186 -75
- package/src/index.tsx +22 -1
- package/src/utf8.ts +40 -0
package/src/fetch.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type {
|
|
|
3
3
|
NitroFetch as NitroFetchModule,
|
|
4
4
|
NitroFormDataPart,
|
|
5
5
|
NitroHeader,
|
|
6
|
-
NitroRequest,
|
|
7
|
-
NitroResponse,
|
|
6
|
+
NitroRequest as NitroRequestNative,
|
|
7
|
+
NitroResponse as NitroResponseNative,
|
|
8
8
|
} from './NitroFetch.nitro';
|
|
9
9
|
import {
|
|
10
10
|
boxedNitroFetch,
|
|
@@ -12,6 +12,11 @@ import {
|
|
|
12
12
|
NitroCronetSingleton,
|
|
13
13
|
} from './NitroInstances';
|
|
14
14
|
import { NativeStorage as NativeStorageSingleton } from './NitroInstances';
|
|
15
|
+
import { NitroHeaders } from './Headers';
|
|
16
|
+
import { NitroResponse } from './Response';
|
|
17
|
+
import { NitroRequest as NitroRequestClass } from './Request';
|
|
18
|
+
import type { RequestRedirect, RequestCache } from './Request';
|
|
19
|
+
import { NetworkInspector } from './NetworkInspector';
|
|
15
20
|
|
|
16
21
|
// No base64: pass strings/ArrayBuffers directly
|
|
17
22
|
|
|
@@ -163,39 +168,63 @@ function ensureClient() {
|
|
|
163
168
|
|
|
164
169
|
function buildNitroRequest(
|
|
165
170
|
input: RequestInfo | URL,
|
|
166
|
-
init?: RequestInit
|
|
167
|
-
):
|
|
171
|
+
init?: RequestInit & { redirect?: RequestRedirect; cache?: RequestCache }
|
|
172
|
+
): NitroRequestNative {
|
|
168
173
|
'worklet';
|
|
169
174
|
let url: string;
|
|
170
175
|
let method: string | undefined;
|
|
171
176
|
let headersInit: HeadersInit | undefined;
|
|
172
177
|
let body: BodyInit | null | undefined;
|
|
178
|
+
let redirectOption: RequestRedirect =
|
|
179
|
+
(init?.redirect as RequestRedirect) ?? 'follow';
|
|
180
|
+
let cacheOption: RequestCache | undefined = init?.cache as
|
|
181
|
+
| RequestCache
|
|
182
|
+
| undefined;
|
|
173
183
|
|
|
174
|
-
if (
|
|
184
|
+
if (input instanceof NitroRequestClass) {
|
|
185
|
+
url = input.url;
|
|
186
|
+
method = init?.method ?? input.method;
|
|
187
|
+
headersInit = init?.headers ?? (input.headers as any);
|
|
188
|
+
body = init?.body ?? input.body ?? null;
|
|
189
|
+
if (!init?.redirect) redirectOption = input.redirect;
|
|
190
|
+
if (!init?.cache) cacheOption = input.cache;
|
|
191
|
+
} else if (typeof input === 'string' || input instanceof URL) {
|
|
175
192
|
url = String(input);
|
|
176
193
|
method = init?.method;
|
|
177
194
|
headersInit = init?.headers;
|
|
178
195
|
body = init?.body ?? null;
|
|
179
196
|
} else {
|
|
180
|
-
// Request object
|
|
197
|
+
// Standard Request object
|
|
181
198
|
url = input.url;
|
|
182
199
|
method = input.method;
|
|
183
200
|
headersInit = input.headers as any;
|
|
184
|
-
// Clone body if needed – Request objects in RN typically allow direct access
|
|
185
201
|
body = init?.body ?? null;
|
|
186
202
|
}
|
|
187
203
|
|
|
188
|
-
const headers = headersToPairs(headersInit);
|
|
204
|
+
const headers = headersToPairs(headersInit) ?? [];
|
|
189
205
|
const normalized = normalizeBody(body);
|
|
190
206
|
|
|
207
|
+
// Inject cache-control headers based on cache option
|
|
208
|
+
if (cacheOption === 'no-store') {
|
|
209
|
+
headers.push({ key: 'Cache-Control', value: 'no-store' });
|
|
210
|
+
} else if (cacheOption === 'no-cache') {
|
|
211
|
+
headers.push({ key: 'Cache-Control', value: 'no-cache' });
|
|
212
|
+
} else if (cacheOption === 'reload') {
|
|
213
|
+
headers.push({ key: 'Cache-Control', value: 'no-cache' });
|
|
214
|
+
headers.push({ key: 'Pragma', value: 'no-cache' });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Determine followRedirects based on redirect option
|
|
218
|
+
const followRedirects = redirectOption === 'follow';
|
|
219
|
+
|
|
191
220
|
return {
|
|
192
221
|
url,
|
|
193
222
|
method: (method?.toUpperCase() as any) ?? 'GET',
|
|
194
|
-
headers,
|
|
223
|
+
headers: headers.length > 0 ? headers : undefined,
|
|
195
224
|
bodyString: normalized?.bodyString,
|
|
196
225
|
bodyBytes: undefined as any,
|
|
197
226
|
bodyFormData: normalized?.bodyFormData,
|
|
198
|
-
followRedirects
|
|
227
|
+
followRedirects,
|
|
199
228
|
};
|
|
200
229
|
}
|
|
201
230
|
|
|
@@ -297,7 +326,7 @@ function normalizeBodyPure(
|
|
|
297
326
|
export function buildNitroRequestPure(
|
|
298
327
|
input: RequestInfo | URL,
|
|
299
328
|
init?: RequestInit
|
|
300
|
-
):
|
|
329
|
+
): NitroRequestNative {
|
|
301
330
|
'worklet';
|
|
302
331
|
let url: string;
|
|
303
332
|
let method: string | undefined;
|
|
@@ -345,10 +374,39 @@ function createAbortError(): Error {
|
|
|
345
374
|
return err;
|
|
346
375
|
}
|
|
347
376
|
|
|
377
|
+
async function resolveBlobBody(
|
|
378
|
+
init: RequestInit | undefined
|
|
379
|
+
): Promise<RequestInit | undefined> {
|
|
380
|
+
if (!init?.body) return init;
|
|
381
|
+
if (typeof Blob !== 'undefined' && init.body instanceof Blob) {
|
|
382
|
+
const blob = init.body as Blob;
|
|
383
|
+
const text = await new Promise<string>((resolve, reject) => {
|
|
384
|
+
const reader = new FileReader();
|
|
385
|
+
reader.onload = () => resolve(reader.result as string);
|
|
386
|
+
reader.onerror = () => reject(reader.error);
|
|
387
|
+
reader.readAsText(blob);
|
|
388
|
+
});
|
|
389
|
+
// Auto-set Content-Type from Blob.type if not already provided
|
|
390
|
+
let headers = init.headers;
|
|
391
|
+
if (blob.type) {
|
|
392
|
+
const pairs = headersToPairs(headers) ?? [];
|
|
393
|
+
const hasContentType = pairs.some(
|
|
394
|
+
(h) => h.key.toLowerCase() === 'content-type'
|
|
395
|
+
);
|
|
396
|
+
if (!hasContentType) {
|
|
397
|
+
pairs.push({ key: 'Content-Type', value: blob.type });
|
|
398
|
+
headers = pairs.map((h) => [h.key, h.value] as [string, string]);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return { ...init, body: text, headers };
|
|
402
|
+
}
|
|
403
|
+
return init;
|
|
404
|
+
}
|
|
405
|
+
|
|
348
406
|
async function nitroFetchRaw(
|
|
349
407
|
input: RequestInfo | URL,
|
|
350
408
|
init?: RequestInit
|
|
351
|
-
): Promise<
|
|
409
|
+
): Promise<NitroResponseNative> {
|
|
352
410
|
const signal = init?.signal as AbortSignal | undefined | null;
|
|
353
411
|
|
|
354
412
|
// Fast-abort: reject synchronously before any bridge work.
|
|
@@ -356,6 +414,9 @@ async function nitroFetchRaw(
|
|
|
356
414
|
throw createAbortError();
|
|
357
415
|
}
|
|
358
416
|
|
|
417
|
+
// Resolve Blob body to string before passing to sync buildNitroRequest
|
|
418
|
+
init = await resolveBlobBody(init);
|
|
419
|
+
|
|
359
420
|
const hasNative =
|
|
360
421
|
typeof (NitroFetchHybrid as any)?.createClient === 'function';
|
|
361
422
|
if (!hasNative) {
|
|
@@ -375,11 +436,24 @@ async function nitroFetchRaw(
|
|
|
375
436
|
headers,
|
|
376
437
|
bodyBytes: bytes,
|
|
377
438
|
bodyString: undefined,
|
|
378
|
-
} as any as
|
|
439
|
+
} as any as NitroResponseNative; // bleee
|
|
379
440
|
}
|
|
380
441
|
|
|
381
442
|
const req = buildNitroRequest(input, init);
|
|
382
443
|
|
|
444
|
+
// Inspector: record start (zero cost when disabled — single boolean check)
|
|
445
|
+
let inspectorId: string | undefined;
|
|
446
|
+
if (NetworkInspector.isEnabled()) {
|
|
447
|
+
inspectorId = String(Date.now()) + '-' + String(Math.random()).slice(2, 8);
|
|
448
|
+
NetworkInspector._recordStart(
|
|
449
|
+
inspectorId,
|
|
450
|
+
req.url,
|
|
451
|
+
req.method ?? 'GET',
|
|
452
|
+
req.headers ?? [],
|
|
453
|
+
req.bodyString
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
|
|
383
457
|
// Only allocate a requestId when a signal is present — zero overhead otherwise.
|
|
384
458
|
const requestId = signal ? String(Math.random()) : undefined;
|
|
385
459
|
if (requestId) req.requestId = requestId;
|
|
@@ -403,9 +477,23 @@ async function nitroFetchRaw(
|
|
|
403
477
|
}
|
|
404
478
|
|
|
405
479
|
try {
|
|
406
|
-
const res:
|
|
480
|
+
const res: NitroResponseNative = await client.request(req);
|
|
481
|
+
if (inspectorId) {
|
|
482
|
+
NetworkInspector._recordEnd(
|
|
483
|
+
inspectorId,
|
|
484
|
+
res.status,
|
|
485
|
+
res.statusText,
|
|
486
|
+
res.headers ?? [],
|
|
487
|
+
res.bodyString?.length ?? 0,
|
|
488
|
+
undefined,
|
|
489
|
+
res.bodyString ?? undefined
|
|
490
|
+
);
|
|
491
|
+
}
|
|
407
492
|
return res;
|
|
408
493
|
} catch (e) {
|
|
494
|
+
if (inspectorId) {
|
|
495
|
+
NetworkInspector._recordEnd(inspectorId, 0, '', [], 0, String(e));
|
|
496
|
+
}
|
|
409
497
|
// If the signal was aborted (either before or during the request),
|
|
410
498
|
// surface a spec-compliant AbortError regardless of what native threw.
|
|
411
499
|
if (signal?.aborted) {
|
|
@@ -421,42 +509,7 @@ async function nitroFetchRaw(
|
|
|
421
509
|
}
|
|
422
510
|
}
|
|
423
511
|
|
|
424
|
-
//
|
|
425
|
-
class NitroHeaders {
|
|
426
|
-
private _headers: Map<string, string>;
|
|
427
|
-
|
|
428
|
-
constructor(headers: NitroHeader[]) {
|
|
429
|
-
this._headers = new Map();
|
|
430
|
-
for (const { key, value } of headers) {
|
|
431
|
-
// Headers are case-insensitive, normalize to lowercase
|
|
432
|
-
this._headers.set(key.toLowerCase(), value);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
get(name: string): string | null {
|
|
437
|
-
return this._headers.get(name.toLowerCase()) ?? null;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
has(name: string): boolean {
|
|
441
|
-
return this._headers.has(name.toLowerCase());
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
forEach(callback: (value: string, key: string) => void): void {
|
|
445
|
-
this._headers.forEach(callback);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
entries(): IterableIterator<[string, string]> {
|
|
449
|
-
return this._headers.entries();
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
keys(): IterableIterator<string> {
|
|
453
|
-
return this._headers.keys();
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
values(): IterableIterator<string> {
|
|
457
|
-
return this._headers.values();
|
|
458
|
-
}
|
|
459
|
-
}
|
|
512
|
+
// NitroHeaders is now imported from './Headers'
|
|
460
513
|
|
|
461
514
|
async function nitroStreamFetch(
|
|
462
515
|
input: RequestInfo | URL,
|
|
@@ -466,6 +519,19 @@ async function nitroStreamFetch(
|
|
|
466
519
|
const method = init?.method?.toUpperCase() ?? 'GET';
|
|
467
520
|
const headers = headersToPairs(init?.headers);
|
|
468
521
|
|
|
522
|
+
// Inspector: record start
|
|
523
|
+
let inspectorId: string | undefined;
|
|
524
|
+
if (NetworkInspector.isEnabled()) {
|
|
525
|
+
inspectorId = String(Date.now()) + '-' + String(Math.random()).slice(2, 8);
|
|
526
|
+
NetworkInspector._recordStart(
|
|
527
|
+
inspectorId,
|
|
528
|
+
url,
|
|
529
|
+
method,
|
|
530
|
+
headers ?? [],
|
|
531
|
+
typeof init?.body === 'string' ? init.body : undefined
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
|
|
469
535
|
const builder = NitroCronetSingleton.newUrlRequestBuilder(url);
|
|
470
536
|
builder.setHttpMethod(method);
|
|
471
537
|
headers?.forEach((h) => builder.addHeader(h.key, h.value));
|
|
@@ -486,6 +552,7 @@ async function nitroStreamFetch(
|
|
|
486
552
|
});
|
|
487
553
|
|
|
488
554
|
let responseResolved = false;
|
|
555
|
+
let streamBytesReceived = 0;
|
|
489
556
|
|
|
490
557
|
builder.onResponseStarted((info) => {
|
|
491
558
|
if (responseResolved) return;
|
|
@@ -494,9 +561,7 @@ async function nitroStreamFetch(
|
|
|
494
561
|
const responseHeaders = new NitroHeaders(
|
|
495
562
|
Object.entries(info.allHeaders).map(([key, value]) => ({ key, value }))
|
|
496
563
|
);
|
|
497
|
-
|
|
498
|
-
// propagate a ReadableStream to .body, so we set it explicitly.
|
|
499
|
-
const response: any = {
|
|
564
|
+
const response = new NitroResponse({
|
|
500
565
|
url: info.url,
|
|
501
566
|
ok: status >= 200 && status < 300,
|
|
502
567
|
status,
|
|
@@ -504,9 +569,8 @@ async function nitroStreamFetch(
|
|
|
504
569
|
headers: responseHeaders,
|
|
505
570
|
redirected: false,
|
|
506
571
|
body: stream,
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
resolveResponse(response as Response);
|
|
572
|
+
});
|
|
573
|
+
resolveResponse(response as unknown as Response);
|
|
510
574
|
// Android/Cronet: kick off the first buffer read.
|
|
511
575
|
// iOS/URLSession handles reading automatically so this is a no-op there.
|
|
512
576
|
request.read();
|
|
@@ -514,16 +578,34 @@ async function nitroStreamFetch(
|
|
|
514
578
|
|
|
515
579
|
builder.onReadCompleted((_info, byteBuffer, bytesRead) => {
|
|
516
580
|
const chunk = new Uint8Array(byteBuffer, 0, bytesRead).slice();
|
|
581
|
+
streamBytesReceived += bytesRead;
|
|
517
582
|
streamController.enqueue(chunk);
|
|
518
583
|
if (!request.isDone()) {
|
|
519
584
|
request.read();
|
|
520
585
|
}
|
|
521
586
|
});
|
|
522
587
|
|
|
523
|
-
builder.onSucceeded(() =>
|
|
588
|
+
builder.onSucceeded((_info) => {
|
|
589
|
+
streamController.close();
|
|
590
|
+
if (inspectorId) {
|
|
591
|
+
const info = _info as any;
|
|
592
|
+
const status = info?.httpStatusCode ?? 0;
|
|
593
|
+
const hdrs = info?.allHeadersAsList ?? [];
|
|
594
|
+
NetworkInspector._recordEnd(
|
|
595
|
+
inspectorId,
|
|
596
|
+
status,
|
|
597
|
+
info?.httpStatusText ?? '',
|
|
598
|
+
hdrs,
|
|
599
|
+
streamBytesReceived
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
});
|
|
524
603
|
|
|
525
604
|
builder.onFailed((_info, error) => {
|
|
526
605
|
const err = new Error(error.message);
|
|
606
|
+
if (inspectorId) {
|
|
607
|
+
NetworkInspector._recordEnd(inspectorId, 0, '', [], 0, error.message);
|
|
608
|
+
}
|
|
527
609
|
if (!responseResolved) {
|
|
528
610
|
responseResolved = true;
|
|
529
611
|
rejectResponse(err);
|
|
@@ -534,6 +616,16 @@ async function nitroStreamFetch(
|
|
|
534
616
|
|
|
535
617
|
builder.onCanceled(() => {
|
|
536
618
|
const err = createAbortError();
|
|
619
|
+
if (inspectorId) {
|
|
620
|
+
NetworkInspector._recordEnd(
|
|
621
|
+
inspectorId,
|
|
622
|
+
0,
|
|
623
|
+
'',
|
|
624
|
+
[],
|
|
625
|
+
0,
|
|
626
|
+
'Request canceled'
|
|
627
|
+
);
|
|
628
|
+
}
|
|
537
629
|
if (!responseResolved) {
|
|
538
630
|
responseResolved = true;
|
|
539
631
|
rejectResponse(err);
|
|
@@ -549,33 +641,48 @@ async function nitroStreamFetch(
|
|
|
549
641
|
|
|
550
642
|
export async function nitroFetch(
|
|
551
643
|
input: RequestInfo | URL,
|
|
552
|
-
init?: RequestInit & {
|
|
644
|
+
init?: RequestInit & {
|
|
645
|
+
stream?: boolean;
|
|
646
|
+
redirect?: RequestRedirect;
|
|
647
|
+
cache?: RequestCache;
|
|
648
|
+
}
|
|
553
649
|
): Promise<Response> {
|
|
650
|
+
// Merge defaults from NitroRequestClass if input is one
|
|
651
|
+
if (input instanceof NitroRequestClass) {
|
|
652
|
+
init = {
|
|
653
|
+
...init,
|
|
654
|
+
signal: init?.signal ?? input.signal,
|
|
655
|
+
redirect: (init?.redirect as RequestRedirect) ?? input.redirect,
|
|
656
|
+
cache: (init?.cache as RequestCache) ?? input.cache,
|
|
657
|
+
} as any;
|
|
658
|
+
}
|
|
659
|
+
|
|
554
660
|
if ((init as any)?.stream === true) {
|
|
555
661
|
return nitroStreamFetch(input, init);
|
|
556
662
|
}
|
|
557
|
-
const res = await nitroFetchRaw(input, init);
|
|
558
663
|
|
|
559
|
-
const
|
|
664
|
+
const redirectOption: RequestRedirect =
|
|
665
|
+
(init?.redirect as RequestRedirect) ?? 'follow';
|
|
666
|
+
const res = await nitroFetchRaw(input, init);
|
|
560
667
|
|
|
561
|
-
|
|
562
|
-
|
|
668
|
+
// Handle redirect: "error" — if we got a 3xx back (followRedirects was false), throw
|
|
669
|
+
if (redirectOption === 'error' && res.status >= 300 && res.status < 400) {
|
|
670
|
+
throw new TypeError(
|
|
671
|
+
`redirect mode is "error": redirected request to "${res.url}"`
|
|
672
|
+
);
|
|
673
|
+
}
|
|
563
674
|
|
|
564
|
-
const
|
|
675
|
+
const response = new NitroResponse({
|
|
565
676
|
url: res.url,
|
|
566
|
-
ok: res.ok,
|
|
567
677
|
status: res.status,
|
|
568
678
|
statusText: res.statusText,
|
|
679
|
+
ok: res.ok,
|
|
569
680
|
redirected: res.redirected,
|
|
570
|
-
headers:
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
json: async () => JSON.parse(bodyString ?? '{}'),
|
|
574
|
-
clone: () => makeLight(),
|
|
681
|
+
headers: res.headers,
|
|
682
|
+
bodyBytes: res.bodyBytes as unknown as ArrayBuffer | undefined,
|
|
683
|
+
bodyString: res.bodyString,
|
|
575
684
|
});
|
|
576
|
-
|
|
577
|
-
const light: any = makeLight();
|
|
578
|
-
return light as Response;
|
|
685
|
+
return response as unknown as Response;
|
|
579
686
|
}
|
|
580
687
|
|
|
581
688
|
// Start a native prefetch. Requires a `prefetchKey` header on the request.
|
|
@@ -778,8 +885,12 @@ export async function nitroFetchOnWorklet<T>(
|
|
|
778
885
|
});
|
|
779
886
|
}
|
|
780
887
|
|
|
888
|
+
export type { NitroFormDataPart } from './NitroFetch.nitro';
|
|
781
889
|
export type {
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
NitroResponse,
|
|
890
|
+
NitroRequest as NitroRequestNativeType,
|
|
891
|
+
NitroResponse as NitroResponseNativeType,
|
|
785
892
|
} from './NitroFetch.nitro';
|
|
893
|
+
export { NitroHeaders } from './Headers';
|
|
894
|
+
export { NitroResponse } from './Response';
|
|
895
|
+
export { NitroRequest as NitroRequestClass } from './Request';
|
|
896
|
+
export type { RequestRedirect, RequestCache } from './Request';
|
package/src/index.tsx
CHANGED
|
@@ -6,7 +6,16 @@ export {
|
|
|
6
6
|
removeFromAutoPrefetch,
|
|
7
7
|
removeAllFromAutoprefetch,
|
|
8
8
|
} from './fetch';
|
|
9
|
-
export type { NitroFormDataPart
|
|
9
|
+
export type { NitroFormDataPart } from './fetch';
|
|
10
|
+
export type {
|
|
11
|
+
NitroRequestNativeType as NitroRequest,
|
|
12
|
+
NitroResponseNativeType as NitroResponse,
|
|
13
|
+
} from './fetch';
|
|
14
|
+
export type { RequestRedirect, RequestCache } from './fetch';
|
|
15
|
+
export type { BodyInit, ResponseInit } from './Response';
|
|
16
|
+
export { NitroHeaders as Headers } from './Headers';
|
|
17
|
+
export { NitroResponse as Response } from './Response';
|
|
18
|
+
export { NitroRequest as Request } from './Request';
|
|
10
19
|
export { NitroFetch } from './NitroInstances';
|
|
11
20
|
export {
|
|
12
21
|
registerTokenRefresh,
|
|
@@ -17,6 +26,18 @@ export {
|
|
|
17
26
|
applyTemplate,
|
|
18
27
|
} from './tokenRefresh';
|
|
19
28
|
export type { TokenRefreshConfig } from './tokenRefresh';
|
|
29
|
+
export { NetworkInspector } from './NetworkInspector';
|
|
30
|
+
export type {
|
|
31
|
+
NetworkEntry,
|
|
32
|
+
NetworkEntryCallback,
|
|
33
|
+
WebSocketEntry,
|
|
34
|
+
WebSocketMessage,
|
|
35
|
+
InspectorEntry,
|
|
36
|
+
} from './NetworkInspector';
|
|
37
|
+
export { generateCurl } from './CurlGenerator';
|
|
38
|
+
export type { CurlOptions } from './CurlGenerator';
|
|
39
|
+
export { profileFetch } from './HermesProfiler';
|
|
40
|
+
export type { ProfileResult } from './HermesProfiler';
|
|
20
41
|
import './fetch';
|
|
21
42
|
|
|
22
43
|
// Keep legacy export to avoid breaking any local tests/usages during scaffolding.
|
package/src/utf8.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
let _TextEncoder: typeof TextEncoder | undefined;
|
|
2
|
+
let _TextDecoder: typeof TextDecoder | undefined;
|
|
3
|
+
|
|
4
|
+
try {
|
|
5
|
+
_TextEncoder =
|
|
6
|
+
typeof TextEncoder !== 'undefined'
|
|
7
|
+
? TextEncoder
|
|
8
|
+
: require('react-native-nitro-text-decoder').TextEncoder;
|
|
9
|
+
} catch {
|
|
10
|
+
/* resolved at first use */
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
_TextDecoder =
|
|
15
|
+
typeof TextDecoder !== 'undefined'
|
|
16
|
+
? TextDecoder
|
|
17
|
+
: require('react-native-nitro-text-decoder').TextDecoder;
|
|
18
|
+
} catch {
|
|
19
|
+
/* resolved at first use */
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function stringToUTF8(str: string): Uint8Array {
|
|
23
|
+
if (!_TextEncoder) {
|
|
24
|
+
console.warn(
|
|
25
|
+
'stringToUTF8: TextEncoder not available. Install react-native-nitro-text-decoder.'
|
|
26
|
+
);
|
|
27
|
+
return new Uint8Array(0);
|
|
28
|
+
}
|
|
29
|
+
return new _TextEncoder().encode(str);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function utf8ToString(bytes: Uint8Array): string {
|
|
33
|
+
if (!_TextDecoder) {
|
|
34
|
+
console.warn(
|
|
35
|
+
'utf8ToString: TextDecoder not available. Install react-native-nitro-text-decoder.'
|
|
36
|
+
);
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
return new _TextDecoder().decode(bytes);
|
|
40
|
+
}
|