diff --git a/.gitignore b/.gitignore index f1ff414e..a003f76c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ node_modules .env.development.local .env.test.local .env.production.local -package-lock.json \ No newline at end of file +package-lock.json +.env \ No newline at end of file diff --git a/package.json b/package.json index 6830a48a..9b027efc 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", "express": "^4.17.3", + "mongodb": "^6.12.0", "mongoose": "^8.0.0", "nodemon": "^3.0.1" } diff --git a/pull_request_template.md b/pull_request_template.md index 39a2aa32..318ae5fe 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,6 +1,5 @@ ## Netlify link -Add your Netlify link here. -PS. Don't forget to add it in your readme as well. +Render link: https://project-18-mongo-api.onrender.com/ (not working yet..) ## Collaborators -Add any collaborators here. +- diff --git a/server.js b/server.js index 647e7b14..8638a475 100644 --- a/server.js +++ b/server.js @@ -1,16 +1,14 @@ import express from "express"; import cors from "cors"; import mongoose from "mongoose"; +import dotenv from "dotenv"; +import expressListEndpoints from "express-list-endpoints"; +import booksData from "./data/books.json" -// If you're using one of our datasets, uncomment the appropriate import below -// to get started! -// import avocadoSalesData from "./data/avocado-sales.json"; -// import booksData from "./data/books.json"; -// import goldenGlobesData from "./data/golden-globes.json"; -// import netflixData from "./data/netflix-titles.json"; -// import topMusicData from "./data/top-music.json"; +dotenv.config() -const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo"; + +const mongoUrl = process.env.MONGO_URL || "https://project-18-mongo-api.onrender.com/ "; mongoose.connect(mongoUrl); mongoose.Promise = Promise; @@ -24,11 +22,146 @@ const app = express(); app.use(cors()); app.use(express.json()); -// Start defining your routes here + +//Check if mongo is connected +mongoose.connect(mongoUrl) + .then(() => console.log("Connected to MongoDB")) + .catch(err => console.error("Failed to connect to MongoDB:", err)); + + +const Book = mongoose.model('Book', { + "bookID": Number, + "title": String, + "authors": String, + "average_rating": Number, + "isbn": Number, + "isbn13": Number, + "language_code": String, + "num_pages": Number, + "ratings_count": Number, + "text_reviews_count": Number +}) + + + +if (process.env.RESET_DB) { + const seedDatabase = async () => { + await Book.deleteMany({}) + + booksData.forEach((book) => { + new Book(book).save() + }) + } + + seedDatabase() +} + + + +// Home page - first route app.get("/", (req, res) => { - res.send("Hello Technigo!"); + res.send("Welcome to the website where you can find your favourite book!"); + + const endpoints = expressListEndpoints(app); + response.json({ + message: "Welcome to the Elves API! Here are the available endpoints:", + description: { + "/books": "all books", + "/books/pages": "by number of pages", + "/books/:bookID": "by ID", + "/test": "Test endpoint", + }, + endpoints: endpoints + }); }); +// Route with all the books - full API +app.get("/books", async (req, res) => { + try { + const books = await Book.find(); + res.json(books); + } catch (error) { + res.status(500).json({ error: "An error occurred while fetching books" }); + } +}); + + +// Ge books based on number of pages (needs to be befor bookID otherwise that route will override this) +app.get("/books/pages", async (req, res) => { + const { min, max } = req.query; + + // Parse min and max values or assign default values + const minPages = parseInt(min, 10) || 0; // Default: 0 pages + const maxPages = parseInt(max, 10) || Number.MAX_SAFE_INTEGER; // Default: No upper limit + + console.log(`Filtering books with num_pages between ${minPages} and ${maxPages}`); + + try { + // Query to find books within the range + const numberOfPages = await Book.find({ + num_pages: { $gte: minPages, $lte: maxPages }, + }); + + // Return books if found, otherwise send 404 + if (numberOfPages.length > 0) { + res.json(numberOfPages); + } else { + res.status(404).json({ + error: `No books found with page count between ${minPages} and ${maxPages}`, + }); + } + } catch (error) { + // Handle any server-side errors + res.status(500).json({ error: "An error occurred while fetching books" }); + } +}); + + +// Get individual books from id +app.get("/books/:bookID", async (req, res) => { + const bookID = parseInt(req.params.bookID); + + try { + const book = await Book.findOne({ bookID: bookID }); + + if (book) { + res.json(book); // return the specifik book + } else { + res.status(404).json({ error: "Book not found" }); // error page if book not founf + } + } catch (error) { + res.status(500).json({ error: "An error occurred while fetching the book" }); // 500 page when wrong + } +}); + + +// Get book-books by author +app.get("/books/authors/:author", async (req, res) => { + const author = req.params.author; + + try { + // $regex = to match name and not case sensitive + const booksByAuthor = await Book.find({ + authors: { $regex: author, $options: "i" }, // "i" case-insensitive + }); + + if (booksByAuthor.length > 0) { + res.json(booksByAuthor); // Returnera böckerna om de finns + } else { + res.status(404).json({ error: "No books found for this author" }); + } + } catch (error) { + res.status(500).json({ error: "An error occurred while fetching books" }); + } +}); + +// test +app.get("/test", (req, res) => { + response.send("Yesbox!"); + console.log("Yesbox!"); +}); + + // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`);