I'm learning JavaScript with Express.js Framework. I'm trying to create a simple project for a restaurant (just for learning purposes), and I'm trying to create the CRUD of ingredients. I created the repository for all Prisma (ORM) requests, the service with business logic, and a controller for request/response handling. I wish to know if there is a better way of instantiating the service and repository on my controller. I'm doing that for each method. It worked, but I'm repeating this code block a lot.
This is IngredientRepository:
const prisma = require("../../prisma/client");
class IngredientRepository {
async create({ name, price, image }) {
return await prisma.ingredient.create({
data: {
name,
price,
image,
},
});
}
async findByName({ name }) {
return await prisma.ingredient.findUnique({ where: { name } });
}
async findById({ id }) {
return await prisma.ingredient.findUnique({
where: { id },
});
}
async updateImage({ id, image }) {
return await prisma.ingredient.update({
where: { id },
data: {
image,
},
});
}
}
module.exports = IngredientRepository;
IngredientService:
const Error = require("../middlewares/Error");
const DiskStorage = require("../providers/DiskStorage");
class IngredientService {
constructor(ingredientRepository, userRepository) {
this.ingredientRepository = ingredientRepository;
this.userRepository = userRepository;
}
async create({ name, price, image, loggedUser }) {
const userIsAdmin = await this.userRepository.findById({ loggedUser });
if (userIsAdmin.admin) {
throw Error("", 401);
}
const ingredient = await this.ingredientRepository.findByName({
name: name.toLowerCase(),
});
if (ingredient) {
throw new Error("Ingredient already exists");
}
return await this.ingredientRepository.create({
name: name.toLowerCase(),
price,
image,
});
}
async updateImage({ id, image }) {
const diskStorage = new DiskStorage();
const ingredient = await this.ingredientRepository.findById({ id: id.id });
if (!ingredient) {
throw new Error("This ingredient doesn't exist", 401);
}
if (ingredient.image) {
await diskStorage.deleteFile(ingredient.image);
}
const filename = await diskStorage.saveFile(image);
ingredient.image = filename;
const updatedIngredient = await this.ingredientRepository.updateImage({
id: id.id,
image: ingredient.image,
});
return updatedIngredient;
}
}
module.exports = IngredientService;
IngredientController:
const IngredientRepository = require("../repositories/IngredientRepository");
const UserRepository = require("../repositories/UserRepository");
const IngredientService = require("../services/IngredientService");
class IngredientController {
async create(request, response) {
const ingredientRepository = new IngredientRepository();
const userRepository = new UserRepository();
const ingredientService = new IngredientService(
ingredientRepository,
userRepository
);
const loggedUser = request.user.id;
const { name, price, image } = request.body;
const ingredientCreated = await ingredientService.create({
loggedUser,
name,
price,
image,
});
return response.json(ingredientCreated);
}
async updateImage(request, response) {
const ingredientRepository = new IngredientRepository();
const userRepository = new UserRepository();
const ingredientService = new IngredientService(
ingredientRepository,
userRepository
);
const loggedUser = request.user.id;
const id = request.params;
const image = request.file.filename;
const ingredientWithImageUpdated = await ingredientService.updateImage({
loggedUser,
id,
image,
});
return response.json(ingredientWithImageUpdated);
}
}
module.exports = IngredientController;
CodePudding user response:
It is possible to create your dependencies in constructor of IngredientController
and then use that objects in methods.
Let me show an example:
class IngredientRepository {
findByName() {
return 'findByName: ' Date.now();
}
}
and:
class IngredientController {
constructor (){
this.ingredientRepository = new IngredientRepository();
}
create(){
// you can use your object here
console.log(this.ingredientRepository.findByName())
}
update(){
// you can use your object here
console.log(this.ingredientRepository.findByName())
}
}
An example:
class IngredientRepository {
findByName() {
return 'findByName: ' Date.now();
}
}
class IngredientController {
constructor (){
this.ingredientRepository = new IngredientRepository();
}
create(){
console.log(this.ingredientRepository.findByName())
}
update(){
console.log(this.ingredientRepository.findByName())
}
}
const ingredientController = new IngredientController();
console.log(ingredientController.create())
console.log(ingredientController.update())