diff --git a/db/index.js b/db/index.js index af723442..cc127fad 100644 --- a/db/index.js +++ b/db/index.js @@ -1,25 +1,17 @@ -// Load our .env file require('dotenv').config() +const {Pool} = require('pg') -// Require Client obj from the postgres node module -const { Client } = require("pg"); -const client = { - query: async (str, values) => { - // Get the connection string from process.env - - // the dotenv library sets this variable based - // on the contents of our env file - // Create a new connection to the database using the Client - // object provided by the postgres node module - const dbClient = new Client(process.env.PGURL) - // connect a connection - await dbClient.connect() - // execute the query - const result = await dbClient.query(str, values) - // close the connection - await dbClient.end() - return result - } -} +const { PGHOST, PGDATABASE, PGUSER, PGPASSWORD } = process.env +const pool = new Pool({ + host: PGHOST, + database: PGDATABASE, + username: PGUSER, + password: PGPASSWORD, + port: 5432, + ssl: { + require: true, + }, +}) -module.exports = client; +module.exports = pool; diff --git a/src/controllers/books.js b/src/controllers/books.js new file mode 100644 index 00000000..29737f4f --- /dev/null +++ b/src/controllers/books.js @@ -0,0 +1,75 @@ +const pool = require('../../db') +const booksRepository = require('../repositories/booksRepository') + +const types = new Map([['Fiction', "type = 'Fiction'"], ['Non-Fiction', "type = 'Non-Fiction'"]]) + +const getBooks = async (req, res) => { + + const result = await booksRepository.getBooks(req) + + res.send({ books: result.rows }) +} + +const createBook = async (req, res) => { + const db = await pool.connect() + + const { title, type, author, topic, publication_date, pages } = req.body + + if ( + !title || + !type || + !author || + !topic || + !publication_date || + !Number.isInteger(pages) + ) { + res.status(400).json({ + error: 'All fields are required and pages must be an integer.', + }) + } + + const result = await booksRepository.createBook(req) + + res.status(201).json({ book: result.rows[0] }) +} + +const getBookById = async (req, res) => { + const result = await booksRepository.getBookById(req) + + res.send({ book: result.rows[0] }) +} + +const updateBookById = async (req, res) => { + const { title, type, author, topic, publication_date, pages } = req.body + + if ( + !title || + !type || + !author || + !topic || + !publication_date || + !Number.isInteger(pages) + ) { + return res.status(400).json({ + error: 'All fields are required and pages must be an integer.', + }) + } + const result = await booksRepository.updateBookById(req) + return res.status(201).json({ book: result.rows[0] }) + +} + +const deleteBookById = async (req, res) => { + + const result = await booksRepository.deleteBookById(req) + + res.status(201).send({ book: result.rows[0] }) +} + +module.exports = { + getBooks, + createBook, + getBookById, + deleteBookById, + updateBookById, +} diff --git a/src/controllers/pets.js b/src/controllers/pets.js new file mode 100644 index 00000000..08f7dd70 --- /dev/null +++ b/src/controllers/pets.js @@ -0,0 +1,70 @@ +const pool = require('../../db') +const petsRepository = require('../repositories/petsRepository') + +const getPets = async (req, res) => { + const result = await petsRepository.getPets() + + res.send({ pets: result.rows }) +} + +const createPet = async (req, res) => { + const { name, age, type, breed, has_microchip } = req.body + + if ( + !name || + !age || + !type || + !breed || + !typeof has_microchip === 'boolean' + ) { + res.status(400).json({ + error: 'All fields are required and has_microchip must be a boolean', + }) + } + + const result = await petsRepository.createPet(req) + + res.status(201).json({ pet: result.rows[0] }) +} + +const getPetById = async (req, res) => { + + const result = await petsRepository.getPetById(req) + + res.send({ pet: result.rows[0] }) +} + +const updatePetById = async (req, res) => { + const { name, age, type, breed, has_microchip } = req.body + + if ( + !name || + !age || + !type || + !breed || + !typeof has_microchip === 'boolean' + ) { + res.status(400).json({ + error: 'All fields are required and has_microchip must be a boolean', + }) + } + + const result = await petsRepository.updatePetById(req) + + res.status(201).json({ pet: result.rows[0] }) + +} + +const deletePetById = async (req, res) => { + const result = await petsRepository.deletePetById(req) + + res.status(201).send({ pet: result.rows[0] }) +} + +module.exports = { + getPets, + createPet, + getPetById, + deletePetById, + updatePetById, +} diff --git a/src/repositories/booksRepository.js b/src/repositories/booksRepository.js new file mode 100644 index 00000000..cc3d8f62 --- /dev/null +++ b/src/repositories/booksRepository.js @@ -0,0 +1,94 @@ +const pool = require('../../db') + +const types = new Map([ + ['Fiction', "type = 'Fiction'"], + ['Non-Fiction', "type = 'Non-Fiction'"], +]) + +async function getBooks(req) { + const db = await pool.connect() + const { type, topic } = req.query + + const queryContents = [] + + let sqlQuery = 'select * from books where 1 = 1' + + if (types.has(type)) { + queryContents.push(type) + sqlQuery += ` and type = $${queryContents.length}` + console.log(sqlQuery) + } + + if (topic) { + queryContents.push(topic) + sqlQuery += ` and topic = $${queryContents.length}` + console.log(sqlQuery) + } + + const result = await db.query(sqlQuery, queryContents) + + db.release() + + return result +} + +async function createBook(req) { + const db = await pool.connect() + const { title, type, author, topic, publication_date, pages } = req.body + + try { + const result = await db.query( + `INSERT INTO books (title, type, author, topic, publication_date, pages) + VALUES ($1, $2, $3, $4, $5, $6) + RETURNING *`, + [title, type, author, topic, publication_date, pages] + ) + + return result + } catch (err) { + console.error('Error inserting book:', err) + } finally { + db.release() + } +} + +async function getBookById(req) { + const db = await pool.connect() + + const sqlQuery = 'select * from books where id = $1' + const result = await db.query(sqlQuery, [Number(req.params.id)]) + + db.release() + + return result +} + +async function updateBookById(req) { + const db = await pool.connect() + const { title, type, author, topic, publication_date, pages } = req.body + + const result = await db.query( + `Update books + Set title = $1 , type = $2 , author = $3 , topic = $4 , publication_date = $5 , pages = $6 + where id = $7 + RETURNING *`, + [title, type, author, topic, publication_date, pages, req.params.id] + ) + + db.release() + + return result +} + +async function deleteBookById(req) { + const db = await pool.connect() + + const sqlQuery = 'delete from books where id = $1 RETURNING *' + const result = await db.query(sqlQuery, [Number(req.params.id)]) + + db.release() + + return result +} + +module.exports = { getBooks, createBook, getBookById , updateBookById, deleteBookById} diff --git a/src/repositories/petsRepository.js b/src/repositories/petsRepository.js new file mode 100644 index 00000000..312a6c0d --- /dev/null +++ b/src/repositories/petsRepository.js @@ -0,0 +1,77 @@ +const pool = require('../../db') + +const getPets = async () => { + const db = await pool.connect() + + const sqlQuery = 'select * from pets' + const result = await db.query(sqlQuery) + + db.release() + + return result +} + +const createPet = async (req) => { + const db = await pool.connect() + + const { name, age, type, breed, has_microchip } = req.body + + const result = await db.query( + `INSERT INTO pets (name, age, type, breed, has_microchip) + VALUES ($1, $2, $3, $4, $5) + RETURNING *`, + [name, age, type, breed, has_microchip] + ) + + db.release() + + return result +} + +const getPetById = async (req) => { + const db = await pool.connect() + + const sqlQuery = 'select * from pets where id = $1' + const result = await db.query(sqlQuery, [Number(req.params.id)]) + + db.release() + + return result +} + +const updatePetById = async (req) => { + const db = await pool.connect() + + const { name, age, type, breed, has_microchip } = req.body + + const result = await db.query( + `Update pets + Set name = $1 , age = $2 , type = $3 , breed = $4 , has_microchip = $5 + where id = $6 + RETURNING *`, + [name, age, type, breed, has_microchip, req.params.id] + ) + + db.release() + + return result +} + +const deletePetById = async (req, res) => { + const db = await pool.connect() + + const sqlQuery = 'delete from pets where id = $1 RETURNING *' + const result = await db.query(sqlQuery, [Number(req.params.id)]) + + db.release() + + return result +} + +module.exports = { + getPets, + createPet, + getPetById, + deletePetById, + updatePetById, +} diff --git a/src/routers/books.js b/src/routers/books.js index 1551dd87..97136642 100644 --- a/src/routers/books.js +++ b/src/routers/books.js @@ -1,9 +1,15 @@ const express = require('express') const router = express.Router() -const db = require("../../db"); +const { getBooks, createBook, getBookById , deleteBookById, updateBookById} = require('../controllers/books') -router.get('/', async (req, res) => { +router.get('/', getBooks) -}) +router.post('/', createBook) + +router.get('/:id', getBookById) + +router.delete('/:id', deleteBookById) + +router.put('/:id', updateBookById) module.exports = router diff --git a/src/routers/pets.js b/src/routers/pets.js new file mode 100644 index 00000000..5736d76d --- /dev/null +++ b/src/routers/pets.js @@ -0,0 +1,15 @@ +const express = require('express') +const router = express.Router() +const { getPets, createPet, getPetById , deletePetById, updatePetById} = require('../controllers/pets') + +router.get('/', getPets) + +router.post('/', createPet) + +router.get('/:id', getPetById) + +router.delete('/:id', deletePetById) + +router.put('/:id', updatePetById) + +module.exports = router diff --git a/src/server.js b/src/server.js index dac55e5d..233ceb88 100644 --- a/src/server.js +++ b/src/server.js @@ -10,7 +10,9 @@ app.use(express.json()); //TODO: Implement books and pets APIs using Express Modular Routers const booksRouter = require('./routers/books.js') +const petsRouter = require('./routers/pets.js') app.use('/books', booksRouter) +app.use('/pets', petsRouter) module.exports = app