1import chalk from 'chalk'; 2import type { NextHandleFunction } from 'connect'; 3import type { IncomingMessage, ServerResponse } from 'http'; 4import net from 'net'; 5import { TLSSocket } from 'tls'; 6import { URL } from 'url'; 7 8import { openJsInspector, queryInspectorAppAsync } from './JsInspector'; 9 10export default function createJsInspectorMiddleware(): NextHandleFunction { 11 return async function (req: IncomingMessage, res: ServerResponse, next: (err?: Error) => void) { 12 const { origin, searchParams } = new URL(req.url ?? '/', getServerBase(req)); 13 const applicationId = searchParams.get('applicationId'); 14 if (!applicationId) { 15 res.writeHead(400).end('Missing applicationId'); 16 return; 17 } 18 19 const app = await queryInspectorAppAsync(origin, applicationId); 20 if (!app) { 21 res.writeHead(404).end('Unable to find inspector target from metro-inspector-proxy'); 22 console.warn( 23 chalk.yellow( 24 'No compatible apps connected. JavaScript Debugging can only be used with the Hermes engine.' 25 ) 26 ); 27 return; 28 } 29 30 if (req.method === 'GET') { 31 const data = JSON.stringify(app); 32 res.writeHead(200, { 33 'Content-Type': 'application/json; charset=UTF-8', 34 'Cache-Control': 'no-cache', 35 'Content-Length': data.length.toString(), 36 }); 37 res.end(data); 38 } else if (req.method === 'POST' || req.method === 'PUT') { 39 try { 40 await openJsInspector(app); 41 } catch (error: any) { 42 // abort(Error: Command failed: osascript -e POSIX path of (path to application "google chrome") 43 // 15:50: execution error: Google Chrome got an error: Application isn’t running. (-600) 44 45 console.error( 46 chalk.red('Error launching JS inspector: ' + (error?.message ?? 'Unknown error occurred')) 47 ); 48 res.writeHead(500); 49 res.end(); 50 return; 51 } 52 res.end(); 53 } else { 54 res.writeHead(405); 55 } 56 }; 57} 58 59function getServerBase(req: IncomingMessage): string { 60 const scheme = 61 req.socket instanceof TLSSocket && req.socket.encrypted === true ? 'https' : 'http'; 62 const { localAddress, localPort } = req.socket; 63 const address = localAddress && net.isIPv6(localAddress) ? `[${localAddress}]` : localAddress; 64 return `${scheme}:${address}:${localPort}`; 65} 66