Current section

Files

Jump to
smol src deno.ffi.mjs
Raw

src/deno.ffi.mjs

import { adapt } from "./adapt.ffi.mjs";
import { started } from "./smol.mjs";
import { upgrade } from "./smol.ffi.mjs";
import {
Builder$Builder$handler,
Builder$Builder$port,
Builder$Builder$interface,
Builder$Builder$on_error,
Builder$Builder$after_start,
} from "./smol/internal/builder.mjs";
export function start(builder) {
const handler = adapt(Builder$Builder$handler(builder));
return new Promise((resolve) => {
const server = Deno.serve({
port: Builder$Builder$port(builder),
hostname: Builder$Builder$interface(builder),
async handler(req) {
const response = await handler(req);
if (response.body[upgrade]) {
const runtime = response.body[upgrade];
const { socket, response: wsResponse } = Deno.upgradeWebSocket(req);
runtime.send = (message) => socket.send(message);
runtime.close = () => socket.close();
socket.addEventListener("open", runtime.onOpen);
socket.addEventListener("message", (event) =>
runtime.onMessage(event.data),
);
socket.addEventListener("close", runtime.onClose);
return wsResponse;
} else {
return response;
}
},
onListen({ port, hostname }) {
let disposed = false;
const stop = async () => {
if (disposed) {
return;
}
disposed = true;
await server.shutdown();
};
// TODO: doesn't seem like Deno lets us bind to SIGINT?
Builder$Builder$after_start(builder)(port, hostname);
resolve(started(port, hostname, stop));
},
onError(error) {
Builder$Builder$on_error(builder)(error.stack, error);
return new Response("Internal Server Error", { status: 500 });
},
});
});
}