import type { InternalEvent } from '@yaakapp/api'; import WebSocket from 'ws'; import { EventChannel } from './EventChannel'; import { PluginHandle } from './PluginHandle'; const port = process.env.PORT; if (!port) { throw new Error('Plugin runtime missing PORT'); } const host = process.env.HOST; if (!host) { throw new Error('Plugin runtime missing HOST'); } const pluginToAppEvents = new EventChannel(); const plugins: Record = {}; const ws = new WebSocket(`ws://${host}:${port}`); ws.on('message', async (e: Buffer) => { try { await handleIncoming(e.toString()); } catch (err) { console.log('Failed to handle incoming plugin event', err); } }); ws.on('open', () => console.log('Plugin runtime connected to websocket')); ws.on('error', (err: unknown) => console.error('Plugin runtime websocket error', err)); ws.on('close', (code: number) => console.log('Plugin runtime websocket closed', code)); // Listen for incoming events from plugins pluginToAppEvents.listen((e) => { const eventStr = JSON.stringify(e); ws.send(eventStr); }); async function handleIncoming(msg: string) { const pluginEvent: InternalEvent = JSON.parse(msg); // Handle special event to bootstrap plugin if (pluginEvent.payload.type === 'boot_request') { const plugin = new PluginHandle( pluginEvent.pluginRefId, pluginEvent.context, pluginEvent.payload, pluginToAppEvents, ); plugins[pluginEvent.pluginRefId] = plugin; } // Once booted, forward all events to the plugin worker const plugin = plugins[pluginEvent.pluginRefId]; if (!plugin) { console.warn('Failed to get plugin for event by', pluginEvent.pluginRefId); return; } if (pluginEvent.payload.type === 'terminate_request') { await plugin.terminate(); console.log('Terminated plugin worker', pluginEvent.pluginRefId); delete plugins[pluginEvent.pluginRefId]; } plugin.sendToWorker(pluginEvent); } process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); }); process.on('uncaughtException', (error) => { console.error('Uncaught Exception:', error); });