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.
- package/NitroFetch.podspec +1 -3
- package/README.md +38 -0
- package/android/build.gradle +12 -0
- package/android/src/main/java/com/margelo/nitro/nitrofetch/AutoPrefetcher.kt +148 -55
- package/android/src/main/java/com/margelo/nitro/nitrofetch/DevToolsReporterImpl.kt +27 -36
- package/ios/NitroAutoPrefetcher.swift +149 -53
- package/ios/NitroDevToolsReporter.mm +37 -31
- package/lib/module/CurlGenerator.js.map +2 -1
- package/lib/module/Headers.js.map +2 -1
- package/lib/module/HermesProfiler.js.map +1 -1
- package/lib/module/NetworkInspector.js +1 -1
- package/lib/module/NetworkInspector.js.map +2 -1
- package/lib/module/NitroCronet.nitro.js.map +2 -1
- package/lib/module/NitroFetch.nitro.js.map +1 -2
- package/lib/module/NitroInstances.js.map +2 -1
- package/lib/module/Response.js.map +1 -2
- package/lib/module/fetch.js +8 -10
- package/lib/module/fetch.js.map +2 -1
- package/lib/module/index.js.map +2 -2
- package/lib/module/index.web.js +2 -1
- package/lib/module/tokenRefresh.js.map +2 -1
- package/lib/module/utf8.js.map +1 -2
- package/lib/typescript/src/fetch.d.ts.map +1 -1
- package/lib/typescript/src/tokenRefresh.d.ts +14 -0
- package/lib/typescript/src/tokenRefresh.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/CurlGenerator.js +23 -26
- package/src/Headers.js +108 -116
- package/src/HermesProfiler.js +16 -18
- package/src/NetworkInspector.js +171 -179
- package/src/NitroInstances.js +2 -1
- package/src/Request.js +167 -164
- package/src/Response.js +244 -242
- package/src/fetch.js +708 -693
- package/src/fetch.ts +15 -16
- package/src/index.js +17 -2
- package/src/index.web.js +69 -67
- package/src/tokenRefresh.js +75 -77
- package/src/tokenRefresh.ts +16 -0
- package/src/utf8.js +28 -27
package/src/fetch.ts
CHANGED
|
@@ -758,6 +758,8 @@ export async function prefetch(
|
|
|
758
758
|
await client.prefetch(req);
|
|
759
759
|
}
|
|
760
760
|
|
|
761
|
+
const AUTOPREFETCH_QUEUE_KEY = 'nitrofetch_autoprefetch_queue';
|
|
762
|
+
|
|
761
763
|
// Persist a request to storage so native can prefetch it on app start.
|
|
762
764
|
export async function prefetchOnAppStart(
|
|
763
765
|
input: RequestInfo | URL,
|
|
@@ -803,12 +805,9 @@ export async function prefetchOnAppStart(
|
|
|
803
805
|
|
|
804
806
|
// Write or append to storage queue
|
|
805
807
|
try {
|
|
806
|
-
const KEY = 'nitrofetch_autoprefetch_queue';
|
|
807
808
|
let arr: any[] = [];
|
|
808
809
|
try {
|
|
809
|
-
const raw = NativeStorageSingleton.getString(
|
|
810
|
-
'nitrofetch_autoprefetch_queue'
|
|
811
|
-
);
|
|
810
|
+
const raw = NativeStorageSingleton.getString(AUTOPREFETCH_QUEUE_KEY);
|
|
812
811
|
if (raw) arr = JSON.parse(raw);
|
|
813
812
|
if (!Array.isArray(arr)) arr = [];
|
|
814
813
|
} catch {
|
|
@@ -818,7 +817,10 @@ export async function prefetchOnAppStart(
|
|
|
818
817
|
arr = arr.filter((e) => e && e.prefetchKey !== prefetchKey);
|
|
819
818
|
}
|
|
820
819
|
arr.push(entry);
|
|
821
|
-
NativeStorageSingleton.setString(
|
|
820
|
+
NativeStorageSingleton.setString(
|
|
821
|
+
AUTOPREFETCH_QUEUE_KEY,
|
|
822
|
+
JSON.stringify(arr)
|
|
823
|
+
);
|
|
822
824
|
} catch (e) {
|
|
823
825
|
console.warn('Failed to persist prefetch queue', e);
|
|
824
826
|
}
|
|
@@ -829,12 +831,9 @@ export async function removeFromAutoPrefetch(
|
|
|
829
831
|
prefetchKey: string
|
|
830
832
|
): Promise<void> {
|
|
831
833
|
try {
|
|
832
|
-
const KEY = 'nitrofetch_autoprefetch_queue';
|
|
833
834
|
let arr: any[] = [];
|
|
834
835
|
try {
|
|
835
|
-
const raw = NativeStorageSingleton.getString(
|
|
836
|
-
'nitrofetch_autoprefetch_queue'
|
|
837
|
-
);
|
|
836
|
+
const raw = NativeStorageSingleton.getString(AUTOPREFETCH_QUEUE_KEY);
|
|
838
837
|
if (raw) arr = JSON.parse(raw);
|
|
839
838
|
if (!Array.isArray(arr)) arr = [];
|
|
840
839
|
} catch {
|
|
@@ -842,9 +841,12 @@ export async function removeFromAutoPrefetch(
|
|
|
842
841
|
}
|
|
843
842
|
const next = arr.filter((e) => e && e.prefetchKey !== prefetchKey);
|
|
844
843
|
if (next.length === 0) {
|
|
845
|
-
NativeStorageSingleton.removeString(
|
|
844
|
+
NativeStorageSingleton.removeString(AUTOPREFETCH_QUEUE_KEY);
|
|
846
845
|
} else if (next.length !== arr.length) {
|
|
847
|
-
NativeStorageSingleton.setString(
|
|
846
|
+
NativeStorageSingleton.setString(
|
|
847
|
+
AUTOPREFETCH_QUEUE_KEY,
|
|
848
|
+
JSON.stringify(next)
|
|
849
|
+
);
|
|
848
850
|
}
|
|
849
851
|
} catch (e) {
|
|
850
852
|
console.warn('Failed to remove from prefetch queue', e);
|
|
@@ -853,15 +855,12 @@ export async function removeFromAutoPrefetch(
|
|
|
853
855
|
|
|
854
856
|
// Remove all entries from the auto-prefetch queue.
|
|
855
857
|
export async function removeAllFromAutoprefetch(): Promise<void> {
|
|
856
|
-
|
|
857
|
-
NativeStorageSingleton.setString(KEY, JSON.stringify([]));
|
|
858
|
+
NativeStorageSingleton.setString(AUTOPREFETCH_QUEUE_KEY, JSON.stringify([]));
|
|
858
859
|
}
|
|
859
860
|
|
|
860
861
|
export function __readAutoPrefetchQueue(): Array<Record<string, any>> {
|
|
861
862
|
try {
|
|
862
|
-
const raw = NativeStorageSingleton.getString(
|
|
863
|
-
'nitrofetch_autoprefetch_queue'
|
|
864
|
-
);
|
|
863
|
+
const raw = NativeStorageSingleton.getString(AUTOPREFETCH_QUEUE_KEY);
|
|
865
864
|
if (!raw) return [];
|
|
866
865
|
const parsed = JSON.parse(raw);
|
|
867
866
|
return Array.isArray(parsed) ? parsed : [];
|
package/src/index.js
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
nitroFetch as fetch,
|
|
3
|
+
nitroFetchOnWorklet,
|
|
4
|
+
prefetch,
|
|
5
|
+
prefetchOnAppStart,
|
|
6
|
+
removeFromAutoPrefetch,
|
|
7
|
+
removeAllFromAutoprefetch,
|
|
8
|
+
__readAutoPrefetchQueue,
|
|
9
|
+
} from './fetch';
|
|
2
10
|
export { NitroHeaders as Headers } from './Headers';
|
|
3
11
|
export { NitroResponse as Response } from './Response';
|
|
4
12
|
export { NitroRequest as Request } from './Request';
|
|
5
13
|
export { NitroFetch } from './NitroInstances';
|
|
6
|
-
export {
|
|
14
|
+
export {
|
|
15
|
+
registerTokenRefresh,
|
|
16
|
+
clearTokenRefresh,
|
|
17
|
+
callRefreshEndpoint,
|
|
18
|
+
getStoredTokenRefreshConfig,
|
|
19
|
+
getNestedField,
|
|
20
|
+
applyTemplate,
|
|
21
|
+
} from './tokenRefresh';
|
|
7
22
|
export { NetworkInspector } from './NetworkInspector';
|
|
8
23
|
export { generateCurl } from './CurlGenerator';
|
|
9
24
|
export { profileFetch } from './HermesProfiler';
|
package/src/index.web.js
CHANGED
|
@@ -9,96 +9,98 @@ export { NetworkInspector } from './NetworkInspector';
|
|
|
9
9
|
export { generateCurl } from './CurlGenerator';
|
|
10
10
|
export { profileFetch } from './HermesProfiler';
|
|
11
11
|
export async function fetch(input, init) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
resolvedInput = input.url;
|
|
23
|
-
resolvedInit = {
|
|
24
|
-
...init,
|
|
25
|
-
method,
|
|
26
|
-
headers: (init?.headers ??
|
|
27
|
-
input.headers),
|
|
28
|
-
body,
|
|
29
|
-
redirect: init?.redirect ?? input.redirect,
|
|
30
|
-
cache: init?.cache ?? input.cache,
|
|
31
|
-
signal: init?.signal ?? input.signal,
|
|
32
|
-
};
|
|
12
|
+
let resolvedInput = input;
|
|
13
|
+
let resolvedInit = init;
|
|
14
|
+
if (input instanceof NitroRequestClass) {
|
|
15
|
+
const method = (init?.method ?? input.method).toUpperCase();
|
|
16
|
+
const hasBodyMethod = method !== 'GET' && method !== 'HEAD';
|
|
17
|
+
let body = init?.body;
|
|
18
|
+
if (body === undefined && hasBodyMethod) {
|
|
19
|
+
const bytes = await input.arrayBuffer().catch(() => undefined);
|
|
20
|
+
body = bytes && bytes.byteLength > 0 ? bytes : null;
|
|
33
21
|
}
|
|
34
|
-
|
|
22
|
+
resolvedInput = input.url;
|
|
23
|
+
resolvedInit = {
|
|
24
|
+
...init,
|
|
25
|
+
method,
|
|
26
|
+
headers: init?.headers ?? input.headers,
|
|
27
|
+
body,
|
|
28
|
+
redirect: init?.redirect ?? input.redirect,
|
|
29
|
+
cache: init?.cache ?? input.cache,
|
|
30
|
+
signal: init?.signal ?? input.signal,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return globalThis.fetch(resolvedInput, resolvedInit);
|
|
35
34
|
}
|
|
36
35
|
export async function nitroFetchOnWorklet(input, init, mapWorklet, _options) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
36
|
+
console.warn(
|
|
37
|
+
'nitroFetchOnWorklet: worklets are not available on web; running on the JS thread'
|
|
38
|
+
);
|
|
39
|
+
const res = await globalThis.fetch(input, init);
|
|
40
|
+
const bodyBytes = await res.clone().arrayBuffer();
|
|
41
|
+
let bodyString;
|
|
42
|
+
try {
|
|
43
|
+
bodyString = await res.clone().text();
|
|
44
|
+
} catch {
|
|
45
|
+
bodyString = undefined;
|
|
46
|
+
}
|
|
47
|
+
const headers = [];
|
|
48
|
+
res.headers.forEach((v, k) => headers.push({ key: k, value: v }));
|
|
49
|
+
return mapWorklet({
|
|
50
|
+
url: res.url,
|
|
51
|
+
status: res.status,
|
|
52
|
+
statusText: res.statusText,
|
|
53
|
+
ok: res.ok,
|
|
54
|
+
redirected: res.redirected ?? false,
|
|
55
|
+
headers,
|
|
56
|
+
bodyBytes,
|
|
57
|
+
bodyString,
|
|
58
|
+
});
|
|
59
59
|
}
|
|
60
60
|
export async function prefetch(_input, _init) {
|
|
61
|
-
|
|
61
|
+
console.warn('prefetch is not available on web');
|
|
62
62
|
}
|
|
63
63
|
export async function prefetchOnAppStart(_input, _init) {
|
|
64
|
-
|
|
64
|
+
console.warn('prefetchOnAppStart is not available on web');
|
|
65
65
|
}
|
|
66
66
|
export async function removeFromAutoPrefetch(_prefetchKey) {
|
|
67
|
-
|
|
67
|
+
console.warn('removeFromAutoPrefetch is not available on web');
|
|
68
68
|
}
|
|
69
69
|
export async function removeAllFromAutoprefetch() {
|
|
70
|
-
|
|
70
|
+
console.warn('removeAllFromAutoprefetch is not available on web');
|
|
71
71
|
}
|
|
72
|
-
export const NitroFetch = new Proxy(
|
|
72
|
+
export const NitroFetch = new Proxy(
|
|
73
|
+
{},
|
|
74
|
+
{
|
|
73
75
|
get(_target, prop) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
console.warn(`NitroFetch.${String(prop)} is not available on web`);
|
|
77
|
+
return undefined;
|
|
76
78
|
},
|
|
77
|
-
}
|
|
79
|
+
}
|
|
80
|
+
);
|
|
78
81
|
export function registerTokenRefresh(_options) {
|
|
79
|
-
|
|
82
|
+
console.warn('registerTokenRefresh is not available on web');
|
|
80
83
|
}
|
|
81
84
|
export function clearTokenRefresh(_target) {
|
|
82
|
-
|
|
85
|
+
console.warn('clearTokenRefresh is not available on web');
|
|
83
86
|
}
|
|
84
87
|
export async function callRefreshEndpoint(_config) {
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
console.warn('callRefreshEndpoint is not available on web');
|
|
89
|
+
return {};
|
|
87
90
|
}
|
|
88
91
|
export function getStoredTokenRefreshConfig(_target) {
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
console.warn('getStoredTokenRefreshConfig is not available on web');
|
|
93
|
+
return null;
|
|
91
94
|
}
|
|
92
95
|
export function getNestedField(obj, dotPath) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return current != null ? String(current) : undefined;
|
|
96
|
+
const parts = dotPath.split('.');
|
|
97
|
+
let current = obj;
|
|
98
|
+
for (const part of parts) {
|
|
99
|
+
if (current == null || typeof current !== 'object') return undefined;
|
|
100
|
+
current = current[part];
|
|
101
|
+
}
|
|
102
|
+
return current != null ? String(current) : undefined;
|
|
101
103
|
}
|
|
102
104
|
export function applyTemplate(template, value) {
|
|
103
|
-
|
|
105
|
+
return template.replace(/\{\{value\}\}/g, value);
|
|
104
106
|
}
|
package/src/tokenRefresh.js
CHANGED
|
@@ -9,96 +9,94 @@ const KEY_FETCH_CACHE = 'nitro_token_refresh_fetch_cache';
|
|
|
9
9
|
* Resolve a dot-notation path inside a parsed JSON object.
|
|
10
10
|
*/
|
|
11
11
|
export function getNestedField(obj, dotPath) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return current != null ? String(current) : undefined;
|
|
12
|
+
const parts = dotPath.split('.');
|
|
13
|
+
let current = obj;
|
|
14
|
+
for (const part of parts) {
|
|
15
|
+
if (current == null || typeof current !== 'object') return undefined;
|
|
16
|
+
current = current[part];
|
|
17
|
+
}
|
|
18
|
+
return current != null ? String(current) : undefined;
|
|
20
19
|
}
|
|
21
20
|
export function applyTemplate(template, value) {
|
|
22
|
-
|
|
21
|
+
return template.replace(/\{\{value\}\}/g, value);
|
|
23
22
|
}
|
|
24
23
|
function applyCompositeTemplate(template, values) {
|
|
25
|
-
|
|
24
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => values[key] ?? '');
|
|
26
25
|
}
|
|
27
26
|
export async function callRefreshEndpoint(config) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
27
|
+
const method = config.method ?? 'POST';
|
|
28
|
+
const response = await fetch(config.url, {
|
|
29
|
+
method,
|
|
30
|
+
headers: config.headers,
|
|
31
|
+
body: config.body,
|
|
32
|
+
});
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`Token refresh failed: ${response.status} ${response.statusText}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const headers = {};
|
|
39
|
+
if (config.responseType === 'text') {
|
|
40
|
+
const text = await response.text();
|
|
41
|
+
if (config.textHeader) {
|
|
42
|
+
headers[config.textHeader] = config.textTemplate
|
|
43
|
+
? applyTemplate(config.textTemplate, text)
|
|
44
|
+
: text;
|
|
46
45
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
return headers;
|
|
47
|
+
}
|
|
48
|
+
// Default: json
|
|
49
|
+
const json = await response.json();
|
|
50
|
+
if (config.mappings) {
|
|
51
|
+
for (const mapping of config.mappings) {
|
|
52
|
+
const value = getNestedField(json, mapping.jsonPath);
|
|
53
|
+
if (value != null) {
|
|
54
|
+
headers[mapping.header] = mapping.valueTemplate
|
|
55
|
+
? applyTemplate(mapping.valueTemplate, value)
|
|
56
|
+
: value;
|
|
57
|
+
}
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
59
|
+
}
|
|
60
|
+
if (config.compositeHeaders) {
|
|
61
|
+
for (const comp of config.compositeHeaders) {
|
|
62
|
+
const values = {};
|
|
63
|
+
for (const [placeholder, jsonPath] of Object.entries(comp.paths)) {
|
|
64
|
+
const val = getNestedField(json, jsonPath);
|
|
65
|
+
if (val != null) values[placeholder] = val;
|
|
66
|
+
}
|
|
67
|
+
headers[comp.header] = applyCompositeTemplate(comp.template, values);
|
|
69
68
|
}
|
|
70
|
-
|
|
69
|
+
}
|
|
70
|
+
return headers;
|
|
71
71
|
}
|
|
72
72
|
export function registerTokenRefresh(options) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
const { target, ...config } = options;
|
|
74
|
+
const raw = JSON.stringify(config);
|
|
75
|
+
if (target === 'websocket' || target === 'all') {
|
|
76
|
+
NativeStorageSingleton.setSecureString(KEY_WS, raw);
|
|
77
|
+
}
|
|
78
|
+
if (target === 'fetch' || target === 'all') {
|
|
79
|
+
NativeStorageSingleton.setSecureString(KEY_FETCH, raw);
|
|
80
|
+
}
|
|
81
81
|
}
|
|
82
82
|
export function clearTokenRefresh(target) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
const t = target ?? 'all';
|
|
84
|
+
if (t === 'websocket' || t === 'all') {
|
|
85
|
+
NativeStorageSingleton.removeSecureString(KEY_WS);
|
|
86
|
+
NativeStorageSingleton.removeSecureString(KEY_WS_CACHE);
|
|
87
|
+
}
|
|
88
|
+
if (t === 'fetch' || t === 'all') {
|
|
89
|
+
NativeStorageSingleton.removeSecureString(KEY_FETCH);
|
|
90
|
+
NativeStorageSingleton.removeSecureString(KEY_FETCH_CACHE);
|
|
91
|
+
}
|
|
92
92
|
}
|
|
93
93
|
export function getStoredTokenRefreshConfig(target) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
94
|
+
const key = target === 'websocket' ? KEY_WS : KEY_FETCH;
|
|
95
|
+
try {
|
|
96
|
+
const raw = NativeStorageSingleton.getSecureString(key);
|
|
97
|
+
if (!raw) return null;
|
|
98
|
+
return JSON.parse(raw);
|
|
99
|
+
} catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
104
102
|
}
|
package/src/tokenRefresh.ts
CHANGED
|
@@ -20,6 +20,18 @@ type TokenRefreshCompositeHeader = {
|
|
|
20
20
|
paths: Record<string, string>;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
type TokenRefreshBodyMapping = {
|
|
24
|
+
jsonPath: string;
|
|
25
|
+
bodyPath: string;
|
|
26
|
+
valueTemplate?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type TokenRefreshFormDataMapping = {
|
|
30
|
+
jsonPath: string;
|
|
31
|
+
field: string;
|
|
32
|
+
valueTemplate?: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
23
35
|
export type TokenRefreshConfig = {
|
|
24
36
|
url: string;
|
|
25
37
|
method?: 'GET' | 'POST' | 'PUT' | 'PATCH';
|
|
@@ -30,6 +42,10 @@ export type TokenRefreshConfig = {
|
|
|
30
42
|
compositeHeaders?: TokenRefreshCompositeHeader[];
|
|
31
43
|
textHeader?: string;
|
|
32
44
|
textTemplate?: string;
|
|
45
|
+
bodyMappings?: TokenRefreshBodyMapping[];
|
|
46
|
+
formDataMappings?: TokenRefreshFormDataMapping[];
|
|
47
|
+
bodyTextPath?: string;
|
|
48
|
+
formDataTextField?: string;
|
|
33
49
|
onFailure?: 'skip' | 'useStoredHeaders';
|
|
34
50
|
};
|
|
35
51
|
|
package/src/utf8.js
CHANGED
|
@@ -2,39 +2,40 @@ let _TextEncoder;
|
|
|
2
2
|
let _TextDecoder;
|
|
3
3
|
const NITRO_TEXT_DECODER_PKG = 'react-native-nitro-text-decoder';
|
|
4
4
|
function loadOptionalTextCodec() {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
5
|
+
try {
|
|
6
|
+
// Hide require from the bundler so the package stays truly optional.
|
|
7
|
+
// eslint-disable-next-line no-new-func
|
|
8
|
+
const dynamicRequire = new Function('mod', 'return require(mod);');
|
|
9
|
+
return dynamicRequire(NITRO_TEXT_DECODER_PKG);
|
|
10
|
+
} catch {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
14
13
|
}
|
|
15
14
|
if (typeof TextEncoder !== 'undefined') {
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
_TextEncoder = loadOptionalTextCodec().TextEncoder;
|
|
15
|
+
_TextEncoder = TextEncoder;
|
|
16
|
+
} else {
|
|
17
|
+
_TextEncoder = loadOptionalTextCodec().TextEncoder;
|
|
20
18
|
}
|
|
21
19
|
if (typeof TextDecoder !== 'undefined') {
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
_TextDecoder = loadOptionalTextCodec().TextDecoder;
|
|
20
|
+
_TextDecoder = TextDecoder;
|
|
21
|
+
} else {
|
|
22
|
+
_TextDecoder = loadOptionalTextCodec().TextDecoder;
|
|
26
23
|
}
|
|
27
24
|
export function stringToUTF8(str) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return new
|
|
25
|
+
if (!_TextEncoder) {
|
|
26
|
+
console.warn(
|
|
27
|
+
'stringToUTF8: TextEncoder not available. Install react-native-nitro-text-decoder.'
|
|
28
|
+
);
|
|
29
|
+
return new Uint8Array(0);
|
|
30
|
+
}
|
|
31
|
+
return new _TextEncoder().encode(str);
|
|
33
32
|
}
|
|
34
33
|
export function utf8ToString(bytes) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return
|
|
34
|
+
if (!_TextDecoder) {
|
|
35
|
+
console.warn(
|
|
36
|
+
'utf8ToString: TextDecoder not available. Install react-native-nitro-text-decoder.'
|
|
37
|
+
);
|
|
38
|
+
return '';
|
|
39
|
+
}
|
|
40
|
+
return new _TextDecoder().decode(bytes);
|
|
40
41
|
}
|