Technologies:
- Node.js
- Nest.js
- TypeScript
- MongoDB
- JWT
- Jest
- Redis
- SuperTest
GET /dishes?ings=ingredient1,ingredient2,ingredientX&type=meal-type&dish=dish-type
- returns all dishes from the database that contain provided ingredients and type asings
,type
anddish
respectively being query params. Additionally, setAccept-Language
header to define language of ingredients.GET /dishes/:id
- returns a specific dish defined by id parameter. It saves to the cache, if it does not exist there. Each request checks the cache.GET /dishes/:id/details
- returns details of a dish. It can be any dish provided by any external or local API.GET /dishes/:id/comments
- returns all comments for a specific dish.GET /dishes/:id/rating
- returns average rating for a specific dish.GET /dishes/proposal/all
- returns top 10 dish proposals for a specific user defined byaccessToken
.GET /dishes/soft/added
- returns all dish havingsoft-added
property.GET /dishes/soft/edited
- returns all dish havingsoft-edited
property.GET /dishes/soft/deleted
- returns all dish havingsoft-deleted
property.POST /dishes/:id/comment
- posts a new comment to a particular dish. You need to be logged-in.
{
"dishId": "123",
"text": "That's an awesome dish!"
}
POST /dishes/:id/rating
- posts a new rating to a specific dish. You need to be logged-in.
{
"dishId": "123",
"rating": 8
}
POST /dishes/proposal
- posts query including ingredients. Works for only logged-in users.
{
"ingredients": [
"ingredient-name-1",
"ingredient-name-2",
"ingredient-name-X"
]
}
POST /dishes/create
- creates a new dish and saves its to the database, marking as soft added. You need to be logged-in and provide following data (imageUrl
is optional):
{
"description": "The best dish ever",
"title": "New awesome dish",
"ingredients": [
{
"id": "ingredient-id-1",
"name": "Ingredient 1",
"amount": 5,
"unit": "piece"
},
{
"id": "ingredient-id-2",
"name": "Ingredient 2",
"amount": 2,
"unit": "jar"
},
{
"id": "ingredient-id-x",
"name": "Ingredient X",
"amount": 1,
"unit": "serving"
}
],
"imageUrl": "https://some.domain/path/to/resource/image.ext",
"readyInMinutes": 50,
"recipeSections": [
{
"name": "",
"steps": [
"Heat up to 100 degrees.",
"Mix everything",
"Enjoy your dish! :)"
]
}
],
"type": "soup",
"mealType": "launch"
}
PUT /dishes/:id
- updates (edits) a dish and marks as soft edited. Provide following data, where each property is optional:
{
"title": "New dish title",
"description": "New description",
"readyInMinutes": 80,
"type": "main course",
"dishType": "launch",
"ingredients": [
{
"id": "ingredient-id-2",
"name": "x2",
"amount": 5,
"unit": "cup"
},
{
"id": "ingredient-id-x",
"name": "x1",
"amount": 1.5,
"unit": "pieces"
}
],
"imgUrl": "https://host.com/new-img-url"
}
DELETE /dishes/:id
- deletes a dish. It marks dish as soft deleted.POST /dishes/:id/create
- confirm adding a new dish. You need to be logged-in and hascanAdd
capability (or be an admin).POST /dishes/:id/edit
- confirm editing a dish. You need to be logged-in and hascanEdit
capability (or be an admin).POST /dishes/:id/delete
- confirm deleting a dish. You need to be logged-in and hascanDelete
capability (or be an admin).
POST /users/create
- register a new user. You need to provide following data:
{
"email": "[email protected]",
"login": "userName",
"password": "123"
}
POST /users/login
- log in a user. Only activated users can log in. You need to provide following data:
{
"login": "userName",
"password": "123"
}
-
POST /users/logout
- log out a user. -
POST /users/refreshTokens
- refreshes the user tokens. -
POST /users/:login/grant/:capability
- grants a new permission to a user by admin. You need to havejwt
token (you need to be logged-in) and you are an admin.login
is user login whom you want to grant a permission.capability
is value one ofcanAdd
,canEdit
,canDelete
. -
POST /users/:login/deny/:capability
- denies a permission to a user by admin. You need to havejwt
token (you need to be logged-in) and you are an admin.login
is user login whom you want to deny a permission.capability
is value one ofcanAdd
,canEdit
,canDelete
. -
POST /users/activate/:userActionId
- activates a user.userActionId
is activation code, sent in the mail message. -
GET /users/not-activated
- returns all not activated user accounts. -
POST /users/:id/activate
- activates a user.id
indicates which user should be activated only by admin. -
POST /users/change-password
- changes password and generates new salt for the user. IncludenewPassword
within a body to define its.
{
"newPassword": "my new password"
}
All above endpoints excluding GET /dishes
and GET /dishes/:id
require accessToken
as a cookie.
-
POST /images/upload
- uploads a new image. You need to be logged-in and havecaAdd
capability or be an admin. Image should be passed asimage
property in form data. The image constraint is 512 KB. -
serverUrl/images/dishes/${filename}
- returns image as a static file.
To set up this backend application, you need to define the following variables:
To connect with local database, you need:
DB_HOSTNAME
(hostname for MongoDB)DB_PORT
(port for MongoDB)DB_COLLECTION
(collection in the database)
However, if you want to connect with MongoDB Atlas, you need these variables:
DB_USER
(MongoDB user)DB_PASS
(password for MongoDB)PROD=true
To connect to Redis, you need:
REDIS_HOSTNAME
(default islocalhost
)REDIS_PORT
(default is6379
)
To connect to MSA, you need:
MAIL_USER
(mail address)MAIL_PASS
(password for mail address)MAIL_HOST
(smtp address)MAIL_PORT
(smtp port)
To connect to Spoonacular API, provide:
SPOONACULAR_API_KEY
(API key defined for a particular account on Spoonacular)
Provide PASSWORD_PEPPER
to protect all user account passwords.
Provide FRONTEND_WEB
, FRONTEND_MOBILE
URLs to enable CORS for themselves, e.g. http://localhost:3000
.
Also, you can add FRONTEND_OTHERS
URLs providing a string, concatenated with ,
character, i.e. http://localhost:3000,http://localhost:3001
.
You need to change version in package.json
and add a record to the CHANGELOG.md
.
Before creating a pull request, you need to execute following commands, with success result:
npm run lint:fix
npm run test
npm run test:e2e
To create a new module, you need to use:
nest g mo modules/<module_name>
to create a new module.nest g co modules/<module_name>
to create a new controller.nest g s modules/<module_name>
to create a new service.