routes/index.js: used for defined all the endpoints:
import express from "express"; import * as notes from "./notes.js"; const router = express.Router(); router.get("/notes", notes.list); router.post("/notes", notes.create); // curl -X POST http://localhost:3000/notes router.get("/notes/:id", notes.read); router.post("/notes/:id", notes.update); // curl -X POST http://localhost:3000/notes/123 router.delete("/notes/:id", notes.deleteNote); // curl -X DELETE http://localhost:3000/notes export default router;
routes/notes.js: used for defined collections for CRUD:
import * as Note from "../model/Note.js"; // curl "http://localhost:3000/notes?sort=DESC" export function list(req, res) { let { sort } = req.query; sort = sort ? sort.toLowerCase() : "desc"; if (sort !== "asc" && sort !== "desc") { return res.status(400).send("invalid sort params"); } const notes = Note.getNotes(sort); res.json({ notes }); } // curl -X POST -d title="hello" -d body="world" http://localhost:3000/notes/ export async function create(req, res) { const { title, body } = req.body; if (title == undefined || body == undefined) { return res.status(400).send("Invalid request"); } const note = Note.createNote({ title, body }); res.status(201).send({ message: "ok", data: note, }); } export async function read(req, res) { const { id } = body.params; if (id == undefined) { return res.status(400).send("Invalid request"); } const note = await Note.getNode(id); res.json(note); } // curl -X POST -d title="hello" -d body="world" http://localhost:3000/notes/123 export async function update(req, res) { const { id } = req.params; const { title, body } = req.body; if (title == undefined && body == undefined) { return res.status(400).send("Invalid request"); } const note = Note.updateNote(id, { title, body }); res.send({ message: "ok", data: note }); } // curl -X DELETE http://localhost:3000/notes/123 export async function deleteNote(req, res) { const { id } = req.params; await Note.deleteNode(id); res.send("ok"); }
model/Note.js: Do CRUD:
import { v4 as uuid } from "uuid";
import MapStore from "../lib/mapstore.js";
const NOTES = new Map();
const store = new MapStore("notes.json");
/*
Note {
id: String
title: String
body: String
lastEdited: Date
}*/
store
.read()
.then((notes) => {
for (let [id, note] of notes) {
NOTES.set(id, note);
}
})
.catch((err) => {
console.error(err);
});
export function getNotes(sort) {
const notes = Array.from(NOTES.values());
if (sort === "asc") {
return notes.sort((a, b) => {
return a.lastEdited - b.lastEdited;
});
} else {
return notes.sort((a, b) => {
return b.lastEdited - a.lastEdited;
});
}
return;
}
export async function createNote({ title, body }) {
const id = uuid();
const lastEdited = Date.now();
const note = {
id,
title,
body,
lastEdited,
};
NOTES.set(id, note);
await store.save(NOTES);
return { ...note };
}
export async function updateNote(id, { title, body }) {
if (!NOTES.has(id)) {
return null;
}
const note = NOTES.get(id);
note.title = title ?? note.title;
note.body = body ?? note.body;
note.lastEdited = Date.now();
await store.save(NOTES);
return { ...note };
}
export function getNode(id) {
if (!NOTES.has(id)) {
return null;
}
const note = NOTES.get(id);
return { ...note };
}
export async function deleteNode(id) {
const successed = NOTES.delete(id);
await store.save(NOTES);
return successed;
}
lib/mapstore.js: runtime memory:
import { readFile, writeFile } from "fs/promises";
import path from "path";
const dataDir = "data";
class MapStore {
constructor(filename) {
this.filepath = path.resolve(dataDir, filename);
}
async save(data) {
console.log(`writing to ${this.filepath}`);
const serializedData = JSON.stringify(Array.from(data.entries()));
await writeFile(this.filepath, serializedData);
}
async read() {
console.log(`readubg frin ${this.filepath}`);
const data = await readFile(this.filepath, "utf-8");
const parsed = JSON.parse(data);
return new Map(parsed);
}
}
export default MapStore;
index.js:
import express from "express"; // Logging import morgan from "morgan"; import routes from "./routes/index.js"; const app = express(); app.use( morgan(":method :url :status :res[content-length] - :response-time ms") ); // encode post body and available on req.body app.use(express.urlencoded({ extended: true })); // Routers app.use(routes); // Trigger a error for testing app.get("/error", function (req, res) { throw new Error("oops I made a mistake"); }); // Error handler middleware app.use(function (err, req, res, next) { console.error(err.stack); res.status(500).send(err.message); }); // 404 catch app.use(function (req, res) { res.status(404).send("not found"); }); app.listen(3000, function () { console.log("app is listening on port 3000"); });