├── .gitignore ├── 1-mongodb-crud ├── .gitignore ├── README.md ├── database-mongodb │ ├── index.js │ └── model.js ├── package-lock.json ├── package.json ├── server │ ├── controller.js │ ├── index.js │ ├── routes.js │ └── server.js ├── solution │ ├── database-mongodb │ │ ├── index.js │ │ └── model.js │ └── server │ │ ├── controller.js │ │ ├── index.js │ │ ├── routes.js │ │ └── server.js └── test │ └── database-mongodb.test.js ├── 2-mysql-crud ├── .gitignore ├── README.md ├── database-mysql-sequelize │ ├── config.example.js │ ├── index.js │ └── models.js ├── database-mysql │ ├── config.example.js │ ├── index.js │ ├── schema.sql │ └── setup.sql ├── package-lock.json ├── package.json ├── server │ ├── controller.js │ ├── controller.solution.js │ ├── index.js │ ├── routes.js │ ├── sequelize │ │ ├── controller.js │ │ └── controller.solution.js │ └── server.js └── test │ ├── database-mysql-sequelize.test.js │ └── database-mysql.test.js ├── 3-promise-me ├── .gitignore ├── README.md ├── exercises │ ├── callbackReview.js │ └── promiseReview.js ├── package-lock.json ├── package.json ├── solutions │ ├── callbackSolutions.js │ └── promiseSolutions.js └── test │ ├── callbackReview.test.js │ └── promiseReview.test.js ├── CONTRIBUTING.md ├── README.md └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /1-mongodb-crud/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /1-mongodb-crud/README.md: -------------------------------------------------------------------------------- 1 | # MongoDB CRUD 2 | 3 | You will implement the database layer of an already running Express app. Specifically, you will implement all CRUD operations (Create, Read, Update, Delete). This time you will be using MongoDB only (using the mongoose npm module). 4 | 5 | ## Getting Started 6 | 7 | Navigate to mongodb-crud in terminal 8 | Run 'npm install' in the mongodb-crud folder 9 | Run 'npm start' to start the server 10 | 11 | ## Your Task 12 | 13 | All of your work will be in the following files: 14 | 15 | - `server/controller.js` 16 | 17 | You are to implement the CRUD methods in the controller. You can run your tests to ensure your methods are working correctly. Instructions below for running tests. 18 | 19 | Pay attention to the `server/routes.js` file to see what the endpoint/s is/are for each CRUD operation. 20 | 21 | There is no front-end for this app. Use [Postman](https://www.getpostman.com/) to debug it. 22 | 23 | As an added challenge, consider refactoring your solution to make use of ES6 arrow functions and const / let variable declarations. 24 | -------------------------------------------------------------------------------- /1-mongodb-crud/database-mongodb/index.js: -------------------------------------------------------------------------------- 1 | // include mongoose in our project 2 | var mongoose = require('mongoose'); 3 | 4 | // open connection to the database on our locally running instance of MongoDB 5 | mongoose.connect('mongodb://localhost/toDoList'); 6 | 7 | var db = mongoose.connection; 8 | 9 | // get notified if we connect succesffuly or if a connection error occurs 10 | db.on( 11 | 'error', 12 | console.log.bind(console, 'Error connection to toDoList database'), 13 | ); 14 | 15 | db.once('open', () => 16 | console.log('Successful connection to toDoList database'), 17 | ); 18 | 19 | module.exports = db; 20 | -------------------------------------------------------------------------------- /1-mongodb-crud/database-mongodb/model.js: -------------------------------------------------------------------------------- 1 | // include mongoose in our project 2 | var mongoose = require('mongoose'); 3 | var db = require('./index'); 4 | 5 | // get a reference to Schema 6 | var Schema = mongoose.Schema; 7 | 8 | // define your toDoListSchema 9 | var toDoListSchema = new Schema({ 10 | name: { type: String, maxlength: 50, required: true }, 11 | }); 12 | 13 | // compile the schema into a Model 14 | var ToDoList = db.model('ToDoList', toDoListSchema); 15 | 16 | module.exports = ToDoList; 17 | -------------------------------------------------------------------------------- /1-mongodb-crud/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "full-stack-js-practice", 3 | "version": "1.0.0", 4 | "description": "Mini-exercises for practicing Full Stack JS.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon server/index.js", 8 | "test": "jest test/database-mongodb.test.js" 9 | }, 10 | "author": "hyperbolic-time-chamber", 11 | "license": "MIT", 12 | "private": true, 13 | "dependencies": { 14 | "body-parser": "^1.18.3", 15 | "express": "^4.16.3", 16 | "jest": "^25.0.0", 17 | "mongoose": "^5.7.3", 18 | "morgan": "^1.9.1", 19 | "supertest": "^3.1.0" 20 | }, 21 | "devDependencies": { 22 | "nodemon": "^1.18.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /1-mongodb-crud/server/controller.js: -------------------------------------------------------------------------------- 1 | var ToDoList = require('../database-mongodb/model'); 2 | 3 | module.exports = { 4 | /* Retrieve all documents. */ 5 | read: function(req, res) {}, 6 | 7 | /* Create one document. */ 8 | create: function(req, res) {}, 9 | 10 | /* Update one document by name. */ 11 | update: function(req, res) {}, 12 | 13 | /* Delete one document by name. */ 14 | delete: function(req, res) {}, 15 | }; 16 | -------------------------------------------------------------------------------- /1-mongodb-crud/server/index.js: -------------------------------------------------------------------------------- 1 | var { app } = require('./server'); 2 | 3 | var port = 3000; 4 | 5 | app.listen(port, function() { 6 | console.log(`Listening on port: ${port}`); 7 | }); 8 | -------------------------------------------------------------------------------- /1-mongodb-crud/server/routes.js: -------------------------------------------------------------------------------- 1 | var routes = require('express').Router(); 2 | var controller = require('./controller'); 3 | 4 | routes 5 | .route('/todolist') 6 | .get(controller.read) 7 | .post(controller.create) 8 | .put(controller.update) 9 | .delete(controller.delete); 10 | 11 | module.exports = { routes }; 12 | -------------------------------------------------------------------------------- /1-mongodb-crud/server/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var bodyParser = require('body-parser'); 3 | 4 | var { routes } = require('./routes'); 5 | 6 | var app = express(); 7 | 8 | // middleware 9 | app.use(bodyParser.json()); 10 | app.use(bodyParser.urlencoded({ extended: true })); 11 | app.use(routes); 12 | 13 | module.exports = { 14 | app, 15 | }; 16 | -------------------------------------------------------------------------------- /1-mongodb-crud/solution/database-mongodb/index.js: -------------------------------------------------------------------------------- 1 | // include mongoose in our project 2 | var mongoose = require('mongoose'); 3 | 4 | // open connection to the database on our locally running instance of MongoDB 5 | mongoose.connect('mongodb://localhost/toDoList'); 6 | 7 | var db = mongoose.connection; 8 | 9 | // get notified if we connect succesffuly or if a connection error occurs 10 | db.on( 11 | 'error', 12 | console.log.bind(console, 'Error connection to toDoList database'), 13 | ); 14 | 15 | db.once('open', function() { 16 | console.log('Successful connection to toDoList database'); 17 | }); 18 | 19 | module.exports = db; 20 | -------------------------------------------------------------------------------- /1-mongodb-crud/solution/database-mongodb/model.js: -------------------------------------------------------------------------------- 1 | // include mongoose in our project 2 | var mongoose = require('mongoose'); 3 | var db = require('./index'); 4 | 5 | // get a reference to Schema 6 | var Schema = mongoose.Schema; 7 | 8 | // define your toDoListSchema 9 | var toDoListSchema = new Schema({ 10 | name: { type: String, maxlength: 50, required: true }, 11 | }); 12 | 13 | // compile the schema into a Model 14 | var ToDoList = db.model('ToDoList', toDoListSchema); 15 | 16 | module.exports = ToDoList; 17 | -------------------------------------------------------------------------------- /1-mongodb-crud/solution/server/controller.js: -------------------------------------------------------------------------------- 1 | const ToDoList = require('../database-mongodb/model'); 2 | 3 | module.exports = { 4 | /* Retrieve all documents. */ 5 | read: function(req, res) { 6 | ToDoList.find({}).exec(function(err, result) { 7 | if (err) { 8 | res.status(400).send('Error on fetching data'); 9 | } 10 | res.status(200).send(result); 11 | }); 12 | }, 13 | 14 | /* Create one document. */ 15 | create: function(req, res) { 16 | const { name } = req.body; 17 | const toDo = new ToDoList({ name }); 18 | toDo.save(function(err, product) { 19 | if (err) { 20 | console.error(err); 21 | res.status(400).send(`Error on creating ${name}`); 22 | } else { 23 | res.status(201).send(product); 24 | } 25 | }); 26 | }, 27 | 28 | /* Update one document by name. */ 29 | update: function(req, res) { 30 | const { name, newName } = req.body; 31 | ToDoList.findOneAndUpdate( 32 | { name }, 33 | { $set: { name: newName } }, 34 | { new: true }, 35 | function(err, doc) { 36 | if (err) { 37 | console.error(err); 38 | res.status(400).send(`Error on updating ${name} to ${newName}`); 39 | } else { 40 | res.status(202).send(`${name} is updated to ${doc}`); 41 | } 42 | }, 43 | ); 44 | }, 45 | 46 | /* Delete one document by name. */ 47 | delete: function(req, res) { 48 | const { name } = req.body; 49 | ToDoList.findOneAndRemove({ name }, function(err) { 50 | if (err) { 51 | console.error(err); 52 | res.status(400).send(`Error on deleting ${name}`); 53 | } else { 54 | res.status(200).send(`${name} is deleted`); 55 | } 56 | }); 57 | }, 58 | }; 59 | -------------------------------------------------------------------------------- /1-mongodb-crud/solution/server/index.js: -------------------------------------------------------------------------------- 1 | var { app } = require('./server'); 2 | 3 | var port = 3000; 4 | 5 | app.listen(port, function() { 6 | console.log(`Listening on port: ${port}`); 7 | }); 8 | -------------------------------------------------------------------------------- /1-mongodb-crud/solution/server/routes.js: -------------------------------------------------------------------------------- 1 | var routes = require('express').Router(); 2 | var controller = require('./controller'); 3 | 4 | routes 5 | .route('/todolist') 6 | .get(controller.read) 7 | .post(controller.create) 8 | .put(controller.update) 9 | .delete(controller.delete); 10 | 11 | module.exports = { routes }; 12 | -------------------------------------------------------------------------------- /1-mongodb-crud/solution/server/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var bodyParser = require('body-parser'); 3 | 4 | var { routes } = require('./routes'); 5 | 6 | var app = express(); 7 | 8 | // middleware 9 | app.use(bodyParser.json()); 10 | app.use(bodyParser.urlencoded({ extended: true })); 11 | app.use(routes); 12 | 13 | module.exports = { 14 | app, 15 | }; 16 | -------------------------------------------------------------------------------- /1-mongodb-crud/test/database-mongodb.test.js: -------------------------------------------------------------------------------- 1 | var request = require('supertest'); 2 | var { app } = require('../server/server'); 3 | var db = require('../database-mongodb/index'); 4 | 5 | describe('Test controllers', function() { 6 | test('It should retrieve todos from database', function(done) { 7 | request(app) 8 | .get('/toDoList') 9 | .then(function(response) { 10 | expect(response.statusCode).toBe(200); 11 | done(); 12 | }); 13 | }); 14 | 15 | test('It should add a new todo to database', function(done) { 16 | request(app) 17 | .post('/toDoList') 18 | .send({ 19 | name: 'Testing post', 20 | }) 21 | .then(function(response) { 22 | expect(response.statusCode).toBe(201); 23 | done(); 24 | }) 25 | .catch(function(err) { 26 | console.error(err); 27 | done(); 28 | }); 29 | }); 30 | 31 | test('It should update a todo in database', function(done) { 32 | request(app) 33 | .put('/toDoList') 34 | .send({ 35 | name: 'Testing post', 36 | newName: 'Updating post', 37 | }) 38 | .then(function(response) { 39 | expect(response.statusCode).toBe(202); 40 | done(); 41 | }); 42 | }); 43 | 44 | test('It should delete a todo in database', function(done) { 45 | request(app) 46 | .delete('/toDoList') 47 | .query({ name: 'Testing post' }) 48 | .then(function(response) { 49 | expect(response.statusCode).toBe(200); 50 | done(); 51 | }); 52 | }); 53 | 54 | afterAll(function() { 55 | db.close(); 56 | // db.disconnect(); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /2-mysql-crud/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /database-mysql/config.js 3 | /database-mysql-sequelize/config.js -------------------------------------------------------------------------------- /2-mysql-crud/README.md: -------------------------------------------------------------------------------- 1 | # MySQL CRUD 2 | 3 | You will implement the database layer of an already running Express app. Specifically, you will implement all CRUD operations (Create, Read, Update, Delete). This time you will be using MySQL only (using the mysql npm module). You may refactor to use Sequelize if you wish but only after implementing CRUD using just MySQL. 4 | 5 | ## Getting Started 6 | 7 | Navigate to mysql-crud in terminal 8 | 9 | Run the following in order: 10 | 11 | 1. `npm install` 12 | 1. `mysql -u root -p < database-mysql/setup.sql` in your terminal to create your database. 13 | 1. `mysql -u root -p < database-mysql/schema.sql` in your terminal to set up the schema. 14 | 1. `cp database-mysql/config.example.js database-mysql/config.js` and ensure you have entered the correct credentials. 15 | 1. `npm start` 16 | 17 | NOTE: 18 | 19 | - Ensure that you have updated your credentials in `database-mysql/config.js`, otherwise you won't connect to your server. 20 | - You may need to manually start your MySQL server via the command `mysql.server start`. 21 | - If you're having trouble running MySQL version 8 along with the mysql npm module, I recommend reverting to MySQL version 5.7. MySQL version 8 is pretty new, 5.7 is battle-tested and works just fine. 22 | 23 | If using Mac / Homebrew: Follow these [instructions](https://stackoverflow.com/a/51031221/8378145). 24 | 25 | If using Windows: Manually uninstall MySQL 8 then install MySQL 5.7. 26 | 27 | There is no front-end for this app. Use [Postman](https://www.getpostman.com/) to debug it. 28 | 29 | ## Your Task 30 | 31 | All of your work will be in the following files: 32 | 33 | - `server/controller.js` 34 | - `server/sequelize/controller.js` 35 | 36 | You are to implement the CRUD methods in the controller. You can run your tests to ensure your methods are working correctly. Instructions below for running tests. 37 | 38 | Pay attention to the `server/routes.js` file to see what the endpoint/s is/are for each CRUD operation. 39 | 40 | As an added challenge, consider refactoring your solution to make use of ES6 arrow functions and const / let variable declarations. 41 | 42 | ### No ORM 43 | 44 | To run tests for No ORM, ensure your server is running and run `npm run test:no-orm`. 45 | 46 | ### Sequelize 47 | 48 | Make sure to uncomment all items in server.js and routes.js pertaining to Sequelize and hide the items 49 | 50 | To run tests for Sequelize, ensure your server is running and run `npm run test:sequelize`. 51 | -------------------------------------------------------------------------------- /2-mysql-crud/database-mysql-sequelize/config.example.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | const connection = new Sequelize('todo_list', 'root', '', { 4 | host: 'localhost', 5 | dialect: 'mysql', 6 | }); 7 | 8 | module.exports = connection; 9 | -------------------------------------------------------------------------------- /2-mysql-crud/database-mysql-sequelize/index.js: -------------------------------------------------------------------------------- 1 | var connection = require('./config'); 2 | 3 | connection 4 | .authenticate() 5 | .then(function() { 6 | console.log('successfully authenticated connected'); 7 | }) 8 | .catch(function(err) { 9 | console.log('error authenticating connection', err); 10 | }); 11 | 12 | module.exports = { 13 | connection, 14 | }; 15 | -------------------------------------------------------------------------------- /2-mysql-crud/database-mysql-sequelize/models.js: -------------------------------------------------------------------------------- 1 | var Sequelize = require('sequelize'); 2 | 3 | var { connection } = require('./'); 4 | 5 | var Todo = connection.define( 6 | 'todo', 7 | { 8 | name: { 9 | type: Sequelize.STRING(50), 10 | allowNull: false, 11 | }, 12 | }, 13 | { timestamps: false }, 14 | ); 15 | 16 | connection 17 | .sync({ force: false }) 18 | .then(function() { 19 | console.log('successfully synced database'); 20 | }) 21 | .catch(function(err) { 22 | console.log('error syncing database ', err); 23 | }); 24 | 25 | module.exports = { 26 | Todo, 27 | }; 28 | -------------------------------------------------------------------------------- /2-mysql-crud/database-mysql/config.example.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | host: 'localhost', 3 | user: 'root', 4 | password: '', 5 | database: 'todo_list', 6 | }; 7 | -------------------------------------------------------------------------------- /2-mysql-crud/database-mysql/index.js: -------------------------------------------------------------------------------- 1 | var mysql = require('mysql'); 2 | var dbConfig = require('./config'); 3 | 4 | var connection = mysql.createConnection(dbConfig); 5 | 6 | connection.connect(function(err) { 7 | if (err) { 8 | console.log('Error connecting to to do list database'); 9 | } else { 10 | console.log('Connected to the to do list database'); 11 | } 12 | }); 13 | 14 | module.exports = { 15 | connection, 16 | }; 17 | -------------------------------------------------------------------------------- /2-mysql-crud/database-mysql/schema.sql: -------------------------------------------------------------------------------- 1 | USE todo_list; 2 | 3 | CREATE TABLE todos ( 4 | id int NOT NULL AUTO_INCREMENT, 5 | name varchar(50) NOT NULL, 6 | PRIMARY KEY (id) 7 | ); -------------------------------------------------------------------------------- /2-mysql-crud/database-mysql/setup.sql: -------------------------------------------------------------------------------- 1 | DROP DATABASE IF EXISTS todo_list; 2 | 3 | CREATE DATABASE todo_list; -------------------------------------------------------------------------------- /2-mysql-crud/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "full-stack-js-practice", 3 | "version": "1.0.0", 4 | "description": "Mini-exercises for practicing Full Stack JS.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon server/index.js", 8 | "test:no-orm": "jest test/database-mysql.test.js", 9 | "test:sequelize": "jest test/database-mysql-sequelize.test.js" 10 | }, 11 | "author": "hyperbolic-time-chamber", 12 | "license": "MIT", 13 | "private": true, 14 | "dependencies": { 15 | "body-parser": "^1.18.3", 16 | "cors": "^2.8.4", 17 | "express": "^4.16.3", 18 | "jest": "^25.0.0", 19 | "morgan": "^1.9.1", 20 | "mysql": "^2.15.0", 21 | "mysql2": "^1.5.3", 22 | "path": "^0.12.7", 23 | "sequelize": "^4.44.3", 24 | "supertest": "^3.1.0" 25 | }, 26 | "devDependencies": { 27 | "nodemon": "^1.18.2" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /2-mysql-crud/server/controller.js: -------------------------------------------------------------------------------- 1 | var { connection } = require('../database-mysql'); 2 | 3 | module.exports = { 4 | /* Get all todos. */ 5 | read: function(req, res) {}, 6 | 7 | /* Create one todo. */ 8 | create: function(req, res) {}, 9 | 10 | /* Update one todo. */ 11 | update: function(req, res) {}, 12 | 13 | /* Delete one todo. */ 14 | delete: function(req, res) {}, 15 | }; 16 | -------------------------------------------------------------------------------- /2-mysql-crud/server/controller.solution.js: -------------------------------------------------------------------------------- 1 | var { connection } = require('../database-mysql'); 2 | 3 | module.exports = { 4 | read: function(req, res) { 5 | connection.query('SELECT * FROM todos', function(err, result) { 6 | if (err) { 7 | return res.status(400).send(err); 8 | } 9 | res.status(200).send(result); 10 | }); 11 | }, 12 | 13 | create: function(req, res) { 14 | var { name } = req.body; 15 | connection.query(`INSERT INTO todos (name) VALUES ('${name}')`, function( 16 | err, 17 | result, 18 | ) { 19 | if (err) { 20 | return res.status(400).send(err); 21 | } 22 | res.status(201).send(`${result.affectedRows} record(s) created`); 23 | }); 24 | }, 25 | 26 | update: function(req, res) { 27 | var { todo } = req.body; 28 | var { id } = req.params; 29 | connection.query( 30 | `UPDATE todos SET name = '${todo}' WHERE id = '${id}'`, 31 | function(err, result) { 32 | if (err) { 33 | return res.status(400).send(err); 34 | } 35 | res.status(202).send(`${result.affectedRows} record(s) updated`); 36 | }, 37 | ); 38 | }, 39 | 40 | delete: function(req, res) { 41 | var { id } = req.params; 42 | connection.query(`DELETE FROM todos WHERE id = '${id}'`, function( 43 | err, 44 | result, 45 | ) { 46 | if (err) { 47 | return res.status(400).send(err); 48 | } 49 | res.status(202).send(`${result.affectedRows} record(s) deleted`); 50 | }); 51 | }, 52 | }; 53 | -------------------------------------------------------------------------------- /2-mysql-crud/server/index.js: -------------------------------------------------------------------------------- 1 | var { app } = require('./server'); 2 | 3 | var port = 3000; 4 | 5 | app.listen(port, function() { 6 | console.log(`Listening on PORT ${port}...`); 7 | }); 8 | -------------------------------------------------------------------------------- /2-mysql-crud/server/routes.js: -------------------------------------------------------------------------------- 1 | var routes = require('express').Router(); 2 | 3 | /* Uncomment for no ORM */ 4 | var controller = require('./controller'); 5 | 6 | /* Uncomment for Sequelize */ 7 | // var controller = require('./sequelize/controller'); 8 | 9 | routes 10 | .route('/todolist') 11 | .get(controller.read) 12 | .post(controller.create); 13 | 14 | routes 15 | .route('/todolist/:id') 16 | .put(controller.update) 17 | .delete(controller.delete); 18 | 19 | module.exports = { routes }; 20 | -------------------------------------------------------------------------------- /2-mysql-crud/server/sequelize/controller.js: -------------------------------------------------------------------------------- 1 | var { Todo } = require('../../database-mysql-sequelize/models'); 2 | 3 | module.exports = { 4 | /* Get all todos. */ 5 | read: function(req, res) {}, 6 | 7 | /* Create one todo. */ 8 | create: function(req, res) {}, 9 | 10 | /* Update one todo. */ 11 | update: function(req, res) {}, 12 | 13 | /* Delete one todo. */ 14 | delete: function(req, res) {}, 15 | }; 16 | -------------------------------------------------------------------------------- /2-mysql-crud/server/sequelize/controller.solution.js: -------------------------------------------------------------------------------- 1 | var { Todo } = require('../../database-mysql-sequelize/models'); 2 | 3 | module.exports = { 4 | read: function(req, res) { 5 | Todo.findAll({}).then(function(result) { 6 | res.status(200).send(result); 7 | }); 8 | }, 9 | 10 | create: function(req, res) { 11 | var { name } = req.body; 12 | Todo.create({ 13 | name, 14 | }) 15 | .then(function(result) { 16 | res.status(201).send(result); 17 | }) 18 | .catch(function(err) { 19 | res.status(400).send(err); 20 | }); 21 | }, 22 | 23 | update: function(req, res) { 24 | var { todo } = req.body; 25 | var { id } = req.params; 26 | Todo.update({ name: todo }, { where: { id } }) 27 | .then(() => { 28 | res.status(202).send('updated'); 29 | }) 30 | .catch(function(err) { 31 | res.status(400).send(err); 32 | }); 33 | }, 34 | 35 | delete: function(req, res) { 36 | var { id } = req.params; 37 | Todo.destroy({ 38 | where: { id }, 39 | }) 40 | .then(function(result) { 41 | res.status(202).send('deleted'); 42 | }) 43 | .catch(function(err) { 44 | res.status(400).send(err); 45 | }); 46 | }, 47 | }; 48 | -------------------------------------------------------------------------------- /2-mysql-crud/server/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var bodyParser = require('body-parser'); 3 | var { routes } = require('./routes'); 4 | 5 | var app = express(); 6 | 7 | /* Uncomment for no ORM */ 8 | require('../database-mysql'); 9 | 10 | /* Uncomment for Sequelize */ 11 | // require('../database-mysql-sequelize'); 12 | // require('../database-mysql-sequelize/models'); 13 | 14 | app.use(bodyParser.json()); 15 | app.use(bodyParser.urlencoded({ extended: true })); 16 | app.use(routes); 17 | 18 | module.exports = { 19 | app, 20 | }; 21 | -------------------------------------------------------------------------------- /2-mysql-crud/test/database-mysql-sequelize.test.js: -------------------------------------------------------------------------------- 1 | var request = require('supertest'); 2 | var { app } = require('../server/server'); 3 | var { connection } = require('../database-mysql-sequelize'); 4 | 5 | describe('Test controllers', function() { 6 | test('It should retrieve todos from database', function(done) { 7 | request(app) 8 | .get('/todolist') 9 | .then(function(response) { 10 | expect(response.statusCode).toBe(200); 11 | done(); 12 | }); 13 | }); 14 | 15 | test('It should add a new todo to database', function(done) { 16 | request(app) 17 | .post('/todolist') 18 | .send({ 19 | name: 'Testing post', 20 | }) 21 | .then(function(response) { 22 | expect(response.statusCode).toBe(201); 23 | done(); 24 | }); 25 | }); 26 | 27 | test('It should update a todo in database', function(done) { 28 | request(app) 29 | .put('/todolist/1') 30 | .send({ 31 | todo: 'Testing post', 32 | }) 33 | .then(function(response) { 34 | expect(response.statusCode).toBe(202); 35 | done(); 36 | }); 37 | }); 38 | 39 | test('It should delete a todo in database', function(done) { 40 | request(app) 41 | .delete('/todolist/1') 42 | .then(function(response) { 43 | expect(response.statusCode).toBe(202); 44 | done(); 45 | }); 46 | }); 47 | 48 | afterAll(function() { 49 | connection.close(); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /2-mysql-crud/test/database-mysql.test.js: -------------------------------------------------------------------------------- 1 | var request = require('supertest'); 2 | var { app } = require('../server/server'); 3 | var { connection } = require('../database-mysql'); 4 | 5 | describe('Test controllers', function() { 6 | test('It should retrieve todos from database', function(done) { 7 | request(app) 8 | .get('/todolist') 9 | .then(function(response) { 10 | expect(response.statusCode).toBe(200); 11 | done(); 12 | }); 13 | }); 14 | 15 | test('It should add a new todo to database', function(done) { 16 | request(app) 17 | .post('/todolist') 18 | .send({ 19 | name: 'Testing post', 20 | }) 21 | .then(function(response) { 22 | expect(response.statusCode).toBe(201); 23 | done(); 24 | }); 25 | }); 26 | 27 | test('It should update a todo in database', function(done) { 28 | request(app) 29 | .put('/todolist/1') 30 | .send({ 31 | todo: 'Updating post', 32 | }) 33 | .then(function(response) { 34 | expect(response.statusCode).toBe(202); 35 | done(); 36 | }); 37 | }); 38 | 39 | test('It should delete a todo in database', function(done) { 40 | request(app) 41 | .delete('/todolist/1') 42 | .then(function(response) { 43 | expect(response.statusCode).toBe(202); 44 | done(); 45 | }); 46 | }); 47 | 48 | afterAll(function() { 49 | connection.destroy(); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /3-promise-me/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | yarn-error.log -------------------------------------------------------------------------------- /3-promise-me/README.md: -------------------------------------------------------------------------------- 1 | # Callback and Promises Review 2 | 3 | !!!!!IMPORTANT!!!!! 4 | DO NOT install any promise-based libraries such as bluebird.js. 5 | 6 | To get the most out of these exercises, try your best at completing callback functions so you know how they work. Then convert them into promises without using any additional dependencies. Hint: There's a native Promise object available to you. 7 | !!!!!IMPORTANT!!!!! 8 | 9 | STEPS: 10 | 11 | 1. complete callbackReview.js 12 | 2. complete promiseReview.js 13 | 3. review the tests and see how they are invoked (you'll notice it's much cooler than callback hell). 14 | 4. review the solutions for examples 15 | 16 | Note: If you're unsure of how to properly chain promises, look to the tests for an example. 17 | 18 | As an added challenge, consider refactoring your solution to make use of ES6 arrow functions and const / let variable declarations. 19 | -------------------------------------------------------------------------------- /3-promise-me/exercises/callbackReview.js: -------------------------------------------------------------------------------- 1 | /* Implement these functions following the Node.js callback pattern. */ 2 | 3 | var fs = require('fs'); 4 | 5 | /* Reads the contents of a file at a specified path. */ 6 | var readMyFile = function(path, callback) { 7 | // TODO 8 | }; 9 | 10 | /* Creates and writes data(string) to specified path. */ 11 | var createMyFile = function(path, data, callback) { 12 | // TODO 13 | }; 14 | 15 | /* 16 | Reads a file that contains multi-line strings and returns one single sentence. 17 | 18 | For example: 19 | 20 | `buy it 21 | use it 22 | break it 23 | fix it 24 | trash it 25 | change it 26 | mail 27 | upgrade it` 28 | 29 | becomes 30 | 31 | `buy it use it break it fix it trash it change it mail upgrade it` 32 | */ 33 | var readFileAndConvertToSentence = function(path, callback) { 34 | // TODO 35 | }; 36 | 37 | module.exports = { createMyFile, readMyFile, readFileAndConvertToSentence }; 38 | -------------------------------------------------------------------------------- /3-promise-me/exercises/promiseReview.js: -------------------------------------------------------------------------------- 1 | /* Implement these functions following the new Promise pattern */ 2 | 3 | var fs = require('fs'); 4 | 5 | /* Reads the contents of a file at a specified path. */ 6 | var readMyFileAsync = function(path) { 7 | // TODO 8 | }; 9 | 10 | /* Creates and writes data(string) to specified path. */ 11 | var createMyFileAsync = function(path, data) { 12 | // TODO 13 | }; 14 | 15 | /* 16 | Reads a file that contains multi-line strings and returns one single sentence. 17 | 18 | For example: 19 | 20 | `buy it 21 | use it 22 | break it 23 | fix it 24 | trash it 25 | change it 26 | mail 27 | upgrade it` 28 | 29 | becomes 30 | 31 | `buy it use it break it fix it trash it change it mail upgrade it` 32 | */ 33 | var readFileAndConvertToSentenceAsync = function(path) { 34 | // TODO 35 | }; 36 | 37 | /* Be sure you understand how to chain two promises. */ 38 | 39 | module.exports = { 40 | createMyFileAsync, 41 | readMyFileAsync, 42 | readFileAndConvertToSentenceAsync, 43 | }; 44 | -------------------------------------------------------------------------------- /3-promise-me/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "promise-me", 3 | "version": "1.0.0", 4 | "description": "Callbacks and promise practice.", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "jest" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "jest": "^25.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /3-promise-me/solutions/callbackSolutions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-arrow-callback, no-undef, func-names, no-var */ 2 | 3 | /* Implement these functions following the Node.js callback pattern. */ 4 | 5 | var fs = require('fs'); 6 | 7 | /* Reads the contents of a file at a specified path. */ 8 | var readMyFile = function(path, callback) { 9 | fs.readFile(path, 'utf8', function(err, content) { 10 | if (err) return callback(err, null); 11 | callback(null, content); 12 | }); 13 | }; 14 | 15 | /* Creates and writes data(string) to specified path. */ 16 | var createMyFile = (path, data, callback) => { 17 | fs.writeFile(path, data, function(err) { 18 | if (err) return console.error(err); 19 | callback(); 20 | }); 21 | }; 22 | 23 | /* 24 | Reads a file that contains multi-line strings and returns one single sentence. 25 | 26 | For example: 27 | 28 | `buy it 29 | use it 30 | break it 31 | fix it 32 | trash it 33 | change it 34 | mail 35 | upgrade it` 36 | 37 | becomes 38 | 39 | `buy it use it break it fix it trash it change it mail upgrade it` 40 | */ 41 | var readFileAndConvertToSentence = function(path, callback) { 42 | readMyFile(path, function(err, content) { 43 | if (err) { 44 | callback(err, null); 45 | } else { 46 | var sentence = content.split('\n').join(' '); 47 | callback(null, sentence); 48 | } 49 | }); 50 | }; 51 | 52 | module.exports = { createMyFile, readMyFile, readFileAndConvertToSentence }; 53 | -------------------------------------------------------------------------------- /3-promise-me/solutions/promiseSolutions.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | // reads file at specified path and returns content 4 | var readMyFileAsync = function(path) { 5 | return new Promise(function(resolve, reject) { 6 | fs.readFile(path, 'utf8', function(err, content) { 7 | if (err) { 8 | reject(err); 9 | } else { 10 | resolve(content); 11 | } 12 | }); 13 | }); 14 | }; 15 | 16 | // creates and writes data(string) to specified path 17 | var createMyFileAsync = function(path, data) { 18 | return new Promise(function(resolve, reject) { 19 | fs.writeFile(path, data, function(err) { 20 | if (err) { 21 | reject(err); 22 | } else { 23 | resolve(); 24 | } 25 | }); 26 | }); 27 | }; 28 | 29 | // reads a file that contains multi-line strings 30 | /* 31 | `let us 32 | make this 33 | into 34 | a promise` 35 | */ 36 | 37 | // and returns one single sentence 38 | /* 39 | "let us make this into a promise" 40 | */ 41 | var readFileAndConvertToSentenceAsync = function(path) { 42 | return new Promise(function(resolve, reject) { 43 | fs.readFile(path, 'utf8', function(err, content) { 44 | if (err) { 45 | reject(err); 46 | } else { 47 | var sentence = content.split('\n').join(' '); 48 | resolve(sentence); 49 | } 50 | }); 51 | }); 52 | }; 53 | 54 | /* Be sure you understand how to chain two promises. */ 55 | 56 | module.exports = { 57 | createMyFileAsync, 58 | readMyFileAsync, 59 | readFileAndConvertToSentenceAsync, 60 | }; 61 | -------------------------------------------------------------------------------- /3-promise-me/test/callbackReview.test.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var { 4 | createMyFile, 5 | readMyFile, 6 | readFileAndConvertToSentence, 7 | } = require('../exercises/callbackReview.js'); 8 | 9 | var filePath = path.join(__dirname, 'callbackFile.txt'); 10 | 11 | describe('Our File System helper functions have a callback as their last parameter that, when invoked,', function() { 12 | afterEach(function() { 13 | fs.unlink(filePath, function(err) { 14 | if (err) { 15 | console.error(err); 16 | } 17 | }); 18 | }); 19 | 20 | test('receives an error as its first argument if there is an error.', function(done) { 21 | var incorrectFilePath = path.join(__dirname, 'some-incorrect-file-path'); 22 | createMyFile(filePath, 'hello', function() { 23 | readMyFile(incorrectFilePath, function(err, content) { 24 | expect(err.code).toEqual('ENOENT'); 25 | expect(content).toBeNull(); 26 | done(); 27 | }); 28 | }); 29 | }); 30 | 31 | test('receives the data retrieved from a file as its second argument.', function(done) { 32 | createMyFile(filePath, 'hello', function() { 33 | readMyFile(filePath, function(err, content) { 34 | expect(err).toBeNull(); 35 | expect(content).toEqual('hello'); 36 | done(); 37 | }); 38 | }); 39 | }); 40 | 41 | test('receives the data retrieved from a file as its second argument.', function(done) { 42 | createMyFile(filePath, 'hello\nyou are\nsuper', function() { 43 | readFileAndConvertToSentence(filePath, function(err, content) { 44 | expect(content).toEqual('hello you are super'); 45 | done(); 46 | }); 47 | }); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /3-promise-me/test/promiseReview.test.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var { 4 | createMyFileAsync, 5 | readMyFileAsync, 6 | readFileAndConvertToSentenceAsync, 7 | } = require('../exercises/promiseReview.js'); 8 | 9 | var filePath = path.join(__dirname, 'promiseFile.txt'); 10 | 11 | describe('Our File System helper functions now return promises that', function() { 12 | afterEach(function() { 13 | fs.unlink(filePath, function(err) { 14 | if (err) { 15 | return; 16 | } 17 | }); 18 | }); 19 | 20 | test('uses the catch method to listen for and log errors.', function(done) { 21 | var error = false; 22 | var incorrectFilePath = path.join(__dirname, 'some-incorrect-file-path'); 23 | return readMyFileAsync(incorrectFilePath).catch(function() { 24 | error = true; 25 | expect(error).toEqual(true); 26 | done(); 27 | }); 28 | }); 29 | 30 | test('uses the then method to access data retrieved after successful execution of a given task.', function(done) { 31 | return createMyFileAsync(filePath, 'promised hello') 32 | .then(function() { 33 | return readMyFileAsync(filePath); 34 | }) 35 | .then(function(content) { 36 | expect(content).toEqual('promised hello'); 37 | done(); 38 | }) 39 | .catch(function(err) { 40 | expect(err).toBeUndefined(); 41 | done(); 42 | }); 43 | }); 44 | 45 | test('uses the then method to access data retrieved after successful execution of a given task.', function(done) { 46 | return createMyFileAsync(filePath, 'hello\nyou are\nsuper') 47 | .then(function() { 48 | return readFileAndConvertToSentenceAsync(filePath); 49 | }) 50 | .then(function(content) { 51 | expect(content).toEqual('hello you are super'); 52 | done(); 53 | }) 54 | .catch(function(err) { 55 | expect(err).toBeUndefined(); 56 | done(); 57 | }); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Full Stack JS Practice 2 | 3 | ## Commit Guidelines 4 | 5 | Please use multi-line messages for any commits that effectively do more than one thing to the codebase. A bigger commit with a multi-line commit message that outlines each change to the codebase is generally more conducive for accurate messaging. The exception to this is when a fix or feature pertains to a single line being changed in the codebase. 6 | 7 | All commits must be prefixed using the following prefixes in brackets: 8 | 9 | ``` 10 | docs | documentation related 11 | ops | operations related (dependency/lock-file updates, configuration changes, etc.) 12 | feat | adds a new feature 13 | prog | progress on a new feature 14 | fix | adds a fix for an issue 15 | test | adds a test 16 | refactor | refactoring-related (DRY-up some parts of the code) 17 | style | code-style related (adding line breaks, removing whitespace, etc.) 18 | visual | front-end UI related changes 19 | ``` 20 | 21 | **Please do not mix up the nature of a single commit.** For example, if you notice that some line breaks need to be added and a bug needs to be fixed, make a separate `[style]` commit for the line breaks and a `[fix]` commit for addressing the bug. 22 | 23 | Example multi-line commit message: 24 | 25 | ``` 26 | [docs] add root and developer docs 27 | - add README.md to project root `/` 28 | - add README.md to project developer documentation `docs/` 29 | ``` 30 | 31 | Example single-line commit messages: 32 | 33 | ``` 34 | [docs] fix typo in first-world-problems API doc 35 | [ops] add lodash dependency to query-generator service 36 | ``` 37 | 38 | ## Branch Guidelines 39 | 40 | Cut a namespaced feature branch from master. 41 | 42 | Your branch should follow this naming convention: 43 | 44 | * bug/... 45 | * feat/... 46 | * test/... 47 | * doc/... 48 | * refactor/... 49 | 50 | These commands will help you do this: 51 | 52 | ```bash 53 | # Creates your branch and brings you there 54 | git checkout -b `your-branch-name` 55 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Full Stack JS Practice 2 | 3 | This repo contains a series of exercises designed to help you practice building pieces of an app or program using JavaScript and/or Node.js. 4 | 5 | Breakdown of the exercises is as follows. 6 | 7 | ## 1 - MongoDB CRUD 8 | 9 | You will implement the database layer of an already running Express app. Specifically, you will implement all CRUD operations (Create, Read, Update, Delete). You will be using Mongo + Mongoose. 10 | 11 | ## 2 - MySQL CRUD 12 | 13 | You will implement the database layer of an already running Express app. Specifically, you will implement all CRUD operations (Create, Read, Update, Delete). This time you will be using MySQL only (using the mysql npm module). You may refactor to use Sequelize if you wish but only after implementing CRUD using just MySQL. 14 | 15 | ## 3 - Promise Me 16 | 17 | You will complete a series of problems using callbacks. You will then promisify these callbacks using the native Promise API and complete the same exercises using promises. 18 | 19 | ## How To Use This Repo 20 | 21 | Fork and clone down. 22 | 23 | `cd` into appropriate directory, read the `README`, and begin your work. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "full-stack-js-practice", 3 | "version": "1.0.0", 4 | "description": "Mini-exercises for practicing Full Stack JS.", 5 | "main": "index.js", 6 | "author": "hyperbolic-time-chamber", 7 | "license": "MIT", 8 | "private": true 9 | } 10 | --------------------------------------------------------------------------------