react-native-nitro-fetch 0.1.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.
Files changed (90) hide show
  1. package/LICENSE +20 -0
  2. package/NitroFetch.podspec +30 -0
  3. package/README.md +134 -0
  4. package/android/CMakeLists.txt +70 -0
  5. package/android/build.gradle +131 -0
  6. package/android/gradle.properties +5 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  9. package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +91 -0
  10. package/android/src/main/java/com/margelo/nitro/nitrofetch/FetchCache.kt +48 -0
  11. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetch.kt +94 -0
  12. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchClient.kt +256 -0
  13. package/android/src/main/java/com/margelo/nitro/nitrofetch/NitroFetchPackage.kt +22 -0
  14. package/ios/FetchCache.swift +56 -0
  15. package/ios/NitroAutoPrefetcher.swift +81 -0
  16. package/ios/NitroBootstrap.mm +27 -0
  17. package/ios/NitroFetch.swift +9 -0
  18. package/ios/NitroFetchClient.swift +205 -0
  19. package/lib/module/NitroFetch.nitro.js +7 -0
  20. package/lib/module/NitroFetch.nitro.js.map +1 -0
  21. package/lib/module/NitroInstances.js +6 -0
  22. package/lib/module/NitroInstances.js.map +1 -0
  23. package/lib/module/fetch.js +441 -0
  24. package/lib/module/fetch.js.map +1 -0
  25. package/lib/module/index.js +12 -0
  26. package/lib/module/index.js.map +1 -0
  27. package/lib/module/package.json +1 -0
  28. package/lib/typescript/package.json +1 -0
  29. package/lib/typescript/src/NitroFetch.nitro.d.ts +39 -0
  30. package/lib/typescript/src/NitroFetch.nitro.d.ts.map +1 -0
  31. package/lib/typescript/src/NitroInstances.d.ts +3 -0
  32. package/lib/typescript/src/NitroInstances.d.ts.map +1 -0
  33. package/lib/typescript/src/fetch.d.ts +26 -0
  34. package/lib/typescript/src/fetch.d.ts.map +1 -0
  35. package/lib/typescript/src/index.d.ts +6 -0
  36. package/lib/typescript/src/index.d.ts.map +1 -0
  37. package/nitro.json +21 -0
  38. package/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.cpp +96 -0
  39. package/nitrogen/generated/android/c++/JHybridNitroFetchClientSpec.hpp +65 -0
  40. package/nitrogen/generated/android/c++/JHybridNitroFetchSpec.cpp +49 -0
  41. package/nitrogen/generated/android/c++/JHybridNitroFetchSpec.hpp +64 -0
  42. package/nitrogen/generated/android/c++/JNitroHeader.hpp +57 -0
  43. package/nitrogen/generated/android/c++/JNitroRequest.hpp +103 -0
  44. package/nitrogen/generated/android/c++/JNitroRequestMethod.hpp +74 -0
  45. package/nitrogen/generated/android/c++/JNitroResponse.hpp +105 -0
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchClientSpec.kt +56 -0
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/HybridNitroFetchSpec.kt +52 -0
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroHeader.kt +32 -0
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroRequest.kt +47 -0
  50. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroRequestMethod.kt +26 -0
  51. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/NitroResponse.kt +50 -0
  52. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofetch/nitrofetchOnLoad.kt +35 -0
  53. package/nitrogen/generated/android/nitrofetch+autolinking.cmake +80 -0
  54. package/nitrogen/generated/android/nitrofetch+autolinking.gradle +27 -0
  55. package/nitrogen/generated/android/nitrofetchOnLoad.cpp +54 -0
  56. package/nitrogen/generated/android/nitrofetchOnLoad.hpp +25 -0
  57. package/nitrogen/generated/ios/NitroFetch+autolinking.rb +60 -0
  58. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.cpp +73 -0
  59. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp +298 -0
  60. package/nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp +67 -0
  61. package/nitrogen/generated/ios/NitroFetchAutolinking.mm +41 -0
  62. package/nitrogen/generated/ios/NitroFetchAutolinking.swift +40 -0
  63. package/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.cpp +11 -0
  64. package/nitrogen/generated/ios/c++/HybridNitroFetchClientSpecSwift.hpp +101 -0
  65. package/nitrogen/generated/ios/c++/HybridNitroFetchSpecSwift.cpp +11 -0
  66. package/nitrogen/generated/ios/c++/HybridNitroFetchSpecSwift.hpp +75 -0
  67. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  68. package/nitrogen/generated/ios/swift/Func_void_NitroResponse.swift +47 -0
  69. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  70. package/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec.swift +50 -0
  71. package/nitrogen/generated/ios/swift/HybridNitroFetchClientSpec_cxx.swift +149 -0
  72. package/nitrogen/generated/ios/swift/HybridNitroFetchSpec.swift +49 -0
  73. package/nitrogen/generated/ios/swift/HybridNitroFetchSpec_cxx.swift +126 -0
  74. package/nitrogen/generated/ios/swift/NitroHeader.swift +46 -0
  75. package/nitrogen/generated/ios/swift/NitroRequest.swift +199 -0
  76. package/nitrogen/generated/ios/swift/NitroRequestMethod.swift +60 -0
  77. package/nitrogen/generated/ios/swift/NitroResponse.swift +155 -0
  78. package/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.cpp +22 -0
  79. package/nitrogen/generated/shared/c++/HybridNitroFetchClientSpec.hpp +68 -0
  80. package/nitrogen/generated/shared/c++/HybridNitroFetchSpec.cpp +21 -0
  81. package/nitrogen/generated/shared/c++/HybridNitroFetchSpec.hpp +64 -0
  82. package/nitrogen/generated/shared/c++/NitroHeader.hpp +71 -0
  83. package/nitrogen/generated/shared/c++/NitroRequest.hpp +101 -0
  84. package/nitrogen/generated/shared/c++/NitroRequestMethod.hpp +96 -0
  85. package/nitrogen/generated/shared/c++/NitroResponse.hpp +102 -0
  86. package/package.json +177 -0
  87. package/src/NitroFetch.nitro.ts +57 -0
  88. package/src/NitroInstances.ts +8 -0
  89. package/src/fetch.ts +426 -0
  90. package/src/index.tsx +17 -0
package/src/fetch.ts ADDED
@@ -0,0 +1,426 @@
1
+ import type {
2
+ NitroFetch as NitroFetchModule,
3
+ NitroHeader,
4
+ NitroRequest,
5
+ NitroResponse,
6
+ } from './NitroFetch.nitro';
7
+ import { NitroFetch as NitroFetchSingleton } from './NitroInstances';
8
+
9
+ // No base64: pass strings/ArrayBuffers directly
10
+
11
+ function headersToPairs(headers?: HeadersInit): NitroHeader[] | undefined {
12
+ 'worklet';
13
+ if (!headers) return undefined;
14
+ const pairs: NitroHeader[] = [];
15
+ if (headers instanceof Headers) {
16
+ headers.forEach((v, k) => pairs.push({ key: k, value: v }));
17
+ return pairs;
18
+ }
19
+ if (Array.isArray(headers)) {
20
+ // Convert tuple pairs to objects if needed
21
+ for (const entry of headers as any[]) {
22
+ if (Array.isArray(entry) && entry.length >= 2) {
23
+ pairs.push({ key: String(entry[0]), value: String(entry[1]) });
24
+ } else if (entry && typeof entry === 'object' && 'key' in entry && 'value' in entry) {
25
+ pairs.push(entry as NitroHeader);
26
+ }
27
+ }
28
+ return pairs;
29
+ }
30
+ // Record<string, string>
31
+ for (const [k, v] of Object.entries(headers)) {
32
+ pairs.push({ key: k, value: String(v) });
33
+ }
34
+ return pairs;
35
+ }
36
+
37
+ function normalizeBody(body: BodyInit | null | undefined): { bodyString?: string; bodyBytes?: ArrayBuffer } | undefined {
38
+ 'worklet';
39
+ if (body == null) return undefined;
40
+ if (typeof body === 'string') return { bodyString: body };
41
+ if (body instanceof URLSearchParams) return { bodyString: body.toString() };
42
+ if (typeof ArrayBuffer !== 'undefined' && body instanceof ArrayBuffer) return { bodyBytes: body };
43
+ if (ArrayBuffer.isView(body)) {
44
+ const view = body as ArrayBufferView;
45
+ // Pass a copy/slice of the underlying bytes without base64
46
+ //@ts-ignore
47
+ return { bodyBytes: view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength) };
48
+ }
49
+ // TODO: Blob/FormData support can be added later
50
+ throw new Error('Unsupported body type for nitro fetch');
51
+ }
52
+
53
+ // @ts-ignore
54
+ function pairsToHeaders(pairs: NitroHeader[]): Headers {
55
+ 'worklet';
56
+ const h = new Headers();
57
+ for (const { key, value } of pairs) h.append(key, value);
58
+ return h;
59
+ }
60
+
61
+ const NitroFetchHybrid: NitroFetchModule = NitroFetchSingleton;
62
+
63
+ let client: ReturnType<NitroFetchModule['createClient']> | undefined;
64
+
65
+ function ensureClient() {
66
+ if (client) return client;
67
+ try {
68
+ client = NitroFetchHybrid.createClient();
69
+ } catch (err) {
70
+ console.error('Failed to create NitroFetch client', err);
71
+ // native not ready; keep undefined
72
+ }
73
+ return client;
74
+ }
75
+
76
+ function buildNitroRequest(input: RequestInfo | URL, init?: RequestInit): NitroRequest {
77
+ 'worklet';
78
+ let url: string;
79
+ let method: string | undefined;
80
+ let headersInit: HeadersInit | undefined;
81
+ let body: BodyInit | null | undefined;
82
+
83
+ if (typeof input === 'string' || input instanceof URL) {
84
+ url = String(input);
85
+ method = init?.method;
86
+ headersInit = init?.headers;
87
+ body = init?.body ?? null;
88
+ } else {
89
+ // Request object
90
+ url = input.url;
91
+ method = input.method;
92
+ headersInit = input.headers as any;
93
+ // Clone body if needed – Request objects in RN typically allow direct access
94
+ body = init?.body ?? null;
95
+ }
96
+
97
+ const headers = headersToPairs(headersInit);
98
+ const normalized = normalizeBody(body);
99
+
100
+ return {
101
+ url,
102
+ method: (method?.toUpperCase() as any) ?? 'GET',
103
+ headers,
104
+ bodyString: normalized?.bodyString,
105
+ bodyBytes: normalized?.bodyBytes,
106
+ followRedirects: true,
107
+ };
108
+ }
109
+
110
+ async function nitroFetchRaw(input: RequestInfo | URL, init?: RequestInit): Promise<NitroResponse> {
111
+ 'worklet';
112
+ const hasNative = typeof (NitroFetchHybrid as any)?.createClient === 'function';
113
+ if (!hasNative) {
114
+ // Fallback path not supported for raw; use global fetch and synthesize minimal shape
115
+ // @ts-ignore: global fetch exists in RN
116
+ const res = await fetch(input as any, init);
117
+ const url = (res as any).url ?? String(input);
118
+ const bytes = await res.arrayBuffer();
119
+ const headers: NitroHeader[] = [];
120
+ res.headers.forEach((v, k) => headers.push({ key: k, value: v }));
121
+ return {
122
+ url,
123
+ status: res.status,
124
+ statusText: res.statusText,
125
+ ok: res.ok,
126
+ redirected: (res as any).redirected ?? false,
127
+ headers,
128
+ bodyBytes: bytes,
129
+ bodyString: undefined,
130
+ } as NitroResponse;
131
+ }
132
+
133
+ const req = buildNitroRequest(input, init);
134
+ ensureClient();
135
+ if (!client || typeof (client as any).request !== 'function') throw new Error('NitroFetch client not available');
136
+ const res: NitroResponse = await client.request(req);
137
+ return res;
138
+ }
139
+
140
+ export async function nitroFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
141
+ 'worklet';
142
+ // If native implementation is not present yet, fallback to global fetch
143
+ const hasNative = typeof (NitroFetchHybrid as any)?.createClient === 'function';
144
+ if (!hasNative) {
145
+ // @ts-ignore: global fetch exists in RN
146
+ return fetch(input as any, init);
147
+ }
148
+
149
+ const res = await nitroFetchRaw(input, init);
150
+
151
+ const bytes = res.bodyBytes
152
+ ? new Uint8Array(res.bodyBytes)
153
+ : res.bodyString != null
154
+ ? new TextEncoder().encode(res.bodyString)
155
+ : new Uint8Array();
156
+
157
+ // If Response is available, construct a real Response object for compatibility
158
+ if (typeof Response !== 'undefined') {
159
+ const respInit: ResponseInit = {
160
+ status: res.status,
161
+ statusText: res.statusText,
162
+ headers: res.headers.reduce((acc, { key, value }) => {
163
+ acc[key] = value;
164
+ return acc;
165
+ }, {} as Record<string, string>),
166
+ };
167
+ // Prefer native bytes if available
168
+ return new Response(res.bodyBytes ?? bytes, respInit);
169
+ }
170
+
171
+ // Fallback lightweight Response-like object (minimal methods)
172
+ const headersObj = res.headers.reduce((acc, { key, value }) => {
173
+ acc[key] = value;
174
+ return acc;
175
+ }, {} as Record<string, string>);
176
+ const light: any = {
177
+ url: res.url,
178
+ ok: res.ok,
179
+ status: res.status,
180
+ statusText: res.statusText,
181
+ redirected: res.redirected,
182
+ headers: headersObj,
183
+ arrayBuffer: async () => (res.bodyBytes ?? bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)),
184
+ text: async () => res.bodyString ?? new TextDecoder().decode(bytes),
185
+ json: async () => JSON.parse(res.bodyString ?? new TextDecoder().decode(bytes)),
186
+ };
187
+ return light as Response;
188
+ }
189
+
190
+ // Start a native prefetch. Requires a `prefetchKey` header on the request.
191
+ export async function prefetch(input: RequestInfo | URL, init?: RequestInit): Promise<void> {
192
+ // If native implementation is not present yet, do nothing
193
+ const hasNative = typeof (NitroFetchHybrid as any)?.createClient === 'function';
194
+ if (!hasNative) return;
195
+
196
+ // Build NitroRequest and ensure prefetchKey header exists
197
+ const req = buildNitroRequest(input, init);
198
+ const hasKey = req.headers?.some(h => h.key.toLowerCase() === 'prefetchkey') ?? false;
199
+ // Also support passing prefetchKey via non-standard field on init
200
+ const fromInit = (init as any)?.prefetchKey as string | undefined;
201
+ if (!hasKey && fromInit) {
202
+ req.headers = (req.headers ?? []).concat([{ key: 'prefetchKey', value: fromInit }]);
203
+ }
204
+ const finalHasKey = req.headers?.some(h => h.key.toLowerCase() === 'prefetchkey');
205
+ if (!finalHasKey) {
206
+ throw new Error('prefetch requires a \"prefetchKey\" header');
207
+ }
208
+
209
+ // Ensure client and call native prefetch
210
+ ensureClient();
211
+ if (!client || typeof (client as any).prefetch !== 'function') return;
212
+ await client.prefetch(req);
213
+ }
214
+
215
+ // Persist a request to MMKV so native can prefetch it on app start.
216
+ // Stores an array of entries under the same key Android reads: "nitrofetch_autoprefetch_queue".
217
+ export async function prefetchOnAppStart(
218
+ input: RequestInfo | URL,
219
+ init?: RequestInit & { prefetchKey?: string }
220
+ ): Promise<void> {
221
+ // Resolve request and prefetchKey
222
+ const req = buildNitroRequest(input, init);
223
+ const fromHeader = req.headers?.find(h => h.key.toLowerCase() === 'prefetchkey')?.value;
224
+ const fromInit = (init as any)?.prefetchKey as string | undefined;
225
+ const prefetchKey = fromHeader ?? fromInit;
226
+ if (!prefetchKey) {
227
+ throw new Error('prefetchOnAppStart requires a "prefetchKey" (header or init.prefetchKey)');
228
+ }
229
+
230
+ // Convert headers to a plain object for storage
231
+ const headersObj = (req.headers ?? []).reduce((acc, { key, value }) => {
232
+ acc[String(key)] = String(value);
233
+ return acc;
234
+ }, {} as Record<string, string>);
235
+
236
+ const entry = {
237
+ url: req.url,
238
+ prefetchKey,
239
+ headers: headersObj,
240
+ } as const;
241
+
242
+ // Write or append to MMKV queue
243
+ try {
244
+ // Dynamically require to keep it optional for consumers
245
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
246
+ const { MMKV } = require('react-native-mmkv');
247
+ const storage = new MMKV(); // default instance matches Android's defaultMMKV
248
+ const KEY = 'nitrofetch_autoprefetch_queue';
249
+ let arr: any[] = [];
250
+ try {
251
+ const raw = storage.getString(KEY);
252
+ if (raw) arr = JSON.parse(raw);
253
+ if (!Array.isArray(arr)) arr = [];
254
+ } catch {
255
+ arr = [];
256
+ }
257
+ arr.push(entry);
258
+ storage.set(KEY, JSON.stringify(arr));
259
+ } catch (e) {
260
+ console.warn('react-native-mmkv not available; prefetchOnAppStart is a no-op', e);
261
+ }
262
+ }
263
+
264
+ // Remove one entry (by prefetchKey) from the auto-prefetch queue in MMKV.
265
+ export async function removeFromAutoPrefetch(prefetchKey: string): Promise<void> {
266
+ // No-op on iOS
267
+ try {
268
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
269
+ const { MMKV } = require('react-native-mmkv');
270
+ const storage = new MMKV();
271
+ const KEY = 'nitrofetch_autoprefetch_queue';
272
+ let arr: any[] = [];
273
+ try {
274
+ const raw = storage.getString(KEY);
275
+ if (raw) arr = JSON.parse(raw);
276
+ if (!Array.isArray(arr)) arr = [];
277
+ } catch {
278
+ arr = [];
279
+ }
280
+ const next = arr.filter((e) => e && e.prefetchKey !== prefetchKey);
281
+ if (next.length === 0) {
282
+ if (typeof (storage as any).delete === 'function') {
283
+ (storage as any).delete(KEY);
284
+ } else {
285
+ storage.set(KEY, JSON.stringify([]));
286
+ }
287
+ } else if (next.length !== arr.length) {
288
+ storage.set(KEY, JSON.stringify(next));
289
+ }
290
+ } catch (e) {
291
+ console.warn('react-native-mmkv not available; removeFromAutoPrefetch is a no-op', e);
292
+ }
293
+ }
294
+
295
+ // Remove all entries from the auto-prefetch queue in MMKV.
296
+ export async function removeAllFromAutoprefetch(): Promise<void> {
297
+ try {
298
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
299
+ const { MMKV } = require('react-native-mmkv');
300
+ const storage = new MMKV();
301
+ const KEY = 'nitrofetch_autoprefetch_queue';
302
+ if (typeof (storage as any).delete === 'function') {
303
+ (storage as any).delete(KEY);
304
+ } else {
305
+ storage.set(KEY, JSON.stringify([]));
306
+ }
307
+ } catch (e) {
308
+ console.warn('react-native-mmkv not available; removeAllFromAutoprefetch is a no-op', e);
309
+ }
310
+ }
311
+
312
+ // Optional off-thread processing using react-native-worklets-core
313
+ export type NitroWorkletMapper<T> = (payload: {
314
+ url: string;
315
+ status: number;
316
+ statusText: string;
317
+ ok: boolean;
318
+ redirected: boolean;
319
+ headers: NitroHeader[];
320
+ bodyBytes?: ArrayBuffer;
321
+ bodyString?: string;
322
+ }) => T;
323
+
324
+ let nitroRuntime: any | undefined;
325
+ let WorkletsRef: any | undefined;
326
+ function ensureWorkletRuntime(name = 'nitro-fetch'): any | undefined {
327
+ console.log('ensuring worklet runtime');
328
+ try {
329
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
330
+ const { Worklets } = require('react-native-worklets-core');
331
+ nitroRuntime = nitroRuntime ?? Worklets.createRuntime(name);
332
+ console.log('nitroRuntime:', !!nitroRuntime);
333
+ return nitroRuntime;
334
+ } catch {
335
+ console.warn('react-native-worklets-core not available');
336
+ return undefined;
337
+ }
338
+ }
339
+
340
+ function getWorklets(): any | undefined {
341
+ try {
342
+ if (WorkletsRef) return WorkletsRef;
343
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
344
+ const { Worklets } = require('react-native-worklets-core');
345
+ WorkletsRef = Worklets;
346
+ return WorkletsRef;
347
+ } catch {
348
+ console.warn('react-native-worklets-core not available');
349
+ return undefined;
350
+ }
351
+ }
352
+
353
+ export async function nitroFetchOnWorklet<T>(
354
+ input: RequestInfo | URL,
355
+ init: RequestInit | undefined,
356
+ mapWorklet: NitroWorkletMapper<T>,
357
+ options?: { preferBytes?: boolean; runtimeName?: string }
358
+ ): Promise<T> {
359
+
360
+ console.log('nitroFetchOnWorklet: starting');
361
+ const preferBytes = options?.preferBytes !== false; // default true
362
+ console.log('nitroFetchOnWorklet: preferBytes:', preferBytes);
363
+ let rt: any | undefined;
364
+ let Worklets: any | undefined;
365
+ try {
366
+ rt = ensureWorkletRuntime(options?.runtimeName);
367
+ console.log('nitroFetchOnWorklet: runtime created?', !!rt);
368
+ Worklets = getWorklets();
369
+ console.log('nitroFetchOnWorklet: Worklets available?', !!Worklets);
370
+ } catch (e) {
371
+ console.error('nitroFetchOnWorklet: setup failed', e);
372
+ }
373
+
374
+ // Fallback: if runtime is not available, do the work on JS
375
+ if (!rt || !Worklets || typeof rt.run !== 'function') {
376
+ console.warn('nitroFetchOnWorklet: no runtime, mapping on JS thread');
377
+ const res = await nitroFetchRaw(input, init);
378
+ const payload = {
379
+ url: res.url,
380
+ status: res.status,
381
+ statusText: res.statusText,
382
+ ok: res.ok,
383
+ redirected: res.redirected,
384
+ headers: res.headers,
385
+ bodyBytes: preferBytes ? res.bodyBytes : undefined,
386
+ bodyString: preferBytes ? undefined : res.bodyString,
387
+ } as const;
388
+ return mapWorklet(payload as any);
389
+ }
390
+
391
+ return await new Promise<T>((resolve, reject) => {
392
+ try {
393
+ console.log('nitroFetchOnWorklet: about to call rt.run');
394
+ rt.run(async (map: NitroWorkletMapper<T>) => {
395
+ 'worklet';
396
+ try {
397
+ console.log('nitroFetchOnWorklet: running fetch on worklet thread');
398
+ const res = await nitroFetchRaw(input, init);
399
+ console.log('nitroFetchOnWorklet: fetch completed');
400
+ const url = res.url;
401
+ const status = res.status;
402
+ const statusText = res.statusText;
403
+ const ok = res.ok;
404
+ const redirected = res.redirected;
405
+ const headersPairs: NitroHeader[] = res.headers;
406
+ const bodyBytes: ArrayBuffer | undefined = preferBytes ? res.bodyBytes : undefined;
407
+ const bodyString: string | undefined = preferBytes ? undefined : res.bodyString;
408
+ const payload = { url, status, statusText, ok, redirected, headers: headersPairs, bodyBytes, bodyString };
409
+ const out = map(payload);
410
+ // Resolve back on JS thread
411
+ Worklets.runOnJS(resolve)(out as any);
412
+ } catch (e) {
413
+ Worklets.runOnJS(reject)(e as any);
414
+ }
415
+ }, mapWorklet as any);
416
+ } catch (e) {
417
+ console.error('nitroFetchOnWorklet: rt.run failed', e);
418
+ reject(e);
419
+ }
420
+ });
421
+ }
422
+
423
+ export const x = ensureWorkletRuntime();
424
+ export const y = getWorklets();
425
+
426
+ export type { NitroRequest, NitroResponse } from './NitroFetch.nitro';
package/src/index.tsx ADDED
@@ -0,0 +1,17 @@
1
+ export {
2
+ nitroFetch as fetch,
3
+ nitroFetchOnWorklet,
4
+ prefetch,
5
+ prefetchOnAppStart,
6
+ removeFromAutoPrefetch,
7
+ removeAllFromAutoprefetch,
8
+ } from './fetch';
9
+ export type { NitroRequest, NitroResponse } from './fetch';
10
+ export { NitroFetch } from './NitroInstances';
11
+ import './fetch';
12
+
13
+ // Keep legacy export to avoid breaking any local tests/usages during scaffolding.
14
+ // Will be removed once native Cronet path is ready.
15
+ export function multiply(a: number, b: number): number {
16
+ return a * b;
17
+ }