Products API is a REST API written in Typescript where products can be created, read, updated and deleted.
Note: This API has been configured for development
environment. To use in a production
environment, further setup will be required.
Requirements:
git clone git@github.com:lucasvmiguel/products-api.git
cd products-api
npm install
- Open a terminal and run the following command to start the persistence (database) required:
npm run persistence:up
- In another terminal, start the application with the following command:
npm run dev
Note: The graphql
schema is not reloaded if there is any changes. You must restart the server to pick up the new changes.
npm run test:unit
npm run test:integration
Requirements:
- Open a terminal and run the following command to start the persistence (database) required:
npm run persistence:up
- In a new terminal, start the application with the following command:
npm run build && npm start
- In another terminal, run the stress test with the following command
npm run test:stress
- To configure how the app will run, check the following file: .env
This section describes what are the goals of the system and some of its design and implementation.
The following list shows all user requirements implemented by the system.
- As a user, I can fetch all products using a REST API.
- As a user, I can fetch a paginated list of products using a REST API.
- As a user, I can fetch a product by its id using a REST API.
- As a user, I can create a product using a REST API.
- As a user, I can update some fields (
name
and/orcode
) of a product by its id using a REST API. - As a user, I can delete a product by its id using a REST API.
The following picture shows all the entities of the system.
The following pictures shows some of the details of how the system is designed and implemented.
/src
: Application source code/test
: All sort of tests. (eg: unit, integration, stress).env
and/src/config.ts
: Configures the application/src/controllers
: Responsible for handling HTTP requests/src/middlewares
: Application middlewares (eg: logging, authentication, etc)/src/services
: Business logic layer for the application/src/resolvers
: Responsible for handling GraphQL queries/src/utils
: Utilities and helpers to create the application/src/routes.ts
: HTTP routes to access the API/src/app.ts
: Configures the application to start/src/index.ts
: Application start file/.github
: CI/CD from Githubdocker-compose.yml
: Used to spin up the persistence layer in development and testingpackage.json
: Project's executable tasks
Inspired by: https://blog.logrocket.com/organizing-express-js-project-structure-better-productivity/
- Language: Node
- API/REST framework: Express
- Database ORM: Prisma
- Config reader: dotenv
- Database: Postgres
This section is described the REST API's endpoints (URL, request, response, etc).
Create product
Endpoint that creates a product
Endpoint: [POST] /api/v1/products
Headers:
Content-Type: application/json
Body:
{
"name": "Product name",
"stock_quantity": 10
}
Success
Status: 201
Body:
{
"id": 1,
"name": "Product name",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 10,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
Bad Request
Status: 400
Internal Server Error
Status: 500
Get products paginated
Endpoint to get products paginated
cursor
: use the response'snext_cursor
fieldlimit
: limit of products to be returned (min=1, max=100)
Endpoint: [GET] /api/v1/products?limit=10&cursor=2
Headers:
Content-Type: application/json
Success
Status: 200
Body:
{
"items": [
{
"id": 1,
"name": "foo",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 1,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
],
"next_cursor": 2
}
Internal Server Error
Status: 500
Get all products
Endpoint to get all products (does not have pagination)
Endpoint: [GET] /api/v1/products/all
Headers:
Content-Type: application/json
Success
Status: 200
Body:
[
{
"id": 1,
"name": "foo",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 1,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
]
Internal Server Error
Status: 500
Get product by id
Endpoint to get a product by id
Endpoint: [GET] /api/v1/products/{id}
Headers:
Content-Type: application/json
Success
Status: 200
Body:
{
"id": 1,
"name": "foo",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 1,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
Not Found
Status: 404
Internal Server Error
Status: 500
Update product by id
Endpoint that updates a product by id
Endpoint: [PUT] /api/v1/products/{id}
Headers:
Content-Type: application/json
Body:
{
"name": "new product name",
"stock_quantity": 5
}
Success
Status: 200
Body:
{
"id": 1,
"name": "new product name",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 5,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
Bad Request
Status: 400
Not Found
Status: 404
Internal Server Error
Status: 500
Delete product by id
Endpoint to delete a product by id
Endpoint: [DELETE] /api/v1/products/{id}
Headers:
Content-Type: application/json
Success
Status: 204
Not Found
Status: 404
Internal Server Error
Status: 500
The API also count with a GraphQL server that can be accessed on the endpoint /graphql
. However, at the moment, only getProduct
resolver is implemented.
A file called .env
has all config used in the project.
In the future, a service like Doppler or Vault could (and should) be used in the project.
The project uses Github CI to run tests, builds (and possibly deployments). You can see the badge below:
Steps:
- Set up Nodejs
- Build
- Unit/Integration Test
- Log in to the Container registry (Github)
- Build and push Docker images
Improvement
: API docs are being described on the Readme. However, OpenAPI might be a good improvement in the future.Improvement
: Using a secret management service like Doppler or VaultChore
add all resolvers from product CRUD to GraphQL's API.Fix
: Date is not returning correctly from the resolvers.Fix
:npm run docker:run
has an issue when copying the prisma client.