Current section

Files

Jump to
smol src bun.ffi.mjs
Raw

src/bun.ffi.mjs

import { Error } from './gleam.mjs';
import { adapt } from './adapt.ffi.mjs';
import { started } from './smol.mjs';
import { from_file as nodeFromFile } from './node.ffi.mjs';
import { upgrade } from './smol.ffi.mjs';
export function start(builder) {
try {
const handler = adapt(builder.handler)
const server = Bun.serve({
port: builder.port,
hostname: builder.interface,
development: false,
async fetch (req, server) {
const res = await handler(req)
if (res.body[upgrade] && server.upgrade(req, {
headers: res.headers,
data: res.body[upgrade]
})) {
return;
} else {
return res;
}
},
error(error) {
console.error('smol:', error.stack)
return new Response('Internal Server Error', { status: 500 })
},
websocket: {
perMessageDeflate: true,
open(ws) {
const runtime = ws.data;
runtime.send = message => ws.send(message);
runtime.close = () => ws.close();
runtime.onOpen();
},
message(ws, message) {
ws.data.onMessage(message)
},
close(ws) {
ws.data.onClose()
}
}
})
let disposed = false;
const stop = async () => {
if (disposed) {
return;
}
disposed = true;
console.log('smol: Gracefully shutting down. Please wait...');
process.off('SIGINT', onExit)
process.off('SIGTERM', onExit)
process.off('exit', onExit)
await server.stop()
}
const onExit = async () => {
try {
await stop()
} finally {
process.exit()
}
}
process.on('SIGINT', onExit);
process.on('SIGTERM', onExit);
process.on('exit', onExit);
builder.after_start(server.port, server.hostname);
return Promise.resolve(started(server.port, server.hostname, stop));
} catch(e) {
return Promise.resolve(new Error());
}
}
export function from_file(path, offset, limit) {
if (limit > 1) {
// TODO: because bun is very buggy, it has an off-by-one error here.
// this makes it impossible to send back a single byte, so in those cases
// you will get 2 bytes. oh well.
limit -= 1;
}
return nodeFromFile(path, offset, limit);
}