From 773b4773ebf318310fbd4aedba1d267541907262 Mon Sep 17 00:00:00 2001 From: Fred Date: Fri, 25 Jul 2025 18:07:20 +0000 Subject: [PATCH] initial production commit --- backend/Dockerfile | 2 +- backend/backendServer.js | 101 ++++++++++++++++----------- backend/knexfile.js | 39 ++++++----- backend/package.json | 3 +- docker-compose.yaml | 8 +-- frontend/Dockerfile | 2 +- frontend/package.json | 3 +- frontend/src/services/frontendApi.js | 41 ++++++----- frontend/vite.config.ts | 10 ++- 9 files changed, 116 insertions(+), 93 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 5f442d8..ce6356c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -10,4 +10,4 @@ COPY . . EXPOSE 3000 -CMD ["npm", "run", "dev"] +CMD ["npm", "run", "production"] diff --git a/backend/backendServer.js b/backend/backendServer.js index d998d67..488efa1 100644 --- a/backend/backendServer.js +++ b/backend/backendServer.js @@ -1,21 +1,26 @@ const express = require("express"); const db = require("./db"); const port = 3000; -const cors = require('cors') +const cors = require("cors"); const app = express(); -app.use(cors()); +app.use( + cors({ + origin: "https://ec683cee72d30c5030.fredzernia.com/", + credentials: true, + }), +); app.use(express.json()); // ####### ROUTES ####### -app.get("/test", async (req, res) => { - console.log('test') - res.json({ test: 'test' }) +app.get("/backend/test", async (req, res) => { + console.log("test"); + res.json({ test: "test" }); }); // ### GET ALL RECIPES ### -app.get("/recipes", async (req, res) => { +app.get("/backend/recipes", async (req, res) => { try { - const recipes = await db('recipes').select('id', 'name', 'cuisine'); + const recipes = await db("recipes").select("id", "name", "cuisine"); res.json(recipes); } catch (err) { console.log(err); @@ -23,9 +28,9 @@ app.get("/recipes", async (req, res) => { } }); // ### GET ALL RECIPE_INGREDIENTS ### -app.get("/recipe-ingredients", async (req, res) => { +app.get("/backend/recipe-ingredients", async (req, res) => { try { - const recipe_ingredients = await db('recipe_ingredients').select('*'); + const recipe_ingredients = await db("recipe_ingredients").select("*"); res.json(recipe_ingredients); } catch (err) { console.log(err); @@ -33,9 +38,9 @@ app.get("/recipe-ingredients", async (req, res) => { } }); // ### GET ALL RECIPE_STEPS ### -app.get("/recipe-steps", async (req, res) => { +app.get("/backend/recipe-steps", async (req, res) => { try { - const recipe_steps = await db('recipe_steps').select('*'); + const recipe_steps = await db("recipe_steps").select("*"); res.json(recipe_steps); } catch (err) { console.log(err); @@ -44,21 +49,32 @@ app.get("/recipe-steps", async (req, res) => { }); // ### GET RECIPE ### -app.get("/recipe/:id", async (req, res) => { - const id = req.params.id +app.get("/backend/recipe/:id", async (req, res) => { + const id = req.params.id; try { - const recipeQuery = db('recipes').where('id', '=', id).select('id', 'name', 'author', 'cuisine', 'stars'); + const recipeQuery = db("recipes") + .where("id", "=", id) + .select("id", "name", "author", "cuisine", "stars"); - const ingredientsQuery = db.from('recipe_ingredients').where('recipe_id', '=', id).select('raw'); + const ingredientsQuery = db + .from("recipe_ingredients") + .where("recipe_id", "=", id) + .select("raw"); - const stepsQuery = db('recipe_steps').where('recipe_id', id).select('step_number', 'instruction'); + const stepsQuery = db("recipe_steps") + .where("recipe_id", id) + .select("step_number", "instruction"); - const [recipe, ingredients, steps] = await Promise.all([recipeQuery, ingredientsQuery, stepsQuery]); + const [recipe, ingredients, steps] = await Promise.all([ + recipeQuery, + ingredientsQuery, + stepsQuery, + ]); const result = { details: recipe[0], ingredients: ingredients, - steps: steps + steps: steps, }; res.json(result); @@ -69,29 +85,32 @@ app.get("/recipe/:id", async (req, res) => { }); // ### ADD RECIPE ### -app.post("/add-recipe", async (req, res) => { +app.post("/backend/add-recipe", async (req, res) => { const { name, author, cuisine, stars, ingredients, steps } = req.body; try { - const [id] = await db('recipes').insert({ - name: name, - author: author, - cuisine: cuisine, - stars: stars - }, ['id']) + const [id] = await db("recipes").insert( + { + name: name, + author: author, + cuisine: cuisine, + stars: stars, + }, + ["id"], + ); - const ingredientInserts = ingredients.map(ing => ({ + const ingredientInserts = ingredients.map((ing) => ({ recipe_id: id.id, - raw: ing + raw: ing, })); // - await db('recipe_ingredients').insert(ingredientInserts); + await db("recipe_ingredients").insert(ingredientInserts); - const stepInserts = Object.keys(steps).map(stepNumber => ({ + const stepInserts = Object.keys(steps).map((stepNumber) => ({ recipe_id: id.id, step_number: parseInt(stepNumber), - instruction: steps[stepNumber] + instruction: steps[stepNumber], })); - await db('recipe_steps').insert(stepInserts); + await db("recipe_steps").insert(stepInserts); res.status(200).send({ message: "Recipe added", id: id.id }); } catch (err) { @@ -101,13 +120,11 @@ app.post("/add-recipe", async (req, res) => { }); // ### SET STARS ### -app.post("/set-stars", async (req, res) => { +app.post("/backend/set-stars", async (req, res) => { const { id, stars } = req.body; try { - await db('recipes') - .where({ id: id }) - .update({ stars: stars }) - res.status(200).send({ message: "stars updated" }) + await db("recipes").where({ id: id }).update({ stars: stars }); + res.status(200).send({ message: "stars updated" }); } catch (err) { console.log(err); res.status(500).json({ error: err.message }); @@ -115,12 +132,12 @@ app.post("/set-stars", async (req, res) => { }); // ### DELETE RECIPE ### -app.delete("/delete-recipe", async (req, res) => { +app.delete("/backend/delete-recipe", async (req, res) => { const { id } = req.body; try { - await db('recipe_steps').where({ recipe_id: id }).del(); - await db('recipe_ingredients').where({ recipe_id: id }).del(); - await db('recipes').where({ id: id }).del(); + await db("recipe_steps").where({ recipe_id: id }).del(); + await db("recipe_ingredients").where({ recipe_id: id }).del(); + await db("recipes").where({ id: id }).del(); res.status(200).send({ message: "Recipe deleted" }); } catch (err) { console.log(err); @@ -130,8 +147,8 @@ app.delete("/delete-recipe", async (req, res) => { app.listen(port, () => console.log(`Server has started on port: ${port}`)); -process.on('SIGINT', async () => { - console.log('Closing database connection...'); +process.on("SIGINT", async () => { + console.log("Closing database connection..."); await db.destroy(); process.exit(0); }); diff --git a/backend/knexfile.js b/backend/knexfile.js index 815faad..74075d9 100644 --- a/backend/knexfile.js +++ b/backend/knexfile.js @@ -1,40 +1,41 @@ -require('dotenv').config(); +require("dotenv").config(); module.exports = { - development: { - client: 'postgresql', + client: "postgresql", connection: { - host: 'db', - port: 5432, + host: "db", + port: process.env.DB_PORT, database: process.env.DB_NAME, user: process.env.DB_USER, - password: process.env.DB_PASSWORD + password: process.env.DB_PASSWORD, }, pool: { min: 2, - max: 10 + max: 10, }, migrations: { - tableName: 'knex_migrations', - directory: './migrations' - } + tableName: "knex_migrations", + directory: "./migrations", + }, }, production: { - client: 'postgresql', + client: "postgresql", connection: { - database: 'my_db', - user: 'username', - password: 'password' + host: "db", + port: process.env.DB_PORT, + database: process.env.DB_NAME, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, }, pool: { min: 2, - max: 10 + max: 10, }, migrations: { - tableName: 'knex_migrations' - } - } - + tableName: "knex_migrations", + directory: "./migrations", + }, + }, }; diff --git a/backend/package.json b/backend/package.json index d80c1a0..9eac5ca 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,7 +4,8 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "dev": "node backendServer.js" + "dev": "node backendServer.js", + "production": "node backendServer.js" }, "keywords": [], "author": "", diff --git a/docker-compose.yaml b/docker-compose.yaml index 6ea828c..99cd7e7 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -10,7 +10,7 @@ services: - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=${DB_NAME} ports: - - "5432:5432" + - "${DB_PORT}:5432" volumes: - ./postgres/db:/var/lib/postgresql/data backend: @@ -22,7 +22,7 @@ services: volumes: - ./backend:/usr/src/app environment: - - NODE_ENV=development + - NODE_ENV=production - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} @@ -31,8 +31,8 @@ services: container_name: recipes_frontend build: ./frontend ports: - - "8080:80" + - "8081:80" volumes: - ./frontend:/usr/src/app environment: - - NODE_ENV=development + - NODE_ENV=production diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 98d1043..765c2ee 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -10,4 +10,4 @@ COPY . . EXPOSE 80 -CMD ["npm", "run", "dev"] +CMD ["npm", "run", "production"] diff --git a/frontend/package.json b/frontend/package.json index 974ef0d..3be63aa 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,7 +4,8 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite --host --port 80", + "dev": "vite --host 0.0.0.0 --port 80", + "production": "vite --host 0.0.0.0 --port 80", "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview" diff --git a/frontend/src/services/frontendApi.js b/frontend/src/services/frontendApi.js index bd0cd53..a788cad 100644 --- a/frontend/src/services/frontendApi.js +++ b/frontend/src/services/frontendApi.js @@ -1,34 +1,34 @@ export const getRecipes = async () => { - const response = await fetch("http://localhost:3000/recipes"); + const response = await fetch("/backend/recipes"); const data = await response.json(); return data; }; export const getRecipeSteps = async () => { - const response = await fetch("http://localhost:3000/recipe-steps"); + const response = await fetch("/backend/recipe-steps"); const data = await response.json(); return data; }; export const getRecipeIngredients = async () => { - const response = await fetch("http://localhost:3000/recipe-ingredients"); + const response = await fetch("/backend/recipe-ingredients"); const data = await response.json(); return data; }; export const getRecipeById = async (id) => { - const response = await fetch(`http://localhost:3000/recipe/${id}`); + const response = await fetch(`/backend/recipe/${id}`); const data = await response.json(); return data; }; export const addRecipe = async (recipeData) => { - console.log(JSON.stringify(recipeData)) + console.log(JSON.stringify(recipeData)); // return - const response = await fetch("http://localhost:3000/add-recipe", { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(recipeData) + const response = await fetch("/backend/add-recipe", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(recipeData), }); const data = await response.json(); console.log(data); @@ -36,27 +36,26 @@ export const addRecipe = async (recipeData) => { }; export const setDBStars = async (id, stars) => { - console.log(JSON.stringify({ id: id, stars: stars })) + console.log(JSON.stringify({ id: id, stars: stars })); // return - const response = await fetch("http://localhost:3000/set-stars", { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ id: id, stars: stars }) + const response = await fetch("/backend/set-stars", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ id: id, stars: stars }), }); const data = await response.json(); console.log(data); return data; -} +}; export const deleteRecipe = async (id) => { - console.log(id) + console.log(id); // return - const response = await fetch("http://localhost:3000/delete-recipe", { - method: 'DELETE', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ id }) + const response = await fetch("/backend/delete-recipe", { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ id }), }); const data = await response.json(); return data; }; - diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 8b0f57b..7b700dd 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,7 +1,11 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; // https://vite.dev/config/ export default defineConfig({ plugins: [react()], -}) + server: { + host: "ec683cee72d30c5030.fredzernia.com", + allowedHosts: ["ec683cee72d30c5030.fredzernia.com"], + }, +});