├── sample.env ├── .gitignore ├── .gitpod.yml ├── README.md ├── package.json ├── views └── index.html ├── myApp.js └── server.js /sample.env: -------------------------------------------------------------------------------- 1 | MONGO_URI= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: gitpod/workspace-node-lts 2 | 3 | ports: 4 | - port: 3000 5 | onOpen: open-preview 6 | visibility: public 7 | 8 | tasks: 9 | - init: npm install 10 | command: npm run start 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MongoDB and Mongoose Challenges 2 | 3 | This is the boilerplate for the MongoDB and Mongoose lessons. Instructions for completing these lessons start at https://www.freecodecamp.org/learn/apis-and-microservices/mongodb-and-mongoose/ 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fcc-mongo-mongoose-challenges", 3 | "version": "0.0.1", 4 | "description": "A boilerplate project", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "node server.js" 8 | }, 9 | "dependencies": { 10 | "body-parser": "^1.15.2", 11 | "dotenv": "^8.2.0", 12 | "express": "^4.12.4", 13 | "mongoose": "^5.11.15" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/freeCodeCamp/boilerplate-mongomongoose.git" 18 | }, 19 | "keywords": [ 20 | "node", 21 | "mongoose", 22 | "express" 23 | ], 24 | "license": "MIT" 25 | } 26 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | MongoDB & Mongoose | freeCodeCamp.org 14 | 19 | 20 | 21 | 22 | 30 | 31 | 32 | 33 |

MongoDB & Mongoose

34 | 35 | 36 | -------------------------------------------------------------------------------- /myApp.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | 3 | 4 | let Person; 5 | 6 | const createAndSavePerson = (done) => { 7 | done(null /*, data*/); 8 | }; 9 | 10 | const createManyPeople = (arrayOfPeople, done) => { 11 | done(null /*, data*/); 12 | }; 13 | 14 | const findPeopleByName = (personName, done) => { 15 | done(null /*, data*/); 16 | }; 17 | 18 | const findOneByFood = (food, done) => { 19 | done(null /*, data*/); 20 | }; 21 | 22 | const findPersonById = (personId, done) => { 23 | done(null /*, data*/); 24 | }; 25 | 26 | const findEditThenSave = (personId, done) => { 27 | const foodToAdd = "hamburger"; 28 | 29 | done(null /*, data*/); 30 | }; 31 | 32 | const findAndUpdate = (personName, done) => { 33 | const ageToSet = 20; 34 | 35 | done(null /*, data*/); 36 | }; 37 | 38 | const removeById = (personId, done) => { 39 | done(null /*, data*/); 40 | }; 41 | 42 | const removeManyPeople = (done) => { 43 | const nameToRemove = "Mary"; 44 | 45 | done(null /*, data*/); 46 | }; 47 | 48 | const queryChain = (done) => { 49 | const foodToSearch = "burrito"; 50 | 51 | done(null /*, data*/); 52 | }; 53 | 54 | /** **Well Done !!** 55 | /* You completed these challenges, let's go celebrate ! 56 | */ 57 | 58 | //----- **DO NOT EDIT BELOW THIS LINE** ---------------------------------- 59 | 60 | exports.PersonModel = Person; 61 | exports.createAndSavePerson = createAndSavePerson; 62 | exports.findPeopleByName = findPeopleByName; 63 | exports.findOneByFood = findOneByFood; 64 | exports.findPersonById = findPersonById; 65 | exports.findEditThenSave = findEditThenSave; 66 | exports.findAndUpdate = findAndUpdate; 67 | exports.createManyPeople = createManyPeople; 68 | exports.removeById = removeById; 69 | exports.removeManyPeople = removeManyPeople; 70 | exports.queryChain = queryChain; 71 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /******************************************** 2 | * DO NOT EDIT THIS FILE 3 | * the verification process may break 4 | *******************************************/ 5 | 6 | const express = require("express"); 7 | const app = express(); 8 | let mongoose; 9 | try { 10 | mongoose = require("mongoose"); 11 | } catch (e) { 12 | console.log(e); 13 | } 14 | const fs = require("fs"); 15 | const path = require("path"); 16 | const bodyParser = require("body-parser"); 17 | const router = express.Router(); 18 | 19 | const enableCORS = function (req, res, next) { 20 | if (!process.env.DISABLE_XORIGIN) { 21 | const allowedOrigins = ["https://www.freecodecamp.org"]; 22 | const origin = req.headers.origin; 23 | if (!process.env.XORIGIN_RESTRICT || allowedOrigins.indexOf(origin) > -1) { 24 | console.log(req.method); 25 | res.set({ 26 | "Access-Control-Allow-Origin": origin, 27 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 28 | "Access-Control-Allow-Headers": 29 | "Origin, X-Requested-With, Content-Type, Accept", 30 | }); 31 | } 32 | } 33 | next(); 34 | }; 35 | 36 | // global setting for safety timeouts to handle possible 37 | // wrong callbacks that will never be called 38 | const TIMEOUT = 10000; 39 | 40 | app.use(bodyParser.urlencoded({ extended: "false" })); 41 | app.use(bodyParser.json()); 42 | 43 | app.get("/", function (req, res) { 44 | res.sendFile(path.join(__dirname, "views", "index.html")); 45 | }); 46 | 47 | router.get("/file/*?", function (req, res, next) { 48 | if (req.params[0] === ".env") { 49 | return next({ status: 401, message: "ACCESS DENIED" }); 50 | } 51 | fs.readFile(path.join(__dirname, req.params[0]), function (err, data) { 52 | if (err) { 53 | return next(err); 54 | } 55 | res.type("txt").send(data.toString()); 56 | }); 57 | }); 58 | 59 | router.get("/is-mongoose-ok", function (req, res) { 60 | if (mongoose) { 61 | res.json({ isMongooseOk: !!mongoose.connection.readyState }); 62 | } else { 63 | res.json({ isMongooseOk: false }); 64 | } 65 | }); 66 | 67 | const Person = require("./myApp.js").PersonModel; 68 | 69 | router.use(function (req, res, next) { 70 | if (req.method !== "OPTIONS" && Person.modelName !== "Person") { 71 | return next({ message: "Person Model is not correct" }); 72 | } 73 | next(); 74 | }); 75 | 76 | router.post("/mongoose-model", function (req, res, next) { 77 | // try to create a new instance based on their model 78 | // verify it's correctly defined in some way 79 | let p; 80 | p = new Person(req.body); 81 | res.json(p); 82 | }); 83 | 84 | const createPerson = require("./myApp.js").createAndSavePerson; 85 | router.get("/create-and-save-person", function (req, res, next) { 86 | // in case of incorrect function use wait timeout then respond 87 | let t = setTimeout(() => { 88 | next({ message: "timeout" }); 89 | }, TIMEOUT); 90 | createPerson(function (err, data) { 91 | clearTimeout(t); 92 | if (err) { 93 | return next(err); 94 | } 95 | if (!data) { 96 | console.log("Missing `done()` argument"); 97 | return next({ message: "Missing callback argument" }); 98 | } 99 | Person.findById(data._id, function (err, pers) { 100 | if (err) { 101 | return next(err); 102 | } 103 | res.json(pers); 104 | pers.remove(); 105 | }); 106 | }); 107 | }); 108 | 109 | const createPeople = require("./myApp.js").createManyPeople; 110 | router.post("/create-many-people", function (req, res, next) { 111 | Person.remove({}, function (err) { 112 | if (err) { 113 | return next(err); 114 | } 115 | // in case of incorrect function use wait timeout then respond 116 | let t = setTimeout(() => { 117 | next({ message: "timeout" }); 118 | }, TIMEOUT); 119 | createPeople(req.body, function (err, data) { 120 | clearTimeout(t); 121 | if (err) { 122 | return next(err); 123 | } 124 | if (!data) { 125 | console.log("Missing `done()` argument"); 126 | return next({ message: "Missing callback argument" }); 127 | } 128 | Person.find({}, function (err, pers) { 129 | if (err) { 130 | return next(err); 131 | } 132 | res.json(pers); 133 | Person.remove().exec(); 134 | }); 135 | }); 136 | }); 137 | }); 138 | 139 | const findByName = require("./myApp.js").findPeopleByName; 140 | router.post("/find-all-by-name", function (req, res, next) { 141 | let t = setTimeout(() => { 142 | next({ message: "timeout" }); 143 | }, TIMEOUT); 144 | Person.create(req.body, function (err, pers) { 145 | if (err) { 146 | return next(err); 147 | } 148 | findByName(pers.name, function (err, data) { 149 | clearTimeout(t); 150 | if (err) { 151 | return next(err); 152 | } 153 | if (!data) { 154 | console.log("Missing `done()` argument"); 155 | return next({ message: "Missing callback argument" }); 156 | } 157 | res.json(data); 158 | Person.remove().exec(); 159 | }); 160 | }); 161 | }); 162 | 163 | const findByFood = require("./myApp.js").findOneByFood; 164 | router.post("/find-one-by-food", function (req, res, next) { 165 | let t = setTimeout(() => { 166 | next({ message: "timeout" }); 167 | }, TIMEOUT); 168 | let p = new Person(req.body); 169 | p.save(function (err, pers) { 170 | if (err) { 171 | return next(err); 172 | } 173 | findByFood(pers.favoriteFoods[0], function (err, data) { 174 | clearTimeout(t); 175 | if (err) { 176 | return next(err); 177 | } 178 | if (!data) { 179 | console.log("Missing `done()` argument"); 180 | return next({ message: "Missing callback argument" }); 181 | } 182 | res.json(data); 183 | p.remove(); 184 | }); 185 | }); 186 | }); 187 | 188 | const findById = require("./myApp.js").findPersonById; 189 | router.get("/find-by-id", function (req, res, next) { 190 | let t = setTimeout(() => { 191 | next({ message: "timeout" }); 192 | }, TIMEOUT); 193 | let p = new Person({ name: "test", age: 0, favoriteFoods: ["none"] }); 194 | p.save(function (err, pers) { 195 | if (err) { 196 | return next(err); 197 | } 198 | findById(pers._id, function (err, data) { 199 | clearTimeout(t); 200 | if (err) { 201 | return next(err); 202 | } 203 | if (!data) { 204 | console.log("Missing `done()` argument"); 205 | return next({ message: "Missing callback argument" }); 206 | } 207 | res.json(data); 208 | p.remove(); 209 | }); 210 | }); 211 | }); 212 | 213 | const findEdit = require("./myApp.js").findEditThenSave; 214 | router.post("/find-edit-save", function (req, res, next) { 215 | let t = setTimeout(() => { 216 | next({ message: "timeout" }); 217 | }, TIMEOUT); 218 | let p = new Person(req.body); 219 | p.save(function (err, pers) { 220 | if (err) { 221 | return next(err); 222 | } 223 | try { 224 | findEdit(pers._id, function (err, data) { 225 | clearTimeout(t); 226 | if (err) { 227 | return next(err); 228 | } 229 | if (!data) { 230 | console.log("Missing `done()` argument"); 231 | return next({ message: "Missing callback argument" }); 232 | } 233 | res.json(data); 234 | p.remove(); 235 | }); 236 | } catch (e) { 237 | console.log(e); 238 | return next(e); 239 | } 240 | }); 241 | }); 242 | 243 | const update = require("./myApp.js").findAndUpdate; 244 | router.post("/find-one-update", function (req, res, next) { 245 | let t = setTimeout(() => { 246 | next({ message: "timeout" }); 247 | }, TIMEOUT); 248 | let p = new Person(req.body); 249 | p.save(function (err, pers) { 250 | if (err) { 251 | return next(err); 252 | } 253 | try { 254 | update(pers.name, function (err, data) { 255 | clearTimeout(t); 256 | if (err) { 257 | return next(err); 258 | } 259 | if (!data) { 260 | console.log("Missing `done()` argument"); 261 | return next({ message: "Missing callback argument" }); 262 | } 263 | res.json(data); 264 | p.remove(); 265 | }); 266 | } catch (e) { 267 | console.log(e); 268 | return next(e); 269 | } 270 | }); 271 | }); 272 | 273 | const removeOne = require("./myApp.js").removeById; 274 | router.post("/remove-one-person", function (req, res, next) { 275 | Person.remove({}, function (err) { 276 | if (err) { 277 | return next(err); 278 | } 279 | let t = setTimeout(() => { 280 | next({ message: "timeout" }); 281 | }, TIMEOUT); 282 | let p = new Person(req.body); 283 | p.save(function (err, pers) { 284 | if (err) { 285 | return next(err); 286 | } 287 | try { 288 | removeOne(pers._id, function (err, data) { 289 | clearTimeout(t); 290 | if (err) { 291 | return next(err); 292 | } 293 | if (!data) { 294 | console.log("Missing `done()` argument"); 295 | return next({ message: "Missing callback argument" }); 296 | } 297 | console.log(data); 298 | Person.count(function (err, cnt) { 299 | if (err) { 300 | return next(err); 301 | } 302 | data = data.toObject(); 303 | data.count = cnt; 304 | console.log(data); 305 | res.json(data); 306 | }); 307 | }); 308 | } catch (e) { 309 | console.log(e); 310 | return next(e); 311 | } 312 | }); 313 | }); 314 | }); 315 | 316 | const removeMany = require("./myApp.js").removeManyPeople; 317 | router.post("/remove-many-people", function (req, res, next) { 318 | Person.remove({}, function (err) { 319 | if (err) { 320 | return next(err); 321 | } 322 | let t = setTimeout(() => { 323 | next({ message: "timeout" }); 324 | }, TIMEOUT); 325 | Person.create(req.body, function (err, pers) { 326 | if (err) { 327 | return next(err); 328 | } 329 | try { 330 | removeMany(function (err, data) { 331 | clearTimeout(t); 332 | if (err) { 333 | return next(err); 334 | } 335 | if (!data) { 336 | console.log("Missing `done()` argument"); 337 | return next({ message: "Missing callback argument" }); 338 | } 339 | Person.count(function (err, cnt) { 340 | if (err) { 341 | return next(err); 342 | } 343 | if (data.ok === undefined) { 344 | // for mongoose v4 345 | try { 346 | data = JSON.parse(data); 347 | } catch (e) { 348 | console.log(e); 349 | return next(e); 350 | } 351 | } 352 | res.json({ 353 | n: data.n, 354 | count: cnt, 355 | ok: data.ok, 356 | }); 357 | }); 358 | }); 359 | } catch (e) { 360 | console.log(e); 361 | return next(e); 362 | } 363 | }); 364 | }); 365 | }); 366 | 367 | const chain = require("./myApp.js").queryChain; 368 | router.post("/query-tools", function (req, res, next) { 369 | let t = setTimeout(() => { 370 | next({ message: "timeout" }); 371 | }, TIMEOUT); 372 | Person.remove({}, function (err) { 373 | if (err) { 374 | return next(err); 375 | } 376 | Person.create(req.body, function (err, pers) { 377 | if (err) { 378 | return next(err); 379 | } 380 | try { 381 | chain(function (err, data) { 382 | clearTimeout(t); 383 | if (err) { 384 | return next(err); 385 | } 386 | if (!data) { 387 | console.log("Missing `done()` argument"); 388 | return next({ message: "Missing callback argument" }); 389 | } 390 | res.json(data); 391 | }); 392 | } catch (e) { 393 | console.log(e); 394 | return next(e); 395 | } 396 | }); 397 | }); 398 | }); 399 | 400 | app.use("/_api", enableCORS, router); 401 | 402 | // Error handler 403 | app.use(function (err, req, res, next) { 404 | if (err) { 405 | res 406 | .status(err.status || 500) 407 | .type("txt") 408 | .send(err.message || "SERVER ERROR"); 409 | } 410 | }); 411 | 412 | // Unmatched routes handler 413 | app.use(function (req, res) { 414 | if (req.method.toLowerCase() === "options") { 415 | res.end(); 416 | } else { 417 | res.status(404).type("txt").send("Not Found"); 418 | } 419 | }); 420 | 421 | const listener = app.listen(process.env.PORT || 3000, function () { 422 | console.log("Your app is listening on port " + listener.address().port); 423 | }); 424 | 425 | /******************************************** 426 | * DO NOT EDIT THIS FILE 427 | * the verification process may break 428 | *******************************************/ 429 | --------------------------------------------------------------------------------