Creating A NodeJS RESTful API without ExpressJS — Part 2
Adding CRUD Operations to the No Dependency API
In the last article, we created a RESTful API capable of handling the specified endpoints and responding to endpoints not defined in the API without breaking the app. We’ve achieved all this without using any NPM packages.
We’ll add CRUD functionality to this API in this article while following the ‘no NPM packages’ rule.
Creating a NodeJS RESTful API without ExpressJS — File Structure
In this article, we’ll be adding a new file, called crud.js
, that will hold the CURD operation logic.
We’ll also be adding a folder called data
, which will hold all the files we’ll perform our CRUD operations on.
Creating a NodeJS RESTful API without ExpressJS — CRUD Operations
In crud.js
, we will keep all the CRUD related functions in that file.
const fs = require('fs')const CRUD = {}module.exports = CRUD
We will be performing CRUD operations on JSON files, hence we are importing fs
for handling file operations.
The CRUD object will hold all the functions and is then exported to be used in other files.
Create File
CRUD.create = async (name, object) => { let result const string = JSON.stringify(object) try { await fs.writeFileSync(`./data/${name}.json`, string) result = true } catch (error) { console.log(error) result = false } return result}
Here, we have name
and object
as parameters, name
is the file name of the JSON file, and object
is the content inside of the JSON file. This method will create a new JSON file with the given name and content.
Read File
CRUD.readOne = async (name) => { let result try { const data = await fs.readFileSync(`./data/${name}.json`, 'utf-8') result = JSON.parse(data) } catch (error) { console.log(error) result = false } return result}
Here, we have name
as the parameter, which is the name of the JSON file. This method will return the contents of the JSON file with the given name.
Update File
CRUD.update = async(name, object) => { const string = JSON.stringify(object) let result try { await fs.writeFileSync(`./data/${name}.json`, string) result = true } catch (error) { console.log(error) result = false } return result}
Here, we take name
and object
are the parameters. This method replaces the old content with the new content provided in the object
, for the given name
of the JSON file.
Delete File
CRUD.delete = async (name) => { let result try { await fs.unlinkSync(`./data/${name}.json`) result = true } catch (error) { console.log(error) result = false } return result}
Here, we are deleting the JSON file with the given name
.
Creating a NodeJS RESTful API without ExpressJS — Implementing CRUD in Handlers
Now, we will be defining handlers for each of the methods for the route /
.
In handlers.js
,
First import the crud.js
file.
const crud = require('./crud')
GET method
We had a handler for the GET
method for route /
, which returned an object with a Hello World
string. We’ll be replacing it with the following.
handlers.fileReadOne = async (data,callback) => { const query = data['query'] const file = await crud.readOne(query.id) if(!file) callback(400, {Error: 'File with id not found'}) callback(200, {file})}
Here, we read an id from the URL query and return the file contents if the file with the name of the id is present. Else we send an error message saying ‘File with id not found’.
POST method
handlers.filePost = async (data, callback) => { const postData = JSON.parse(data['payload']) const isSuccess = await crud.create(postData.id, postData) if(!isSuccess) callback(404, {Error: 'Error While creating the file'}) callback(201, {Success: 'File created Successfully!!'})}
Here, we are calling the create method of crud object, which creates a JSON file with the name id.json
. This handler sends the response stating if the file creation was successful or not.
DELETE method
handlers.fileDelete = async (data,callback) => { const query = data['query'] const isSuccess = await crud.delete(query.id) if(!isSuccess) callback(400, {Error: 'File with id not found'}) callback(200, {Success: 'File Deleted!!'})}
Here, we are calling the delete method of the crud object, which deletes the file with the given name. This handler sends the response stating if the deletion of the file was complete or not.
PATCH method
handlers.fileUpdate = async (data, callback) => { const postData = JSON.parse(data['payload']) const isSuccess = await crud.create(postData.id, postData) if(!isSuccess) callback(404, {Error: 'Error While updating the file'}) callback(201, {Success: 'File updated Successfully!!'})}
This handler sends the response stating if the file update was successful or not.
Creating a NodeJS RESTful API without ExpressJS — Connecting Routes with Handlers
In router.js
,
const handlers = require('./handlers')const router = { '/' : { 'GET': handlers.fileReadOne, 'POST': handlers.filePost, 'DELETE': handlers.fileDelete, 'PATCH': handlers.fileUpdate }, '/ping' : { 'GET': handlers.ping }, 'notFound': handlers.notFound}module.exports = router
Here, we are defining which handler should be active for which method in the path /
.
Creating a NodeJS RESTful API without ExpressJS — CRUD Results
For the POST
method, we get the following result.
Which creates a JSON file as follows.
For the GET
method, we get the following result.
Here, we are reading a JSON file with the name 01.json
, and returning its contents.
For PATCH
method, we get the following result.
This updates the file named 02.json
with the content provided in the body.
For DELETE
method, we get the following result.
This deletes the file 02.json
that we created at the start.
And so, we’ve added CRUD operations to our RESTful API without ExressJS.
But we have a problem. The /
route without any queries used to send a Hello World
string but now doesn’t because we replaced the previous handler at the GET
method with a handler that only accepts queries and returns the error message otherwise.
But we want both, we want the URL to return a different message/information if the queries are included or not. We also want to add nested routing and dynamic routing to the API.
Hence in the following article, we’ll discuss implementing nested routes and dynamic routes to our API.
My previously written articles,