prisma #1

Merged
fred merged 4 commits from prisma into main 2025-08-15 20:52:39 +00:00
11 changed files with 2 additions and 371 deletions
Showing only changes of commit ec4324c53e - Show all commits

View file

@ -1,154 +0,0 @@
const express = require("express");
const db = require("./db");
const port = 3000;
const cors = require("cors");
const app = express();
app.use(cors());
app.use(express.json());
// ####### ROUTES #######
app.get("/backend/test", async (req, res) => {
console.log("test");
res.json({ env: process.env.NODE_ENV });
});
// ### GET ALL RECIPES ###
app.get("/backend/recipes", async (req, res) => {
try {
const recipes = await db("recipes").select("id", "name", "cuisine", "stars", "prep_minutes", "cook_minutes");
res.json(recipes);
} catch (err) {
console.log(err);
res.status(500).json({ error: err.message });
}
});
// ### GET ALL RECIPE_INGREDIENTS ###
app.get("/backend/recipe-ingredients", async (req, res) => {
try {
const recipe_ingredients = await db("recipe_ingredients").select("*");
res.json(recipe_ingredients);
} catch (err) {
console.log(err);
res.status(500).json({ error: err.message });
}
});
// ### GET ALL RECIPE_STEPS ###
app.get("/backend/recipe-steps", async (req, res) => {
try {
const recipe_steps = await db("recipe_steps").select("*");
res.json(recipe_steps);
} catch (err) {
console.log(err);
res.status(500).json({ error: err.message });
}
});
// ### GET RECIPE ###
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", "prep_minutes", "cook_minutes");
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 [recipe, ingredients, steps] = await Promise.all([
recipeQuery,
ingredientsQuery,
stepsQuery,
]);
const result = {
details: recipe[0],
ingredients: ingredients,
steps: steps,
};
res.json(result);
} catch (err) {
console.log(err);
res.status(500).json({ error: err.message });
}
});
// ### ADD RECIPE ###
app.post("/backend/add-recipe", async (req, res) => {
if (process.env.NODE_ENV === 'demo') { return; };
const { name, author, cuisine, stars, ingredients, steps, prep_minutes, cook_minutes } = req.body;
try {
const [id] = await db("recipes").insert(
{
name: name,
author: author,
cuisine: cuisine,
prep_minutes: prep_minutes,
cook_minutes: cook_minutes,
stars: stars,
},
["id"],
);
const ingredientInserts = ingredients.map((ing) => ({
recipe_id: id.id,
raw: ing,
}));
//
await db("recipe_ingredients").insert(ingredientInserts);
const stepInserts = Object.keys(steps).map((stepNumber) => ({
recipe_id: id.id,
step_number: parseInt(stepNumber),
instruction: steps[stepNumber],
}));
await db("recipe_steps").insert(stepInserts);
res.status(200).send({ message: "Recipe added", id: id.id });
} catch (err) {
console.log(err);
res.status(500).json({ error: err.message });
}
});
// ### SET STARS ###
app.post("/backend/set-stars", async (req, res) => {
if (process.env.NODE_ENV === 'demo') { return; };
const { id, stars } = req.body;
try {
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 });
}
});
// ### DELETE RECIPE ###
app.delete("/backend/delete-recipe", async (req, res) => {
if (process.env.NODE_ENV === 'demo') { return; };
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();
res.status(200).send({ message: "Recipe deleted" });
} catch (err) {
console.log(err);
res.status(500).json({ error: err.message });
}
});
app.listen(port, () => console.log(`Server has started on port: ${port}`));
process.on("SIGINT", async () => {
console.log("Closing database connection...");
await db.destroy();
process.exit(0);
});

View file

@ -1,10 +0,0 @@
const knex = require('knex');
const knexConfig = require('./knexfile.js');
const environment = process.env.NODE_ENV || 'dev';
const config = knexConfig[environment];
const db = knex(config);
module.exports = db;

View file

@ -1,60 +0,0 @@
require("dotenv").config();
module.exports = {
dev: {
client: "postgresql",
connection: {
host: "db",
port: 5432,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
},
pool: {
min: 2,
max: 10,
},
migrations: {
tableName: "knex_migrations",
directory: "./migrations",
},
},
demo: {
client: "postgresql",
connection: {
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,
},
migrations: {
tableName: "knex_migrations",
directory: "./migrations",
},
},
production: {
client: "postgresql",
connection: {
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,
},
migrations: {
tableName: "knex_migrations",
directory: "./migrations",
},
},
};

View file

@ -1,21 +0,0 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function (knex) {
return knex.schema.createTable('recipes', function (table) {
table.increments('id').primary();
table.string('name').notNullable().unique();
table.string('cuisine').notNullable();
table.timestamps(true, true);
})
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function (knex) {
return knex.schema.dropTable('users');
};

View file

@ -1,43 +0,0 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function (knex) {
return knex.schema.createTable('ingredients', function (table) {
table.increments('id').primary();
table.string('name').notNullable().unique();
table.string('type');
table.string('notes');
table.timestamps(true, true);
}).
createTable('recipe_ingredients', function (table) {
table.increments('id').primary();
table.integer('recipe_id').notNullable();
table.integer('ingredient_id').notNullable();
table.string('quantity').notNullable();
table.string('unit').notNullable();
table.string('notes');
table.index(['recipe_id']);
table.index(['ingredient_id']);
table.timestamps(true, true);
}).
createTable('recipe_steps', function (table) {
table.increments('id').primary();
table.integer('recipe_id');
table.integer('step_number');
table.string('instruction');
table.unique(['recipe_id', 'step_number']);
table.index(['recipe_id'])
table.timestamps(true, true);
})
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function (knex) {
return knex.schema.dropTableIfExists('ingredients')
.dropTableIfExists('recipe_ingredients')
.dropTableIfExists('recipe_steps')
};

View file

@ -1,24 +0,0 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function (knex) {
return knex.schema.table('recipe_ingredients', table => {
table.string('raw', 255).defaultTo('');
table.integer('ingredient_id').nullable().alter();
table.string('quantity').nullable().alter();
table.string('unit').nullable().alter();
}).table('recipe_steps', table => {
table.string('instruction', 510).alter();
});
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function (knex) {
return knex.schema.table('recipe_ingredients', table => {
table.dropColumn('raw');
});
};

View file

@ -1,22 +0,0 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function (knex) {
return knex.schema.table('recipes', table => {
table.string('author');
table.integer('stars');
})
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function (knex) {
return knex.schema.table('recipes', table => {
table.dropColumn('author');
table.dropColumn('stars')
})
};

View file

@ -1,22 +0,0 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function (knex) {
return knex.schema.table('recipes', table => {
table.integer('prep_minutes');
table.integer('cook_minutes');
})
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function (knex) {
return knex.schema.table('recipes', table => {
table.dropColumn('prep_minutes');
table.dropColumn('cook_minutes')
})
};

View file

@ -38,7 +38,7 @@ class recipeModel {
}, },
ingredients: recipe.recipeIngredients.map((ing) => ing.raw), ingredients: recipe.recipeIngredients.map((ing) => ing.raw),
steps: recipe.recipeSteps.map((step, idx) => ({ steps: recipe.recipeSteps.map((step, idx) => ({
step_idx: step.step_number, step_number: step.step_number,
instruction: step.instruction, instruction: step.instruction,
})), })),
}; };

View file

@ -1,14 +0,0 @@
const db = require('./db');
async function testConnection() {
try {
await db.raw('SELECT 1+1 as result');
console.log('Database connected successfully!');
} catch (error) {
console.error('Database connection failed:', error);
} finally {
await db.destroy();
}
}
testConnection();

View file

@ -30,6 +30,7 @@ services:
- DB_USER=${DB_USER} - DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD} - DB_PASSWORD=${DB_PASSWORD}
- DB_NAME=${DB_NAME} - DB_NAME=${DB_NAME}
- DATABASE_URL=${PRISMA_DB_URL}
frontend: frontend:
image: recipes_frontend image: recipes_frontend
container_name: recipes_frontend_${ID} container_name: recipes_frontend_${ID}