add typescript to backend

This commit is contained in:
fred 2025-08-15 15:02:11 -07:00
parent 0a41568a2e
commit 30b28056de
10 changed files with 221 additions and 67 deletions

View file

@ -1,12 +1,17 @@
const RecipeModel = require("../models/recipeModel");
import { Request, Response } from "express";
import RecipeModel from "../models/recipeModel";
const model = new RecipeModel();
exports.test = async (req, res) => {
export const test = async (req: Request, res: Response): Promise<void> => {
console.log("test");
res.json({ env: process.env.NODE_ENV });
};
exports.getAllRecipes = async (req, res) => {
export const getAllRecipes = async (
req: Request,
res: Response,
): Promise<void> => {
try {
const recipes = await model.getAllRecipes();
res.json(recipes);
@ -14,12 +19,15 @@ exports.getAllRecipes = async (req, res) => {
res.status(500).json({
msg: "Failed to fetch all recipes",
source: "recipeController",
error: error.message,
error: error instanceof Error ? error.message : "Unknown error",
});
}
};
exports.getRecipeById = async (req, res) => {
export const getRecipeById = async (
req: Request,
res: Response,
): Promise<void> => {
const id = parseInt(req.params.id, 10);
try {
const recipe = await model.findById(id);
@ -32,12 +40,12 @@ exports.getRecipeById = async (req, res) => {
res.status(500).json({
msg: "Failed to fetch recipe",
source: "recipeController",
error: error.message,
error: error instanceof Error ? error.message : "Unknown error",
});
}
};
exports.addRecipe = async (req, res) => {
export const addRecipe = async (req: Request, res: Response): Promise<void> => {
if (process.env.NODE_ENV === "demo") {
return;
}
@ -48,30 +56,33 @@ exports.addRecipe = async (req, res) => {
res.status(500).json({
msg: "Failed to add recipe",
source: "recipeController",
error: error.message,
error: error instanceof Error ? error.message : "Unknown error",
});
}
};
exports.setStars = async (req, res) => {
export const setStars = async (req: Request, res: Response): Promise<void> => {
if (process.env.NODE_ENV === "demo") {
return;
}
const id = parseInt(req.body.id, 10);
const stars = parseInt(req.body.stars, 10);
try {
const createdRecipe = await model.setStars(id, stars);
res.status(202).json(createdRecipe);
const updatedRecipe = await model.setStars(id, stars);
res.status(202).json(updatedRecipe);
} catch (error) {
res.status(500).json({
msg: "Failed to set stars",
source: "recipeController",
error: error.message,
error: error instanceof Error ? error.message : "Unknown error",
});
}
};
exports.deleteRecipe = async (req, res) => {
export const deleteRecipe = async (
req: Request,
res: Response,
): Promise<void> => {
if (process.env.NODE_ENV === "demo") {
return;
}
@ -83,7 +94,16 @@ exports.deleteRecipe = async (req, res) => {
res.status(500).json({
msg: "Failed to delete recipe",
source: "recipeController",
error: error.message,
error: error instanceof Error ? error.message : "Unknown error",
});
}
};
export default {
test,
getAllRecipes,
getRecipeById,
addRecipe,
setStars,
deleteRecipe,
};

View file

@ -1,18 +1,17 @@
const express = require("express");
const cors = require("cors");
const { PrismaClient } = require("@prisma/client");
const appRoutes = require("./routes/appRoutes");
import express, { Express } from "express";
import cors from "cors";
import { PrismaClient } from "@prisma/client";
import appRoutes from "./routes/appRoutes";
const app = express();
const app: Express = express();
const port = process.env.PORT || 3000;
const prisma = new PrismaClient();
function setupMiddleware(app) {
function setupMiddleware(app: Express) {
app.use(cors());
app.use(express.json());
app.use("/api", appRoutes);
}
setupMiddleware(app);
// Start server

View file

@ -1,29 +1,32 @@
const { PrismaClient } = require("@prisma/client");
const Logger = require("../utils/logger.js");
import { PrismaClient } from "@prisma/client";
import Logger from "../utils/logger";
const logger = new Logger();
class recipeModel {
class RecipeModel {
private prisma: PrismaClient;
constructor() {
this.prisma = new PrismaClient();
}
async getAllRecipes() {
async getAllRecipes(): Promise<any[]> {
try {
return await this.prisma.recipes.findMany();
} catch (err) {
console.error("Error fetching all recipies:", err);
throw new Error(err.message);
console.error("Error fetching all recipes:", err);
throw new Error(err instanceof Error ? err.message : "Unknown error");
}
}
async findById(id) {
async findById(id: number): Promise<any | null> {
try {
const recipe = await this.prisma.recipes.findUnique({
where: { id },
include: { recipeSteps: true, recipeIngredients: true },
});
if (!recipe) {
logger.warn(`recipe with id ${id} cannot be found`);
logger.warn(`Recipe with id ${id} cannot be found`);
return null;
}
const data = {
@ -37,7 +40,7 @@ class recipeModel {
cook_minutes: recipe.cook_minutes,
},
ingredients: recipe.recipeIngredients.map((ing) => ing.raw),
steps: recipe.recipeSteps.map((step, idx) => ({
steps: recipe.recipeSteps.map((step) => ({
step_number: step.step_number,
instruction: step.instruction,
})),
@ -45,11 +48,23 @@ class recipeModel {
return data;
} catch (err) {
console.log("Error finding recipe:", err);
logger.error("error finding recipe", err);
throw new Error(err.message);
logger.error("Error finding recipe", {
message: err instanceof Error ? err.message : "Unknown error",
});
throw new Error(err instanceof Error ? err.message : "Unknown error");
}
}
async addRecipe(recipeData) {
async addRecipe(recipeData: {
name: string;
author: string;
cuisine: string;
stars: number;
ingredients: string[];
steps: { [key: string]: string };
prep_minutes: number;
cook_minutes: number;
}): Promise<any> {
const {
name,
author,
@ -81,33 +96,37 @@ class recipeModel {
},
});
logger.info("new recipe created", {
logger.info("New recipe created", {
id: createdRecipe.id,
name: createdRecipe.name,
});
return createdRecipe;
} catch (error) {
console.log(error);
logger.error("error creating recipe", err);
} catch (err) {
console.log("Error creating recipe:", err);
logger.error("Error creating recipe", {
message: err instanceof Error ? err.message : "Unknown error",
});
throw new Error("Failed to add recipe");
}
}
async setStars(id, stars) {
async setStars(id: number, stars: number): Promise<{ message: string }> {
try {
await this.prisma.recipes.update({
where: { id },
data: { stars },
});
return { message: "stars updated" };
return { message: "Stars updated" };
} catch (err) {
console.error("Error updating stars:", err);
logger.error("error setting stars", err);
throw new Error(err.message);
logger.error("Error setting stars", {
message: err instanceof Error ? err.message : "Unknown error",
});
throw new Error(err instanceof Error ? err.message : "Unknown error");
}
}
async deleteRecipe(id) {
async deleteRecipe(id: number): Promise<{ message: string }> {
try {
await this.prisma.recipe_ingredients.deleteMany({
where: { recipe_id: id },
@ -119,16 +138,19 @@ class recipeModel {
const deletedRecipe = await this.prisma.recipes.delete({
where: { id },
});
logger.info("recipe deleted", {
logger.info("Recipe deleted", {
id: deletedRecipe.id,
name: deletedRecipe.name,
});
return { message: "Recipe deleted successfully" };
} catch (err) {
console.error("Error deleting recipe:", err);
logger.error("error deleting recipe", err);
throw new Error(err.message);
logger.error("Error deleting recipe", {
message: err instanceof Error ? err.message : "Unknown error",
});
throw new Error(err instanceof Error ? err.message : "Unknown error");
}
}
}
module.exports = recipeModel;
export default RecipeModel;

View file

@ -1,5 +1,5 @@
const express = require("express");
const recipeController = require("../controllers/recipeController");
import express, { Router } from "express";
import recipeController from "../controllers/recipeController";
const router = express.Router();
@ -15,4 +15,4 @@ router.post("/set-stars", recipeController.setStars);
router.delete("/delete-recipe", recipeController.deleteRecipe);
module.exports = router;
export default router;

View file

@ -1,11 +1,13 @@
const fs = require("fs");
import fs from "fs";
class Logger {
constructor(filePath) {
this.filePath = "/logs/app.log";
private filePath: string;
constructor(filePath: string = "/logs/app.log") {
this.filePath = filePath;
}
log(level, message, params) {
private log(level: string, message: string, params?: object) {
const logEntry = {
timestamp: new Date().toISOString(),
level: level,
@ -17,17 +19,17 @@ class Logger {
});
}
info(message, params = {}) {
info(message: string, params: object = {}) {
this.log("info", message, params);
}
warn(message, params = {}) {
warn(message: string, params: object = {}) {
this.log("warn", message, params);
}
error(message, params = {}) {
error(message: string, params: object = {}) {
this.log("error", message, params);
}
}
module.exports = Logger;
export default Logger;