Overview
The events module provides a type-safe event system for Bunli runtime lifecycle events. Events are emitted through a transport interface and validated with Zod schemas.
Imports
import {
emitRuntimeEvent ,
type RuntimeEvent ,
type RuntimeTransport ,
type RuntimeTransportObserver
} from '@bunli/runtime'
Event Types
All runtime events follow a discriminated union pattern with a type field.
RuntimeRendererStartedEvent
Emitted when the renderer starts.
type
'runtime.renderer.started'
required
Event type discriminator
Unix timestamp in milliseconds when event occurred
Active terminal buffer mode
RuntimeRendererDestroyedEvent
Emitted when the renderer is destroyed.
type
'runtime.renderer.destroyed'
required
Event type discriminator
Unix timestamp in milliseconds when event occurred
RuntimeRendererMissingRenderEvent
Emitted when a required render function is missing.
type
'runtime.renderer.missing-render'
required
Event type discriminator
Unix timestamp in milliseconds when event occurred
RuntimePromptStartedEvent
Emitted when a prompt is started.
type
'runtime.prompt.started'
required
Event type discriminator
Unix timestamp in milliseconds when event occurred
promptType
'text' | 'password' | 'confirm' | 'select' | 'multiselect' | 'group' | 'session'
required
Type of prompt that was started
RuntimePromptCancelledEvent
Emitted when a prompt is cancelled.
type
'runtime.prompt.cancelled'
required
Event type discriminator
Unix timestamp in milliseconds when event occurred
promptType
'text' | 'password' | 'confirm' | 'select' | 'multiselect' | 'group' | 'session'
required
Type of prompt that was cancelled
RuntimeTransportErrorEvent
Emitted when a transport error occurs.
type
'runtime.transport.error'
required
Event type discriminator
Unix timestamp in milliseconds when event occurred
Error message describing what went wrong
Transport Interface
Implement the RuntimeTransport interface to receive runtime events.
interface RuntimeTransport {
send ( event : RuntimeEvent ) : void | Promise < void >
}
Example Transport
import type { RuntimeTransport , RuntimeEvent } from '@bunli/runtime'
class LoggingTransport implements RuntimeTransport {
send ( event : RuntimeEvent ) : void {
console . log ( `[ ${ event . type } ]` , event )
}
}
// Use with renderer
import { runTuiRender } from '@bunli/runtime/renderer'
const transport = new LoggingTransport ()
await runTuiRender ({
command: {
render : () => < App />
},
transport
})
File Transport Example
import { writeFile , appendFile } from 'node:fs/promises'
import type { RuntimeTransport , RuntimeEvent } from '@bunli/runtime'
class FileTransport implements RuntimeTransport {
constructor ( private logPath : string ) {}
async send ( event : RuntimeEvent ) : Promise < void > {
const line = JSON . stringify ( event ) + ' \n '
await appendFile ( this . logPath , line , 'utf-8' )
}
}
HTTP Transport Example
import type { RuntimeTransport , RuntimeEvent } from '@bunli/runtime'
class HTTPTransport implements RuntimeTransport {
constructor ( private endpoint : string ) {}
async send ( event : RuntimeEvent ) : Promise < void > {
await fetch ( this . endpoint , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( event )
})
}
}
emitRuntimeEvent
Utility function to emit events through a transport with validation and error handling.
async function emitRuntimeEvent (
transport : RuntimeTransport | undefined ,
event : RuntimeEvent ,
observer ?: RuntimeTransportObserver
) : Promise < void >
Parameters
transport
RuntimeTransport | undefined
Transport to send event through. If undefined, event is not sent.
Event to emit. Will be validated against event schema.
Optional observer for transport errors onTransportError
(error: unknown, event: RuntimeEvent) => void
Called when transport fails or validation fails
Example
import { emitRuntimeEvent } from '@bunli/runtime'
import type { RuntimeTransport } from '@bunli/runtime'
const transport : RuntimeTransport = {
send : async ( event ) => {
console . log ( 'Event:' , event )
}
}
// Emit event with error handling
await emitRuntimeEvent (
transport ,
{
type: 'runtime.renderer.started' ,
timestamp: Date . now (),
bufferMode: 'alternate'
},
{
onTransportError : ( error , event ) => {
console . error ( 'Failed to send event:' , event . type , error )
}
}
)
Transport Observer
Provide a RuntimeTransportObserver to handle transport errors.
interface RuntimeTransportObserver {
onTransportError ? ( error : unknown , event : RuntimeEvent ) : void
}
Example
import { emitRuntimeEvent } from '@bunli/runtime'
const observer = {
onTransportError ( error : unknown , event : RuntimeEvent ) {
// Log to error tracking service
logger . error ( 'Transport error' , {
eventType: event . type ,
error
})
}
}
// Use observer
await emitRuntimeEvent ( transport , event , observer )
Event Schemas
All events are validated using Zod schemas. You can import schemas directly:
import {
RuntimeEventSchema ,
RuntimeRendererStartedEventSchema ,
RuntimeRendererDestroyedEventSchema ,
RuntimeRendererMissingRenderEventSchema ,
RuntimePromptStartedEventSchema ,
RuntimePromptCancelledEventSchema ,
RuntimeTransportErrorEventSchema
} from '@bunli/runtime/events'
// Validate event
const result = RuntimeEventSchema . safeParse ( unknownEvent )
if ( result . success ) {
const event : RuntimeEvent = result . data
}
Complete Example
import { runTuiRender } from '@bunli/runtime/renderer'
import type { RuntimeTransport , RuntimeEvent } from '@bunli/runtime'
import { App } from './app'
// Multi-target transport
class MultiTransport implements RuntimeTransport {
private transports : RuntimeTransport []
constructor ( ... transports : RuntimeTransport []) {
this . transports = transports
}
async send ( event : RuntimeEvent ) : Promise < void > {
await Promise . all (
this . transports . map ( t => t . send ( event ))
)
}
}
// Console transport
class ConsoleTransport implements RuntimeTransport {
send ( event : RuntimeEvent ) : void {
const { timestamp , ... rest } = event
const time = new Date ( timestamp ). toISOString ()
console . log ( `[ ${ time } ]` , rest )
}
}
// File transport
import { appendFile } from 'node:fs/promises'
class FileTransport implements RuntimeTransport {
constructor ( private path : string ) {}
async send ( event : RuntimeEvent ) : Promise < void > {
await appendFile (
this . path ,
JSON . stringify ( event ) + ' \n ' ,
'utf-8'
)
}
}
// Use multiple transports
const transport = new MultiTransport (
new ConsoleTransport (),
new FileTransport ( './events.log' )
)
await runTuiRender ({
command: {
render : () => < App />
},
transport
})
Best Practices
Error Handling
Always provide a RuntimeTransportObserver for production
Handle transport failures gracefully
Don’t let transport errors crash your application
Performance
Use async transports for I/O operations
Batch events if sending to external services
Consider buffering events during high-frequency operations
Debugging
Log all events in development
Filter events by type in production
Include event timestamps for correlation
Type Safety
Use discriminated unions to narrow event types
Leverage Zod schemas for runtime validation
Type your transport implementations