After I examine the codes you have written, I could see some things that are not rightly done. Below are the few things I highlighted:
- The structuring of the codebase is not okay hence it can be maintainable and scalable if the codebase grows.
- The RESTful API naming convention is not an acceptable one. Endpoints of any REST API should contain only resources (nouns) and use HTTP methods (verbs) for actions. You named your endpoint as /qanda instead of /qandas. I recommend you read this RESTful API Designing guidelines by Mahesh Haldar posted at Hackernoon. It's a great resource for developers.
- Thirdly, you did not separate your server from express; they are both coupled together. It's not best practice to do so.
- When API is being consumed by other applications, upgrading the APIs with some changes would also lead to breaking the existing services contract - this has been noticed by a lot of applications that provide API services. It is a best practice to always prefix all your URLs with /api/v1/users . If there is any major breaking update, we can name the new set of APIs as v2, v3, or v1.X.X. respectively.
From my experience, this is how I would approach it:
- Firstly, I will create a directory called, qanda-api, inside it, I'll create other directories called src and two files app.js and server.js that reside inside the root directory with src
- Secondly, inside src I will create two sub-directories called routes and controllers
- Thirdly, I will initialize an npm registry in the root of the project directory that keeps track of all npm installed packages by typing the command below via the terminal:
npm init
- After that, I will install the three dependencies that I will be using via the same terminal, but this time you must have internet access:
npm install express dotenv morgan
- If the above process executes successfully, you will see the installed packages inside a file called package.json
Now let's do the coding by getting our hands dirty
- Let's first create a file named controllers/qandaController.js in other to write our qanda logic that will be exported to its route file.
exports.getAllQandas = (req, res) => {
res.status(200).json({
status: 'success',
message: 'Documments retrieved successfully',
data: 'The data goes here from the data!'
});
};
exports.getQanda = (req, res) => {
res.status(200).json({
status: 'success',
message: 'Doc retrieved successfully',
data: 'The data goes here from the data!'
});
};
exports.createQanda = (req, res) => {
res.status(201).json({
status: 'success',
message: 'Qanda created successfully',
data: 'Return the created data here!'
});
};
exports.updateQanda = (req, res) => {
res.status(200).json({
status: 'success',
message: 'Doc updated successfully',
data: 'The updated data goes here!'
});
};
exports.deleteQanda = (req, res) => {
res.status(200).json({
status: 'success',
message: 'Doc deleted!',
data: 'Return the Deleted data'
});
};
- Now, it's time for us to create our qanda route in routes/qandaRoutes.js. We will then import the controller logic in its route handler below.
const express = require('express');
/**
* import the qanda controller
*/
const qandaController = require('./../controllers/qandaController');
const router = express.Router();
router
.route('/')
.get(qandaController.getAllQandas)
.post(qandaController.createQanda);
router
.route('/:id')
.get(qandaController.getQanda)
.patch(qandaController.updateQanda)
.delete(qandaController.deleteQanda);
module.exports = router;
- Let's open the file we created earlier on called app.js in other to make use of the express we had installed. The content of this file is only for express which is then exported to its server:
const express = require('express');
const morgan = require('morgan');
const qandaRouter = require('./routes/qandaRoutes');
const app = express();
if (process.env.NODE_ENV === 'development') app.use(morgan('dev'));
// ROUTES
app.use('/api/v1/qandas', qandaRouter);
/*
** HANDLING UNHANDLED ROUTES
*/
app.all('*', (req, res, next) => {
res.status(404).json({
status: 'fail',
message: `Can't find ${req.originalUrl} on this Server!`
});
});
module.exports = app;
- Let's create our server which becomes our entry point to the application. This where the actual execution happens whereby the exported app.js get used by inserting it as an argument in the createServer() function.
require('dotenv').config({ path: '.env' });
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 5000;
const server = http.createServer(app);
server.listen(port, () => console.log(`App running on port ${port}`));
Conclusion
It's highly recommended to always have separation of concerns while writing codes and to aptly have a clean codebase that is maintainable and scalable over time. There's more to code organization when it comes to API design, one of it is the DRY principle (Don't Repeat Yourself). If you want to learn more about API design in Node.JS I recommend you take this course by Jonas. He demystifies the abstract concepts and taught best practices to the core. I've wrapped this answer with API design projects in Github: API and Tourism API. Feel free to clone or modify as you need.