react-native-nitro-fetch 0.1.7 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +3 -1
- package/android/src/main/java/com/margelo/nitro/nitrofetch/CronetExtensions.kt +31 -0
- package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroCronet.kt +89 -0
- package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt +115 -28
- package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroUrlRequest.kt +35 -0
- package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroUrlRequestBuilder.kt +181 -0
- package/ios/HybridNitroCronet.swift +31 -0
- package/ios/HybridUrlRequest.swift +41 -0
- package/ios/HybridUrlRequestBuilder.swift +255 -0
- package/ios/NitroAutoPrefetcher.swift +3 -1
- package/ios/NitroFetchClient.swift +87 -5
- package/ios/URLSessionExtensions.swift +36 -0
- package/lib/module/NitroCronet.nitro.js +4 -0
- package/lib/module/NitroCronet.nitro.js.map +1 -0
- package/lib/module/NitroInstances.js +1 -0
- package/lib/module/NitroInstances.js.map +1 -1
- package/lib/module/fetch.js +179 -9
- package/lib/module/fetch.js.map +1 -1
- package/lib/typescript/src/NitroCronet.nitro.d.ts +53 -0
- package/lib/typescript/src/NitroCronet.nitro.d.ts.map +1 -0
- package/lib/typescript/src/NitroFetch.nitro.d.ts +10 -0
- package/lib/typescript/src/NitroFetch.nitro.d.ts.map +1 -1
- package/lib/typescript/src/NitroInstances.d.ts +3 -1
- package/lib/typescript/src/NitroInstances.d.ts.map +1 -1
- package/lib/typescript/src/fetch.d.ts +5 -2
- package/lib/typescript/src/fetch.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/nitro.json +34 -6
- package/nitrogen/generated/android/c++/JFunc_void_UrlResponseInfo.hpp +82 -0
- package/nitrogen/generated/android/c++/JFunc_void_UrlResponseInfo_std__shared_ptr_ArrayBuffer__double.hpp +84 -0
- package/nitrogen/generated/android/c++/JFunc_void_UrlResponseInfo_std__string.hpp +82 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_UrlResponseInfo_.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_UrlResponseInfo__RequestException.hpp +85 -0
- package/nitrogen/generated/android/c++/JHttpHeader.hpp +61 -0
- package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.cpp +23 -16
- package/nitrogen/generated/android/c++/JHybridNativeStorageSpec.hpp +20 -21
- package/nitrogen/generated/android/c++/JHybridNitroCronetSpec.cpp +57 -0
- package/nitrogen/generated/android/c++/JHybridNitroCronetSpec.hpp +63 -0
- package/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp +32 -16
- package/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.hpp +21 -21
- package/nitrogen/generated/android/c++/JHybridNitroFetchSpec.cpp +22 -15
- package/nitrogen/generated/android/c++/JHybridNitroFetchSpec.hpp +20 -21
- package/nitrogen/generated/android/c++/JHybridUrlRequestBuilderSpec.cpp +123 -0
- package/nitrogen/generated/android/c++/JHybridUrlRequestBuilderSpec.hpp +73 -0
- package/nitrogen/generated/android/c++/JHybridUrlRequestSpec.cpp +69 -0
- package/nitrogen/generated/android/c++/JHybridUrlRequestSpec.hpp +67 -0
- package/nitrogen/generated/android/c++/JNitroFormDataPart.hpp +74 -0
- package/nitrogen/generated/android/c++/JNitroHeader.hpp +7 -3
- package/nitrogen/generated/android/c++/JNitroRequest.hpp +39 -6
- package/nitrogen/generated/android/c++/JNitroRequestMethod.hpp +9 -10
- package/nitrogen/generated/android/c++/JNitroResponse.hpp +9 -4
- package/nitrogen/generated/android/c++/JRequestException.hpp +57 -0
- package/nitrogen/generated/android/c++/JUrlResponseInfo.hpp +146 -0
- package/nitrogen/generated/android/c++/JVariant_ArrayBuffer_String.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_ArrayBuffer_String.hpp +70 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/Func_void_UrlResponseInfo.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/Func_void_UrlResponseInfo_std__shared_ptr_ArrayBuffer__double.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/Func_void_UrlResponseInfo_std__string.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/Func_void_std__optional_UrlResponseInfo_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/Func_void_std__optional_UrlResponseInfo__RequestException.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HttpHeader.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNativeStorageSpec.kt +18 -16
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroCronetSpec.kt +54 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchClientSpec.kt +23 -16
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchSpec.kt +18 -16
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridUrlRequestBuilderSpec.kt +125 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridUrlRequestSpec.kt +70 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroFormDataPart.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroHeader.kt +19 -10
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroRequest.kt +40 -25
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroRequestMethod.kt +3 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroResponse.kt +39 -30
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/RequestException.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/UrlResponseInfo.kt +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/Variant_ArrayBuffer_String.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/nitrofetchOnLoad.kt +1 -1
- package/nitrogen/generated/android/nitrofetch+autolinking.cmake +8 -1
- package/nitrogen/generated/android/nitrofetch+autolinking.gradle +1 -1
- package/nitrogen/generated/android/nitrofetchOnLoad.cpp +85 -33
- package/nitrogen/generated/android/nitrofetchOnLoad.hpp +14 -5
- package/nitrogen/generated/ios/NitroFetch+autolinking.rb +2 -2
- package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.cpp +102 -10
- package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp +359 -24
- package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp +32 -1
- package/nitrogen/generated/ios/NitroFetchAutolinking.mm +9 -1
- package/nitrogen/generated/ios/NitroFetchAutolinking.swift +29 -22
- package/nitrogen/generated/ios/c++/HybridNativeStorageSpecSwift.cpp +1 -1
- package/nitrogen/generated/ios/c++/HybridNativeStorageSpecSwift.hpp +10 -1
- package/nitrogen/generated/ios/c++/HybridNitroCronetSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNitroCronetSpecSwift.hpp +85 -0
- package/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.cpp +1 -1
- package/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp +22 -4
- package/nitrogen/generated/ios/c++/HybridNitroFetchSpecSwift.cpp +1 -1
- package/nitrogen/generated/ios/c++/HybridNitroFetchSpecSwift.hpp +10 -1
- package/nitrogen/generated/ios/c++/HybridUrlRequestBuilderSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridUrlRequestBuilderSpecSwift.hpp +163 -0
- package/nitrogen/generated/ios/c++/HybridUrlRequestSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridUrlRequestSpecSwift.hpp +106 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +1 -2
- package/nitrogen/generated/ios/swift/Func_void_NitroResponse.swift +1 -2
- package/nitrogen/generated/ios/swift/Func_void_UrlResponseInfo.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_UrlResponseInfo_std__shared_ptr_ArrayBuffer__double.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_UrlResponseInfo_std__string.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -2
- package/nitrogen/generated/ios/swift/Func_void_std__optional_UrlResponseInfo_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_UrlResponseInfo__RequestException.swift +46 -0
- package/nitrogen/generated/ios/swift/HttpHeader.swift +34 -0
- package/nitrogen/generated/ios/swift/HybridNativeStorageSpec.swift +10 -4
- package/nitrogen/generated/ios/swift/HybridNativeStorageSpec_cxx.swift +18 -3
- package/nitrogen/generated/ios/swift/HybridNitroCronetSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridNitroCronetSpec_cxx.swift +141 -0
- package/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec.swift +11 -4
- package/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec_cxx.swift +29 -3
- package/nitrogen/generated/ios/swift/HybridNitroFetchSpec.swift +10 -4
- package/nitrogen/generated/ios/swift/HybridNitroFetchSpec_cxx.swift +18 -3
- package/nitrogen/generated/ios/swift/HybridUrlRequestBuilderSpec.swift +65 -0
- package/nitrogen/generated/ios/swift/HybridUrlRequestBuilderSpec_cxx.swift +305 -0
- package/nitrogen/generated/ios/swift/HybridUrlRequestSpec.swift +59 -0
- package/nitrogen/generated/ios/swift/HybridUrlRequestSpec_cxx.swift +182 -0
- package/nitrogen/generated/ios/swift/NitroFormDataPart.swift +101 -0
- package/nitrogen/generated/ios/swift/NitroHeader.swift +5 -17
- package/nitrogen/generated/ios/swift/NitroRequest.swift +111 -121
- package/nitrogen/generated/ios/swift/NitroRequestMethod.swift +1 -1
- package/nitrogen/generated/ios/swift/NitroResponse.swift +40 -97
- package/nitrogen/generated/ios/swift/RequestException.swift +29 -0
- package/nitrogen/generated/ios/swift/UrlResponseInfo.swift +118 -0
- package/nitrogen/generated/ios/swift/Variant_ArrayBuffer_String.swift +18 -0
- package/nitrogen/generated/shared/c++/HttpHeader.hpp +87 -0
- package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridNativeStorageSpec.hpp +1 -1
- package/nitrogen/generated/shared/c++/HybridNitroCronetSpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridNitroCronetSpec.hpp +65 -0
- package/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.cpp +2 -1
- package/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.hpp +3 -1
- package/nitrogen/generated/shared/c++/HybridNitroFetchSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridNitroFetchSpec.hpp +1 -1
- package/nitrogen/generated/shared/c++/HybridUrlRequestBuilderSpec.cpp +31 -0
- package/nitrogen/generated/shared/c++/HybridUrlRequestBuilderSpec.hpp +85 -0
- package/nitrogen/generated/shared/c++/HybridUrlRequestSpec.cpp +25 -0
- package/nitrogen/generated/shared/c++/HybridUrlRequestSpec.hpp +66 -0
- package/nitrogen/generated/shared/c++/NitroFormDataPart.hpp +100 -0
- package/nitrogen/generated/shared/c++/NitroHeader.hpp +24 -8
- package/nitrogen/generated/shared/c++/NitroRequest.hpp +51 -24
- package/nitrogen/generated/shared/c++/NitroRequestMethod.hpp +1 -1
- package/nitrogen/generated/shared/c++/NitroResponse.hpp +42 -26
- package/nitrogen/generated/shared/c++/RequestException.hpp +83 -0
- package/nitrogen/generated/shared/c++/UrlResponseInfo.hpp +123 -0
- package/package.json +13 -10
- package/src/NitroCronet.nitro.ts +72 -0
- package/src/NitroFetch.nitro.ts +28 -6
- package/src/NitroInstances.ts +4 -0
- package/src/fetch.ts +214 -13
- package/src/index.tsx +1 -1
package/src/fetch.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import 'web-streams-polyfill/polyfill';
|
|
1
2
|
import type {
|
|
2
3
|
NitroFetch as NitroFetchModule,
|
|
4
|
+
NitroFormDataPart,
|
|
3
5
|
NitroHeader,
|
|
4
6
|
NitroRequest,
|
|
5
7
|
NitroResponse,
|
|
@@ -7,6 +9,7 @@ import type {
|
|
|
7
9
|
import {
|
|
8
10
|
boxedNitroFetch,
|
|
9
11
|
NitroFetch as NitroFetchSingleton,
|
|
12
|
+
NitroCronetSingleton,
|
|
10
13
|
} from './NitroInstances';
|
|
11
14
|
import { NativeStorage as NativeStorageSingleton } from './NitroInstances';
|
|
12
15
|
|
|
@@ -65,18 +68,73 @@ function headersToPairs(headers?: HeadersInit): NitroHeader[] | undefined {
|
|
|
65
68
|
return pairs;
|
|
66
69
|
}
|
|
67
70
|
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
function serializeFormData(fd: FormData): NitroFormDataPart[] {
|
|
72
|
+
const parts: NitroFormDataPart[] = [];
|
|
73
|
+
|
|
74
|
+
if (typeof (fd as any).getParts === 'function') {
|
|
75
|
+
const rnParts: any[] = (fd as any).getParts();
|
|
76
|
+
for (const part of rnParts) {
|
|
77
|
+
if (part.string !== undefined) {
|
|
78
|
+
parts.push({ name: part.fieldName, value: String(part.string) });
|
|
79
|
+
} else if (part.uri) {
|
|
80
|
+
parts.push({
|
|
81
|
+
name: part.fieldName,
|
|
82
|
+
fileUri: part.uri,
|
|
83
|
+
fileName: part.fileName ?? part.name ?? 'file',
|
|
84
|
+
mimeType: part.type ?? 'application/octet-stream',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return parts;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fd.forEach((value: any, key: string) => {
|
|
92
|
+
if (typeof value === 'string') {
|
|
93
|
+
parts.push({ name: key, value });
|
|
94
|
+
} else if (value && typeof value === 'object') {
|
|
95
|
+
parts.push({
|
|
96
|
+
name: key,
|
|
97
|
+
fileUri: value.uri ?? value.fileUri,
|
|
98
|
+
fileName: value.name ?? value.fileName ?? 'file',
|
|
99
|
+
mimeType: value.type ?? value.mimeType ?? 'application/octet-stream',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
return parts;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function isFormData(body: unknown): body is FormData {
|
|
107
|
+
if (typeof FormData !== 'undefined' && body instanceof FormData) return true;
|
|
108
|
+
if (
|
|
109
|
+
body &&
|
|
110
|
+
typeof body === 'object' &&
|
|
111
|
+
typeof (body as any).append === 'function' &&
|
|
112
|
+
typeof (body as any).getParts === 'function'
|
|
113
|
+
) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function normalizeBody(body: BodyInit | null | undefined):
|
|
120
|
+
| {
|
|
121
|
+
bodyString?: string;
|
|
122
|
+
bodyBytes?: ArrayBuffer;
|
|
123
|
+
bodyFormData?: NitroFormDataPart[];
|
|
124
|
+
}
|
|
125
|
+
| undefined {
|
|
71
126
|
'worklet';
|
|
72
127
|
if (body == null) return undefined;
|
|
73
128
|
if (typeof body === 'string') return { bodyString: body };
|
|
129
|
+
|
|
130
|
+
if (isFormData(body)) {
|
|
131
|
+
return { bodyFormData: serializeFormData(body as FormData) };
|
|
132
|
+
}
|
|
74
133
|
if (body instanceof URLSearchParams) return { bodyString: body.toString() };
|
|
75
134
|
if (typeof ArrayBuffer !== 'undefined' && body instanceof ArrayBuffer)
|
|
76
135
|
return { bodyBytes: body };
|
|
77
136
|
if (ArrayBuffer.isView(body)) {
|
|
78
137
|
const view = body as ArrayBufferView;
|
|
79
|
-
// Pass a copy/slice of the underlying bytes without base64
|
|
80
138
|
return {
|
|
81
139
|
//@ts-ignore
|
|
82
140
|
bodyBytes: view.buffer.slice(
|
|
@@ -85,7 +143,6 @@ function normalizeBody(
|
|
|
85
143
|
),
|
|
86
144
|
};
|
|
87
145
|
}
|
|
88
|
-
// TODO: Blob/FormData support can be added later
|
|
89
146
|
throw new Error('Unsupported body type for nitro fetch');
|
|
90
147
|
}
|
|
91
148
|
|
|
@@ -136,8 +193,8 @@ function buildNitroRequest(
|
|
|
136
193
|
method: (method?.toUpperCase() as any) ?? 'GET',
|
|
137
194
|
headers,
|
|
138
195
|
bodyString: normalized?.bodyString,
|
|
139
|
-
// Only include bodyBytes when provided to avoid signaling upload data unintentionally
|
|
140
196
|
bodyBytes: undefined as any,
|
|
197
|
+
bodyFormData: normalized?.bodyFormData,
|
|
141
198
|
followRedirects: true,
|
|
142
199
|
};
|
|
143
200
|
}
|
|
@@ -224,7 +281,6 @@ function normalizeBodyPure(
|
|
|
224
281
|
|
|
225
282
|
if (ArrayBuffer.isView(body)) {
|
|
226
283
|
const view = body as ArrayBufferView;
|
|
227
|
-
// Pass a copy/slice of the underlying bytes without base64
|
|
228
284
|
return {
|
|
229
285
|
//@ts-ignore
|
|
230
286
|
bodyBytes: view.buffer.slice(
|
|
@@ -233,8 +289,9 @@ function normalizeBodyPure(
|
|
|
233
289
|
),
|
|
234
290
|
};
|
|
235
291
|
}
|
|
236
|
-
|
|
237
|
-
|
|
292
|
+
throw new Error(
|
|
293
|
+
'Unsupported body type for nitro fetch worklet (FormData is not available in worklets)'
|
|
294
|
+
);
|
|
238
295
|
}
|
|
239
296
|
// Pure JS version of buildNitroRequest that doesnt use anything that breaks worklets
|
|
240
297
|
export function buildNitroRequestPure(
|
|
@@ -282,10 +339,23 @@ export function buildNitroRequestPure(
|
|
|
282
339
|
};
|
|
283
340
|
}
|
|
284
341
|
|
|
342
|
+
function createAbortError(): Error {
|
|
343
|
+
const err = new Error('The operation was aborted.');
|
|
344
|
+
err.name = 'AbortError';
|
|
345
|
+
return err;
|
|
346
|
+
}
|
|
347
|
+
|
|
285
348
|
async function nitroFetchRaw(
|
|
286
349
|
input: RequestInfo | URL,
|
|
287
350
|
init?: RequestInit
|
|
288
351
|
): Promise<NitroResponse> {
|
|
352
|
+
const signal = init?.signal as AbortSignal | undefined | null;
|
|
353
|
+
|
|
354
|
+
// Fast-abort: reject synchronously before any bridge work.
|
|
355
|
+
if (signal?.aborted) {
|
|
356
|
+
throw createAbortError();
|
|
357
|
+
}
|
|
358
|
+
|
|
289
359
|
const hasNative =
|
|
290
360
|
typeof (NitroFetchHybrid as any)?.createClient === 'function';
|
|
291
361
|
if (!hasNative) {
|
|
@@ -309,11 +379,46 @@ async function nitroFetchRaw(
|
|
|
309
379
|
}
|
|
310
380
|
|
|
311
381
|
const req = buildNitroRequest(input, init);
|
|
382
|
+
|
|
383
|
+
// Only allocate a requestId when a signal is present — zero overhead otherwise.
|
|
384
|
+
const requestId = signal ? String(Math.random()) : undefined;
|
|
385
|
+
if (requestId) req.requestId = requestId;
|
|
386
|
+
|
|
312
387
|
ensureClient();
|
|
313
388
|
if (!client || typeof (client as any).request !== 'function')
|
|
314
389
|
throw new Error('NitroFetch client not available');
|
|
315
|
-
|
|
316
|
-
|
|
390
|
+
|
|
391
|
+
// Wire up the abort listener with { once: true } so it auto-removes
|
|
392
|
+
// after firing, avoiding a dangling reference to the client closure.
|
|
393
|
+
let abortListener: (() => void) | undefined;
|
|
394
|
+
if (signal && requestId) {
|
|
395
|
+
abortListener = () => {
|
|
396
|
+
try {
|
|
397
|
+
client!.cancelRequest(requestId);
|
|
398
|
+
} catch {
|
|
399
|
+
// Client may already be torn down — swallow.
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
signal.addEventListener('abort', abortListener, { once: true });
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
try {
|
|
406
|
+
const res: NitroResponse = await client.request(req);
|
|
407
|
+
return res;
|
|
408
|
+
} catch (e) {
|
|
409
|
+
// If the signal was aborted (either before or during the request),
|
|
410
|
+
// surface a spec-compliant AbortError regardless of what native threw.
|
|
411
|
+
if (signal?.aborted) {
|
|
412
|
+
throw createAbortError();
|
|
413
|
+
}
|
|
414
|
+
throw e;
|
|
415
|
+
} finally {
|
|
416
|
+
// Idempotent cleanup — removeEventListener is a no-op if the listener
|
|
417
|
+
// already fired (thanks to { once: true }) or was never added.
|
|
418
|
+
if (signal && abortListener) {
|
|
419
|
+
signal.removeEventListener('abort', abortListener);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
317
422
|
}
|
|
318
423
|
|
|
319
424
|
// Simple Headers-like class that supports get() method
|
|
@@ -353,10 +458,102 @@ class NitroHeaders {
|
|
|
353
458
|
}
|
|
354
459
|
}
|
|
355
460
|
|
|
356
|
-
|
|
461
|
+
async function nitroStreamFetch(
|
|
357
462
|
input: RequestInfo | URL,
|
|
358
463
|
init?: RequestInit
|
|
359
464
|
): Promise<Response> {
|
|
465
|
+
const url = typeof input === 'string' ? input : String(input);
|
|
466
|
+
const method = init?.method?.toUpperCase() ?? 'GET';
|
|
467
|
+
const headers = headersToPairs(init?.headers);
|
|
468
|
+
|
|
469
|
+
const builder = NitroCronetSingleton.newUrlRequestBuilder(url);
|
|
470
|
+
builder.setHttpMethod(method);
|
|
471
|
+
headers?.forEach((h) => builder.addHeader(h.key, h.value));
|
|
472
|
+
|
|
473
|
+
const body = init?.body;
|
|
474
|
+
if (body != null) {
|
|
475
|
+
if (typeof body === 'string') builder.setUploadBody(body);
|
|
476
|
+
else if (body instanceof ArrayBuffer) builder.setUploadBody(body);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return new Promise((resolveResponse, rejectResponse) => {
|
|
480
|
+
let streamController: ReadableStreamDefaultController<Uint8Array>;
|
|
481
|
+
|
|
482
|
+
const stream = new ReadableStream<Uint8Array>({
|
|
483
|
+
start(controller) {
|
|
484
|
+
streamController = controller;
|
|
485
|
+
},
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
let responseResolved = false;
|
|
489
|
+
|
|
490
|
+
builder.onResponseStarted((info) => {
|
|
491
|
+
if (responseResolved) return;
|
|
492
|
+
responseResolved = true;
|
|
493
|
+
const status = info.httpStatusCode;
|
|
494
|
+
const responseHeaders = new NitroHeaders(
|
|
495
|
+
Object.entries(info.allHeaders).map(([key, value]) => ({ key, value }))
|
|
496
|
+
);
|
|
497
|
+
// Use a plain object — React Native's Response constructor does not
|
|
498
|
+
// propagate a ReadableStream to .body, so we set it explicitly.
|
|
499
|
+
const response: any = {
|
|
500
|
+
url: info.url,
|
|
501
|
+
ok: status >= 200 && status < 300,
|
|
502
|
+
status,
|
|
503
|
+
statusText: info.httpStatusText,
|
|
504
|
+
headers: responseHeaders,
|
|
505
|
+
redirected: false,
|
|
506
|
+
body: stream,
|
|
507
|
+
bodyUsed: false,
|
|
508
|
+
};
|
|
509
|
+
resolveResponse(response as Response);
|
|
510
|
+
// Android/Cronet: kick off the first buffer read.
|
|
511
|
+
// iOS/URLSession handles reading automatically so this is a no-op there.
|
|
512
|
+
request.read();
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
builder.onReadCompleted((_info, byteBuffer, bytesRead) => {
|
|
516
|
+
const chunk = new Uint8Array(byteBuffer, 0, bytesRead).slice();
|
|
517
|
+
streamController.enqueue(chunk);
|
|
518
|
+
if (!request.isDone()) {
|
|
519
|
+
request.read();
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
builder.onSucceeded(() => streamController.close());
|
|
524
|
+
|
|
525
|
+
builder.onFailed((_info, error) => {
|
|
526
|
+
const err = new Error(error.message);
|
|
527
|
+
if (!responseResolved) {
|
|
528
|
+
responseResolved = true;
|
|
529
|
+
rejectResponse(err);
|
|
530
|
+
} else {
|
|
531
|
+
streamController.error(err);
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
builder.onCanceled(() => {
|
|
536
|
+
const err = createAbortError();
|
|
537
|
+
if (!responseResolved) {
|
|
538
|
+
responseResolved = true;
|
|
539
|
+
rejectResponse(err);
|
|
540
|
+
} else {
|
|
541
|
+
streamController.error(err);
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
const request = builder.build();
|
|
546
|
+
request.start();
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export async function nitroFetch(
|
|
551
|
+
input: RequestInfo | URL,
|
|
552
|
+
init?: RequestInit & { stream?: boolean }
|
|
553
|
+
): Promise<Response> {
|
|
554
|
+
if ((init as any)?.stream === true) {
|
|
555
|
+
return nitroStreamFetch(input, init);
|
|
556
|
+
}
|
|
360
557
|
const res = await nitroFetchRaw(input, init);
|
|
361
558
|
|
|
362
559
|
const headersObj = new NitroHeaders(res.headers);
|
|
@@ -598,4 +795,8 @@ export async function nitroFetchOnWorklet<T>(
|
|
|
598
795
|
export const x = ensureWorkletRuntime();
|
|
599
796
|
export const y = getWorklets();
|
|
600
797
|
|
|
601
|
-
export type {
|
|
798
|
+
export type {
|
|
799
|
+
NitroFormDataPart,
|
|
800
|
+
NitroRequest,
|
|
801
|
+
NitroResponse,
|
|
802
|
+
} from './NitroFetch.nitro';
|
package/src/index.tsx
CHANGED
|
@@ -6,7 +6,7 @@ export {
|
|
|
6
6
|
removeFromAutoPrefetch,
|
|
7
7
|
removeAllFromAutoprefetch,
|
|
8
8
|
} from './fetch';
|
|
9
|
-
export type { NitroRequest, NitroResponse } from './fetch';
|
|
9
|
+
export type { NitroFormDataPart, NitroRequest, NitroResponse } from './fetch';
|
|
10
10
|
export { NitroFetch } from './NitroInstances';
|
|
11
11
|
import './fetch';
|
|
12
12
|
|