From 1d45fd0928e3bc696b92713f55da5c34f353c3ed Mon Sep 17 00:00:00 2001 From: Jenny Date: Fri, 6 Dec 2024 20:41:11 +0100 Subject: [PATCH 1/5] added new dog breed dataset --- data/dog-breeds.json | 162 +++++++++++++++++++++++++++++++++++++++++++ package.json | 7 +- server.js | 40 +++++------ 3 files changed, 184 insertions(+), 25 deletions(-) create mode 100644 data/dog-breeds.json diff --git a/data/dog-breeds.json b/data/dog-breeds.json new file mode 100644 index 000000000..3f0831dc1 --- /dev/null +++ b/data/dog-breeds.json @@ -0,0 +1,162 @@ +[ + { + "id": 1, + "name": "German Shepherd", + "origin": "Germany", + "category": "Herding", + "familyFriendly": "Yes", + "size": "Large" + }, + { + "id": 2, + "name": "Labrador Retriever", + "origin": "Canada", + "category": "Sporting", + "familyFriendly": "Yes", + "size": "Large" + }, + { + "id": 3, + "name": "Poodle", + "origin": "Germany/France", + "category": "Non-Sporting", + "familyFriendly": "Yes", + "size": "Various" + }, + { + "id": 4, + "name": "Golden Retriever", + "origin": "Scotland", + "category": "Sporting", + "familyFriendly": "Yes", + "size": "Large" + }, + { + "id": 5, + "name": "Bulldog", + "origin": "England", + "category": "Non-Sporting", + "familyFriendly": "Yes", + "size": "Medium" + }, + { + "id": 6, + "name": "Rottweiler", + "origin": "Germany", + "category": "Working", + "familyFriendly": "Yes", + "size": "Large" + }, + { + "id": 7, + "name": "Beagle", + "origin": "England", + "category": "Hound", + "familyFriendly": "Yes", + "size": "Small" + }, + { + "id": 8, + "name": "Siberian Husky", + "origin": "Russia", + "category": "Working", + "familyFriendly": "Yes", + "size": "Medium" + }, + { + "id": 9, + "name": "Chihuahua", + "origin": "Mexico", + "category": "Toy", + "familyFriendly": "No", + "size": "Small" + }, + { + "id": 10, + "name": "Great Dane", + "origin": "Germany", + "category": "Working", + "familyFriendly": "Yes", + "size": "Large" + }, + { + "id": 11, + "name": "Pug", + "origin": "China", + "category": "Toy", + "familyFriendly": "Yes", + "size": "Small" + }, + { + "id": 12, + "name": "Doberman Pinscher", + "origin": "Germany", + "category": "Working", + "familyFriendly": "Yes", + "size": "Large" + }, + { + "id": 13, + "name": "Yorkshire Terrier", + "origin": "England", + "category": "Toy", + "familyFriendly": "No", + "size": "Small" + }, + { + "id": 14, + "name": "Boxer", + "origin": "Germany", + "category": "Working", + "familyFriendly": "Yes", + "size": "Large" + }, + { + "id": 15, + "name": "Shih Tzu", + "origin": "Tibet", + "category": "Toy", + "familyFriendly": "Yes", + "size": "Small" + }, + { + "id": 16, + "name": "Australian Shepherd", + "origin": "United States", + "category": "Herding", + "familyFriendly": "Yes", + "size": "Medium" + }, + { + "id": 17, + "name": "Border Collie", + "origin": "Scotland", + "category": "Herding", + "familyFriendly": "Yes", + "size": "Medium" + }, + { + "id": 18, + "name": "Chow Chow", + "origin": "China", + "category": "Non-Sporting", + "familyFriendly": "No", + "size": "Medium" + }, + { + "id": 19, + "name": "Bernese Mountain Dog", + "origin": "Switzerland", + "category": "Working", + "familyFriendly": "Yes", + "size": "Large" + }, + { + "id": 20, + "name": "French Bulldog", + "origin": "France", + "category": "Non-Sporting", + "familyFriendly": "Yes", + "size": "Small" + } +] \ No newline at end of file diff --git a/package.json b/package.json index f93ddb524..b803e8db5 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,10 @@ "@babel/node": "^7.16.8", "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", - "express": "^4.17.3", + "express": "^4.21.2", + "express-list-endpoints": "^7.1.1", "nodemon": "^3.0.1" - } + }, + "main": "server.js", + "keywords": [] } diff --git a/server.js b/server.js index b5fec6fe2..d7548eb21 100644 --- a/server.js +++ b/server.js @@ -1,30 +1,24 @@ -import express from "express"; -import cors from "cors"; +const express = require("express"); +const cors = require("cors"); +const dogs = require("./data/dogs.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"; - -// Defines the port the app will run on. Defaults to 8080, but can be overridden -// when starting the server. Example command to overwrite PORT env variable value: -// PORT=9000 npm start const port = process.env.PORT || 8080; const app = express(); -// Add middlewares to enable cors and json body parsing app.use(cors()); app.use(express.json()); -// Start defining your routes here -app.get("/", (req, res) => { - res.send("Hello Technigo!"); -}); - -// Start the server -app.listen(port, () => { - console.log(`Server running on http://localhost:${port}`); -}); +app.get("/dogs/:id", (req, res) => { + const id = req.params.id; + console.log("Requested ID:", id, "Type:", typeof id); + + const dog = dogs.find(dog => { + return dog.id === parseInt(id); + }); + + if (!dog) { + res.status(404).json({ error: "Dog breed not found" }); + } else { + res.json(dog); + } +}); \ No newline at end of file From cedfab93ad2cedb767cd5a52c6ba25a02fe3e6fd Mon Sep 17 00:00:00 2001 From: Jenny Date: Fri, 6 Dec 2024 21:05:04 +0100 Subject: [PATCH 2/5] added more breeds + updated server.js --- data/dog-breeds.json | 120 +++++++++++++++++++++++++++++++++++-------- server.js | 23 ++++++++- 2 files changed, 122 insertions(+), 21 deletions(-) diff --git a/data/dog-breeds.json b/data/dog-breeds.json index 3f0831dc1..c739b21b0 100644 --- a/data/dog-breeds.json +++ b/data/dog-breeds.json @@ -4,7 +4,7 @@ "name": "German Shepherd", "origin": "Germany", "category": "Herding", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Large" }, { @@ -12,7 +12,7 @@ "name": "Labrador Retriever", "origin": "Canada", "category": "Sporting", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Large" }, { @@ -20,7 +20,7 @@ "name": "Poodle", "origin": "Germany/France", "category": "Non-Sporting", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Various" }, { @@ -28,7 +28,7 @@ "name": "Golden Retriever", "origin": "Scotland", "category": "Sporting", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Large" }, { @@ -36,7 +36,7 @@ "name": "Bulldog", "origin": "England", "category": "Non-Sporting", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Medium" }, { @@ -44,7 +44,7 @@ "name": "Rottweiler", "origin": "Germany", "category": "Working", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Large" }, { @@ -52,7 +52,7 @@ "name": "Beagle", "origin": "England", "category": "Hound", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Small" }, { @@ -60,7 +60,7 @@ "name": "Siberian Husky", "origin": "Russia", "category": "Working", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Medium" }, { @@ -68,7 +68,7 @@ "name": "Chihuahua", "origin": "Mexico", "category": "Toy", - "familyFriendly": "No", + "familyFriendly": "no", "size": "Small" }, { @@ -76,7 +76,7 @@ "name": "Great Dane", "origin": "Germany", "category": "Working", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Large" }, { @@ -84,7 +84,7 @@ "name": "Pug", "origin": "China", "category": "Toy", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Small" }, { @@ -92,7 +92,7 @@ "name": "Doberman Pinscher", "origin": "Germany", "category": "Working", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Large" }, { @@ -100,7 +100,7 @@ "name": "Yorkshire Terrier", "origin": "England", "category": "Toy", - "familyFriendly": "No", + "familyFriendly": "no", "size": "Small" }, { @@ -108,7 +108,7 @@ "name": "Boxer", "origin": "Germany", "category": "Working", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Large" }, { @@ -116,7 +116,7 @@ "name": "Shih Tzu", "origin": "Tibet", "category": "Toy", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Small" }, { @@ -124,7 +124,7 @@ "name": "Australian Shepherd", "origin": "United States", "category": "Herding", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Medium" }, { @@ -132,7 +132,7 @@ "name": "Border Collie", "origin": "Scotland", "category": "Herding", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Medium" }, { @@ -140,7 +140,7 @@ "name": "Chow Chow", "origin": "China", "category": "Non-Sporting", - "familyFriendly": "No", + "familyFriendly": "no", "size": "Medium" }, { @@ -148,7 +148,7 @@ "name": "Bernese Mountain Dog", "origin": "Switzerland", "category": "Working", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Large" }, { @@ -156,7 +156,87 @@ "name": "French Bulldog", "origin": "France", "category": "Non-Sporting", - "familyFriendly": "Yes", + "familyFriendly": "yes", "size": "Small" + }, + { + "id": 21, + "name": "Dachshund", + "origin": "Germany", + "category": "Hound", + "familyFriendly": "yes", + "size": "Small" + }, + { + "id": 22, + "name": "Saint Bernard", + "origin": "Switzerland", + "category": "Working", + "familyFriendly": "yes", + "size": "Large" + }, + { + "id": 23, + "name": "Corgi", + "origin": "Wales", + "category": "Herding", + "familyFriendly": "yes", + "size": "Small" + }, + { + "id": 24, + "name": "Dalmatian", + "origin": "Croatia", + "category": "Non-Sporting", + "familyFriendly": "yes", + "size": "Medium" + }, + { + "id": 25, + "name": "Afghan Hound", + "origin": "Afghanistan", + "category": "Hound", + "familyFriendly": "no", + "size": "Large" + }, + { + "id": 26, + "name": "Alaskan Malamute", + "origin": "United States", + "category": "Working", + "familyFriendly": "yes", + "size": "Large" + }, + { + "id": 27, + "name": "Bichon Frise", + "origin": "Spain", + "category": "Non-Sporting", + "familyFriendly": "yes", + "size": "Small" + }, + { + "id": 28, + "name": "Bull Terrier", + "origin": "England", + "category": "Terrier", + "familyFriendly": "yes", + "size": "Medium" + }, + { + "id": 29, + "name": "Greyhound", + "origin": "Egypt", + "category": "Hound", + "familyFriendly": "yes", + "size": "Large" + }, + { + "id": 30, + "name": "Newfoundland", + "origin": "Canada", + "category": "Working", + "familyFriendly": "yes", + "size": "Large" } ] \ No newline at end of file diff --git a/server.js b/server.js index d7548eb21..631662e9e 100644 --- a/server.js +++ b/server.js @@ -1,6 +1,7 @@ +const listEndpoints = require('express-list-endpoints'); const express = require("express"); const cors = require("cors"); -const dogs = require("./data/dogs.json"); +const dogs = require("./data/dog-breeds.json"); const port = process.env.PORT || 8080; const app = express(); @@ -21,4 +22,24 @@ app.get("/dogs/:id", (req, res) => { } else { res.json(dog); } +}); + +app.get("/dogs", (req, res) => { + const category = req.query.category; + const filteredDogs = category + ? dogs.filter(dog => dog.category === category) + : dogs; + res.json(filteredDogs); +}); + +app.get("/", (req, res) => { + const endpoints = listEndpoints(app); + res.json({ + description: "Dog Breeds API - Information about different dog breeds", + endpoints: endpoints + }); +}); + +app.listen(port, () => { + console.log(`Server running on http://localhost:${port}`); }); \ No newline at end of file From 7cd37b09bfe4fa1259fafcd5ff7f7d322a00fbfd Mon Sep 17 00:00:00 2001 From: Jenny Date: Fri, 6 Dec 2024 21:08:23 +0100 Subject: [PATCH 3/5] added comments --- server.js | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/server.js b/server.js index 631662e9e..e691b4d23 100644 --- a/server.js +++ b/server.js @@ -1,45 +1,55 @@ -const listEndpoints = require('express-list-endpoints'); -const express = require("express"); -const cors = require("cors"); -const dogs = require("./data/dog-breeds.json"); +const express = require("express"); // Web application framework +const cors = require("cors"); // CORS is needed to allow requests from different domains +const listEndpoints = require('express-list-endpoints'); // Used to generate API documentation +const dogs = require("./data/dog-breeds.json"); // Import our dogs data from JSON file +// Sets up server port - uses environment variable if available, otherwise use 8080 const port = process.env.PORT || 8080; +// Initialize express application const app = express(); -app.use(cors()); -app.use(express.json()); +// Middleware setup +app.use(cors()); // Enable CORS for all routes +app.use(express.json()); // Parse incoming JSON requests +// Route for getting a single dog by ID app.get("/dogs/:id", (req, res) => { - const id = req.params.id; + const id = req.params.id; // Get the ID from the URL parameter console.log("Requested ID:", id, "Type:", typeof id); + // Finds the dog with matching ID (converts string ID to number for comparison) const dog = dogs.find(dog => { return dog.id === parseInt(id); }); + // If no dog is found with that ID, return 404 error if (!dog) { res.status(404).json({ error: "Dog breed not found" }); } else { - res.json(dog); + res.json(dog); // Return the found dog } }); +// Route for getting all dogs, with optional category filter app.get("/dogs", (req, res) => { - const category = req.query.category; + const category = req.query.category; // Get category from query parameter if exists + // If category parameter exists, filter dogs by category, otherwise return all dogs const filteredDogs = category ? dogs.filter(dog => dog.category === category) : dogs; res.json(filteredDogs); }); +// Root route - returns API documentation app.get("/", (req, res) => { - const endpoints = listEndpoints(app); + const endpoints = listEndpoints(app); // Generate list of all available endpoints res.json({ - description: "Dog Breeds API - Information about different dog breeds", - endpoints: endpoints + description: "Dog Breeds API - Access information about different dog breeds", + endpoints: endpoints // Shows all available API endpoints }); }); +// Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); }); \ No newline at end of file From 160901e02b1c43a17bae8a5fa9ef563b64ed4ac5 Mon Sep 17 00:00:00 2001 From: Jenny Date: Sun, 8 Dec 2024 15:59:53 +0100 Subject: [PATCH 4/5] added deploy link --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5241826b3..f76351a7a 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ # Project Express API -Replace this readme with your own information about your project. - -Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. +In our first step into backend, the assigment was to create an API using Express. The API should have at least a couple of RESTful endpoints which return either an array of data or a single item. ## The problem -Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? +I created an API about dog breeds using Express.js and Node.js. The main challenge was getting the file paths right and figuring out how to filter the data by categories. I learned a lot about working with JSON data and API endpoints. +If I had more time, I would add more filtering options and create a simple frontend to display the data in a user-friendly way. ## View it live -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. +https://project-express-api-y1pr.onrender.com/ + +GET "/" - Shows API documentation +GET "/dogs" - Returns all dogs (can be filtered by category using ?category=...) +GET "/dogs/:id" - Returns a specific dog by ID \ No newline at end of file From 639e1cdc340c40378bbbade701015c40e7455e21 Mon Sep 17 00:00:00 2001 From: Jenny Date: Mon, 9 Dec 2024 21:01:16 +0100 Subject: [PATCH 5/5] added more filters --- server.js | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/server.js b/server.js index e691b4d23..1ca482022 100644 --- a/server.js +++ b/server.js @@ -30,13 +30,34 @@ app.get("/dogs/:id", (req, res) => { } }); -// Route for getting all dogs, with optional category filter +// Route for getting all dogs, with optional filters app.get("/dogs", (req, res) => { - const category = req.query.category; // Get category from query parameter if exists - // If category parameter exists, filter dogs by category, otherwise return all dogs - const filteredDogs = category - ? dogs.filter(dog => dog.category === category) - : dogs; + const { category, size, origin, familyFriendly } = req.query; // Get all filters from query parameters + console.log("Query parameters:", req.query); + + let filteredDogs = [...dogs]; + + if (category) { + filteredDogs = filteredDogs.filter(dog => + dog.category.toLowerCase() === category.toLowerCase() + ); + } + if (size) { + filteredDogs = filteredDogs.filter(dog => + dog.size.toLowerCase() === size.toLowerCase() + ); + } + if (origin) { + filteredDogs = filteredDogs.filter(dog => + dog.origin.toLowerCase() === origin.toLowerCase() + ); + } + if (familyFriendly) { + filteredDogs = filteredDogs.filter(dog => + dog.familyFriendly.toLowerCase() === familyFriendly.toLowerCase() + ); + } + res.json(filteredDogs); });