// A small local JSON server for the reading list, made with node:http. You do not need to change it.
import {createServer} from "node:http";
export async function startServer(books = []) {
let nextId = books.length + 1;
const server = createServer(async (request, response) => {
const json = (status, value) => {
response.writeHead(status, {"Content-Type": "application/json"});
response.end(JSON.stringify(value));
};
let body = "";
for await (const chunk of request) body += chunk;
const {method, url} = request;
const match = url.match(/^\/books\/(\d+)$/);
if (method === "GET" && url === "/books") json(200, books);
else if (method === "POST" && url === "/books") {
const {title, author} = JSON.parse(body || "{}");
if (typeof title !== "string" || title.trim() === "") return json(400, {error: "title is required"});
const book = {id: nextId++, title: title.trim(), author: author ?? "", read: false};
books.push(book);
json(201, book);
} else if (method === "PATCH" && match) {
const book = books.find((b) => b.id === Number(match[1]));
if (!book) return json(404, {error: "no such book"});
book.read = JSON.parse(body || "{}").read === true;
json(200, book);
} else if (url === "/broken") json(500, {error: "database is down"});
else if (url === "/slow") {
// answers after 300 ms, unless the client gave up
const timer = setTimeout(() => json(200, books), 300);
response.on("close", () => clearTimeout(timer));
} else json(404, {error: "not found"});
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); // port 0: any free port
return {
url: `http://127.0.0.1:${server.address().port}`,
close: () => new Promise((resolve) => server.close(resolve))
};
}