|
1 | | -import type { BirpcReturn } from 'birpc' |
| 1 | +import type { WebSocketRpcClientOptions } from '@vitejs/devtools-rpc/presets/ws/client' |
| 2 | +import type { BirpcOptions, BirpcReturn } from 'birpc' |
2 | 3 | import type { ConnectionMeta, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions } from '../types' |
3 | 4 | import { createRpcClient } from '@vitejs/devtools-rpc' |
4 | 5 | import { createWsRpcPreset } from '@vitejs/devtools-rpc/presets/ws/client' |
5 | 6 |
|
6 | | -function isNumeric(str: string | number) { |
| 7 | +function isNumeric(str: string | number | undefined) { |
| 8 | + if (str == null) |
| 9 | + return false |
7 | 10 | return `${+str}` === `${str}` |
8 | 11 | } |
9 | 12 |
|
10 | | -export async function getDevToolsRpc(baseURL = '/__vite_devtools__/api/'): Promise<BirpcReturn<DevToolsRpcServerFunctions, DevToolsRpcClientFunctions>> { |
11 | | - const metadata = await fetch(`${baseURL}metadata.json`) |
12 | | - .then(r => r.json()) as ConnectionMeta |
| 13 | +export interface DevToolsRpcClientOptions { |
| 14 | + connectionMeta?: ConnectionMeta |
| 15 | + baseURL?: string[] |
| 16 | + wsOptions?: Partial<WebSocketRpcClientOptions> |
| 17 | + rpcOptions?: Partial<BirpcOptions<DevToolsRpcServerFunctions>> |
| 18 | +} |
| 19 | + |
| 20 | +export async function getDevToolsRpcClient( |
| 21 | + options: DevToolsRpcClientOptions = {}, |
| 22 | +): Promise<{ |
| 23 | + connectionMeta: ConnectionMeta |
| 24 | + rpc: BirpcReturn<DevToolsRpcServerFunctions, DevToolsRpcClientFunctions> |
| 25 | +}> { |
| 26 | + const { |
| 27 | + baseURL = '/__vite_devtools__/api/', |
| 28 | + } = options |
| 29 | + const urls = Array.isArray(baseURL) ? baseURL : [baseURL] |
| 30 | + let connectionMeta: ConnectionMeta | undefined = options.connectionMeta |
| 31 | + |
| 32 | + if (!connectionMeta) { |
| 33 | + const errors: Error[] = [] |
| 34 | + for (const url of urls) { |
| 35 | + try { |
| 36 | + connectionMeta = await fetch(`${url}connection.json`) |
| 37 | + .then(r => r.json()) as ConnectionMeta |
| 38 | + break |
| 39 | + } |
| 40 | + catch (e) { |
| 41 | + errors.push(e as Error) |
| 42 | + } |
| 43 | + } |
| 44 | + if (!connectionMeta) { |
| 45 | + throw new Error(`Failed to get connection meta from ${urls.join(', ')}`, { |
| 46 | + cause: errors, |
| 47 | + }) |
| 48 | + } |
| 49 | + } |
13 | 50 |
|
14 | | - const url = isNumeric(metadata.websocket) |
15 | | - ? `${location.protocol.replace('http', 'ws')}//${location.hostname}:${metadata.websocket}` |
16 | | - : metadata.websocket as string |
| 51 | + const url = isNumeric(connectionMeta.websocket) |
| 52 | + ? `${location.protocol.replace('http', 'ws')}//${location.hostname}:${connectionMeta.websocket}` |
| 53 | + : connectionMeta.websocket as string |
17 | 54 |
|
18 | 55 | const rpc = createRpcClient<DevToolsRpcServerFunctions, DevToolsRpcClientFunctions>({}, { |
19 | 56 | preset: createWsRpcPreset({ |
20 | 57 | url, |
| 58 | + ...options.wsOptions, |
21 | 59 | }), |
| 60 | + ...options.rpcOptions, |
22 | 61 | }) |
23 | 62 |
|
24 | | - return rpc |
| 63 | + return { |
| 64 | + connectionMeta, |
| 65 | + rpc, |
| 66 | + } |
25 | 67 | } |
0 commit comments