Skip to main content
Module

x/ultra/src/server.ts

πŸ’Ž Modern Streaming React Framework in Deno
Go to Latest
File
import { LRU, readableStreamFromReader, serve } from "./deps.ts";import assets from "./assets.ts";import transform from "./transform.ts";import render from "./render.ts";import { jsxify, resolveFileUrl, stripTrailingSlash, tsify, tsxify,} from "./resolver.ts";import { disableStreaming, isDev, lang, port, root, sourceDirectory, vendorDirectory,} from "./env.ts";import { APIHandler } from "./types.ts";import { resolveConfig, resolveImportMap } from "./config.ts";
const memory = new LRU(500);const cwd = Deno.cwd();
const config = await resolveConfig(cwd);const importMap = await resolveImportMap(cwd, config);
const server = () => { const serverStart = Math.ceil(+new Date() / 100); const listeners = new Set<WebSocket>();
const handler = async (request: Request) => { const requestStart = Math.ceil(+new Date() / 100); const cacheBuster = isDev ? requestStart : serverStart; const { raw, transpile } = await assets(sourceDirectory); const vendor = await assets(`.ultra/${vendorDirectory}`); const requestUrl = new URL(request.url);
// web socket listener if (isDev) { if (requestUrl.pathname == "/_ultra_socket") { const { socket, response } = Deno.upgradeWebSocket(request); listeners.add(socket); socket.onclose = () => { listeners.delete(socket); }; return response; } }
// vendor map if (vendor.raw.has(".ultra" + requestUrl.pathname)) { const headers = { "content-type": "text/javascript", };
const file = await Deno.open( `./.ultra${requestUrl.pathname}`, ); const body = readableStreamFromReader(file);
return new Response(body, { headers }); }
// static assets if (raw.has(`${sourceDirectory}${requestUrl.pathname}`)) { const contentType = raw.get(`${sourceDirectory}${requestUrl.pathname}`); const headers = { "content-type": contentType, };
const file = await Deno.open( `./${sourceDirectory}${requestUrl.pathname}`, ); const body = readableStreamFromReader(file);
return new Response(body, { headers }); }
const transpilation = async (file: string) => { const headers = { "content-type": "text/javascript", };
let js = memory.get(requestUrl.pathname);
if (!js) { const source = await Deno.readTextFile(resolveFileUrl(cwd, file)); const t0 = performance.now();
js = await transform({ source, sourceUrl: requestUrl, importMap, cacheBuster, });
const t1 = performance.now(); const duration = (t1 - t0).toFixed(2);
console.log(`Transpile ${file} in ${duration}ms`);
if (!isDev) memory.set(requestUrl.pathname, js); }
//@ts-ignore any return new Response(js, { headers }); };
// API if (requestUrl.pathname.startsWith("/api")) { const apiPaths = new Map([...raw, ...transpile]); const importAPIRoute = async (pathname: string): Promise<APIHandler> => { let path = `${sourceDirectory}${pathname}`; if (apiPaths.has(`${path}.js`)) { path = `file://${cwd}/${path}.js`; } else if (apiPaths.has(`${path}.ts`)) { path = `file://${cwd}/${path}.ts`; } else if (apiPaths.has(`${path}/index.js`)) { path = `file://${cwd}/${path}/index.js`; } else if (apiPaths.has(`${path}/index.ts`)) { path = `file://${cwd}/${path}/index.ts`; } return (await import(`${path}?ts=${cacheBuster}`)).default; }; try { const pathname = stripTrailingSlash(requestUrl.pathname); const handler = await importAPIRoute(pathname); const response = await handler(request); return response; } catch (error) { console.error(error); return new Response("Internal Server Error", { status: 500, headers: { "content-type": "text/html; charset=utf-8", }, }); } }
// jsx const jsx = `${sourceDirectory}${jsxify(requestUrl.pathname)}`; if (transpile.has(jsx)) { return await transpilation(jsx); }
// tsx const tsx = `${sourceDirectory}${tsxify(requestUrl.pathname)}`; if (transpile.has(tsx)) { return await transpilation(tsx); }
// ts const ts = `${sourceDirectory}${tsify(requestUrl.pathname)}`; if (transpile.has(ts)) { return await transpilation(ts); }
return new Response( await render({ url: requestUrl, root, importMap, lang, disableStreaming: !!disableStreaming, }), { headers: { "content-type": "text/html; charset=utf-8", }, }, ); };
// async file watcher to send socket messages if (isDev) { (async () => { for await ( const { kind } of Deno.watchFs(sourceDirectory, { recursive: true }) ) { if (kind === "modify" || kind === "create") { for (const socket of listeners) { socket.send("reload"); } } } })(); }
console.log(`Ultra running ${root}`);
return serve(handler, { port: +port });};
export default server;