fetch-native-bridge 0.1.0
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/README.md +93 -0
- package/dist/native/index.cjs +115 -0
- package/dist/native/index.cjs.map +1 -0
- package/dist/native/index.d.ts +33 -0
- package/dist/native/index.mjs +113 -0
- package/dist/native/index.mjs.map +1 -0
- package/dist/web/index.cjs +158 -0
- package/dist/web/index.cjs.map +1 -0
- package/dist/web/index.d.ts +10 -0
- package/dist/web/index.mjs +155 -0
- package/dist/web/index.mjs.map +1 -0
- package/package.json +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# fetch-native-bridge
|
|
2
|
+
|
|
3
|
+
Bridge `fetch` calls from a React Native WebView to the native app. Useful for file downloads and other requests that can't be handled inside a WebView.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
- **Web/WebView side**: call `fetchBridge()` instead of `fetch()`. In a normal browser it behaves identically to `fetch`. Inside a React Native WebView it posts a message to the native app with all request parameters.
|
|
8
|
+
- **Native side**: call `setupFetchHandler()` with a ref to the WebView. It intercepts incoming messages, performs the real fetch from the RN app, and posts the response back.
|
|
9
|
+
|
|
10
|
+
The auth context (cookies, tokens) must be available on the native side — the library does not transfer credentials from the WebView.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install fetch-native-bridge
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### WebView side (web app)
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { fetchBridge } from 'fetch-native-bridge';
|
|
24
|
+
|
|
25
|
+
const response = await fetchBridge('https://api.example.com/file.pdf', {
|
|
26
|
+
method: 'GET',
|
|
27
|
+
headers: { Authorization: 'Bearer ...' },
|
|
28
|
+
timeout: 60_000, // optional, default 30s
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const blob = await response.blob();
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Native side (React Native app)
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { useRef } from 'react';
|
|
38
|
+
import WebView from 'react-native-webview';
|
|
39
|
+
import { setupFetchHandler } from 'fetch-native-bridge/native';
|
|
40
|
+
import * as FileSystem from 'expo-file-system'; // or react-native-fs
|
|
41
|
+
|
|
42
|
+
export function MyWebView() {
|
|
43
|
+
const webViewRef = useRef(null);
|
|
44
|
+
|
|
45
|
+
const { onMessage } = setupFetchHandler(webViewRef, {
|
|
46
|
+
// Return false to handle the response yourself (e.g. save a file)
|
|
47
|
+
onFetch: async (req, res) => {
|
|
48
|
+
if (req.url.endsWith('.pdf')) {
|
|
49
|
+
const blob = await res.blob();
|
|
50
|
+
// save blob to disk...
|
|
51
|
+
return false; // suppress sending response back to WebView
|
|
52
|
+
}
|
|
53
|
+
return true; // send response back normally
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<WebView
|
|
59
|
+
ref={webViewRef}
|
|
60
|
+
source={{ uri: 'https://my-app.com' }}
|
|
61
|
+
onMessage={onMessage}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## API
|
|
68
|
+
|
|
69
|
+
### `fetchBridge(input, init?)`
|
|
70
|
+
|
|
71
|
+
Drop-in replacement for `fetch`. Accepts an optional `timeout` (ms) in `init`.
|
|
72
|
+
|
|
73
|
+
### `isReactNativeWebView()`
|
|
74
|
+
|
|
75
|
+
Returns `true` if running inside a React Native WebView. Detected via `window.ReactNativeWebView` or `window.__isReactNativeWebView`.
|
|
76
|
+
|
|
77
|
+
### `setupFetchHandler(webViewRef, options?)`
|
|
78
|
+
|
|
79
|
+
Sets up the native message handler. Returns `{ onMessage, teardown }`.
|
|
80
|
+
|
|
81
|
+
| Option | Type | Default | Description |
|
|
82
|
+
|--------|------|---------|-------------|
|
|
83
|
+
| `timeout` | `number` | `30000` | Request timeout in ms |
|
|
84
|
+
| `onFetch` | `(req, res) => boolean \| Promise<boolean>` | — | Called after fetch completes. Return `false` to skip posting the response back to the WebView. |
|
|
85
|
+
|
|
86
|
+
Call `teardown()` to abort in-flight requests (e.g. on component unmount).
|
|
87
|
+
|
|
88
|
+
## Publishing
|
|
89
|
+
|
|
90
|
+
1. Bump version in `package.json`
|
|
91
|
+
2. Commit and push
|
|
92
|
+
3. Create a GitHub Release with tag `v0.x.x`
|
|
93
|
+
4. CI publishes to npm automatically (requires `NPM_TOKEN` secret)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function isFetchRequestMessage(m) {
|
|
4
|
+
return (typeof m === 'object' &&
|
|
5
|
+
m !== null &&
|
|
6
|
+
m.type === 'FETCH_REQUEST' &&
|
|
7
|
+
typeof m.id === 'string' &&
|
|
8
|
+
typeof m.url === 'string');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const BINARY_CONTENT_TYPES = ['image/', 'application/octet-stream', 'application/pdf', 'audio/', 'video/'];
|
|
12
|
+
function isBinary(contentType) {
|
|
13
|
+
return BINARY_CONTENT_TYPES.some((prefix) => contentType.startsWith(prefix));
|
|
14
|
+
}
|
|
15
|
+
function uint8ArrayToBase64(bytes) {
|
|
16
|
+
let binary = '';
|
|
17
|
+
for (let i = 0; i < bytes.length; i++)
|
|
18
|
+
binary += String.fromCharCode(bytes[i]);
|
|
19
|
+
return btoa(binary);
|
|
20
|
+
}
|
|
21
|
+
async function serializeResponse(id, response) {
|
|
22
|
+
var _a;
|
|
23
|
+
const headers = {};
|
|
24
|
+
response.headers.forEach((value, key) => { headers[key] = value; });
|
|
25
|
+
const contentType = (_a = headers['content-type']) !== null && _a !== void 0 ? _a : '';
|
|
26
|
+
let body;
|
|
27
|
+
let bodyEncoding;
|
|
28
|
+
if (isBinary(contentType)) {
|
|
29
|
+
const buffer = await response.arrayBuffer();
|
|
30
|
+
body = uint8ArrayToBase64(new Uint8Array(buffer));
|
|
31
|
+
bodyEncoding = 'base64';
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
body = await response.text();
|
|
35
|
+
bodyEncoding = 'text';
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
type: 'FETCH_RESPONSE',
|
|
39
|
+
id,
|
|
40
|
+
status: response.status,
|
|
41
|
+
statusText: response.statusText,
|
|
42
|
+
headers,
|
|
43
|
+
body,
|
|
44
|
+
bodyEncoding,
|
|
45
|
+
ok: response.ok,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
50
|
+
function setupFetchHandler(webViewRef, options) {
|
|
51
|
+
var _a;
|
|
52
|
+
const controllers = new Map();
|
|
53
|
+
const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT;
|
|
54
|
+
async function handleRequest(req) {
|
|
55
|
+
var _a, _b, _c;
|
|
56
|
+
const controller = new AbortController();
|
|
57
|
+
controllers.set(req.id, controller);
|
|
58
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
59
|
+
try {
|
|
60
|
+
const response = await globalThis.fetch(req.url, {
|
|
61
|
+
method: req.method,
|
|
62
|
+
headers: req.headers,
|
|
63
|
+
body: (_a = req.body) !== null && _a !== void 0 ? _a : undefined,
|
|
64
|
+
signal: controller.signal,
|
|
65
|
+
});
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
controllers.delete(req.id);
|
|
68
|
+
if (options === null || options === void 0 ? void 0 : options.onFetch) {
|
|
69
|
+
const shouldSend = await options.onFetch(req, response.clone());
|
|
70
|
+
if (!shouldSend)
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const msg = await serializeResponse(req.id, response);
|
|
74
|
+
(_b = webViewRef.current) === null || _b === void 0 ? void 0 : _b.postMessage(JSON.stringify(msg));
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
clearTimeout(timer);
|
|
78
|
+
controllers.delete(req.id);
|
|
79
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
80
|
+
const msg = {
|
|
81
|
+
type: 'FETCH_RESPONSE',
|
|
82
|
+
id: req.id,
|
|
83
|
+
status: 0,
|
|
84
|
+
statusText: '',
|
|
85
|
+
headers: {},
|
|
86
|
+
body: '',
|
|
87
|
+
bodyEncoding: 'text',
|
|
88
|
+
ok: false,
|
|
89
|
+
error: errorMsg,
|
|
90
|
+
};
|
|
91
|
+
(_c = webViewRef.current) === null || _c === void 0 ? void 0 : _c.postMessage(JSON.stringify(msg));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function onMessage(event) {
|
|
95
|
+
let data;
|
|
96
|
+
try {
|
|
97
|
+
data = JSON.parse(event.nativeEvent.data);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!isFetchRequestMessage(data))
|
|
103
|
+
return;
|
|
104
|
+
void handleRequest(data);
|
|
105
|
+
}
|
|
106
|
+
function teardown() {
|
|
107
|
+
for (const controller of controllers.values())
|
|
108
|
+
controller.abort();
|
|
109
|
+
controllers.clear();
|
|
110
|
+
}
|
|
111
|
+
return { onMessage, teardown };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
exports.setupFetchHandler = setupFetchHandler;
|
|
115
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/protocol.ts","../../src/native/response.ts","../../src/native/handler.ts"],"sourcesContent":[null,null,null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
interface FetchRequestMessage {
|
|
2
|
+
type: 'FETCH_REQUEST';
|
|
3
|
+
id: string;
|
|
4
|
+
url: string;
|
|
5
|
+
method: string;
|
|
6
|
+
headers: Record<string, string>;
|
|
7
|
+
body: string | null;
|
|
8
|
+
}
|
|
9
|
+
interface SetupFetchHandlerOptions {
|
|
10
|
+
timeout?: number;
|
|
11
|
+
onFetch?: (req: FetchRequestMessage, res: Response) => boolean | Promise<boolean>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface WebViewRef {
|
|
15
|
+
current: {
|
|
16
|
+
postMessage(message: string): void;
|
|
17
|
+
injectJavaScript(script: string): void;
|
|
18
|
+
} | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface WebViewMessageEvent {
|
|
22
|
+
nativeEvent: {
|
|
23
|
+
data: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare function setupFetchHandler(webViewRef: WebViewRef, options?: SetupFetchHandlerOptions): {
|
|
28
|
+
onMessage: (event: WebViewMessageEvent) => void;
|
|
29
|
+
teardown: () => void;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { setupFetchHandler };
|
|
33
|
+
export type { SetupFetchHandlerOptions, WebViewMessageEvent, WebViewRef };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
function isFetchRequestMessage(m) {
|
|
2
|
+
return (typeof m === 'object' &&
|
|
3
|
+
m !== null &&
|
|
4
|
+
m.type === 'FETCH_REQUEST' &&
|
|
5
|
+
typeof m.id === 'string' &&
|
|
6
|
+
typeof m.url === 'string');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const BINARY_CONTENT_TYPES = ['image/', 'application/octet-stream', 'application/pdf', 'audio/', 'video/'];
|
|
10
|
+
function isBinary(contentType) {
|
|
11
|
+
return BINARY_CONTENT_TYPES.some((prefix) => contentType.startsWith(prefix));
|
|
12
|
+
}
|
|
13
|
+
function uint8ArrayToBase64(bytes) {
|
|
14
|
+
let binary = '';
|
|
15
|
+
for (let i = 0; i < bytes.length; i++)
|
|
16
|
+
binary += String.fromCharCode(bytes[i]);
|
|
17
|
+
return btoa(binary);
|
|
18
|
+
}
|
|
19
|
+
async function serializeResponse(id, response) {
|
|
20
|
+
var _a;
|
|
21
|
+
const headers = {};
|
|
22
|
+
response.headers.forEach((value, key) => { headers[key] = value; });
|
|
23
|
+
const contentType = (_a = headers['content-type']) !== null && _a !== void 0 ? _a : '';
|
|
24
|
+
let body;
|
|
25
|
+
let bodyEncoding;
|
|
26
|
+
if (isBinary(contentType)) {
|
|
27
|
+
const buffer = await response.arrayBuffer();
|
|
28
|
+
body = uint8ArrayToBase64(new Uint8Array(buffer));
|
|
29
|
+
bodyEncoding = 'base64';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
body = await response.text();
|
|
33
|
+
bodyEncoding = 'text';
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
type: 'FETCH_RESPONSE',
|
|
37
|
+
id,
|
|
38
|
+
status: response.status,
|
|
39
|
+
statusText: response.statusText,
|
|
40
|
+
headers,
|
|
41
|
+
body,
|
|
42
|
+
bodyEncoding,
|
|
43
|
+
ok: response.ok,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
48
|
+
function setupFetchHandler(webViewRef, options) {
|
|
49
|
+
var _a;
|
|
50
|
+
const controllers = new Map();
|
|
51
|
+
const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT;
|
|
52
|
+
async function handleRequest(req) {
|
|
53
|
+
var _a, _b, _c;
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
controllers.set(req.id, controller);
|
|
56
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
57
|
+
try {
|
|
58
|
+
const response = await globalThis.fetch(req.url, {
|
|
59
|
+
method: req.method,
|
|
60
|
+
headers: req.headers,
|
|
61
|
+
body: (_a = req.body) !== null && _a !== void 0 ? _a : undefined,
|
|
62
|
+
signal: controller.signal,
|
|
63
|
+
});
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
controllers.delete(req.id);
|
|
66
|
+
if (options === null || options === void 0 ? void 0 : options.onFetch) {
|
|
67
|
+
const shouldSend = await options.onFetch(req, response.clone());
|
|
68
|
+
if (!shouldSend)
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const msg = await serializeResponse(req.id, response);
|
|
72
|
+
(_b = webViewRef.current) === null || _b === void 0 ? void 0 : _b.postMessage(JSON.stringify(msg));
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
clearTimeout(timer);
|
|
76
|
+
controllers.delete(req.id);
|
|
77
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
78
|
+
const msg = {
|
|
79
|
+
type: 'FETCH_RESPONSE',
|
|
80
|
+
id: req.id,
|
|
81
|
+
status: 0,
|
|
82
|
+
statusText: '',
|
|
83
|
+
headers: {},
|
|
84
|
+
body: '',
|
|
85
|
+
bodyEncoding: 'text',
|
|
86
|
+
ok: false,
|
|
87
|
+
error: errorMsg,
|
|
88
|
+
};
|
|
89
|
+
(_c = webViewRef.current) === null || _c === void 0 ? void 0 : _c.postMessage(JSON.stringify(msg));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function onMessage(event) {
|
|
93
|
+
let data;
|
|
94
|
+
try {
|
|
95
|
+
data = JSON.parse(event.nativeEvent.data);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!isFetchRequestMessage(data))
|
|
101
|
+
return;
|
|
102
|
+
void handleRequest(data);
|
|
103
|
+
}
|
|
104
|
+
function teardown() {
|
|
105
|
+
for (const controller of controllers.values())
|
|
106
|
+
controller.abort();
|
|
107
|
+
controllers.clear();
|
|
108
|
+
}
|
|
109
|
+
return { onMessage, teardown };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { setupFetchHandler };
|
|
113
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/shared/protocol.ts","../../src/native/response.ts","../../src/native/handler.ts"],"sourcesContent":[null,null,null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function generateUUID() {
|
|
4
|
+
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
|
5
|
+
const bytes = new Uint8Array(16);
|
|
6
|
+
crypto.getRandomValues(bytes);
|
|
7
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
8
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
9
|
+
return [...bytes]
|
|
10
|
+
.map((b, i) => [4, 6, 8, 10].includes(i) ? `-${b.toString(16).padStart(2, '0')}` : b.toString(16).padStart(2, '0'))
|
|
11
|
+
.join('');
|
|
12
|
+
}
|
|
13
|
+
// Fallback for envs without crypto (old RN < 0.71)
|
|
14
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
15
|
+
const r = (Math.random() * 16) | 0;
|
|
16
|
+
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isFetchResponseMessage(m) {
|
|
21
|
+
return (typeof m === 'object' &&
|
|
22
|
+
m !== null &&
|
|
23
|
+
m.type === 'FETCH_RESPONSE' &&
|
|
24
|
+
typeof m.id === 'string' &&
|
|
25
|
+
typeof m.status === 'number');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isReactNativeWebView() {
|
|
29
|
+
return (typeof window !== 'undefined' &&
|
|
30
|
+
(typeof window.ReactNativeWebView !== 'undefined' ||
|
|
31
|
+
window.__isReactNativeWebView === true));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class PendingRequestMap {
|
|
35
|
+
constructor() {
|
|
36
|
+
this.map = new Map();
|
|
37
|
+
}
|
|
38
|
+
add(id, resolve, reject, timeoutMs) {
|
|
39
|
+
const timer = setTimeout(() => {
|
|
40
|
+
if (this.map.has(id)) {
|
|
41
|
+
this.map.delete(id);
|
|
42
|
+
reject(new Error(`fetchBridge: request ${id} timed out after ${timeoutMs}ms`));
|
|
43
|
+
}
|
|
44
|
+
}, timeoutMs);
|
|
45
|
+
this.map.set(id, { resolve, reject, timer });
|
|
46
|
+
}
|
|
47
|
+
resolve(id, msg) {
|
|
48
|
+
const entry = this.map.get(id);
|
|
49
|
+
if (!entry)
|
|
50
|
+
return;
|
|
51
|
+
clearTimeout(entry.timer);
|
|
52
|
+
this.map.delete(id);
|
|
53
|
+
entry.resolve(msg);
|
|
54
|
+
}
|
|
55
|
+
reject(id, reason) {
|
|
56
|
+
const entry = this.map.get(id);
|
|
57
|
+
if (!entry)
|
|
58
|
+
return;
|
|
59
|
+
clearTimeout(entry.timer);
|
|
60
|
+
this.map.delete(id);
|
|
61
|
+
entry.reject(reason);
|
|
62
|
+
}
|
|
63
|
+
clear() {
|
|
64
|
+
const err = new Error('fetchBridge: torn down');
|
|
65
|
+
for (const [id, entry] of this.map) {
|
|
66
|
+
clearTimeout(entry.timer);
|
|
67
|
+
entry.reject(err);
|
|
68
|
+
this.map.delete(id);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
74
|
+
const pending = new PendingRequestMap();
|
|
75
|
+
function buildHeaders(init) {
|
|
76
|
+
const result = {};
|
|
77
|
+
if (!(init === null || init === void 0 ? void 0 : init.headers))
|
|
78
|
+
return result;
|
|
79
|
+
if (init.headers instanceof Headers) {
|
|
80
|
+
init.headers.forEach((value, key) => { result[key] = value; });
|
|
81
|
+
}
|
|
82
|
+
else if (Array.isArray(init.headers)) {
|
|
83
|
+
for (const [key, value] of init.headers)
|
|
84
|
+
result[key] = value;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
Object.assign(result, init.headers);
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
function buildBody(init) {
|
|
92
|
+
if (!(init === null || init === void 0 ? void 0 : init.body))
|
|
93
|
+
return null;
|
|
94
|
+
if (typeof init.body === 'string')
|
|
95
|
+
return init.body;
|
|
96
|
+
return String(init.body);
|
|
97
|
+
}
|
|
98
|
+
function base64ToUint8Array(b64) {
|
|
99
|
+
const binary = atob(b64);
|
|
100
|
+
const bytes = new Uint8Array(binary.length);
|
|
101
|
+
for (let i = 0; i < binary.length; i++)
|
|
102
|
+
bytes[i] = binary.charCodeAt(i);
|
|
103
|
+
return bytes;
|
|
104
|
+
}
|
|
105
|
+
function buildResponse(msg) {
|
|
106
|
+
const responseBody = msg.bodyEncoding === 'base64'
|
|
107
|
+
? base64ToUint8Array(msg.body).buffer
|
|
108
|
+
: msg.body;
|
|
109
|
+
return new Response(responseBody, {
|
|
110
|
+
status: msg.status,
|
|
111
|
+
statusText: msg.statusText,
|
|
112
|
+
headers: msg.headers,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async function fetchBridge(input, init) {
|
|
116
|
+
var _a, _b;
|
|
117
|
+
if (!isReactNativeWebView()) {
|
|
118
|
+
const { timeout: _t, ...fetchInit } = init !== null && init !== void 0 ? init : {};
|
|
119
|
+
return globalThis.fetch(input, fetchInit);
|
|
120
|
+
}
|
|
121
|
+
const url = input instanceof URL ? input.href : typeof input === 'string' ? input : input.url;
|
|
122
|
+
const id = generateUUID();
|
|
123
|
+
const timeout = (_a = init === null || init === void 0 ? void 0 : init.timeout) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT;
|
|
124
|
+
const msg = {
|
|
125
|
+
type: 'FETCH_REQUEST',
|
|
126
|
+
id,
|
|
127
|
+
url,
|
|
128
|
+
method: (_b = init === null || init === void 0 ? void 0 : init.method) !== null && _b !== void 0 ? _b : 'GET',
|
|
129
|
+
headers: buildHeaders(init),
|
|
130
|
+
body: buildBody(init),
|
|
131
|
+
};
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
function onMessage(event) {
|
|
134
|
+
let data;
|
|
135
|
+
try {
|
|
136
|
+
data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!isFetchResponseMessage(data) || data.id !== id)
|
|
142
|
+
return;
|
|
143
|
+
window.removeEventListener('message', onMessage);
|
|
144
|
+
if (data.error) {
|
|
145
|
+
pending.reject(id, new Error(data.error));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
pending.resolve(id, data);
|
|
149
|
+
}
|
|
150
|
+
pending.add(id, (responseMsg) => resolve(buildResponse(responseMsg)), reject, timeout);
|
|
151
|
+
window.addEventListener('message', onMessage);
|
|
152
|
+
window.ReactNativeWebView.postMessage(JSON.stringify(msg));
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
exports.fetchBridge = fetchBridge;
|
|
157
|
+
exports.isReactNativeWebView = isReactNativeWebView;
|
|
158
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/uuid.ts","../../src/shared/protocol.ts","../../src/web/detect.ts","../../src/web/pending.ts","../../src/web/fetchBridge.ts"],"sourcesContent":[null,null,null,null,null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface FetchBridgeOptions extends RequestInit {
|
|
2
|
+
timeout?: number;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
declare function fetchBridge(input: RequestInfo | URL, init?: FetchBridgeOptions): Promise<Response>;
|
|
6
|
+
|
|
7
|
+
declare function isReactNativeWebView(): boolean;
|
|
8
|
+
|
|
9
|
+
export { fetchBridge, isReactNativeWebView };
|
|
10
|
+
export type { FetchBridgeOptions };
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
function generateUUID() {
|
|
2
|
+
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
|
3
|
+
const bytes = new Uint8Array(16);
|
|
4
|
+
crypto.getRandomValues(bytes);
|
|
5
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
6
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
7
|
+
return [...bytes]
|
|
8
|
+
.map((b, i) => [4, 6, 8, 10].includes(i) ? `-${b.toString(16).padStart(2, '0')}` : b.toString(16).padStart(2, '0'))
|
|
9
|
+
.join('');
|
|
10
|
+
}
|
|
11
|
+
// Fallback for envs without crypto (old RN < 0.71)
|
|
12
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
13
|
+
const r = (Math.random() * 16) | 0;
|
|
14
|
+
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isFetchResponseMessage(m) {
|
|
19
|
+
return (typeof m === 'object' &&
|
|
20
|
+
m !== null &&
|
|
21
|
+
m.type === 'FETCH_RESPONSE' &&
|
|
22
|
+
typeof m.id === 'string' &&
|
|
23
|
+
typeof m.status === 'number');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isReactNativeWebView() {
|
|
27
|
+
return (typeof window !== 'undefined' &&
|
|
28
|
+
(typeof window.ReactNativeWebView !== 'undefined' ||
|
|
29
|
+
window.__isReactNativeWebView === true));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class PendingRequestMap {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.map = new Map();
|
|
35
|
+
}
|
|
36
|
+
add(id, resolve, reject, timeoutMs) {
|
|
37
|
+
const timer = setTimeout(() => {
|
|
38
|
+
if (this.map.has(id)) {
|
|
39
|
+
this.map.delete(id);
|
|
40
|
+
reject(new Error(`fetchBridge: request ${id} timed out after ${timeoutMs}ms`));
|
|
41
|
+
}
|
|
42
|
+
}, timeoutMs);
|
|
43
|
+
this.map.set(id, { resolve, reject, timer });
|
|
44
|
+
}
|
|
45
|
+
resolve(id, msg) {
|
|
46
|
+
const entry = this.map.get(id);
|
|
47
|
+
if (!entry)
|
|
48
|
+
return;
|
|
49
|
+
clearTimeout(entry.timer);
|
|
50
|
+
this.map.delete(id);
|
|
51
|
+
entry.resolve(msg);
|
|
52
|
+
}
|
|
53
|
+
reject(id, reason) {
|
|
54
|
+
const entry = this.map.get(id);
|
|
55
|
+
if (!entry)
|
|
56
|
+
return;
|
|
57
|
+
clearTimeout(entry.timer);
|
|
58
|
+
this.map.delete(id);
|
|
59
|
+
entry.reject(reason);
|
|
60
|
+
}
|
|
61
|
+
clear() {
|
|
62
|
+
const err = new Error('fetchBridge: torn down');
|
|
63
|
+
for (const [id, entry] of this.map) {
|
|
64
|
+
clearTimeout(entry.timer);
|
|
65
|
+
entry.reject(err);
|
|
66
|
+
this.map.delete(id);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
72
|
+
const pending = new PendingRequestMap();
|
|
73
|
+
function buildHeaders(init) {
|
|
74
|
+
const result = {};
|
|
75
|
+
if (!(init === null || init === void 0 ? void 0 : init.headers))
|
|
76
|
+
return result;
|
|
77
|
+
if (init.headers instanceof Headers) {
|
|
78
|
+
init.headers.forEach((value, key) => { result[key] = value; });
|
|
79
|
+
}
|
|
80
|
+
else if (Array.isArray(init.headers)) {
|
|
81
|
+
for (const [key, value] of init.headers)
|
|
82
|
+
result[key] = value;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
Object.assign(result, init.headers);
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
function buildBody(init) {
|
|
90
|
+
if (!(init === null || init === void 0 ? void 0 : init.body))
|
|
91
|
+
return null;
|
|
92
|
+
if (typeof init.body === 'string')
|
|
93
|
+
return init.body;
|
|
94
|
+
return String(init.body);
|
|
95
|
+
}
|
|
96
|
+
function base64ToUint8Array(b64) {
|
|
97
|
+
const binary = atob(b64);
|
|
98
|
+
const bytes = new Uint8Array(binary.length);
|
|
99
|
+
for (let i = 0; i < binary.length; i++)
|
|
100
|
+
bytes[i] = binary.charCodeAt(i);
|
|
101
|
+
return bytes;
|
|
102
|
+
}
|
|
103
|
+
function buildResponse(msg) {
|
|
104
|
+
const responseBody = msg.bodyEncoding === 'base64'
|
|
105
|
+
? base64ToUint8Array(msg.body).buffer
|
|
106
|
+
: msg.body;
|
|
107
|
+
return new Response(responseBody, {
|
|
108
|
+
status: msg.status,
|
|
109
|
+
statusText: msg.statusText,
|
|
110
|
+
headers: msg.headers,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
async function fetchBridge(input, init) {
|
|
114
|
+
var _a, _b;
|
|
115
|
+
if (!isReactNativeWebView()) {
|
|
116
|
+
const { timeout: _t, ...fetchInit } = init !== null && init !== void 0 ? init : {};
|
|
117
|
+
return globalThis.fetch(input, fetchInit);
|
|
118
|
+
}
|
|
119
|
+
const url = input instanceof URL ? input.href : typeof input === 'string' ? input : input.url;
|
|
120
|
+
const id = generateUUID();
|
|
121
|
+
const timeout = (_a = init === null || init === void 0 ? void 0 : init.timeout) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT;
|
|
122
|
+
const msg = {
|
|
123
|
+
type: 'FETCH_REQUEST',
|
|
124
|
+
id,
|
|
125
|
+
url,
|
|
126
|
+
method: (_b = init === null || init === void 0 ? void 0 : init.method) !== null && _b !== void 0 ? _b : 'GET',
|
|
127
|
+
headers: buildHeaders(init),
|
|
128
|
+
body: buildBody(init),
|
|
129
|
+
};
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
function onMessage(event) {
|
|
132
|
+
let data;
|
|
133
|
+
try {
|
|
134
|
+
data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (!isFetchResponseMessage(data) || data.id !== id)
|
|
140
|
+
return;
|
|
141
|
+
window.removeEventListener('message', onMessage);
|
|
142
|
+
if (data.error) {
|
|
143
|
+
pending.reject(id, new Error(data.error));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
pending.resolve(id, data);
|
|
147
|
+
}
|
|
148
|
+
pending.add(id, (responseMsg) => resolve(buildResponse(responseMsg)), reject, timeout);
|
|
149
|
+
window.addEventListener('message', onMessage);
|
|
150
|
+
window.ReactNativeWebView.postMessage(JSON.stringify(msg));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { fetchBridge, isReactNativeWebView };
|
|
155
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/shared/uuid.ts","../../src/shared/protocol.ts","../../src/web/detect.ts","../../src/web/pending.ts","../../src/web/fetchBridge.ts"],"sourcesContent":[null,null,null,null,null],"names":[],"mappings":"SAAgB,YAAY,GAAA;IAC1B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,eAAe,EAAE;AAC3D,QAAA,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC;AAChC,QAAA,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC;AAC7B,QAAA,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI;AACnC,QAAA,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI;QACnC,OAAO,CAAC,GAAG,KAAK;aACb,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KACR,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAA,CAAA,EAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA,CAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;aAEpG,IAAI,CAAC,EAAE,CAAC;IACb;;IAEA,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,KAAI;AACnE,QAAA,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC;QAClC,OAAO,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;AACvD,IAAA,CAAC,CAAC;AACJ;;ACuBM,SAAU,sBAAsB,CAAC,CAAU,EAAA;AAC/C,IAAA,QACE,OAAO,CAAC,KAAK,QAAQ;AACrB,QAAA,CAAC,KAAK,IAAI;QACT,CAA0B,CAAC,IAAI,KAAK,gBAAgB;AACrD,QAAA,OAAQ,CAA0B,CAAC,EAAE,KAAK,QAAQ;AAClD,QAAA,OAAQ,CAA0B,CAAC,MAAM,KAAK,QAAQ;AAE1D;;SChDgB,oBAAoB,GAAA;AAClC,IAAA,QACE,OAAO,MAAM,KAAK,WAAW;AAC7B,SAAC,OAAQ,MAAc,CAAC,kBAAkB,KAAK,WAAW;AACvD,YAAA,MAAc,CAAC,sBAAsB,KAAK,IAAI,CAAC;AAEtD;;MCEa,iBAAiB,CAAA;AAA9B,IAAA,WAAA,GAAA;AACU,QAAA,IAAA,CAAA,GAAG,GAAG,IAAI,GAAG,EAAwB;IAyC/C;AAvCE,IAAA,GAAG,CACD,EAAU,EACV,OAA4C,EAC5C,MAA+B,EAC/B,SAAiB,EAAA;AAEjB,QAAA,MAAM,KAAK,GAAG,UAAU,CAAC,MAAK;YAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AACpB,gBAAA,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,KAAK,CAAC,CAAA,qBAAA,EAAwB,EAAE,CAAA,iBAAA,EAAoB,SAAS,CAAA,EAAA,CAAI,CAAC,CAAC;YAChF;QACF,CAAC,EAAE,SAAS,CAAC;AACb,QAAA,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC9C;IAEA,OAAO,CAAC,EAAU,EAAE,GAAyB,EAAA;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;AAC9B,QAAA,IAAI,CAAC,KAAK;YAAE;AACZ,QAAA,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;AACnB,QAAA,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;IACpB;IAEA,MAAM,CAAC,EAAU,EAAE,MAAa,EAAA;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;AAC9B,QAAA,IAAI,CAAC,KAAK;YAAE;AACZ,QAAA,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;AACnB,QAAA,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IACtB;IAEA,KAAK,GAAA;AACH,QAAA,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,wBAAwB,CAAC;QAC/C,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE;AAClC,YAAA,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC;AACzB,YAAA,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;AACjB,YAAA,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB;IACF;AACD;;AC7CD,MAAM,eAAe,GAAG,KAAM;AAC9B,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE;AAEvC,SAAS,YAAY,CAAC,IAAkB,EAAA;IACtC,MAAM,MAAM,GAA2B,EAAE;IACzC,IAAI,EAAC,IAAI,KAAA,IAAA,IAAJ,IAAI,KAAA,MAAA,GAAA,MAAA,GAAJ,IAAI,CAAE,OAAO,CAAA;AAAE,QAAA,OAAO,MAAM;AACjC,IAAA,IAAI,IAAI,CAAC,OAAO,YAAY,OAAO,EAAE;QACnC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE;SAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;QACtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO;AAAE,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK;IAC9D;SAAO;QACL,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC;IACrC;AACA,IAAA,OAAO,MAAM;AACf;AAEA,SAAS,SAAS,CAAC,IAAkB,EAAA;IACnC,IAAI,EAAC,IAAI,KAAA,IAAA,IAAJ,IAAI,KAAA,MAAA,GAAA,MAAA,GAAJ,IAAI,CAAE,IAAI,CAAA;AAAE,QAAA,OAAO,IAAI;AAC5B,IAAA,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,IAAI;AACnD,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAC1B;AAEA,SAAS,kBAAkB,CAAC,GAAW,EAAA;AACrC,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC;AAC3C,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AACvE,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,aAAa,CAAC,GAOtB,EAAA;AACC,IAAA,MAAM,YAAY,GAChB,GAAG,CAAC,YAAY,KAAK;UACjB,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC/B,UAAE,GAAG,CAAC,IAAI;AAEd,IAAA,OAAO,IAAI,QAAQ,CAAC,YAAY,EAAE;QAChC,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,OAAO,EAAE,GAAG,CAAC,OAAO;AACrB,KAAA,CAAC;AACJ;AAEO,eAAe,WAAW,CAC/B,KAAwB,EACxB,IAAyB,EAAA;;AAEzB,IAAA,IAAI,CAAC,oBAAoB,EAAE,EAAE;AAC3B,QAAA,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,IAAI,aAAJ,IAAI,KAAA,MAAA,GAAJ,IAAI,GAAI,EAAE;QAChD,OAAO,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;IAC3C;AAEA,IAAA,MAAM,GAAG,GAAG,KAAK,YAAY,GAAG,GAAG,KAAK,CAAC,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC,GAAG;AAC7F,IAAA,MAAM,EAAE,GAAG,YAAY,EAAE;AACzB,IAAA,MAAM,OAAO,GAAG,CAAA,EAAA,GAAA,IAAI,KAAA,IAAA,IAAJ,IAAI,KAAA,MAAA,GAAA,MAAA,GAAJ,IAAI,CAAE,OAAO,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,eAAe;AAEhD,IAAA,MAAM,GAAG,GAAwB;AAC/B,QAAA,IAAI,EAAE,eAAe;QACrB,EAAE;QACF,GAAG;QACH,MAAM,EAAE,CAAA,EAAA,GAAA,IAAI,KAAA,IAAA,IAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,KAAK;AAC7B,QAAA,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC;KACtB;IAED,OAAO,IAAI,OAAO,CAAW,CAAC,OAAO,EAAE,MAAM,KAAI;QAC/C,SAAS,SAAS,CAAC,KAAmB,EAAA;AACpC,YAAA,IAAI,IAAa;AACjB,YAAA,IAAI;gBACF,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI;YAC7E;AAAE,YAAA,MAAM;gBACN;YACF;YACA,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE;gBAAE;AAErD,YAAA,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC;AAEhD,YAAA,IAAI,IAAI,CAAC,KAAK,EAAE;AACd,gBAAA,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACzC;YACF;AACA,YAAA,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC;QAC3B;QAEA,OAAO,CAAC,GAAG,CACT,EAAE,EACF,CAAC,WAAW,KAAK,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACpD,MAAM,EACN,OAAO,CACR;AAED,QAAA,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC;AAC3C,QAAA,MAAc,CAAC,kBAAkB,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACtE,IAAA,CAAC,CAAC;AACJ;;;;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fetch-native-bridge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Fetch wrapper that bridges React Native WebView and the native app — routes fetch calls natively for file downloads and beyond",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "massimomoffa02@gmail.com",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/web/index.d.ts",
|
|
15
|
+
"import": "./dist/web/index.mjs",
|
|
16
|
+
"require": "./dist/web/index.cjs"
|
|
17
|
+
},
|
|
18
|
+
"./native": {
|
|
19
|
+
"types": "./dist/native/index.d.ts",
|
|
20
|
+
"import": "./dist/native/index.mjs",
|
|
21
|
+
"require": "./dist/native/index.cjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/web/index.cjs",
|
|
25
|
+
"module": "./dist/web/index.mjs",
|
|
26
|
+
"types": "./dist/web/index.d.ts",
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "rollup -c rollup.config.js",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
"test:coverage": "vitest run --coverage",
|
|
33
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
34
|
+
"prepublishOnly": "npm run typecheck && npm run test && npm run build"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@rollup/plugin-node-resolve": "^15.3.1",
|
|
38
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
39
|
+
"@vitest/coverage-v8": "^3.2.2",
|
|
40
|
+
"jsdom": "^26.1.0",
|
|
41
|
+
"rollup": "^4.41.0",
|
|
42
|
+
"rollup-plugin-dts": "^6.2.1",
|
|
43
|
+
"tslib": "^2.8.1",
|
|
44
|
+
"typescript": "^5.8.3",
|
|
45
|
+
"vitest": "^3.2.2"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"react-native": ">=0.70.0",
|
|
49
|
+
"react-native-webview": ">=11.0.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependenciesMeta": {
|
|
52
|
+
"react-native": {
|
|
53
|
+
"optional": true
|
|
54
|
+
},
|
|
55
|
+
"react-native-webview": {
|
|
56
|
+
"optional": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"keywords": [
|
|
60
|
+
"react-native",
|
|
61
|
+
"webview",
|
|
62
|
+
"fetch",
|
|
63
|
+
"bridge",
|
|
64
|
+
"file-download",
|
|
65
|
+
"native"
|
|
66
|
+
],
|
|
67
|
+
"repository": {
|
|
68
|
+
"type": "git",
|
|
69
|
+
"url": "https://github.com/massimomoffa02/fetch-native-bridge.git"
|
|
70
|
+
},
|
|
71
|
+
"bugs": {
|
|
72
|
+
"url": "https://github.com/massimomoffa02/fetch-native-bridge/issues"
|
|
73
|
+
},
|
|
74
|
+
"homepage": "https://github.com/massimomoffa02/fetch-native-bridge#readme"
|
|
75
|
+
}
|