Building a CRUD REST API for Employee Records using Express.js and In-Memory Array
Published: 2023-02-05 12:47:21

In this tutorial, we will create a REST API to manage employee records with Express.js, a fast, unopinionated, and minimalist Node.js web framework. We will be able to use the API to perform standard CRUD (Create, Read, Update, Delete) operations on employee records that are stored in an in-memory array.

We'll begin by creating a new Express.js project and installing the required dependencies. Then, using the Express.js router and an in-memory array as our database, we'll define the API endpoints and implement the CRUD operations. Finally, we will use Postman to ensure that the API is operational.


Make sure you have Node.js installed on your machine before we begin.

Setting up the Project

To set up a new Express.js project, create a new directory and run the following command:
`npm init -y`

This will create a package.json file that we will use to manage our dependencies. Next, we will install Express.js and the necessary middleware to handle HTTP requests and parse JSON data.

`npm install express body-parser`

Creating the Express.js Server

Create a new file named index.js and add the following code:

```
const express = require("express");
const bodyParser = require("body-parser");
const app = express();

app.use(bodyParser.json());

const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}...`));
```
this code sets up a new Express.js application, enables JSON parsing for incoming requests, and starts the server on port 3000.

Defining the API Endpoints

Now that we have set up our Express.js server, we can define the API endpoints for our CRUD operations. We will use an in-memory array to store our employee records.

Add the following code to index.js:

```
const router = express.Router();

const employees = [];

// Get all employees
router.get("/employees", (req, res) => {
  res.json(employees);
});

// Get a single employee
router.get("/employees/:id", (req, res) => {
  const employee = employees.find(e => e.id === parseInt(req.params.id));
  if (!employee) {
    return res.status(404).send("Employee not found");
  }
  res.json(employee);
});

// Create a new employee
router.post("/employees", (req, res) => {
  const employee = {
    id: employees.length + 1,
    name: req.body.name,
    age: req.body.age,
    department: req.body.department
  };
  employees.push(employee);
  res.json(employee);
});

// Update an employee
router.put("/employees/:id", (req, res) => {
  const employee = employees.find(e => e.id === parseInt(req.params.id));
  if (!employee) {
    return res.status(404).send("Employee not found");
}
employee.name = req.body.name;
employee.age = req.body.age;
employee.department = req.body.department;
res.json(employee);
});

// Delete an employee
router.delete("/employees/:id", (req, res) => {
const employee = employees.find(e => e.id === parseInt(req.params.id));
if (!employee) {
return res.status(404).send("Employee not found");
}
const index = employees.indexOf(employee);
employees.splice(index, 1);
res.send("Employee deleted");
});

app.use("/api", router)
```
n this code, we have defined the API endpoints for our CRUD operations using the Express.js router. We have also defined an in-memory array to store our employee records.

For each endpoint, we are performing the following operations:

- `GET /employees`: Returns an array of all employee records.
- `GET /employees/:id`: Returns a single employee record based on the ID provided in the URL.
- `POST /employees`: Creates a new employee record based on the data provided in the request body.
- `PUT /employees/:id`: Updates an existing employee record based on the ID provided in the URL and the data provided in the request body.
- `DELETE /employees/:id`: Deletes an existing employee record based on the ID provided in the URL.

Testing the API

To test the API, we can use Postman, a powerful API development tool. Start the Express.js server by running the following command in your terminal:
`node index.js`
In Postman, create a new request and set the method to `GET`, and the URL to `http://localhost:3000/api/employees`. Send the request and you should see an empty array returned in the response.

Next, create a new request with the method set to `POST`, and the URL set to `http://localhost:3000/api/employees`. In the request body, set the content type to `application/json` and provide the following data:

```
{
"name": "Raj Arul",
"age": 30,
"department": "IT"
}
```
end the request and you should see the newly created employee record returned in the response. Repeat this process to create additional employee records.

To retrieve a single employee record, create a new request with the method set to `GET` and the URL set to `http://localhost:3000/api/employees/1` (where 1 is the ID of the employee you want to retrieve). Send the request and you should see the employee record returned in the response.

To update an employee record, create a new request with the method set to `PUT` and the URL set to `http://localhost:3000/api/employees/1` (where 1 is the ID of the employee you want to update). In the request body, set the content type to `application/json` and provide the updated data:

```
{
"name": "Raj Arul",
"age": 32,
"department": "Dev Ops
}
```
Finally, to delete an employee record, create a new request with the method set to DELETE and the URL set to http://localhost:3000/api/employees/1 (where 1 is the ID of the employee you want to delete). Send the request and you should see a message indicating that the employee has been deleted.

we can implement same in layered architecture,

Using a layered architecture in Express.js (or any other web application) is considered a good practice for several reasons:

Separation of concerns: A layered architecture separates different responsibilities of the application into separate components. This helps keep the code organized and easier to maintain.

Reusability: By breaking down the application into smaller components, it becomes easier to reuse code in different parts of the application, making it more efficient.

Testing: A layered architecture makes it easier to write automated tests for different components in isolation, leading to more robust and reliable code.

Scalability: A well-designed layered architecture makes it easier to scale the application, by allowing you to add new components or make changes to existing components without affecting the entire application.

Improved Code Quality: By having a clear separation of responsibilities and modularized components, code quality can be improved, making it easier to understand, maintain, and extend the application.

Overall, using a layered architecture in Express.js helps make the application more structured, maintainable, and scalable, leading to a better user experience.
 Here's an example of how you could implement the CRUD REST API for employee records using a layered architecture with controllers, repositories, and services in Express.js with an in-memory array:

```
// employee.repository.js

const employees = [];

class EmployeeRepository {
  static findAll() {
    return employees;
  }

  static findById(id) {
    return employees.find((employee) => employee.id === id);
  }

  static add(employee) {
    employees.push(employee);
    return employee;
  }

  static update(id, employee) {
    const index = employees.findIndex((e) => e.id === id);
    employees[index] = employee;
    return employees[index];
  }

  static delete(id) {
    const index = employees.findIndex((employee) => employee.id === id);
    employees.splice(index, 1);
    return employees;
  }
}

module.exports = EmployeeRepository;

// employee.service.js
const EmployeeRepository = require("./employee.repository");

class EmployeeService {
  static findAll() {
    return EmployeeRepository.findAll();
  }

  static findById(id) {
    return EmployeeRepository.findById(id);
  }

  static add(employee) {
    return EmployeeRepository.add(employee);
  }

  static update(id, employee) {
    return EmployeeRepository.update(id, employee);
  }

  static delete(id) {
    return EmployeeRepository.delete(id);
  }
}

module.exports = EmployeeService;

// employee.controller.js
const express = require("express");
const EmployeeService = require("./employee.service");

const router = express.Router();

router.get("/", (req, res) => {
  const employees = EmployeeService.findAll();
  res.status(200).json({ employees });
});

router.get("/:id", (req, res) => {
  const employee = EmployeeService.findById(req.params.id);
  if (!employee) {
    res.status(404).json({ message: "Employee not found." });
    return;
  }
  res.status(200).json({ employee });
});

router.post("/", (req, res) => {
  const employee = EmployeeService.add(req.body);
  res.status(201).json({ employee });
});

router.put("/:id", (req, res) => {
  const employee = EmployeeService.update(req.params.id, req.body);
  if (!employee) {
    res.status(404).json({ message: "Employee not found." });
    return;
  }
  res.status(200).json({ employee });
});

router.delete("/:id", (req, res) => {
  const employees = EmployeeService.delete(req.params.id);
  if (!employees) {
    res.status(404).json({ message: "Employee not found." });
    return;
  }
  res.status(200).json({ employees });
});

module.exports = router;

// server.js
const express = require("express");
const employeeController = require("./employee.controller");

const app = express();

app.use(express.json());
app.use("/employees", employeeController);

app.listen(3000, () => {
  console.log("Employee API server started on port 3000");
});

```
This is a basic implementation of the CRUD REST API for employee records using a layered architecture with controllers, repositories, and services in Express.js with an in-memory array. This can be further enhanced and optimized according to your needs.