diff --git a/README.md b/README.md index c1cad55..aeae015 100644 --- a/README.md +++ b/README.md @@ -58,4 +58,5 @@ Then go to your server folder (backend), and set your database within `server.js > cors: ^2.8.5     --->     Enable HTTP requests
dotenv: ^8.2.0 >     --->     Secure sensitive information
express: ^4.17.1 >     --->     Server app
mongoose: ^5.11.8     -> --->     MongoDB database +> --->     MongoDB database
morgan: ^1.10.0     ---> +>     Logs requests diff --git a/client/src/App.js b/client/src/App.js deleted file mode 100644 index 22912d7..0000000 --- a/client/src/App.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import HelloWorld from './components/HelloWorld/HelloWorld'; -// import * as api from './api'; -// ^ ^ ^ un-comment this to import api endpoints - -function App() { - // const [data, setData] = React.useState([]); - // React.useEffect(() => { - // api - // .getSomething() // replace this with your endpoint - // .then((response) => console.log(`✅ ${response.status} ${response.statusText}`, setData(response.data))) - // .catch((error) => console.log(`❌ ${error}`)); - // }, []); - // - // ^ ^ ^ example using the api endpoint - - return ( -
- -
- ); -} - -export default App; diff --git a/client/src/api/index.js b/client/src/api/index.js index a8aeee2..173292e 100644 --- a/client/src/api/index.js +++ b/client/src/api/index.js @@ -3,10 +3,38 @@ import axios from 'axios'; // api base-url (that you created on server side) const url = 'http://localhost:8080/api/v1'; -// current path: http://localhost:8080/api/v1/example // current method: GET -// export const getSomething = () => axios.get(url + '/example'); +// current path: http://localhost:8080/api/v1/example +export const getExample = () => axios.get(`${url}/example`); -// current path: http://localhost:8080/api/v1/example/upload // current method: POST -// export const postSometing = (form) => axios.post(url + '/example/upload', form); +// current path: http://localhost:8080/api/v1/example/upload +export const uploadExample = (form) => axios.post(`${url}/example/upload`, form); + +// Example using your API: +// +// +// +// 1) in your Component file, import a method from above like so: +// +// import { getExample } from './api'; +// +// +// +// 2) Then call the method and handle it's errors/response, like so: +// +// function ExampleFetching() { +// const [data, setData] = React.useState([]); +// +// React.useEffect(() => { +// getExample() +// .then((response) => setData(response.data)) +// .catch((error) => console.log(error)); +// }, []); +// +// return ( +//
+// {data} +//
+// ); +// } diff --git a/client/src/components/App/App.js b/client/src/components/App/App.js new file mode 100644 index 0000000..528a8d4 --- /dev/null +++ b/client/src/components/App/App.js @@ -0,0 +1,12 @@ +import React from 'react'; +import HelloWorld from './../HelloWorld/HelloWorld'; + +function App() { + return ( +
+ +
+ ); +} + +export default App; diff --git a/client/src/components/HelloWorld/HelloWorld.jsx b/client/src/components/HelloWorld/HelloWorld.jsx index cbaebd3..f6e4924 100644 --- a/client/src/components/HelloWorld/HelloWorld.jsx +++ b/client/src/components/HelloWorld/HelloWorld.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import styles from './HelloWorld.module.css'; // CSS module -> className={styles.App} (AKA styled components) +import styles from './HelloWorld.module.css'; +// CSS module -> className={styles.App} (AKA styled components) function HelloWorld() { return
Hello World - React.js
; diff --git a/client/src/index.js b/client/src/index.js index d70223e..390ebc7 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -1,6 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import App from './App'; +import App from './components/App/App'; import './style/reset.css'; ReactDOM.render( diff --git a/server/api/controllers/controller.js b/server/api/controllers/controller.js deleted file mode 100644 index 3cd8297..0000000 --- a/server/api/controllers/controller.js +++ /dev/null @@ -1,26 +0,0 @@ -import mongoose from 'mongoose'; -import Example from './../models/model.js'; -// more about response status codes ---> https://restapitutorial.com/httpstatuscodes.html - -export const getExamples = async (request, response, next) => { - try { - const allExamples = await Example.find(); // what is .find() ??? ---> https://mongoosejs.com/docs/queries.html - response.status(200).json(allExamples); - } catch (error) { - response.status(500).json(error); - } -}; - -export const uploadExample = async (request, response, next) => { - let newExample = new Example({ - _id: mongoose.Types.ObjectId(), // _id is set by default, (you can remove this line) - name: request.body.fieldName, // fieldName === name used on client side - }); - - try { - const savedExample = await newExample.save(); // what is .save() ??? ---> https://mongoosejs.com/docs/api.html#document_Document-save - response.status(201).json(savedExample); - } catch (error) { - response.status(500).json(error); - } -}; diff --git a/server/api/controllers/exampleControllers.js b/server/api/controllers/exampleControllers.js new file mode 100644 index 0000000..064c87e --- /dev/null +++ b/server/api/controllers/exampleControllers.js @@ -0,0 +1,28 @@ +import mongoose from 'mongoose'; +import Example from '../models/Example.js'; +// more about response status codes ---> https://restapitutorial.com/httpstatuscodes.html + +export async function getExamples(request, response, next) { + try { + const allExamples = await Example.find(); + response.status(200).json(allExamples); + } catch (error) { + console.log(error); + response.status(500).json(error); + } +} + +export const uploadExample = async (request, response, next) => { + try { + let newExample = new Example({ + _id: mongoose.Types.ObjectId(), // _id is set by default, (you can remove this line) + name: request.body.fieldName, // fieldName === name used on client side + }); + + const savedExample = await newExample.save(); + response.status(201).json(savedExample); + } catch (error) { + console.log(error); + response.status(500).json(error); + } +}; diff --git a/server/api/models/model.js b/server/api/models/Example.js similarity index 71% rename from server/api/models/model.js rename to server/api/models/Example.js index 9130dff..2985a8a 100644 --- a/server/api/models/model.js +++ b/server/api/models/Example.js @@ -3,19 +3,19 @@ import mongoose from 'mongoose'; const instance = new mongoose.Schema( { _id: mongoose.Schema.Types.ObjectId, // _id is set by default, (you can remove this line) + name: String, /* name = property of document object String = type of value ---> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures */ - name: String, }, { timestamps: true, }, ); -// modelName ---> https://mongoosejs.com/docs/guide.html -// note: use a singular name, mongoose automatically creates a collection like so -> model: 'Person' === collection: 'people' +// NOTE! use a singular model name, mongoose automatically creates a collection like so: +// model: 'Person' === collection: 'people' const modelName = 'Example'; export default mongoose.model(modelName, instance); diff --git a/server/api/routes/route.js b/server/api/routes/exampleRoutes.js similarity index 64% rename from server/api/routes/route.js rename to server/api/routes/exampleRoutes.js index 5e009ca..96b7180 100644 --- a/server/api/routes/route.js +++ b/server/api/routes/exampleRoutes.js @@ -1,16 +1,19 @@ import express from 'express'; -import { getExamples, uploadExample } from './../controllers/controller.js'; // import request & response function +import { getExamples, uploadExample } from '../controllers/exampleControllers.js'; // import request & response function // initialize router const router = express.Router(); - /* request methods ---> https://www.tutorialspoint.com/http/http_methods.htm 1st param = extended url path 2nd param = middlewares (optional) 3rd param = request & response function (controller) */ -router.get('/', (request, response, next) => next(), getExamples); // current path: http://localhost:8080/api/v1/example -router.post('/upload', (request, response, next) => next(), uploadExample); // current path: http://localhost:8080/api/v1/example/upload + +// current path: http://localhost:8080/api/v1/example +router.get('/', (request, response, next) => next(), getExamples); + +// current path: http://localhost:8080/api/v1/example/upload +router.post('/upload', (request, response, next) => next(), uploadExample); export default router; diff --git a/server/package.json b/server/package.json index 8b7509c..f67e7a5 100644 --- a/server/package.json +++ b/server/package.json @@ -11,6 +11,7 @@ "cors": "^2.8.5", "dotenv": "^8.2.0", "express": "^4.17.1", - "mongoose": "^5.11.8" + "mongoose": "^5.11.8", + "morgan": "^1.10.0" } } diff --git a/server/server.js b/server/server.js index fe7dbe0..2ac61f3 100644 --- a/server/server.js +++ b/server/server.js @@ -1,37 +1,42 @@ import mongoose from 'mongoose'; // MongoDB (database) import express from 'express'; // Backend App (server) -import dotenv from 'dotenv'; // Secures content -import cors from 'cors'; // HTTP headers +import cors from 'cors'; // HTTP headers (enable requests) +import morgan from 'morgan'; // Logs incoming requests +import dotenv from 'dotenv'; // Secures variables + // import IMPORTED_ROUTES from './api/routes/route.js'; // ^ ^ ^ un-comment this to use imported route(s) -// doing this will link the following files: index.js -> route.js -> controller.js -> model.js +// doing this will link the following files: server.js -> exampleRoutes.js -> exampleControllers.js -> Example.js // initialize app const app = express(); -dotenv.config(); // what is dotenv ---> https://github.com/motdotla/dotenv#readme // middlewares -app.use(express.json()); // body parser -app.use(express.urlencoded({ extended: false })); // url parser -app.use(cors()); // enables http requests +app.use(express.json({ limit: '10mb', extended: true })); // body parser +app.use(express.urlencoded({ limit: '10mb', extended: true })); // url parser +app.use(cors({ origin: 'http://localhost:3000' })); // enables http requests on react development server +app.use(morgan('common')); // logs requests +dotenv.config(); // protected variables -// configure db ---> if you want to connect to cloud server: edit "CONNECTION_URL" in -> .env file -const DB_NAME = 'exampleDB'; // if you want to use local server: edit this "DB_NAME" (and remove the "CONNECTION_URL" from -> .env file) +// configure db: +// if you want to connect to cloud server (atlas): edit "CONNECTION_URL" in -> .env file +// if you want to use local server (community): edit "DB_NAME" +const DB_NAME = 'exampleDB'; const CONNECTION_URL = process.env.CONNECTION_URL || `mongodb://localhost:27017/${DB_NAME}`; const PORT = process.env.PORT || 8080; // 8080 === development port -const DEPRECATED_FIX = { useNewUrlParser: true, useUnifiedTopology: true }; // change this with (possible) warnings on first connection +const DEPRECATED_FIX = { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }; // update this with (possible) deprecated warnings -// mongoose connections ---> https://mongoosejs.com/docs/connections.html // connect to db -mongoose.connect(CONNECTION_URL, DEPRECATED_FIX).catch((error) => console.log('❌ MongoDB:', error)); // listen for errors on initial connection -mongoose.connection.on('connected', () => console.log('✅ MongoDB connected')); -mongoose.connection.on('error', (error) => console.log('❌ MongoDB:', error)); // listen for errors after the connection is established (errors during the session) -mongoose.connection.on('disconnected', () => console.log('❌ MongoDB disconnected')); -mongoose.set('useCreateIndex', true); -// ^ ^ ^ fix to a deprecated warning +mongoose + .connect(CONNECTION_URL, DEPRECATED_FIX) + .catch((error) => console.log('❌ MongoDB connection error', error)); // listen for errors on initial connection +mongoose.connection.on('connected', () => console.log('✅ MongoDB connected')); // connected +mongoose.connection.on('disconnected', () => console.log('❌ MongoDB disconnected')); // disconnected +mongoose.connection.on('error', (error) => console.log('❌ MongoDB connection error', error)); // listen for errors after the connection is established (errors during the session) // routes -app.get('/', (req, res) => res.send('Hello World - Express.js')); +app.get('/', (request, response, next) => response.send('Hello World - Express.js')); + // app.use('/api/v1/example', IMPORTED_ROUTES); // ^ ^ ^ un-comment this to use imported route(s)