From e89bc6d508c7f82b9e8a7e9a629c7ee5edb8c119 Mon Sep 17 00:00:00 2001 From: Sugui Date: Wed, 27 Dec 2023 17:58:59 +0100 Subject: [PATCH] Separated things into Model-Service-Controller pattern --- src/controllers/ImageController.ts | 33 ++++++++++++++++++++++++++++++ src/index.ts | 31 ++++------------------------ src/{ => models}/ImageModel.ts | 10 +++++++-- src/services/ImageService.ts | 14 +++++++++++++ tests/app.test.ts | 10 ++++++--- 5 files changed, 66 insertions(+), 32 deletions(-) create mode 100644 src/controllers/ImageController.ts rename src/{ => models}/ImageModel.ts (55%) create mode 100644 src/services/ImageService.ts diff --git a/src/controllers/ImageController.ts b/src/controllers/ImageController.ts new file mode 100644 index 0000000..1b24a08 --- /dev/null +++ b/src/controllers/ImageController.ts @@ -0,0 +1,33 @@ +import { Request, Response } from "express"; +import imageService from "../services/ImageService"; + +class ImageController { + async getAllImages(req: Request, res: Response): Promise { + try { + const images = await imageService.findAll(); + res.json({ message: images }); + } catch (error) { + console.error(error); + res.status(500).json({ message: "Internal Server Error" }); + } + } + + async addImage(req: Request, res: Response): Promise { + try { + // Should add auth here before doing stuff + // Thowing a 401 if not auth provided + // Throwing a 403 for incorrect auth + const image = await imageService.add(req.body); + res.status(201).json({ message: image }); + } catch (error: any) { + if (error.code === 11000) { + // Should return 409 Conflict for existing urls + res.status(409).json({ message: "Existing URL" }); + } + // Should return 400 Bad request for invalid requests + res.status(400).json({ message: error }); + } + } +} + +export default new ImageController(); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 9fbb393..8113fb9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import express from "express"; import mongoose from "mongoose"; -import ImageModel from "./ImageModel"; import listEndpoints from "express-list-endpoints"; +import imageController from "./controllers/ImageController"; export const app = express(); @@ -9,34 +9,11 @@ app.use(express.json()); app.get("/", (_, res) => { const endpoints = listEndpoints(app); - res.json({ endpoints }); + res.json({ message: endpoints }); }); -app.get("/images", async (_, res) => { - try { - const allImages = await ImageModel.find(); - res.json({ message: allImages }); - } catch (error) { - res.status(500).json({ message: error }); - } -}); - -app.post("/images", async (req, res) => { - try { - // Should add auth here before doing stuff - // Thowing a 401 if not auth provided - // Throwing a 403 for incorrect auth - const image = await ImageModel.create(req.body); - res.status(201).json({ message: image }); - } catch (error: any) { - if (error.code == 11000) { - // Should return 409 Conflict for existing urls - res.status(409).json({ message: "Existing URL" }); - } - // Should return 400 Bad request for invalid requests - res.status(400).json({ message: error }); - } -}); +app.get("/images", imageController.getAllImages); +app.post("/images", imageController.addImage); // Set the default port to 8080, or use the PORT environment variable diff --git a/src/ImageModel.ts b/src/models/ImageModel.ts similarity index 55% rename from src/ImageModel.ts rename to src/models/ImageModel.ts index 0a74f50..5ef3b70 100644 --- a/src/ImageModel.ts +++ b/src/models/ImageModel.ts @@ -1,4 +1,10 @@ -import mongoose from "mongoose"; +import mongoose, { Document } from "mongoose"; + +export interface Image extends Document { + url: String; + enum: "consumed" | "unavailable" | "available"; + tags?: String[]; +} const ImageSchema = new mongoose.Schema({ url: { @@ -17,4 +23,4 @@ const ImageSchema = new mongoose.Schema({ } }); -export default mongoose.model('images', ImageSchema); +export default mongoose.model('images', ImageSchema); diff --git a/src/services/ImageService.ts b/src/services/ImageService.ts new file mode 100644 index 0000000..c8a3c16 --- /dev/null +++ b/src/services/ImageService.ts @@ -0,0 +1,14 @@ +import ImageModel, { Image } from "../models/ImageModel"; + +class ImageService { + async findAll(): Promise { + const allImages = await ImageModel.find(); + return allImages; + } + async add(image: Image): Promise { + const newImage = await ImageModel.create(image); + return newImage; + } +} + +export default new ImageService(); \ No newline at end of file diff --git a/tests/app.test.ts b/tests/app.test.ts index 59a1810..895542c 100644 --- a/tests/app.test.ts +++ b/tests/app.test.ts @@ -2,18 +2,22 @@ import { describe, expect, it, mock } from "bun:test"; import request from "supertest"; import { app } from "../src"; -describe("GET / shows what it should",async () => { +describe("GET / shows all of the endpoints", async () => { const res = await request(app).get("/"); it("should be", async () => { - expect(res.body).toHaveProperty("message", "Blazing fast 🚀"); + expect(res.body).toHaveProperty("message"); }); + + it("should be an array", () => { + expect(Array.isArray(res.body.message)).toBeTrue(); + }) }) describe("GET /images works properly", async () => { const res = await request(app).get("/images"); - it("should be an array", async () => { + it("should be an array", () => { expect(Array.isArray(res.body.message)).toBeTrue(); });