import http from "node:http"; import { readFile } from "node:fs/promises"; import { extname } from "node:path"; const PORT = Number(process.env.PORT || 5173); const API_BASE = process.env.DOCLINK_API_BASE || "https://devbandungraya.aplikasi.web.id/one-api-doctor/doctor_mitra"; const sessionKey = "doclink_session"; const sampleLogin = { username: "yogayogi", doctorId: "31010002", mouId: "2773", password: "123456", }; function escapeHtml(value) { return String(value) .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """); } function statusClass(status) { const mapping = { Processing: "warning", Ready: "success", "Needs review": "danger", Released: "success", Pending: "warning", Review: "danger", Confirmed: "success", Unconfirmed: "danger", }; return mapping[status] || "neutral"; } function statusBadge(text) { return `${escapeHtml(text)}`; } function emptyState(title, text, action = "") { return `
${escapeHtml(title)}

${escapeHtml(text)}

${action}
`; } function icon(name) { const map = { search: '', plus: '', bell: '', arrow: '', login: '', }; return map[name] || ""; } function layout(title, body, { authenticated = false, activePath = "/", subtitle = "", shell = true, accountName = "", accountMeta = "" } = {}) { const nav = authenticated ? desktopNav(activePath) : ""; const mobile = authenticated ? mobileNav(activePath) : ""; const header = authenticated ? topbar(activePath, subtitle, accountName, accountMeta) : ""; return ` ${escapeHtml(title)}
${shell && authenticated ? `
${nav}
${header} ${body}
${mobile}
` : body}
`; } function topbar(activePath, subtitle, accountName = "", accountMeta = "") { const titleMap = { "/": ["Dashboard", "Overview of orders, results, and work queues."], "/orders": ["Orders", "Search, review, and create patient orders."], "/results": ["Results", "Monitor released and pending laboratory results."], "/fpp": ["FPP", "Browse grouped reference packages and filters."], "/patients": ["Patients", "Landing for patient registration and lookup."], "/settings": ["Settings", "Account profile and password management."], }; const [title, fallbackSubtitle] = titleMap[activePath] || ["DocLink Web", "Responsive clinical workflow shell."]; const displayName = accountName || sampleLogin.username; const displayMeta = accountMeta || `Doctor ID ${sampleLogin.doctorId}`; return `
${escapeHtml(activePath === "/" ? "Clinical dashboard" : "Workflow view")}

${escapeHtml(title)}

${escapeHtml(subtitle || fallbackSubtitle)}

${icon("plus")} New order
`; } function desktopNav(activePath) { const items = [ ["/", "Home", "Dashboard"], ["/orders", "Order", "Create & list"], ["/results", "Result", "History"], ]; const active = (href) => activePath === href || activePath.startsWith(`${href}/`); return ` `; } function mobileNav(activePath) { const items = [ ["/", "Home", "Dashboard"], ["/orders", "Order", "Create"], ["/results", "Result", "History"], ]; const active = (href) => activePath === href || activePath.startsWith(`${href}/`); return ` `; } function panelHeader(title, text, action = "") { return `

${escapeHtml(title)}

${escapeHtml(text)}

${action}
`; } function resolveFppRouteIds(session) { return { doctorId: String(session?.doctorId || sampleLogin.doctorId || "1"), mouId: String(session?.mouId || sampleLogin.mouId || "1"), }; } function accountLayoutOptions(session = {}) { return { accountName: session?.username || sampleLogin.username, accountMeta: session?.doctorId ? `Doctor ID ${session.doctorId}` : `Doctor ID ${sampleLogin.doctorId}`, }; } async function dashboardPage(session) { const orders = await loadDesktopOrders(session, { currentPage: 1, month: new Date().getMonth() + 1, year: new Date().getFullYear() }); const stats = [ { label: "Orders this month", value: String(orders.items.length), trend: `${orders.month}/${orders.year}`, hint: "" }, { label: "Confirmed", value: String(orders.items.filter((item) => item.status === "Confirmed").length), trend: "Home", hint: "" }, { label: "Unconfirmed", value: String(orders.items.filter((item) => item.status === "Unconfirmed").length), trend: "Home", hint: "" }, ]; return `
${stats .map( (item) => `
${escapeHtml(item.label)} ${escapeHtml(item.trend)}
${escapeHtml(item.value)} ${item.hint ? `${escapeHtml(item.hint)}` : ""}
`, ) .join("")}
${panelHeader("Recent orders", "", 'View all')}
${(orders.items || []).length ? orders.items .slice(0, 5) .map( (order) => ` `, ) .join("") : ``}
PatientOrderStatusUpdated
${escapeHtml(order.patient || "Unknown patient")}
${escapeHtml(order.mode || "-")}
${escapeHtml(order.id)}
${escapeHtml(order.diagnosis || "-")}
${statusBadge(order.status || "Unconfirmed")} ${escapeHtml(order.updated || "-")}
${emptyState("No orders returned", "The desktop order endpoint did not return any rows for this page.")}
`; } function renderOrdersTable({ items = [], search = "", month = "", year = "", currentPage = 1, hasNext = false, hasPrev = false, selectedOrderId = "", } = {}) { const now = new Date(); const resolvedMonth = String(month || now.getMonth() + 1).padStart(2, "0"); const resolvedYear = String(year || now.getFullYear()); const monthOptions = Array.from({ length: 12 }, (_, index) => { const value = String(index + 1).padStart(2, "0"); return ``; }).join(""); const yearStart = Number(resolvedYear) - 1; const yearOptions = Array.from({ length: 3 }, (_, index) => { const value = String(yearStart + index); return ``; }).join(""); const prevPage = Math.max(1, Number(currentPage) - 1); const nextPage = Math.max(1, Number(currentPage) + 1); const selected = items.find((item) => item.id === selectedOrderId) || items[0] || null; const selectedId = selected?.id || ""; return `
${panelHeader("Orders", "Monthly order list from the desktop endpoint with name, month, and year filters.", 'Create order')}
${ items.length ? `
${items .map( (order) => ` `, ) .join("")}
PatientOrder IDOrder QRDate
${escapeHtml(order.patient || "Unknown patient")}
${escapeHtml(order.diagnosis || "-")}
${escapeHtml(order.id || "-")} ${escapeHtml(order.qrcode || "-")} ${escapeHtml(order.updated || "-")}
` : emptyState("No orders returned", "The desktop order endpoint did not return any rows for this filter.") }
Page ${escapeHtml(String(currentPage || 1))}
`; } function renderOrderDetail(order) { return `
${panelHeader( `${order.patient} · ${order.id}`, "Order detail with the same structure as the proposed master-detail workflow.", ``, )}
Status
${statusBadge(order.status)}
Patient${escapeHtml(order.patient || "-")}${escapeHtml(order.updated || "-")}
Doctor ID${escapeHtml(order.doctor || "-")}Pramita Bandungraya
${panelHeader("Order details", "The source API returns identity fields, so the card copies stay aligned with the payload.")}
Order date

${escapeHtml(order.orderDate || order.updated || "-")}

NIK

${escapeHtml(order.orderNik || "-")}

Phone

${escapeHtml(order.orderHp || "-")}

Address

${escapeHtml(order.orderAddress || "-")}

`; } function qrImageUrl(value, size = 240) { const data = encodeURIComponent(String(value || "")); return `https://api.qrserver.com/v1/create-qr-code/?size=${size}x${size}&data=${data}`; } function formatOrderDisplayDate(value) { const text = String(value || "").trim(); const match = text.match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}:\d{2}:\d{2}))?$/); if (!match) return text; return `${match[3]}-${match[2]}-${match[1]}${match[4] ? ` ${match[4]}` : ""}`; } function renderOrderSaved(order) { const details = Array.isArray(order.details) ? order.details : []; const qrText = order.orderCode || order.id || ""; const printableDate = formatOrderDisplayDate(order.orderDate || ""); const printableDoctor = order.doctorName || order.doctor || sampleLogin.username; return `
${panelHeader( "QR Step", "Order is saved. Share it to WhatsApp or print the slip below.", ``, )}
Tanggal Order
${escapeHtml(printableDate || "-")}
Nama
${escapeHtml(order.patient || "-")}
Dokter
${escapeHtml(printableDoctor)}
Pemeriksaan
${ details.length ? details .map( (item) => `
- ${escapeHtml(item.test_name || item.testName || "-")}
`, ) .join("") : `
-
` }
${ qrText ? `QR code for order ${escapeHtml(qrText)}` : `
QR code not available.
` }
${escapeHtml(qrText || "-")}
${ qrText ? `Share WhatsApp` : "" }
Review

Saved payload summary from the backend response.

Patient

${escapeHtml(order.patient || "-")}

Diagnosis

${escapeHtml(order.diagnosis || "-")}

Notes

${escapeHtml(order.message || "-")}

Saved at

${escapeHtml(order.orderDate || "-")}

${panelHeader("Selected tests", "These items are the `details[]` sent to the backend on submit.")} ${ details.length ? `
${details .map( (item) => `
${escapeHtml(item.test_name || item.testName || "-")}

Test ID ${escapeHtml(item.test_id || item.testId || "-")} · Rp ${escapeHtml(item.price || "0")}

`, ) .join("")}
` : emptyState("No tests saved", "The saved order did not return any detail rows.") }
`; } function renderOrderForm(step, stepKey = "demografi", fppTests = [], mouId = "") { const fppGroups = groupFppTestsForSelection(fppTests); const packedGroups = packFppGroupsIntoColumns(fppGroups, 5); const steps = [ ["demografi", "Demografi", "Patient identity and contact details."], ["diagnosa", "Diagnosa", "Clinical indication and diagnosis."], ["pemeriksaan", "Pemeriksaan", "Choose examination groups."], ]; const normalizedStep = steps.some((item) => item[0] === stepKey) ? stepKey : "demografi"; const activeIndex = Math.max(0, steps.findIndex((item) => item[0] === normalizedStep)); const stepBody = { demografi: `
${panelHeader("Mandatory", "These fields are required before save.", '')}
${panelHeader("Optional", "These fields can be filled when available.")}
`, diagnosa: `
${panelHeader("Mandatory", "Clinical indication is expected before save.")}
${panelHeader("Optional", "Notes are useful for the lab or front office.")}
`, pemeriksaan: `
${panelHeader("Mandatory", "Select examinations from the FPP catalog. Only doctortest=true rows are interactive.")}
Selected tests

0 selected

${ packedGroups.length ? `
${packedGroups .map( (column) => `
${column .map( (group) => `
${escapeHtml(group.heading)}
${group.sections.reduce((sum, section) => sum + section.tests.length, 0)} tests
${group.sections .map( (section) => `
${section.title ? `
${escapeHtml(section.title)}
` : ""}
    ${section.tests .map( (test) => `
  • `, ) .join("")}
`, ) .join("")}
`, ) .join("")}
`, ) .join("")}
` : `
FPP catalog not available yet.
` }
`, }[normalizedStep]; const prev = steps[activeIndex - 1]; const next = steps[activeIndex + 1]; return `
${panelHeader("Create new order", "The new project collapses the old step-heavy flow into a cleaner shell while keeping the same workflow.", 'Cancel')}
${steps .map( (item, index) => ` ${escapeHtml(item[1])} ${escapeHtml(item[2])} `, ) .join("")}
${stepBody}
Back
Save draft ${next ? `Continue` : ""}
`; } function renderResultsTable(results, selectedResultId) { const selected = results.find((item) => item.id === selectedResultId) || results[0] || null; return `
${panelHeader("Result history", "Desktop shows table detail. Mobile collapses into stacked cards.")}
Released

${results.filter((item) => item.status === "Released").length} items

Pending

${results.filter((item) => item.status === "Pending").length} items

Reviewed

${results.filter((item) => item.status === "Review").length} items

${ results.length ? `
${results .map( (result) => ` `, ) .join("")}
PatientResult IDTestStatusDate
${escapeHtml(result.patient || "Unknown patient")}
${escapeHtml(result.summary || "-")}
${escapeHtml(result.id)} ${escapeHtml(result.test || "-")} ${statusBadge(result.status)} ${escapeHtml(result.date || "-")}
${results .map( (result) => `
${escapeHtml(result.patient || "Unknown patient")}

${escapeHtml(result.test || "-")} · ${escapeHtml(result.date || "-")}

${statusBadge(result.status)}
Open detail

${escapeHtml(result.summary || "-")}

`, ) .join("")}
` : emptyState("No results returned", "The result endpoint did not return any rows for this search.") }
`; } function renderResultDetail(result) { if (!result) { return `
${panelHeader("Result detail", "The API returned no matching result.", 'Back to results')} ${emptyState("No result found", "No detail payload was returned for this result ID.")}
`; } return `
${panelHeader(`${result.patient} · ${result.id}`, "Result detail with summary, status, and interpretation fields.", 'Back to results')}
Status
${statusBadge(result.status)}
Test${escapeHtml(result.test)}
Value${escapeHtml(result.value)}
${escapeHtml(result.summary)}
`; } function groupFppTestsForSelection(tests = []) { const groups = new Map(); for (const test of tests) { const heading = test.heading || "FPP"; const sectionTitle = test.subcategory || ""; if (!groups.has(heading)) { groups.set(heading, { heading, sections: new Map() }); } const group = groups.get(heading); const sectionKey = sectionTitle || "__ungrouped__"; if (!group.sections.has(sectionKey)) { group.sections.set(sectionKey, { title: sectionTitle, tests: [] }); } group.sections.get(sectionKey).tests.push(test); } return Array.from(groups.values()).map((group) => ({ heading: group.heading, sections: Array.from(group.sections.values()), })); } function packFppGroupsIntoColumns(groups = [], maxColumns = 5) { const columnCount = Math.min(Math.max(groups.length, 1), maxColumns); const columns = Array.from({ length: columnCount }, () => ({ items: [], score: 0 })); const estimateScore = (group) => 1 + group.sections.length + group.sections.reduce((sum, section) => sum + section.tests.length * 0.12, 0); for (const group of groups) { let target = columns[0]; for (const column of columns) { if (column.score < target.score) target = column; } target.items.push(group); target.score += estimateScore(group); } return columns.map((column) => column.items); } function renderFpp(groups, activeGroup = "All") { const availableGroups = groups.map((item) => item.heading); const visibleGroups = activeGroup === "All" ? groups : groups.filter((item) => item.heading === activeGroup); const packedGroups = packFppGroupsIntoColumns(visibleGroups, 5); return `
${panelHeader("FPP", `Paper-style catalog with ${availableGroups.length} grouped panels, aligned to the manual reference sheet.`)}
${ visibleGroups.length ? `
Pemeriksaan
Hitam putih, padat, dan mengikuti pembagian grup seperti form manual.
${packedGroups .map( (column) => `
${column .map( (group) => `
${escapeHtml(group.heading)}
${group.sections.reduce((sum, section) => sum + section.tests.length, 0)} tests
${group.sections .map( (section) => `
${section.title ? `
${escapeHtml(section.title)}
` : ""}
    ${section.tests .map( (test) => `
  • ${escapeHtml(test.name)}
  • `, ) .join("")}
`, ) .join("")}
`, ) .join("")}
`, ) .join("")}
` : `
${emptyState("No FPP items", "The API returned no catalog rows for this filter.")}
` }
`; } async function renderPatients(session) { const orders = await loadOrders(session, "", "All"); const recentPatients = Array.from( new Map(orders.filter((order) => order.patient).map((order) => [order.patient, order])).values(), ).slice(0, 4); return `
${panelHeader("Patient registration", "A landing zone for registration, lookup, and intake shortcuts.", 'Start registration')}
${[ ["Today's intake", String(orders.length), "From API response"], ["Active visits", String(orders.filter((item) => item.status === "Processing").length), "From API response"], ["QR scans", String(orders.filter((item) => String(item.mode).toLowerCase().includes("qr")).length), "From API response"], ["Needs review", String(orders.filter((item) => item.status === "Needs review").length), "From API response"], ] .map( ([label, value, hint]) => `
${escapeHtml(label)} Live
${escapeHtml(value)} ${escapeHtml(hint)}
`, ) .join("")}
${panelHeader("Quick intake", "Route into the proper entry flow without forcing the user through extra screens.")}
Lookup patient

Search existing records and attach them to the next order.

New patient

Jump straight into demographic capture.

Use the registration stepper when the patient is not yet in the system.
`; } function renderSettings(session) { return `
${panelHeader("Account", "Profile data and security entry points.")}
Name${escapeHtml(session?.username || "-")}
Doctor ID${escapeHtml(session?.doctorCode || session?.doctorId || "-")}
RoleDoctor
Internal ID${escapeHtml(session?.doctorId || "-")}
`; } function renderChangePassword(session) { return `
${panelHeader("Change password", "Inline validation and a straightforward submit path.")}
Cancel
`; } function loginPage({ error = "" } = {}) { return layout( "DocLink Login", `

DocLink Pramita

${error ? `
${escapeHtml(error)}
` : ""}
`, { authenticated: false, shell: false, activePath: "/login" }, ); } function splashPage() { return layout( "DocLink Splash", `

DocLink Pramita

Redirecting

We will move you to the correct route in a moment.

`, { authenticated: false, shell: false, activePath: "/splash" }, ); } function problemLoginPage() { return layout( "Problem Login", `

DocLink Pramita

Session expired

The session was cleared. Go back to login and sign in again.

Back to login
`, { authenticated: false, shell: false, activePath: "/problem-login" }, ); } async function orderNewPage(session, path) { const allowedSteps = new Set(["demografi", "diagnosa", "pemeriksaan"]); const step = path.split("/").filter(Boolean)[2] || "demografi"; const normalizedStep = allowedSteps.has(step) ? step : "demografi"; const fppTests = await loadFppCatalog(session); return layout("Create Order", `
${renderOrderForm({}, normalizedStep, fppTests, session?.mouId || "")}
`, { authenticated: true, activePath: "/orders", subtitle: "The new project collapses the old step-heavy flow into a cleaner shell while keeping the same workflow.", ...accountLayoutOptions(session), }); } function ordersPage(data = {}, session = {}) { return layout("Orders", `
${renderOrdersTable(data)}
`, { authenticated: true, activePath: "/orders", ...accountLayoutOptions(session), }); } function resultsPage({ query = {}, results = [], selectedResultId = "" } = {}, session = {}) { return layout("Results", `
${renderResultsTable(results, selectedResultId)}
`, { authenticated: true, activePath: "/results", ...accountLayoutOptions(session), }); } function fppPage({ group = "All", groups = [] } = {}, session = {}) { return layout("FPP", `
${renderFpp(groups, group)}
`, { authenticated: true, activePath: "/fpp", ...accountLayoutOptions(session), }); } async function patientsPage(session) { return layout("Patients", await renderPatients(session), { authenticated: true, activePath: "/patients", ...accountLayoutOptions(session) }); } function settingsPage(session) { return layout("Settings", renderSettings(session), { authenticated: true, activePath: "/settings", ...accountLayoutOptions(session) }); } function changePasswordPage(session) { return layout("Change Password", renderChangePassword(session), { authenticated: true, activePath: "/settings/change-password", ...accountLayoutOptions(session), }); } function orderDetailPage(order, session = {}) { return layout("Order Detail", renderOrderDetail(order), { authenticated: true, activePath: "/orders", ...accountLayoutOptions(session), }); } function resultDetailPage(result, session = {}) { return layout("Result Detail", renderResultDetail(result), { authenticated: true, activePath: "/results", ...accountLayoutOptions(session), }); } function specialMessagePage(order, session = {}) { return layout( "Pesan Khusus", `
${panelHeader("Pesan khusus", "Desktop can treat this as a modal-style panel; mobile reads it as a dedicated page.", `Back`)}
${escapeHtml(order.patient)}

${escapeHtml(order.id)}

${statusBadge(order.status)}

${escapeHtml(order.message)}

${order.apiSaran ? `
${escapeHtml(typeof order.apiSaran === "string" ? order.apiSaran : JSON.stringify(order.apiSaran))}
` : ""}
Cancel
`, { authenticated: true, activePath: "/orders", ...accountLayoutOptions(session) }, ); } function emptyRoute(path) { return layout("Not Found", `
Route not found

${escapeHtml(path)} is not part of the current rebuild scope.

Go to dashboard
`, { authenticated: true, activePath: "/", }); } function cookieHeader(req) { return req.headers.cookie || ""; } function getCookie(req, name) { const cookies = cookieHeader(req) .split(";") .map((part) => part.trim()) .filter(Boolean); for (const item of cookies) { const [key, ...rest] = item.split("="); if (key === name) return decodeURIComponent(rest.join("=")); } return ""; } function setCookie(name, value, opts = {}) { const parts = [`${name}=${encodeURIComponent(value)}`, "Path=/", "HttpOnly", "SameSite=Lax"]; if (opts.maxAge != null) parts.push(`Max-Age=${opts.maxAge}`); if (opts.secure) parts.push("Secure"); return parts.join("; "); } function deleteCookie(name) { return `${name}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`; } function readSession(req) { const raw = getCookie(req, sessionKey); if (!raw) return null; try { return JSON.parse(raw); } catch { return null; } } function requireAuth(req, res) { const session = readSession(req); if (session) return session; redirect(res, "/login"); return null; } async function fetchJson(url, options = {}) { const response = await fetch(url, options); const contentType = response.headers.get("content-type") || ""; const text = await response.text(); let body = text; if (contentType.includes("application/json") || /^\s*[\[{]/.test(text)) { try { body = JSON.parse(text); } catch { body = text; } } if (!response.ok) { const error = new Error(`Upstream error ${response.status}`); error.status = response.status; error.body = body; throw error; } return body; } async function apiPost(path, payload, token = "") { const headers = { "Content-Type": "application/json" }; if (token) { headers.Authorization = `Bearer ${token}`; payload.token = payload.token || token; } const url = `${API_BASE}${path}`; return fetchJson(url, { method: "POST", headers, body: JSON.stringify(payload), }); } function normalizeSession(payload) { const data = payload?.data || payload?.result || payload; const user = data?.user || data?.data || {}; const token = data?.token || data?.access_token || data?.accessToken || payload?.token || ""; const username = user?.M_UserUsername || data?.username || data?.M_UserUsername || data?.name || ""; const doctorId = user?.M_UserM_DoctorID || data?.doctor_id || data?.doctorId || ""; const doctorCode = user?.M_UserM_DoctorCode || data?.doctor_code || ""; const mouId = user?.M_UserM_MouID || data?.M_UserM_MouID || data?.mou_id || ""; const userId = user?.M_UserID || data?.M_UserID || data?.user_id || ""; return { token, username, doctorId, doctorCode, mouId, userId, raw: payload, }; } function extractArray(payload) { if (Array.isArray(payload)) return payload; if (!payload || typeof payload !== "object") return null; for (const key of ["data", "result", "results", "items", "list"]) { const value = payload[key]; const found = extractArray(value); if (found) return found; } return null; } function normalizeOrder(raw, index = 0) { const status = raw?.status || raw?.order_status || raw?.state || "Processing"; return { id: raw?.order_patient_id || raw?.order_id || raw?.id || raw?.OrderPatientID || raw?.OrderID || "", patient: raw?.order_name || raw?.patient_name || raw?.name || raw?.patient || raw?.patient_fullname || "", doctor: raw?.doctor_id || raw?.doctor_name || raw?.doctor || raw?.M_UserUsername || "", updated: raw?.order_date || raw?.updated_at || raw?.updated || raw?.created_at || "", status, tone: statusClass(status), mode: raw?.mode || raw?.visit_type || raw?.patient_type || "", age: String(raw?.age || raw?.patient_age || ""), gender: raw?.gender || raw?.patient_gender || "", tests: [], diagnosis: raw?.order_nik || raw?.patient_diagnosa || raw?.diagnosis || raw?.note || "", message: raw?.order_address || raw?.message || raw?.patient_note || "", orderDate: raw?.order_date || "", orderNik: raw?.order_nik || "", orderHp: raw?.order_hp || "", orderAddress: raw?.order_address || "", orderDob: raw?.order_dob || "", }; } function normalizeHomeOrder(raw, index = 0) { const status = String(raw?.is_confirm || raw?.status || "").toUpperCase() === "Y" ? "Confirmed" : "Unconfirmed"; return { id: raw?.order_id || raw?.id || raw?.order_patient_id || "", patient: raw?.order_name || raw?.patient_name || raw?.name || "", doctor: raw?.doctor_id || raw?.doctor_name || raw?.doctor || "", updated: raw?.order_date || raw?.updated_at || raw?.updated || "", status, tone: statusClass(status), mode: raw?.LabNumber && raw?.LabNumber !== "-" ? raw.LabNumber : raw?.order_qrcode || "", age: String(raw?.age || raw?.patient_age || ""), gender: raw?.gender || raw?.patient_gender || "", tests: Array.isArray(raw?.details) ? raw.details.map((item) => item?.test_name || item?.name || "").filter(Boolean) : [], diagnosis: raw?.order_diagnosa || raw?.diagnosis || "", message: raw?.order_note || raw?.note || "", orderDate: raw?.order_date || "", orderNik: raw?.order_nik || "", orderHp: raw?.order_hp || "", orderAddress: raw?.order_address || "", orderDob: raw?.order_dob || "", }; } function normalizeDesktopOrder(raw, index = 0) { return { id: raw?.order_id || raw?.id || raw?.order_patient_id || "", patient: raw?.order_name || raw?.patient_name || raw?.name || "", doctor: raw?.doctor_id || raw?.doctor_name || raw?.doctor || "", updated: raw?.order_date || raw?.updated_at || raw?.updated || "", qrcode: raw?.order_qrcode || raw?.qrcode || "", orderNik: raw?.order_nik || "", orderHp: raw?.order_hp || "", orderAddress: raw?.order_address || "", orderDob: raw?.order_dob || "", diagnosis: raw?.order_diagnosa || raw?.diagnosis || "", message: raw?.order_note || raw?.note || "", status: String(raw?.is_confirm || raw?.status || "").toUpperCase() === "Y" ? "Confirmed" : "Unconfirmed", }; } function normalizePatientOrder(raw, index = 0) { return { id: raw?.order_id || raw?.id || raw?.order_patient_id || "", patient: raw?.order_name || raw?.patient_name || raw?.name || "", orderDob: raw?.order_dob || "", orderNik: raw?.order_nik || "", orderHp: raw?.order_hp || "", orderAddress: raw?.order_address || "", updated: raw?.order_date || raw?.updated_at || raw?.updated || "", }; } function normalizeResult(raw, index = 0) { const status = raw?.status || raw?.result_status || raw?.order_status || "Pending"; const detailsSource = raw?.details || raw?.items || raw?.order_details || []; const details = Array.isArray(detailsSource) ? detailsSource .map((item) => { if (typeof item === "string") return item; return item?.test_name || item?.name || item?.detail_name || item?.exam || item?.label || ""; }) .filter(Boolean) : []; return { id: raw?.result_id || raw?.order_id || raw?.id || raw?.hasil_id || "", patient: raw?.order_name || raw?.patient_name || raw?.name || raw?.patient || "", test: details.join(", ") || raw?.test_name || raw?.item_name || raw?.test || "", status, tone: statusClass(status), date: raw?.order_date || raw?.date || raw?.created_at || raw?.updated_at || "", summary: raw?.order_diagnosa || raw?.summary || raw?.note || raw?.result_summary || "", value: raw?.order_note || raw?.value || raw?.result_value || raw?.result || "", details, orderCode: raw?.order_qrcode || "", orderDob: raw?.order_dob || "", orderAddress: raw?.order_address || "", orderNik: raw?.order_nik || "", orderHp: raw?.order_hp || "", }; } async function loadOrders(session, search = "", status = "All") { const term = String(search || "").trim(); try { const payload = await apiPost( "/order/search_order_pasien_by_doktorid", { token: session.token, OrderPatientM_DoctorID: session.doctorId || sampleLogin.doctorId, search: term, }, session.token, ); const rows = extractArray(payload) || []; return rows.map((row, index) => normalizeOrder(row, index)).filter((item) => { if (!item.id) return false; const matchesSearch = !term || [item.id, item.patient, item.status, item.diagnosis, item.message].some((value) => String(value).toLowerCase().includes(term.toLowerCase()), ); const matchesStatus = !status || status === "All" || item.status === status; return matchesSearch && matchesStatus; }); } catch { return []; } return []; } async function loadHomeOrders(session) { try { const now = new Date(); const payload = await apiPost( "/order/home", { token: session.token, month: String(now.getMonth() + 1), year: String(now.getFullYear()), }, session.token, ); const rows = extractArray(payload) || payload?.data || []; const items = Array.isArray(rows) ? rows.map((row, index) => normalizeHomeOrder(row, index)).filter((item) => item.id) : []; const totals = { total: Number(payload?.total_order || payload?.total || items.length || 0), confirmed: Number(payload?.total_confirmed || items.filter((item) => item.status === "Confirmed").length || 0), unconfirmed: Number(payload?.total_unconfirmed || items.filter((item) => item.status === "Unconfirmed").length || 0), }; return { items, totals, month: String(now.getMonth() + 1), year: String(now.getFullYear()) }; } catch { return { items: [], totals: { total: 0, confirmed: 0, unconfirmed: 0 }, month: "", year: "" }; } } async function loadDesktopOrders(session, { search = "", month = "", year = "", currentPage = 1 } = {}) { try { const now = new Date(); const resolvedMonth = String(month || now.getMonth() + 1); const resolvedYear = String(year || now.getFullYear()); const resolvedPage = String(Math.max(1, Number(currentPage) || 1)); const payload = await apiPost( "/order/search_order_pasien_by_doktorid_desktop", { token: session.token, month: resolvedMonth, year: resolvedYear, search: String(search || ""), current_page: resolvedPage, OrderPatientM_DoctorID: session.doctorId || sampleLogin.doctorId, }, session.token, ); const rows = extractArray(payload) || payload?.data || []; const items = Array.isArray(rows) ? rows.map((row, index) => normalizeDesktopOrder(row, index)).filter((item) => item.id) : []; return { items, month: resolvedMonth, year: resolvedYear, currentPage: Number(resolvedPage), search: String(search || ""), hasNext: items.length > 0, hasPrev: Number(resolvedPage) > 1, }; } catch { const now = new Date(); return { items: [], month: String(month || now.getMonth() + 1), year: String(year || now.getFullYear()), currentPage: Number(currentPage) || 1, search: String(search || ""), hasNext: false, hasPrev: false, }; } } async function loadPatientSearch(session, search = "") { try { const payload = await apiPost( "/order/search_order_pasien_by_doktorid", { token: session.token, OrderPatientM_DoctorID: session.doctorId || sampleLogin.doctorId, search: String(search || ""), }, session.token, ); const rows = extractArray(payload) || []; return Array.isArray(rows) ? rows.map((row, index) => normalizePatientOrder(row, index)).filter((item) => item.id || item.patient) : []; } catch { return []; } } async function loadResults(session, search = "") { const term = String(search || "").trim(); try { const orders = await loadOrders(session, "", "All"); const orderId = session.orderId || orders[0]?.id || ""; const payload = await apiPost( "/order/hasil_belum_keluar_by_id", { token: session.token, order_id: orderId }, session.token, ); const rawRows = extractArray(payload) || (payload?.data ? [payload.data] : []); return rawRows.map((row, index) => normalizeResult(row, index)).filter((item) => { if (!item.id) return false; if (!term) return true; return [item.id, item.patient, item.test, item.status, item.summary].some((value) => String(value).toLowerCase().includes(term.toLowerCase()), ); }); } catch { return []; } return []; } async function loadResultDetail(session, resultId) { try { const payload = await apiPost( "/result/getResult", { token: session.token, result_id: resultId, order_id: resultId, }, session.token, ); const rows = extractArray(payload); if (rows?.length) return normalizeResult(rows[0], 0); if (payload?.data && typeof payload.data === "object") return normalizeResult(payload.data, 0); if (payload && typeof payload === "object") return normalizeResult(payload, 0); const related = await loadResults(session, resultId); return related.find((item) => item.id === resultId) || null; } catch { const related = await loadResults(session, resultId); return related.find((item) => item.id === resultId) || related[0] || null; } } async function loadFpp(session, group = "All") { try { const payload = await apiPost("/Fpp/load/1/1", { token: session.token }, session.token); const rows = extractArray(payload) || []; const items = rows.map((row, index) => ({ group: row?.group || row?.kategori || row?.name || `GROUP-${index + 1}`, count: Number(row?.count || row?.total || row?.qty || 1), desc: row?.description || row?.desc || "Laboratory reference item.", })); const filtered = group === "All" ? items : items.filter((item) => item.group === group); return { items: filtered, filter: group }; } catch { return { items: [], filter: group }; } } async function loadFppCatalog(session) { try { const { doctorId, mouId } = resolveFppRouteIds(session); const payload = await apiPost(`/Fpp/loadFPP/${doctorId}/${mouId}`, { token: session.token }, session.token); const rows = extractArray(payload) || payload?.rows || []; const headings = Array.isArray(rows) ? rows : []; const tests = headings.flatMap((heading) => (heading?.details || []).flatMap((detail) => (detail?.tests || []).map((test) => ({ heading: heading?.heading || "FPP", subcategory: detail?.subcategories || "", testId: String(test?.testid || ""), code: String(test?.code || ""), name: String(test?.name || ""), price: String(test?.price || "0"), checked: Boolean(test?.checked), doctortest: test?.doctortest !== false && test?.doctortest !== "false", })), ), ); return tests.filter((item) => item.name); } catch { return []; } } async function loadFppPosterGroups(session) { try { const { doctorId, mouId } = resolveFppRouteIds(session); const payload = await apiPost(`/Fpp/loadFPP/${doctorId}/${mouId}`, { token: session.token }, session.token); const rows = extractArray(payload) || payload?.rows || []; const headings = Array.isArray(rows) ? rows : []; return headings .map((heading) => ({ heading: heading?.heading || "FPP", sections: (heading?.details || []) .map((detail) => ({ title: detail?.subcategories || "", tests: (detail?.tests || []) .map((test) => ({ testId: String(test?.testid || ""), code: String(test?.code || ""), name: String(test?.name || ""), price: String(test?.price || "0"), checked: Boolean(test?.checked), doctortest: test?.doctortest !== false && test?.doctortest !== "false", })) .filter((test) => test.name), })) .filter((section) => section.tests.length), })) .filter((group) => group.sections.length); } catch { return []; } } async function loadOrderDetail(session, orderId) { const [orders, saran, hasil] = await Promise.all([ loadOrders(session, "", "All"), apiPost( "/order/get_order_saran_by_order_patient_id", { token: session.token, order_patient_id: orderId }, session.token, ).catch(() => null), apiPost( "/order/hasil_belum_keluar_by_id", { token: session.token, order_id: orderId }, session.token, ).catch(() => null), ]); const order = orders.find((item) => item.id === orderId) || orders[0] || null; if (!order) return null; const detail = { ...order }; try { detail.apiSaran = saran ? extractArray(saran) || saran?.message || saran?.note || saran?.result || "" : ""; detail.apiHasil = hasil ? extractArray(hasil) || hasil?.message || hasil?.note || hasil?.result || "" : ""; } catch { detail.apiSaran = ""; detail.apiHasil = ""; } return detail; } function json(res, status, payload) { res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" }); res.end(JSON.stringify(payload)); } function redirect(res, location, headers = {}) { res.writeHead(302, { Location: location, ...headers }); res.end(); } function html(res, status, body, headers = {}) { res.writeHead(status, { "Content-Type": "text/html; charset=utf-8", ...headers }); res.end(body); } function isHtmx(req) { return req.headers["hx-request"] === "true"; } async function readBody(req) { const chunks = []; for await (const chunk of req) chunks.push(chunk); const raw = Buffer.concat(chunks).toString("utf8"); const contentType = req.headers["content-type"] || ""; if (contentType.includes("application/json")) return raw ? JSON.parse(raw) : {}; const flat = Object.fromEntries(new URLSearchParams(raw)); const details = []; for (const [key, value] of Object.entries(flat)) { const match = key.match(/^details\[(\d+)\]\[(\w+)\]$/); if (!match) continue; const index = Number(match[1]); const field = match[2]; details[index] ||= {}; details[index][field] = value; delete flat[key]; } if (details.length) flat.details = details.filter(Boolean); return flat; } function fragmentOrdersTable(search = "", month = "", year = "", currentPage = 1, selected = "", data = null) { return renderOrdersTable({ ...(data || {}), search, month, year, currentPage, selectedOrderId: selected, }); } function fragmentResultsTable(search = "", resultsData = null) { const results = resultsData || []; const selected = results[0] || null; return `
${panelHeader("Result history", "Desktop shows table detail. Mobile collapses into stacked cards.")}
Released

${results.filter((item) => item.status === "Released").length} items

Pending

${results.filter((item) => item.status === "Pending").length} items

Reviewed

${results.filter((item) => item.status === "Review").length} items

${ results.length ? `
${results .map( (result) => ` `, ) .join("")}
PatientResult IDTestStatusDate
${escapeHtml(result.patient || "Unknown patient")}
${escapeHtml(result.summary || "-")}
${escapeHtml(result.id)} ${escapeHtml(result.test || "-")} ${statusBadge(result.status)} ${escapeHtml(result.date || "-")}
` : emptyState("No results returned", "The result endpoint did not return any rows for this search.") }
`; } function fragmentFpp(groups = [], group = "All") { return renderFpp(groups, group); } async function fragmentOrderStep(session, step) { const fppTests = await loadFppCatalog(session); return renderOrderForm({}, step, fppTests, session?.mouId || ""); } function fragmentPesanKhusus(orderId) { const order = orderId ? { id: orderId, patient: "", status: "Processing", message: "", apiSaran: "" } : { id: "", patient: "", status: "Processing", message: "", apiSaran: "" }; return ` `; } async function fragmentPatientSearch(session, search = "") { const patients = await loadPatientSearch(session, search); return ` `; } async function fragmentResultDetail(session, resultId) { const result = await loadResultDetail(session, resultId); return `
${renderResultDetail(result)}
`; } async function renderRoute(req, res, url) { const path = url.pathname; const query = Object.fromEntries(url.searchParams.entries()); const session = readSession(req); const authed = Boolean(session); const isGet = req.method === "GET" || req.method === "HEAD"; if (path === "/styles.css") { const css = await readFile(new URL("./styles.css", import.meta.url), "utf8"); res.writeHead(200, { "Content-Type": "text/css; charset=utf-8" }); res.end(css); return; } if (path === "/logo.png") { const logo = await readFile(new URL("./logo.png", import.meta.url)); res.writeHead(200, { "Content-Type": "image/png" }); res.end(logo); return; } if (path === "/login" && isGet) { html(res, 200, loginPage(), { "Cache-Control": "no-store" }); return; } if (path === "/splash" && isGet) { html(res, 200, splashPage(), { "Cache-Control": "no-store" }); return; } if (path === "/problem-login" && isGet) { html(res, 200, problemLoginPage(), { "Cache-Control": "no-store" }); return; } if (path === "/login" && req.method === "POST") { const body = await readBody(req); try { const payload = await apiPost("/auth/login", body); const normalized = normalizeSession(payload); const upstreamFailed = String(payload?.status || payload?.result_status || "").toUpperCase() === "ERR" || !normalized.token; if (upstreamFailed) { throw new Error(payload?.message || "Invalid login response"); } const sessionValue = JSON.stringify({ token: normalized.token, username: normalized.username || body.username || "", doctorId: normalized.doctorId || body.doctor_id || "", doctorCode: normalized.doctorCode || body.doctor_id || "", mouId: normalized.mouId || body.M_MouID || "", userId: normalized.userId || "", raw: payload, }); redirect(res, "/", { "Set-Cookie": setCookie(sessionKey, sessionValue, { maxAge: 60 * 60 * 12 }), }); } catch (error) { html(res, 200, loginPage({ error: `Login failed: ${error.message}. Check credentials and network.` })); } return; } if (path === "/logout" && req.method === "POST") { const sessionData = readSession(req); if (sessionData?.token) { try { await apiPost( "/auth/logout", { M_UserID: sessionData.userId || "", M_UserUsername: sessionData.username || sampleLogin.username, }, sessionData.token, ); } catch { // Ignore upstream logout failures and still clear local session. } } redirect(res, "/login", { "Set-Cookie": deleteCookie(sessionKey) }); return; } if (path === "/settings/change-password" && req.method === "POST") { const sessionData = requireAuth(req, res); if (!sessionData) return; const body = await readBody(req); try { await apiPost( "/auth/change_password", { token: sessionData.token, M_UserID: sessionData.userId || "", username: sessionData.username || sampleLogin.username, doctor_id: sessionData.doctorCode || sessionData.doctorId || sampleLogin.doctorId, new_password: body.new_password, confirm_password: body.confirm_password, }, sessionData.token, ); redirect(res, "/settings"); } catch (error) { html( res, 200, layout( "Change Password", `
${panelHeader("Change password", "Inline validation and a straightforward submit path.")}
Upstream change password call failed. Check API availability.
`, { authenticated: true, activePath: "/settings/change-password", ...accountLayoutOptions(sessionData) }, ), ); } return; } if (path === "/orders/new" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, await orderNewPage(session, path)); return; } if (path.startsWith("/orders/new/") && isGet) { if (!requireAuth(req, res)) return; html(res, 200, await orderNewPage(session, path)); return; } if (path === "/orders" && isGet) { if (!requireAuth(req, res)) return; const orders = await loadDesktopOrders(session, query); html(res, 200, ordersPage({ ...orders, selectedOrderId: query.selected || orders.items[0]?.id || "" }, session)); return; } if (path === "/results" && isGet) { if (!requireAuth(req, res)) return; const results = await loadResults(session, query.search || ""); html(res, 200, resultsPage({ query, results, selectedResultId: results[0]?.id || "" }, session)); return; } if (path === "/results/historical" && isGet) { if (!requireAuth(req, res)) return; const results = await loadResults(session, ""); html(res, 200, layout("Historical results", `
${panelHeader("Historical results", "A compact historic view that still fits the responsive shell.")}${results.length ? `
${results.map((item) => `
${escapeHtml(item.patient || "Unknown patient")}

${escapeHtml(item.test || "-")} · ${escapeHtml(item.date || "-")}

${statusBadge(item.status)}
`).join("")}
` : emptyState("No results returned", "The API returned no historical result rows.")}
`, { authenticated: true, activePath: "/results", ...accountLayoutOptions(session) })); return; } if (path === "/results/pending" && isGet) { if (!requireAuth(req, res)) return; const results = (await loadResults(session, "")).filter((item) => item.status !== "Released"); html(res, 200, layout("Pending results", `
${panelHeader("Pending results", "Items that need attention before release.")}${results.length ? `
${results.map((item) => `
${escapeHtml(item.patient || "Unknown patient")}${statusBadge(item.status)}

${escapeHtml(item.test || "-")} · ${escapeHtml(item.summary || "-")}

Open detail
`).join("")}
` : emptyState("No pending results", "The API returned no unreleased rows.")}
`, { authenticated: true, activePath: "/results", ...accountLayoutOptions(session) })); return; } if (path === "/fpp" && isGet) { if (!requireAuth(req, res)) return; const groups = await loadFppPosterGroups(session); html(res, 200, fppPage({ group: query.group || "All", groups }, session)); return; } if (path === "/patients" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, await patientsPage(session)); return; } if ((path === "/settings" || path === "/settings/account") && isGet) { if (!requireAuth(req, res)) return; html(res, 200, settingsPage(session)); return; } if (path === "/settings/change-password" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, changePasswordPage(session)); return; } if (path === "/" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, layout("Dashboard", await dashboardPage(session), { authenticated: true, activePath: "/", ...accountLayoutOptions(session) })); return; } if (path.startsWith("/orders/") && path.endsWith("/pesan-khusus") && isGet) { if (!requireAuth(req, res)) return; const orderId = path.split("/")[2]; const order = await loadOrderDetail(session, orderId); if (!order) { html(res, 200, layout("Pesan Khusus", `
${emptyState("No order found", "The API returned no matching order for this ID.")}
`, { authenticated: true, activePath: "/orders", ...accountLayoutOptions(session) })); return; } html(res, 200, specialMessagePage(order, session)); return; } if (path.startsWith("/orders/") && isGet) { if (!requireAuth(req, res)) return; const orderId = path.split("/")[2]; const order = await loadOrderDetail(session, orderId); if (!order) { html(res, 200, layout("Order Detail", `
${emptyState("No order found", "The API returned no matching order for this ID.")}
`, { authenticated: true, activePath: "/orders", ...accountLayoutOptions(session) })); return; } html(res, 200, orderDetailPage(order, session)); return; } if (path.startsWith("/results/") && isGet) { if (!requireAuth(req, res)) return; const resultId = path.split("/")[2]; const result = await loadResultDetail(session, resultId); if (!result) { html(res, 200, layout("Result Detail", `
${emptyState("No result found", "The API returned no matching result for this ID.")}
`, { authenticated: true, activePath: "/results", ...accountLayoutOptions(session) })); return; } html(res, 200, resultDetailPage(result, session)); return; } if (path === "/fragments/orders/table" && isGet) { if (!requireAuth(req, res)) return; const orders = await loadDesktopOrders(session, query); html( res, 200, fragmentOrdersTable(query.search || "", query.month || "", query.year || "", query.current_page || 1, query.selected || orders.items[0]?.id || "", orders), { "HX-Trigger": JSON.stringify({ "doclink:orders-updated": true }) }, ); return; } if (path === "/fragments/results/table" && isGet) { if (!requireAuth(req, res)) return; const results = await loadResults(session, query.search || ""); html(res, 200, fragmentResultsTable(query.search || "", results)); return; } if (path === "/fragments/fpp/list" && isGet) { if (!requireAuth(req, res)) return; const groups = await loadFppPosterGroups(session); html(res, 200, fragmentFpp(groups, query.group || "All")); return; } if (path.startsWith("/fragments/forms/order-step/") && isGet) { if (!requireAuth(req, res)) return; const step = path.split("/")[4] || "demografi"; html(res, 200, await fragmentOrderStep(session, step)); return; } if (path === "/fragments/modals/pesan-khusus" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, fragmentPesanKhusus(query.order_id || "")); return; } if (path === "/fragments/modals/patient-search" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, await fragmentPatientSearch(session, query.search || "")); return; } if (path.startsWith("/fragments/results/detail/") && isGet) { if (!requireAuth(req, res)) return; const resultId = path.split("/")[4] || ""; html(res, 200, await fragmentResultDetail(session, resultId)); return; } if (path.startsWith("/api/") && isGet) { json(res, 200, { ok: true }); return; } if (path === "/orders" && req.method === "POST") { const sessionData = requireAuth(req, res); if (!sessionData) return; const body = await readBody(req); try { const payload = await apiPost( "/order/order_patient", { token: sessionData.token, M_MouID: body.M_MouID || sessionData.mouId || sampleLogin.mouId || "", patient_name: body.patient_name || "", patient_diagnosa: body.patient_diagnosa || "", patient_address: body.patient_address || "", patient_nik: body.patient_nik || "", patient_hp: body.patient_hp || "", patient_dob: body.patient_dob || "", patient_note: body.patient_note || "", details: body.details || [], }, sessionData.token, ); const saved = payload?.data || payload?.result || payload || {}; const normalizedSaved = { id: saved.order_id || saved.id || saved.order_patient_id || "", patient: saved.order_name || body.patient_name || "", diagnosis: saved.order_diagnosa || body.patient_diagnosa || "", message: saved.order_note || body.patient_note || "", orderDate: saved.order_date || "", orderCode: saved.order_qrcode || "", doctorName: sessionData.username || sampleLogin.username, details: Array.isArray(saved.details) ? saved.details : Array.isArray(body.details) ? body.details : [], }; html( res, 200, layout("Order saved", renderOrderSaved(normalizedSaved), { authenticated: true, activePath: "/orders", subtitle: "QR Code and review are shown after the order has been submitted successfully.", }), ); } catch { html( res, 200, layout( "Create Order", `
${panelHeader("Create new order", "The new project collapses the old step-heavy flow into a cleaner shell while keeping the same workflow.")}
Upstream order create call failed. Check API availability.
`, { authenticated: true, activePath: "/orders", ...accountLayoutOptions(sessionData) }, ), ); } return; } if (path.startsWith("/orders/") && path.endsWith("/pesan-khusus") && req.method === "POST") { const sessionData = requireAuth(req, res); if (!sessionData) return; const orderId = path.split("/")[2]; const body = await readBody(req); try { await apiPost( "/Pesankhusus/add_pesan_khusus", { token: sessionData.token, order_id: orderId, pesan_khusus: body.pesan_khusus, }, sessionData.token, ); redirect(res, `/orders/${orderId}`); } catch { html( res, 200, layout( "Pesan Khusus", `
${panelHeader("Pesan khusus", "Desktop can treat this as a modal-style panel; mobile reads it as a dedicated page.")}
Upstream save failed. Check API availability.
`, { authenticated: true, activePath: "/orders", ...accountLayoutOptions(sessionData) }, ), ); } return; } html(res, 404, emptyRoute(path)); } const server = http.createServer(async (req, res) => { try { const url = new URL(req.url, `http://${req.headers.host}`); await renderRoute(req, res, url); } catch (error) { res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" }); res.end(`Internal error: ${error.message}`); } }); server.listen(PORT, () => { console.log(`DocLink Web running on http://localhost:${PORT}`); });