react-native-nitro-fetch 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/NitroFetch.podspec +1 -3
  2. package/README.md +38 -0
  3. package/android/build.gradle +12 -0
  4. package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +148 -55
  5. package/android/src/main/java/com/margelo/nitro/nitrofetch/DevToolsReporterImpl.kt +27 -36
  6. package/ios/NitroAutoPrefetcher.swift +149 -53
  7. package/ios/NitroDevToolsReporter.mm +37 -31
  8. package/lib/module/CurlGenerator.js.map +2 -1
  9. package/lib/module/Headers.js.map +2 -1
  10. package/lib/module/HermesProfiler.js.map +1 -1
  11. package/lib/module/NetworkInspector.js +1 -1
  12. package/lib/module/NetworkInspector.js.map +2 -1
  13. package/lib/module/NitroCronet.nitro.js.map +2 -1
  14. package/lib/module/NitroFetch.nitro.js.map +1 -2
  15. package/lib/module/NitroInstances.js.map +2 -1
  16. package/lib/module/Response.js.map +1 -2
  17. package/lib/module/fetch.js +8 -10
  18. package/lib/module/fetch.js.map +2 -1
  19. package/lib/module/index.js.map +2 -2
  20. package/lib/module/index.web.js +2 -1
  21. package/lib/module/tokenRefresh.js.map +2 -1
  22. package/lib/module/utf8.js.map +1 -2
  23. package/lib/typescript/src/fetch.d.ts.map +1 -1
  24. package/lib/typescript/src/tokenRefresh.d.ts +14 -0
  25. package/lib/typescript/src/tokenRefresh.d.ts.map +1 -1
  26. package/package.json +1 -1
  27. package/src/CurlGenerator.js +23 -26
  28. package/src/Headers.js +108 -116
  29. package/src/HermesProfiler.js +16 -18
  30. package/src/NetworkInspector.js +171 -179
  31. package/src/NitroInstances.js +2 -1
  32. package/src/Request.js +167 -164
  33. package/src/Response.js +244 -242
  34. package/src/fetch.js +708 -693
  35. package/src/fetch.ts +15 -16
  36. package/src/index.js +17 -2
  37. package/src/index.web.js +69 -67
  38. package/src/tokenRefresh.js +75 -77
  39. package/src/tokenRefresh.ts +16 -0
  40. package/src/utf8.js +28 -27
package/src/Response.js CHANGED
@@ -1,258 +1,260 @@
1
1
  import { NitroHeaders } from './Headers';
2
2
  import { stringToUTF8, utf8ToString } from './utf8';
3
3
  function isNitroResponseInit(arg) {
4
- return (arg != null &&
5
- typeof arg === 'object' &&
6
- 'url' in arg &&
7
- 'status' in arg &&
8
- 'ok' in arg);
4
+ return (
5
+ arg != null &&
6
+ typeof arg === 'object' &&
7
+ 'url' in arg &&
8
+ 'status' in arg &&
9
+ 'ok' in arg
10
+ );
9
11
  }
10
12
  export class NitroResponse {
11
- url;
12
- ok;
13
- status;
14
- statusText;
15
- redirected;
16
- headers;
17
- type;
18
- _bodyBytes;
19
- _bodyString;
20
- _bodyStream;
21
- _bodyUsed = false;
22
- constructor(bodyOrInit, init) {
23
- if (isNitroResponseInit(bodyOrInit)) {
24
- // Internal constructor path
25
- const nitroInit = bodyOrInit;
26
- this.url = nitroInit.url;
27
- this.ok = nitroInit.ok;
28
- this.status = nitroInit.status;
29
- this.statusText = nitroInit.statusText;
30
- this.redirected = nitroInit.redirected;
31
- this.type = nitroInit.type ?? 'basic';
32
- if (nitroInit.headers instanceof NitroHeaders) {
33
- this.headers = nitroInit.headers;
34
- }
35
- else {
36
- this.headers = new NitroHeaders(nitroInit.headers);
37
- }
38
- this._bodyBytes = nitroInit.bodyBytes;
39
- this._bodyString = nitroInit.bodyString;
40
- this._bodyStream = nitroInit.body;
13
+ url;
14
+ ok;
15
+ status;
16
+ statusText;
17
+ redirected;
18
+ headers;
19
+ type;
20
+ _bodyBytes;
21
+ _bodyString;
22
+ _bodyStream;
23
+ _bodyUsed = false;
24
+ constructor(bodyOrInit, init) {
25
+ if (isNitroResponseInit(bodyOrInit)) {
26
+ // Internal constructor path
27
+ const nitroInit = bodyOrInit;
28
+ this.url = nitroInit.url;
29
+ this.ok = nitroInit.ok;
30
+ this.status = nitroInit.status;
31
+ this.statusText = nitroInit.statusText;
32
+ this.redirected = nitroInit.redirected;
33
+ this.type = nitroInit.type ?? 'basic';
34
+ if (nitroInit.headers instanceof NitroHeaders) {
35
+ this.headers = nitroInit.headers;
36
+ } else {
37
+ this.headers = new NitroHeaders(nitroInit.headers);
38
+ }
39
+ this._bodyBytes = nitroInit.bodyBytes;
40
+ this._bodyString = nitroInit.bodyString;
41
+ this._bodyStream = nitroInit.body;
42
+ } else {
43
+ // Public constructor: new Response(body?, init?)
44
+ const body = bodyOrInit;
45
+ this.status = init?.status ?? 200;
46
+ this.statusText = init?.statusText ?? '';
47
+ this.ok = this.status >= 200 && this.status < 300;
48
+ this.url = '';
49
+ this.redirected = false;
50
+ this.type = 'default';
51
+ this.headers = new NitroHeaders(init?.headers);
52
+ if (body == null) {
53
+ // no body
54
+ } else if (typeof body === 'string') {
55
+ this._bodyString = body;
56
+ } else if (body instanceof ArrayBuffer) {
57
+ this._bodyBytes = body;
58
+ } else if (ArrayBuffer.isView(body)) {
59
+ const view = body;
60
+ this._bodyBytes = view.buffer.slice(
61
+ view.byteOffset,
62
+ view.byteOffset + view.byteLength
63
+ );
64
+ } else if (
65
+ typeof ReadableStream !== 'undefined' &&
66
+ body instanceof ReadableStream
67
+ ) {
68
+ this._bodyStream = body;
69
+ } else if (
70
+ typeof URLSearchParams !== 'undefined' &&
71
+ body instanceof URLSearchParams
72
+ ) {
73
+ this._bodyString = body.toString();
74
+ if (!this.headers.has('content-type')) {
75
+ this.headers.set(
76
+ 'content-type',
77
+ 'application/x-www-form-urlencoded;charset=UTF-8'
78
+ );
41
79
  }
42
- else {
43
- // Public constructor: new Response(body?, init?)
44
- const body = bodyOrInit;
45
- this.status = init?.status ?? 200;
46
- this.statusText = init?.statusText ?? '';
47
- this.ok = this.status >= 200 && this.status < 300;
48
- this.url = '';
49
- this.redirected = false;
50
- this.type = 'default';
51
- this.headers = new NitroHeaders(init?.headers);
52
- if (body == null) {
53
- // no body
54
- }
55
- else if (typeof body === 'string') {
56
- this._bodyString = body;
57
- }
58
- else if (body instanceof ArrayBuffer) {
59
- this._bodyBytes = body;
60
- }
61
- else if (ArrayBuffer.isView(body)) {
62
- const view = body;
63
- this._bodyBytes = view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
64
- }
65
- else if (typeof ReadableStream !== 'undefined' &&
66
- body instanceof ReadableStream) {
67
- this._bodyStream = body;
68
- }
69
- else if (typeof URLSearchParams !== 'undefined' &&
70
- body instanceof URLSearchParams) {
71
- this._bodyString = body.toString();
72
- if (!this.headers.has('content-type')) {
73
- this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
74
- }
75
- }
76
- else if (typeof Blob !== 'undefined' && body instanceof Blob) {
77
- // Store as string — RN Blobs are string-backed
78
- this._bodyString = '';
79
- this._bodyStream = body.stream?.();
80
- }
81
- }
82
- }
83
- get bodyUsed() {
84
- return this._bodyUsed;
85
- }
86
- get body() {
87
- if (this._bodyStream)
88
- return this._bodyStream;
89
- const bytes = this._getBodyBytes();
90
- if (!bytes)
91
- return null;
92
- return new ReadableStream({
93
- start(controller) {
94
- controller.enqueue(new Uint8Array(bytes));
95
- controller.close();
96
- },
97
- });
98
- }
99
- _throwIfBodyUsed() {
100
- if (this._bodyUsed) {
101
- throw new TypeError('Body has already been consumed.');
102
- }
103
- }
104
- _getBodyBytes() {
105
- // TODO: copy buffer to avoid clone being modifying res
106
- if (this._bodyBytes != null)
107
- return this._bodyBytes;
108
- if (this._bodyString != null) {
109
- const encoded = stringToUTF8(this._bodyString);
110
- return encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
111
- }
112
- return undefined;
113
- }
114
- _getBodyString() {
115
- if (this._bodyString != null)
116
- return this._bodyString;
117
- if (this._bodyBytes) {
118
- return utf8ToString(new Uint8Array(this._bodyBytes));
119
- }
120
- return '';
121
- }
122
- async text() {
123
- this._throwIfBodyUsed();
124
- this._bodyUsed = true;
125
- if (this._bodyStream && !this._bodyBytes && this._bodyString == null) {
126
- const reader = this._bodyStream.getReader();
127
- const chunks = [];
128
- while (true) {
129
- const { done, value } = await reader.read();
130
- if (done)
131
- break;
132
- if (value)
133
- chunks.push(value);
134
- }
135
- // Concatenate chunks
136
- let totalLen = 0;
137
- for (const c of chunks)
138
- totalLen += c.byteLength;
139
- const merged = new Uint8Array(totalLen);
140
- let offset = 0;
141
- for (const c of chunks) {
142
- merged.set(c, offset);
143
- offset += c.byteLength;
144
- }
145
- return utf8ToString(merged);
146
- }
147
- return this._getBodyString();
148
- }
149
- async json() {
150
- this._throwIfBodyUsed();
151
- this._bodyUsed = true;
152
- const t = this._getBodyString();
153
- return JSON.parse(t || '{}');
80
+ } else if (typeof Blob !== 'undefined' && body instanceof Blob) {
81
+ // Store as string RN Blobs are string-backed
82
+ this._bodyString = '';
83
+ this._bodyStream = body.stream?.();
84
+ }
154
85
  }
155
- async arrayBuffer() {
156
- this._throwIfBodyUsed();
157
- this._bodyUsed = true;
158
- if (this._bodyStream && !this._bodyBytes && this._bodyString == null) {
159
- const reader = this._bodyStream.getReader();
160
- const chunks = [];
161
- while (true) {
162
- const { done, value } = await reader.read();
163
- if (done)
164
- break;
165
- if (value)
166
- chunks.push(value);
167
- }
168
- let totalLen = 0;
169
- for (const c of chunks)
170
- totalLen += c.byteLength;
171
- const merged = new Uint8Array(totalLen);
172
- let offset = 0;
173
- for (const c of chunks) {
174
- merged.set(c, offset);
175
- offset += c.byteLength;
176
- }
177
- return merged.buffer.slice(merged.byteOffset, merged.byteOffset + merged.byteLength);
178
- }
179
- return this._getBodyBytes() ?? new ArrayBuffer(0);
86
+ }
87
+ get bodyUsed() {
88
+ return this._bodyUsed;
89
+ }
90
+ get body() {
91
+ if (this._bodyStream) return this._bodyStream;
92
+ const bytes = this._getBodyBytes();
93
+ if (!bytes) return null;
94
+ return new ReadableStream({
95
+ start(controller) {
96
+ controller.enqueue(new Uint8Array(bytes));
97
+ controller.close();
98
+ },
99
+ });
100
+ }
101
+ _throwIfBodyUsed() {
102
+ if (this._bodyUsed) {
103
+ throw new TypeError('Body has already been consumed.');
180
104
  }
181
- async blob() {
182
- this._throwIfBodyUsed();
183
- this._bodyUsed = true;
184
- // RN's Blob doesn't support ArrayBuffer/ArrayBufferView — use string body
185
- const bodyStr = this._getBodyString();
186
- const contentType = this.headers.get('content-type') ?? '';
187
- return new Blob([bodyStr], { type: contentType });
105
+ }
106
+ _getBodyBytes() {
107
+ // TODO: copy buffer to avoid clone being modifying res
108
+ if (this._bodyBytes != null) return this._bodyBytes;
109
+ if (this._bodyString != null) {
110
+ const encoded = stringToUTF8(this._bodyString);
111
+ return encoded.buffer.slice(
112
+ encoded.byteOffset,
113
+ encoded.byteOffset + encoded.byteLength
114
+ );
188
115
  }
189
- async bytes() {
190
- this._throwIfBodyUsed();
191
- this._bodyUsed = true;
192
- const buffer = this._getBodyBytes() ?? new ArrayBuffer(0);
193
- return new Uint8Array(buffer);
116
+ return undefined;
117
+ }
118
+ _getBodyString() {
119
+ if (this._bodyString != null) return this._bodyString;
120
+ if (this._bodyBytes) {
121
+ return utf8ToString(new Uint8Array(this._bodyBytes));
194
122
  }
195
- clone() {
196
- if (this._bodyUsed) {
197
- throw new TypeError('Cannot clone a Response whose body has been used.');
198
- }
199
- return new NitroResponse({
200
- url: this.url,
201
- status: this.status,
202
- statusText: this.statusText,
203
- ok: this.ok,
204
- redirected: this.redirected,
205
- headers: this.headers,
206
- bodyBytes: this._bodyBytes,
207
- bodyString: this._bodyString,
208
- type: this.type,
209
- });
123
+ return '';
124
+ }
125
+ async text() {
126
+ this._throwIfBodyUsed();
127
+ this._bodyUsed = true;
128
+ if (this._bodyStream && !this._bodyBytes && this._bodyString == null) {
129
+ const reader = this._bodyStream.getReader();
130
+ const chunks = [];
131
+ while (true) {
132
+ const { done, value } = await reader.read();
133
+ if (done) break;
134
+ if (value) chunks.push(value);
135
+ }
136
+ // Concatenate chunks
137
+ let totalLen = 0;
138
+ for (const c of chunks) totalLen += c.byteLength;
139
+ const merged = new Uint8Array(totalLen);
140
+ let offset = 0;
141
+ for (const c of chunks) {
142
+ merged.set(c, offset);
143
+ offset += c.byteLength;
144
+ }
145
+ return utf8ToString(merged);
210
146
  }
211
- async formData() {
212
- throw new TypeError('formData() is not supported in NitroResponse');
147
+ return this._getBodyString();
148
+ }
149
+ async json() {
150
+ this._throwIfBodyUsed();
151
+ this._bodyUsed = true;
152
+ const t = this._getBodyString();
153
+ return JSON.parse(t || '{}');
154
+ }
155
+ async arrayBuffer() {
156
+ this._throwIfBodyUsed();
157
+ this._bodyUsed = true;
158
+ if (this._bodyStream && !this._bodyBytes && this._bodyString == null) {
159
+ const reader = this._bodyStream.getReader();
160
+ const chunks = [];
161
+ while (true) {
162
+ const { done, value } = await reader.read();
163
+ if (done) break;
164
+ if (value) chunks.push(value);
165
+ }
166
+ let totalLen = 0;
167
+ for (const c of chunks) totalLen += c.byteLength;
168
+ const merged = new Uint8Array(totalLen);
169
+ let offset = 0;
170
+ for (const c of chunks) {
171
+ merged.set(c, offset);
172
+ offset += c.byteLength;
173
+ }
174
+ return merged.buffer.slice(
175
+ merged.byteOffset,
176
+ merged.byteOffset + merged.byteLength
177
+ );
213
178
  }
214
- // --- Static methods ---
215
- static error() {
216
- return new NitroResponse({
217
- url: '',
218
- status: 0,
219
- statusText: '',
220
- ok: false,
221
- redirected: false,
222
- headers: [],
223
- type: 'error',
224
- });
179
+ return this._getBodyBytes() ?? new ArrayBuffer(0);
180
+ }
181
+ async blob() {
182
+ this._throwIfBodyUsed();
183
+ this._bodyUsed = true;
184
+ // RN's Blob doesn't support ArrayBuffer/ArrayBufferView — use string body
185
+ const bodyStr = this._getBodyString();
186
+ const contentType = this.headers.get('content-type') ?? '';
187
+ return new Blob([bodyStr], { type: contentType });
188
+ }
189
+ async bytes() {
190
+ this._throwIfBodyUsed();
191
+ this._bodyUsed = true;
192
+ const buffer = this._getBodyBytes() ?? new ArrayBuffer(0);
193
+ return new Uint8Array(buffer);
194
+ }
195
+ clone() {
196
+ if (this._bodyUsed) {
197
+ throw new TypeError('Cannot clone a Response whose body has been used.');
225
198
  }
226
- static json(data, init) {
227
- const body = JSON.stringify(data);
228
- const headers = new NitroHeaders(init?.headers);
229
- if (!headers.has('content-type')) {
230
- headers.set('content-type', 'application/json');
231
- }
232
- return new NitroResponse({
233
- url: '',
234
- status: init?.status ?? 200,
235
- statusText: init?.statusText ?? '',
236
- ok: (init?.status ?? 200) >= 200 && (init?.status ?? 200) < 300,
237
- redirected: false,
238
- headers,
239
- bodyString: body,
240
- });
199
+ return new NitroResponse({
200
+ url: this.url,
201
+ status: this.status,
202
+ statusText: this.statusText,
203
+ ok: this.ok,
204
+ redirected: this.redirected,
205
+ headers: this.headers,
206
+ bodyBytes: this._bodyBytes,
207
+ bodyString: this._bodyString,
208
+ type: this.type,
209
+ });
210
+ }
211
+ async formData() {
212
+ throw new TypeError('formData() is not supported in NitroResponse');
213
+ }
214
+ // --- Static methods ---
215
+ static error() {
216
+ return new NitroResponse({
217
+ url: '',
218
+ status: 0,
219
+ statusText: '',
220
+ ok: false,
221
+ redirected: false,
222
+ headers: [],
223
+ type: 'error',
224
+ });
225
+ }
226
+ static json(data, init) {
227
+ const body = JSON.stringify(data);
228
+ const headers = new NitroHeaders(init?.headers);
229
+ if (!headers.has('content-type')) {
230
+ headers.set('content-type', 'application/json');
241
231
  }
242
- static redirect(url, status = 302) {
243
- const validStatuses = [301, 302, 303, 307, 308];
244
- if (!validStatuses.includes(status)) {
245
- throw new RangeError(`Invalid redirect status: ${status}. Must be one of ${validStatuses.join(', ')}`);
246
- }
247
- const headers = new NitroHeaders();
248
- headers.set('location', url);
249
- return new NitroResponse({
250
- url: '',
251
- status,
252
- statusText: '',
253
- ok: false,
254
- redirected: false,
255
- headers,
256
- });
232
+ return new NitroResponse({
233
+ url: '',
234
+ status: init?.status ?? 200,
235
+ statusText: init?.statusText ?? '',
236
+ ok: (init?.status ?? 200) >= 200 && (init?.status ?? 200) < 300,
237
+ redirected: false,
238
+ headers,
239
+ bodyString: body,
240
+ });
241
+ }
242
+ static redirect(url, status = 302) {
243
+ const validStatuses = [301, 302, 303, 307, 308];
244
+ if (!validStatuses.includes(status)) {
245
+ throw new RangeError(
246
+ `Invalid redirect status: ${status}. Must be one of ${validStatuses.join(', ')}`
247
+ );
257
248
  }
249
+ const headers = new NitroHeaders();
250
+ headers.set('location', url);
251
+ return new NitroResponse({
252
+ url: '',
253
+ status,
254
+ statusText: '',
255
+ ok: false,
256
+ redirected: false,
257
+ headers,
258
+ });
259
+ }
258
260
  }