/notesdata/notes.json (no database)backend-notes/backend-notes/src/server.mjsbackend-notes/data/notes.jsonbackend-notes/package.jsonGET /health → quick server checkGET /notes → list notesPOST /notes → createGET /notes/:id → read onePUT /notes/:id → updateDELETE /notes/:id → deletenpm run dev (auto-restart) and npm start (normal)..mjs) so import works naturally.npm installnpm run devGET /health200404/health working. If it breaks, rollback and fix.curl http://localhost:3000/health{"ok":true}json(res, status, payload) — one function to set JSON headers + stringifynotFound(res) — one place for the standard 404 response// NEW / // CHANGED is highlighted.readBody(req) added to read streaming request bodiesnew URL(req.url, ...) added (clean path parsing)POST /echo returns the JSON you sentcurl -X POST http://localhost:3000/echo -H "Content-Type: application/json" -d '{"msg":"hi"}'{"received":{"msg":"hi"}}Start with an empty array. Every note will be an object with id, text, createdAt, updatedAt.
data/notes.json as our “database”.loadNotes() and saveNotes() using fs/promisesNOTES_PATH built from import.meta.url so it works from any working directoryGET /notescurl http://localhost:3000/notes → [] (for now)readBody() (we need it for POST)nextId(notes) (max+1) so ids survive server restartsPOST /notes with validation (text required)curl -X POST http://localhost:3000/notes -H "Content-Type: application/json" -d '{"text":"first note"}'curl http://localhost:3000/notes/notes/3 means “note with id=3”.400; if not found → 404.parseId() to extract ids from pathsGET /notes/:id and implemented “not found” logiccurl http://localhost:3000/notes/1curl http://localhost:3000/notes/999 → 404updatedAt.PUT /notes/:idtext again (never trust client input)notes.jsoncurl -X PUT http://localhost:3000/notes/1 -H "Content-Type: application/json" -d '{"text":"updated note"}'curl http://localhost:3000/notes/1204 No Content on success.DELETE /notes/:id204curl -i -X DELETE http://localhost:3000/notes/1 → status 204curl http://localhost:3000/notessetCors(res) headersOPTIONS preflight requestsPORT configurable (env var)GET /notes?contains=word filters notes by substring (case-insensitive)GET /notes?limit=5 returns only the first N notesGET /notes?order=desc returns newest notes firstGET /notes/count returns {"count": number}limit values return 400 Bad RequestGET /notes?updatedAfter=TIMESTAMP returns recently updated notes onlyconst url = new URL(req.url, 'http://localhost');url.searchParams.get('contains')url.searchParams.get('limit')