prisma #1
11 changed files with 2 additions and 371 deletions
|
@ -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);
|
|
||||||
});
|
|
|
@ -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;
|
|
||||||
|
|
|
@ -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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -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');
|
|
||||||
};
|
|
|
@ -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')
|
|
||||||
};
|
|
|
@ -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');
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -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')
|
|
||||||
})
|
|
||||||
};
|
|
|
@ -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')
|
|
||||||
})
|
|
||||||
};
|
|
|
@ -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,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
|
|
@ -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}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue