1import { MetroDevServerOptions } from '@expo/dev-server'; 2import http from 'http'; 3import Metro from 'metro'; 4import { Terminal } from 'metro-core'; 5 6import { createDevServerMiddleware } from '../middleware/createDevServerMiddleware'; 7import { MetroTerminalReporter } from './MetroTerminalReporter'; 8import { importExpoMetroConfigFromProject, importMetroFromProject } from './resolveFromProject'; 9 10// From expo/dev-server but with ability to use custom logger. 11type MessageSocket = { 12 broadcast: (method: string, params?: Record<string, any> | undefined) => void; 13}; 14 15/** The most generic possible setup for Metro bundler. */ 16export async function instantiateMetroAsync( 17 projectRoot: string, 18 options: Omit<MetroDevServerOptions, 'logger'> 19): Promise<{ 20 server: http.Server; 21 middleware: any; 22 messageSocket: MessageSocket; 23}> { 24 let reportEvent: ((event: any) => void) | undefined; 25 26 const Metro = importMetroFromProject(projectRoot); 27 const ExpoMetroConfig = importExpoMetroConfigFromProject(projectRoot); 28 29 const terminal = new Terminal(process.stdout); 30 const terminalReporter = new MetroTerminalReporter(projectRoot, terminal); 31 32 const reporter = { 33 update(event: any) { 34 terminalReporter.update(event); 35 if (reportEvent) { 36 reportEvent(event); 37 } 38 }, 39 }; 40 41 const metroConfig = await ExpoMetroConfig.loadAsync(projectRoot, { reporter, ...options }); 42 43 const { middleware, attachToServer } = createDevServerMiddleware({ 44 port: metroConfig.server.port, 45 watchFolders: metroConfig.watchFolders, 46 }); 47 48 const customEnhanceMiddleware = metroConfig.server.enhanceMiddleware; 49 // @ts-ignore can't mutate readonly config 50 metroConfig.server.enhanceMiddleware = (metroMiddleware: any, server: Metro.Server) => { 51 if (customEnhanceMiddleware) { 52 metroMiddleware = customEnhanceMiddleware(metroMiddleware, server); 53 } 54 return middleware.use(metroMiddleware); 55 }; 56 57 const server = await Metro.runServer(metroConfig, { 58 // @ts-expect-error: TODO: Update the types. 59 hmrEnabled: true, 60 }); 61 62 const { messageSocket, eventsSocket } = attachToServer(server); 63 reportEvent = eventsSocket.reportEvent; 64 65 return { 66 server, 67 middleware, 68 messageSocket, 69 }; 70} 71