This project was developed as a technical challenge for the Lexart junior full-stack developer position. It is a full-stack web application designed for product management.
The application is currently deployed and accessible at this link
- First of all, you need to have the Docker and Docker Compose installed.
- Ensure that ports
3000
,3001
and5432
on your computer are available; otherwise, errors may occur. - Install all dependencies running:
npm run install:all
- Inside each directory there is a
.env.example
file that you can configure manually or run the command:
npm run setup:env
- Finally run:
npm run docker:up
Now just go to localhost:3000 that you will see something like that:
And go to localhost:3001 that you will see something like that:
The application will spin up three containers: one for the backend, one for the frontend, and one for the database.
See more
The database used was Postgres for its speed, versatility and easy use. The structure chosen was as follows.See more
/signup
Parameter | Type | Description |
---|---|---|
username |
string |
At least 3 characters. |
password |
string |
At least 5 characters. |
Expected return
- status code
201
{
"id": 1,
"username": "Jorel",
"token": "exampletoken.exampletoken.exampletoken"
}
/login
Parameter | Type | Description |
---|---|---|
username |
string |
At least 3 characters. |
password |
string |
At least 5 characters. |
Expected return
- status code
200
{
"id": 1,
"username": "example",
"token": "exampletoken.exampletoken.exampletoken"
}
Token
is required onAuthorization
header. Ex:Baerer ${token}
this route accept three different structures
- First structure
{
"name": "Xiaomi Redmi 9",
"brand": "Xiaomi",
"model": "Redmi 9",
"price": 10000,
"color": "red"
}
- Second structure
{
"name": "Xiaomi Redmi 9",
"price": 10000,
"details": {
"brand": "Xiaomi",
"model": "Redmi 9",
"color": "red"
},
}
- Third structure
[
{
"name": "Xiaomi Redmi 9",
"brand": "Xiaomi",
"model": "Redmi 9",
"data": [
{
"price": 10000,
"color": "red"
},
{
"price": 10000,
"color": "blue"
}
]
},
{
"name": "Iphone 14 Pro",
"brand": "Iphone",
"model": "14 Pro",
"data": [
{
"price": 30000,
"color": "silver"
},
{
"price": 30100,
"color": "gold"
}
]
}
]
/dashboard/product
Parameter | Type | Description |
---|---|---|
name |
string |
At least 1 characters. |
brand |
string |
At least 1 characters. |
model |
string |
At least 1 characters. |
color |
string |
At least 1 characters. |
price |
number |
Is required. |
Expected return
- status code
201
this route can return two different structures
- First structure
{
"id": 1
"name": "Xiaomi Redmi 9",
"brand": "Xiaomi",
"model": "Redmi 9",
"price": 10000,
"color": "red",
"userId": 1
}
- Second structure
[
{
"id": 5,
"name": "Xiaomi Redmi 9",
"brand": "Xiaomi",
"model": "Redmi 9",
"price": 10000,
"color": "red",
"userId": 1
},
{
"id": 6,
"name": "Xiaomi Redmi 9",
"brand": "Xiaomi",
"model": "Redmi 9",
"price": 10000,
"color": "blue",
"userId": 1
},
{
"id": 7,
"name": "Iphone 14 Pro",
"brand": "Iphone",
"model": "14 Pro",
"price": 30000,
"color": "silver",
"userId": 1
},
{
"id": 8,
"name": "Iphone 14 Pro",
"brand": "Iphone",
"model": "14 Pro",
"price": 30100,
"color": "gold",
"userId": 1
}
]
Token
is required onAuthorization
header. Ex:Baerer ${token}
/dashboard/product
Expected return
- status code
200
[
{
"id": 5,
"name": "Xiaomi Redmi 9",
"brand": "Xiaomi",
"model": "Redmi 9",
"price": 10000,
"color": "red",
},
{
"id": 6,
"name": "Xiaomi Redmi 9",
"brand": "Xiaomi",
"model": "Redmi 9",
"price": 10000,
"color": "blue",
},
{
"id": 7,
"name": "Iphone 14 Pro",
"brand": "Iphone",
"model": "14 Pro",
"price": 30000,
"color": "silver",
},
{
"id": 8,
"name": "Iphone 14 Pro",
"brand": "Iphone",
"model": "14 Pro",
"price": 30100,
"color": "gold",
}
]
Token
is required onAuthorization
header. Ex:Baerer ${token}
/dashboard/product
Parameter | Type | Description |
---|---|---|
id |
number |
Is required. |
name |
string |
At least 1 characters. |
brand |
string |
At least 1 characters. |
model |
string |
At least 1 characters. |
color |
string |
At least 1 characters. |
price |
number |
At least 1 characters. |
Expected return
- status code
200
{
"id": 4,
"name": "Xiaomi Poco F3",
"price": 2000,
"brand": "Xiaomi",
"model": "Poco F3",
"color": "Blue"
}
Token
is required onAuthorization
header. Ex:Baerer ${token}
/dashboard/product/:id
Expected return
- status code
204
empty return
Token
is required onAuthorization
header. Ex:Baerer ${token}
/user
Expected return
- status code
200
{
"username": "Jorel"
}
See more
The API tests were run by the Mocha
, Chai
, and Sinon
. Also nyc
librarie that test file coverage.
There are both integration and unit tests for better security in future updates.
To run tests coverage use:
npm run test:api:coverage
See more
The MSC (Model, Service, Controller) architectural pattern provides a structured approach to building APIs by segregating responsibilities into distinct layers: Model, Service, and Controller. This separation enhances maintainability, facilitates easier troubleshooting, and promotes scalability within the application.
The Model layer serves as the interface for database interactions. It encapsulates all database-related operations, such as querying, inserting, updating, and deleting data. By handling these tasks, the Model ensures data integrity and consistency while abstracting the database complexity from other layers.
The Service layer encapsulates the business logic and rules of the application. It utilizes the functionalities provided by the Model layer and implements the core logic required to process requests. This layer orchestrates different operations, enforces business rules, and acts as an intermediary between the Controller and the Model.
The Controller layer serves as the entry point for incoming requests and handles the interaction with the client. It receives requests, processes input data, calls the appropriate Service methods, and generates responses to send back to the client. The Controller ensures that the responses adhere to the required format and contain the necessary information.
- Maintainability: The separation of concerns allows for easier maintenance and updates. Each layer can be modified or expanded without affecting the others, facilitating code management.
- Scalability: The modular structure enables easy scalability as different layers can be scaled independently based on the application's requirements.
- Testing: The distinct layers facilitate unit testing, as each layer can be tested separately, promoting better test coverage and reliability.
See more
The API use Bcrypt the keep your password safe even if the database have a invasion.
The database dashboard:
Both the /frontend
and /backend
folders have their respective README.md
for some more details. Visit to find out more.
Thank you for your attention.