diff --git a/README.md b/README.md index 35019cd8a..0bcddf256 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,17 @@ # Project Mongo 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. +The project demonstrates working with MongoDB/Mongoose, implementing RESTful principles, and building a functional API with filtering capabilities. ## 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 set up a MongoDB database with environment variables for secure access and added database seeding to populate MongoDB with The Sims npcs data. Had to troubleshoot MongoDB connection issues but eventually got it to work. +I created API endpoints to: +Get all NPCs with filtering options +Find specific NPCs by ID +View API documentation + +I also implemented filtering by game version, life stage, and category ## 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-mongo-api-npcs.onrender.com/ diff --git a/data/sims-npcs.json b/data/sims-npcs.json new file mode 100644 index 000000000..120344b8f --- /dev/null +++ b/data/sims-npcs.json @@ -0,0 +1,565 @@ +{ + "npcs": [ + { + "id": "TWN001", + "name": "Don Lothario", + "gameVersion": "The Sims 2", + "category": "Townie", + "occupation": "Doctor", + "lifeStage": "Adult", + "appearanceMethod": "Pleasantview Resident", + "traits": ["Romantic", "Flirty"], + "notableFeature": "Known for romancing multiple Sims" + }, + { + "id": "TWN002", + "name": "Mortimer Goth", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Author", + "lifeStage": "Adult", + "appearanceMethod": "Willow Creek Resident", + "traits": ["Genius", "Sophisticated"], + "notableFeature": "Wealthy widower of Bella Goth" + }, + { + "id": "TWN003", + "name": "Agnes Crumplebottom", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Flower Shop Owner", + "lifeStage": "Adult", + "appearanceMethod": "Henford-on-Bagley Resident", + "traits": ["Proper", "Traditional"], + "notableFeature": "Younger version of Mrs. Crumplebottom" + }, + { + "id": "TWN004", + "name": "Bob Pancakes", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Unemployed", + "lifeStage": "Adult", + "appearanceMethod": "Willow Creek Resident", + "traits": ["Gloomy", "Lazy"], + "notableFeature": "Unhappily married to Eliza Pancakes" + }, + { + "id": "TWN005", + "name": "Nina Caliente", + "gameVersion": "The Sims 2", + "category": "Townie", + "occupation": "Entertainment", + "lifeStage": "Adult", + "appearanceMethod": "Pleasantview Resident", + "traits": ["Outgoing", "Hot-Headed"], + "notableFeature": "One of the Caliente twins" + }, + { + "id": "TWN006", + "name": "Johnny Smith", + "gameVersion": "The Sims 2", + "category": "Townie", + "occupation": "Student", + "lifeStage": "Teen", + "appearanceMethod": "Strangetown Resident", + "traits": ["Genius", "Alien Heritage"], + "notableFeature": "Half-alien teen living in Strangetown" + }, + { + "id": "TWN007", + "name": "Malcolm Landgraab", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Business", + "lifeStage": "Adult", + "appearanceMethod": "Oasis Springs Resident", + "traits": ["Snob", "Materialistic"], + "notableFeature": "From the wealthy Landgraab family" + }, + { + "id": "TWN008", + "name": "Dustin Broke", + "gameVersion": "The Sims 2", + "category": "Townie", + "occupation": "Part-time Worker", + "lifeStage": "Teen", + "appearanceMethod": "Pleasantview Resident", + "traits": ["Family-Oriented", "Rebellious"], + "notableFeature": "From the struggling Broke family" + }, + { + "id": "TWN009", + "name": "Cassandra Goth", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Scientist", + "lifeStage": "Young Adult", + "appearanceMethod": "Willow Creek Resident", + "traits": ["Genius", "Bookworm"], + "notableFeature": "Daughter of Mortimer and Bella Goth" + }, + { + "id": "TWN010", + "name": "Jennifer Burb", + "gameVersion": "The Sims 2", + "category": "Townie", + "occupation": "Business", + "lifeStage": "Adult", + "appearanceMethod": "Pleasantview Resident", + "traits": ["Family-Oriented", "Ambitious"], + "notableFeature": "Sister of Betty Pleasant" + }, + { + "id": "TWN011", + "name": "Geoffrey Landgraab", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Business Executive", + "lifeStage": "Adult", + "appearanceMethod": "Oasis Springs Resident", + "traits": ["Business-Savvy", "Proper"], + "notableFeature": "Married to Nancy Landgraab" + }, + { + "id": "TWN012", + "name": "Liberty Lee", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Tech Guru", + "lifeStage": "Young Adult", + "appearanceMethod": "Willow Creek Resident", + "traits": ["Geek", "Creative"], + "notableFeature": "Lives with Travis Scott" + }, + { + "id": "TWN013", + "name": "Brandi Broke", + "gameVersion": "The Sims 2", + "category": "Townie", + "occupation": "Unemployed", + "lifeStage": "Adult", + "appearanceMethod": "Pleasantview Resident", + "traits": ["Family-Oriented", "Struggling"], + "notableFeature": "Pregnant widow with two sons" + }, + { + "id": "TWN014", + "name": "Judith Ward", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Actress", + "lifeStage": "Adult", + "appearanceMethod": "Del Sol Valley Resident", + "traits": ["Self-Absorbed", "Famous"], + "notableFeature": "Famous actress living in Del Sol Valley" + }, + { + "id": "TWN015", + "name": "Skip Broke", + "gameVersion": "The Sims 3", + "category": "Townie", + "occupation": "Unemployed", + "lifeStage": "Young Adult", + "appearanceMethod": "Sunset Valley Resident", + "traits": ["Good", "Unlucky"], + "notableFeature": "Ancestor of the Broke family" + }, + { + "id": "TWN016", + "name": "Summer Holiday", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Entertainer", + "lifeStage": "Young Adult", + "appearanceMethod": "Willow Creek Resident", + "traits": ["Active", "Cheerful"], + "notableFeature": "Fitness enthusiast" + }, + { + "id": "TWN017", + "name": "Michael Bachelor", + "gameVersion": "The Sims 3", + "category": "Townie", + "occupation": "Business", + "lifeStage": "Young Adult", + "appearanceMethod": "Sunset Valley Resident", + "traits": ["Good", "Charismatic"], + "notableFeature": "Bella Goth's brother" + }, + { + "id": "TWN018", + "name": "Eliza Pancakes", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Chef", + "lifeStage": "Adult", + "appearanceMethod": "Willow Creek Resident", + "traits": ["Perfectionist", "Ambitious"], + "notableFeature": "Married to Bob Pancakes" + }, + { + "id": "TWN019", + "name": "Dina Caliente", + "gameVersion": "The Sims 2", + "category": "Townie", + "occupation": "Unemployed", + "lifeStage": "Adult", + "appearanceMethod": "Pleasantview Resident", + "traits": ["Romantic", "Ambitious"], + "notableFeature": "One of the Caliente twins" + }, + { + "id": "TWN020", + "name": "Travis Scott", + "gameVersion": "The Sims 4", + "category": "Townie", + "occupation": "Food Critic", + "lifeStage": "Young Adult", + "appearanceMethod": "Willow Creek Resident", + "traits": ["Foodie", "Creative"], + "notableFeature": "Lives with Liberty Lee" + }, + { + "id": "TRA001", + "name": "Tragic Clown", + "gameVersion": "The Sims 1", + "category": "Service NPC", + "occupation": "Entertainment", + "lifeStage": "Adult", + "appearanceMethod": "Painting Interaction", + "traits": ["Depressed", "Entertaining"], + "notableFeature": "Appears when Sims are sad and makes them sadder" + }, + { + "id": "BEL001", + "name": "Bella Goth", + "gameVersion": "The Sims 2", + "category": "Pre-made Sim", + "occupation": "Missing Person", + "lifeStage": "Adult", + "appearanceMethod": "Strangetown Resident", + "traits": ["Mysterious", "Elegant"], + "notableFeature": "Central character in The Sims lore" + }, + { + "id": "CRU001", + "name": "Mrs. Crumplebottom", + "gameVersion": "The Sims 3", + "category": "Special NPC", + "occupation": "Public Moral Guardian", + "lifeStage": "Elder", + "appearanceMethod": "Public Locations", + "traits": ["Proper", "Hot-Headed"], + "notableFeature": "Hits inappropriate Sims with her purse" + }, + { + "id": "GRI001", + "name": "Grim Reaper", + "gameVersion": "The Sims 4", + "category": "Service NPC", + "occupation": "Death Manager", + "lifeStage": "Immortal", + "appearanceMethod": "Death Events", + "traits": ["Gloomy", "Mysterious"], + "notableFeature": "Can be befriended and joined as household member" + }, + { + "id": "SOC001", + "name": "Social Bunny", + "gameVersion": "The Sims 2", + "category": "Imaginary NPC", + "occupation": "Comfort Character", + "lifeStage": "Not Applicable", + "appearanceMethod": "Low Social Need", + "traits": ["Friendly", "Supportive"], + "notableFeature": "Appears when Sims are extremely lonely" + }, + { + "id": "BUR001", + "name": "Burglar", + "gameVersion": "The Sims 1", + "category": "Event NPC", + "occupation": "Thief", + "lifeStage": "Adult", + "appearanceMethod": "Random Night Event", + "traits": ["Sneaky", "Kleptomaniac"], + "notableFeature": "Steals objects during night time" + }, + { + "id": "SAN001", + "name": "Santa Claus", + "gameVersion": "The Sims 3", + "category": "Special NPC", + "occupation": "Gift Giver", + "lifeStage": "Adult", + "appearanceMethod": "Winter Holiday", + "traits": ["Cheerful", "Generous"], + "notableFeature": "Delivers presents during Winterfest" + }, + { + "id": "VLA001", + "name": "Vladislaus Straud", + "gameVersion": "The Sims 4", + "category": "Special NPC", + "occupation": "Master Vampire", + "lifeStage": "Adult", + "appearanceMethod": "Forgotten Hollow", + "traits": ["Evil", "Vampire"], + "notableFeature": "Founder of Forgotten Hollow" + }, + { + "id": "PTS001", + "name": "Pizza Delivery Person", + "gameVersion": "The Sims 1", + "category": "Service NPC", + "occupation": "Food Delivery", + "lifeStage": "Young Adult", + "appearanceMethod": "Phone Order", + "traits": ["Quick", "Friendly"], + "notableFeature": "Delivers pizza when ordered" + }, + { + "id": "BON001", + "name": "Bonehilda", + "gameVersion": "The Sims 4", + "category": "Service NPC", + "occupation": "Skeleton Maid", + "lifeStage": "Undead", + "appearanceMethod": "Summoning", + "traits": ["Neat", "Helpful"], + "notableFeature": "Skeletal maid who helps with housework" + }, + { + "id": "PBA001", + "name": "Pascal Bertrand Alien", + "gameVersion": "The Sims 2", + "category": "Special NPC", + "occupation": "Alien Visitor", + "lifeStage": "Adult", + "appearanceMethod": "Telescope Use", + "traits": ["Genius", "Extraterrestrial"], + "notableFeature": "Abducts Sims using telescope" + }, + { + "id": "SAS001", + "name": "Servo", + "gameVersion": "The Sims 3", + "category": "Buildable NPC", + "occupation": "Robot Assistant", + "lifeStage": "Not Applicable", + "appearanceMethod": "Building", + "traits": ["Artificial", "Helpful"], + "notableFeature": "Can be built with high robotics skill" + }, + { + "id": "MAI001", + "name": "Mailman", + "gameVersion": "The Sims 1", + "category": "Service NPC", + "occupation": "Mail Delivery", + "lifeStage": "Adult", + "appearanceMethod": "Daily Service", + "traits": ["Punctual", "Professional"], + "notableFeature": "Delivers mail daily" + }, + { + "id": "NIN001", + "name": "Ninja", + "gameVersion": "The Sims 3", + "category": "Special NPC", + "occupation": "Martial Artist", + "lifeStage": "Adult", + "appearanceMethod": "Dojo Training", + "traits": ["Athletic", "Disciplined"], + "notableFeature": "Appears at martial arts training grounds" + }, + { + "id": "REP001", + "name": "Repairman", + "gameVersion": "The Sims 1", + "category": "Service NPC", + "occupation": "Repair Service", + "lifeStage": "Adult", + "appearanceMethod": "Phone Call", + "traits": ["Handy", "Professional"], + "notableFeature": "Fixes broken objects" + }, + { + "id": "GYP001", + "name": "Gypsy Matchmaker", + "gameVersion": "The Sims 2", + "category": "Service NPC", + "occupation": "Matchmaker", + "lifeStage": "Adult", + "appearanceMethod": "Phone Call", + "traits": ["Romantic", "Mysterious"], + "notableFeature": "Creates love potions and arranges dates" + }, + { + "id": "FAI001", + "name": "Garden Fairy", + "gameVersion": "The Sims 3", + "category": "Magical NPC", + "occupation": "Garden Helper", + "lifeStage": "Immortal", + "appearanceMethod": "Perfect Garden", + "traits": ["Green Thumb", "Cheerful"], + "notableFeature": "Helps maintain perfect gardens" + }, + { + "id": "MAG001", + "name": "Magical Sage", + "gameVersion": "The Sims 4", + "category": "Special NPC", + "occupation": "Magic Teacher", + "lifeStage": "Adult", + "appearanceMethod": "Magic Realm", + "traits": ["Wise", "Magical"], + "notableFeature": "Teaches magic to other Sims" + }, + { + "id": "SLN001", + "name": "Salesman", + "gameVersion": "The Sims 1", + "category": "Event NPC", + "occupation": "Door-to-door Sales", + "lifeStage": "Adult", + "appearanceMethod": "Random Event", + "traits": ["Charismatic", "Persistent"], + "notableFeature": "Tries to sell expensive items" + }, + { + "id": "MER001", + "name": "Mermaid Queen", + "gameVersion": "The Sims 4", + "category": "Special NPC", + "occupation": "Ocean Ruler", + "lifeStage": "Adult", + "appearanceMethod": "Ocean Swimming", + "traits": ["Aquatic", "Charismatic"], + "notableFeature": "Rules over merfolk community" + }, + { + "id": "PLS001", + "name": "Pleasant Twins", + "gameVersion": "The Sims 2", + "category": "Pre-made Sim", + "occupation": "Students", + "lifeStage": "Teen", + "appearanceMethod": "Pleasantview", + "traits": ["Family-Oriented", "Dramatic"], + "notableFeature": "Part of the Pleasant family storyline" + }, + { + "id": "UNI001", + "name": "University Mascot", + "gameVersion": "The Sims 3", + "category": "Special NPC", + "occupation": "Mascot", + "lifeStage": "Young Adult", + "appearanceMethod": "University World", + "traits": ["Outgoing", "Energetic"], + "notableFeature": "Raises university spirit" + }, + { + "id": "SNB001", + "name": "Snowman", + "gameVersion": "The Sims 4", + "category": "Buildable NPC", + "occupation": "Winter Decoration", + "lifeStage": "Not Applicable", + "appearanceMethod": "Winter Building", + "traits": ["Cool", "Friendly"], + "notableFeature": "Comes to life in winter" + }, + { + "id": "SCA001", + "name": "Scarecrow", + "gameVersion": "The Sims 3", + "category": "Buildable NPC", + "occupation": "Garden Guardian", + "lifeStage": "Not Applicable", + "appearanceMethod": "Garden Building", + "traits": ["Protective", "Steady"], + "notableFeature": "Protects gardens from birds" + }, + { + "id": "GEN001", + "name": "Genie", + "gameVersion": "The Sims 2", + "category": "Magical NPC", + "occupation": "Wish Granter", + "lifeStage": "Immortal", + "appearanceMethod": "Lamp Rubbing", + "traits": ["Magical", "Wish Granter"], + "notableFeature": "Grants wishes to Sims" + }, + { + "id": "MAD001", + "name": "Mad Scientist", + "gameVersion": "The Sims 3", + "category": "Career NPC", + "occupation": "Scientist", + "lifeStage": "Adult", + "appearanceMethod": "Science Career", + "traits": ["Genius", "Eccentric"], + "notableFeature": "Creates unusual experiments" + }, + { + "id": "BEA001", + "name": "Bella Bachelor", + "gameVersion": "The Sims 3", + "category": "Pre-made Sim", + "occupation": "Student", + "lifeStage": "Teen", + "appearanceMethod": "Sunset Valley", + "traits": ["Artistic", "Romantic"], + "notableFeature": "Young version of Bella Goth" + }, + { + "id": "AGE001", + "name": "Age Transition Helper", + "gameVersion": "The Sims 4", + "category": "Service NPC", + "occupation": "Birthday Assistant", + "lifeStage": "Adult", + "appearanceMethod": "Birthday Events", + "traits": ["Helpful", "Cheerful"], + "notableFeature": "Helps with birthday transitions" + }, + { + "id": "TOW001", + "name": "Tow Truck Driver", + "gameVersion": "The Sims 2", + "category": "Service NPC", + "occupation": "Vehicle Recovery", + "lifeStage": "Adult", + "appearanceMethod": "Car Breakdown", + "traits": ["Helpful", "Mechanical"], + "notableFeature": "Recovers broken-down cars" + }, + { + "id": "GOB001", + "name": "Goblin King", + "gameVersion": "The Sims 4", + "category": "Special NPC", + "occupation": "Underground Ruler", + "lifeStage": "Immortal", + "appearanceMethod": "Underground Areas", + "traits": ["Mischievous", "Royal"], + "notableFeature": "Rules over underground kingdom" + }, + { + "id": "NEW001", + "name": "Newspaper Delivery", + "gameVersion": "The Sims 1", + "category": "Service NPC", + "occupation": "Paper Delivery", + "lifeStage": "Teen", + "appearanceMethod": "Daily Service", + "traits": ["Punctual", "Reliable"], + "notableFeature": "Delivers daily newspaper" + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 6830a48aa..33f4d53f9 100644 --- a/package.json +++ b/package.json @@ -4,17 +4,22 @@ "description": "Starter project to get up and running with express quickly", "scripts": { "start": "babel-node server.js", - "dev": "nodemon server.js --exec babel-node" + "dev": "nodemon server.js --exec babel-node", + "build": "npm install" }, "author": "", "license": "ISC", "dependencies": { - "@babel/core": "^7.17.9", - "@babel/node": "^7.16.8", - "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", - "express": "^4.17.3", - "mongoose": "^8.0.0", + "dotenv": "^16.4.7", + "express": "^4.21.2", + "express-list-endpoints": "^7.1.1", + "mongoose": "^8.8.4", "nodemon": "^3.0.1" + }, + "devDependencies": { + "@babel/core": "^7.26.0", + "@babel/node": "^7.26.0", + "@babel/preset-env": "^7.26.0" } } diff --git a/server.js b/server.js index 647e7b144..0eb1df0d5 100644 --- a/server.js +++ b/server.js @@ -1,35 +1,142 @@ import express from "express"; import cors from "cors"; import mongoose from "mongoose"; +import simsData from "./data/sims-npcs.json"; +import listEndpoints from "express-list-endpoints"; +import dotenv from 'dotenv'; -// 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"; +// Configure dotenv to use .env file +dotenv.config(); + +// Use environment variable for MongoDB connection +const mongoUrl = process.env.MONGO_URL; + +// Connect to MongoDB with some basic error handling +mongoose.connect(mongoUrl) + .then(() => console.log('Connected to MongoDB')) + .catch((err) => console.error('Could not connect to MongoDB', err)); -const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo"; -mongoose.connect(mongoUrl); mongoose.Promise = Promise; -// 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 port = process.env.PORT || 3000; const app = express(); -// Add middlewares to enable cors and json body parsing app.use(cors()); app.use(express.json()); -// Start defining your routes here +// Define the NPC Schema +const Npc = mongoose.model('Npc', { + id: String, + name: String, + gameVersion: String, + category: String, + occupation: String, + lifeStage: String, + appearanceMethod: String, + traits: [String], + notableFeature: String +}); + +// Seed database +if (process.env.RESET_DB) { + const seedDatabase = async () => { + try { + await Npc.deleteMany({}); + await Promise.all(simsData.npcs.map(npcData => { + const npc = new Npc(npcData); + return npc.save(); + })); + console.log("Database seeded successfully!"); + } catch (error) { + console.error("Error seeding database:", error); + } + }; + seedDatabase(); +} + +// API Documentation endpoint app.get("/", (req, res) => { - res.send("Hello Technigo!"); + const documentation = { + Welcome: "Welcome to the Sims NPCs API!", + Endpoints: listEndpoints(app).map((endpoint) => { + return { + path: endpoint.path, + methods: endpoint.methods, + middlewares: endpoint.middlewares, + } + }), + QueryParameters: { + gameVersion: "Filter NPCs by game version (e.g., '4')", + lifeStage: "Filter NPCs by life stage", + category: "Filter NPCs by category", + sorted: "Sort NPCs by name (true/false)" + } + } + res.json(documentation) +}); + +// Get all NPCs with query parameters +app.get("/npcs", async (req, res) => { + const { sorted, gameVersion, lifeStage, category } = req.query; + + try { + // Build query object + const query = {}; + + if (gameVersion) { + query.gameVersion = { $regex: `The Sims ${gameVersion}`, $options: "i" }; + } + + if (lifeStage) { + query.lifeStage = { $regex: lifeStage, $options: "i" }; + } + + if (category) { + query.category = { $regex: category, $options: "i" }; + } + + // Execute query + let npcsQuery = Npc.find(query); + + // Add sorting if requested + if (sorted === 'true') { + npcsQuery = npcsQuery.sort({ name: 1 }); + } + + const npcs = await npcsQuery; + + res.json({ + success: true, + count: npcs.length, + results: npcs + }); + } catch (error) { + res.status(500).json({ success: false, error: error.message }); + } +}); + +// Get single NPC by ID +app.get("/npcs/:id", async (req, res) => { + try { + const npc = await Npc.findOne({ id: req.params.id }); + + if (!npc) { + return res.status(404).json({ + success: false, + error: 'NPC not found' + }); + } + + res.json({ + success: true, + data: npc + }); + } catch (error) { + res.status(500).json({ success: false, error: error.message }); + } }); // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); -}); +}); \ No newline at end of file