import createNewDbConnection, { StoccaTreDbConn } from "./database.ts"; import * as resources from "./resources/main.ts"; import config from "./config.ts"; import StoccaTreRequest, { HttpMethod } from "./StoccaTreRequest.ts"; import { JSONObject } from "./JSON.ts"; import StoccaTreServer from "./StoccaTreServer.ts"; import {Result, StoccaTreError} from "./Result.ts"; type StoccaTreApiBody = { data: JSONObject; error?: string; }; function newStoccaTreApiBody(): StoccaTreApiBody { return { data: {}, }; } async function getJSONBody(request: Request): Promise> { let json; try { if (request.body) { json = await request.json(); } else { json = null; } } catch (e: unknown) { return [new StoccaTreError((e as Error).message ?? "Body was invalid JSON.", 400)]; } return [, json]; } async function respondWithError(requestEvent: Deno.RequestEvent, error: StoccaTreError) { const body = newStoccaTreApiBody(); await requestEvent.respondWith( Response.json({ ...body, status: error.status, error: error.qualified("Error: ").message, }, { status: error.status }), ); } async function processRequest( server: StoccaTreServer, requestEvent: Deno.RequestEvent, ) { const [bodyError, requestBody] = await getJSONBody(requestEvent.request); if (bodyError) { await respondWithError(requestEvent, bodyError); return; } const route = /^https?:\/\/[^\/]*(\/.*)$/.exec(requestEvent.request.url)?.[1] ?? "/"; const method: HttpMethod = requestEvent.request.method as HttpMethod; const body: StoccaTreApiBody = newStoccaTreApiBody(); const [error, result] = await server.handleRequest(new StoccaTreRequest(method, route, requestBody)); if (error) { await respondWithError(requestEvent, error); return; } body.data = result; await requestEvent.respondWith(Response.json(body, { status: 200 })); } const [error, database] = await createNewDbConnection(); if (error) { console.log(error.qualified("Failed to create the database: ").message); } else { const server = new StoccaTreServer(database); server.addResource({ pattern: /ingredient/ }, new resources.IngredientResource(database)); server.addResource({ pattern: /user/ }, new resources.UserResource(database)); const stoccaTreListener = Deno.listen({ port: config.port ?? 8080 }); console.log(`Stocca Tre Server is running. Access it at: http://${ config.hostname }:${ config.port }/`); for await (const conn of stoccaTreListener) { const httpConn = Deno.serveHttp(conn); for await (const requestEvent of httpConn) { await processRequest(server, requestEvent); } } }