Compare commits

..

No commits in common. "6535faf82a33362975828874f63114243bde46b0" and "ea382adda3ea280fd279e3e70c59e76613713404" have entirely different histories.

15 changed files with 153 additions and 265 deletions

View file

@ -1,7 +0,0 @@
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_NAME=whiskey_collection_test
DB_USER=whiskey_admin
DB_PASSWORD=t2B^IwrR
JWT_SECRET=dsl0ECYSJV999

View file

@ -5,10 +5,7 @@
"scripts": { "scripts": {
"start": "node src/app.js", "start": "node src/app.js",
"dev": "nodemon src/app.js", "dev": "nodemon src/app.js",
"prod": "NODE_ENV=production node src/app.js", "test": "echo \"Error: no test specified\" && exit 1"
"test": "NODE_ENV=test jest --forceExit",
"test:watch": "NODE_ENV=test jest --watch",
"start:test": "NODE_ENV=test node src/app.js"
}, },
"keywords": [ "keywords": [
"whiskey", "whiskey",

View file

@ -1,57 +0,0 @@
const express = require('express');
const cors = require('cors');
const dotenv = require('dotenv');
const { sequelize, testConnection } = require('./config/db');
const { Op } = require('sequelize');
// Import routes
const authRoutes = require('./routes/authRoutes');
const whiskeyRoutes = require('./routes/whiskeyRoutes');
const collectionRoutes = require('./routes/collectionRoutes');
const ratingRoutes = require('./routes/ratingRoutes');
// Load environment variables
dotenv.config();
// Initialize app
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware
app.use(cors());
app.use(express.json());
// Routes
app.use('/api/auth', authRoutes);
app.use('/api/whiskies', whiskeyRoutes);
app.use('/api/collection', collectionRoutes);
app.use('/api/ratings', ratingRoutes);
// Root route
app.get('/', (req, res) => {
res.send('Whiskey Collection API is running');
});
// Sync database and start server
const startServer = async () => {
try {
// Test database connection
await testConnection();
// Sync models with database
await sequelize.sync({ alter: true });
console.log('Database synchronized');
// Start server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
};
startServer();
module.exports = app;

View file

@ -1,20 +1,7 @@
// src/config/db.js
const { Sequelize } = require('sequelize'); const { Sequelize } = require('sequelize');
const dotenv = require('dotenv'); const dotenv = require('dotenv');
const path = require('path');
// Load environment-specific variables dotenv.config();
if (process.env.NODE_ENV === 'test') {
console.log('Loading TEST environment variables');
dotenv.config({ path: path.resolve(__dirname, '../../.env.test') });
} else {
console.log('Loading DEVELOPMENT environment variables');
dotenv.config();
}
console.log('Environment:', process.env.NODE_ENV);
console.log('Database:', process.env.DB_NAME);
console.log('User:', process.env.DB_USER);
const sequelize = new Sequelize( const sequelize = new Sequelize(
process.env.DB_NAME, process.env.DB_NAME,

View file

@ -1,17 +0,0 @@
const dotenv = require('dotenv');
const path = require('path');
// Load test environment variables
dotenv.config({ path: path.resolve(__dirname, '../../.env.test') });
module.exports = {
testDbConfig: {
database: process.env.DB_NAME,
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: 'postgres',
logging: false
}
};

View file

@ -1,5 +1,5 @@
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
const { User } = require('../models'); const { User } = require('../models/User');
const { Op } = require('sequelize'); const { Op } = require('sequelize');
exports.register = async (req, res) => { exports.register = async (req, res) => {

View file

@ -1,4 +1,4 @@
const { Collection, Whiskey } = require('../models'); const { Collection, Whiskey } = require('../models/Whiskey');
// Get user's collection // Get user's collection
exports.getUserCollection = async (req, res) => { exports.getUserCollection = async (req, res) => {

View file

@ -1,4 +1,4 @@
const { Rating, Whiskey, User } = require('../models'); const { Rating, Whiskey, User } = require('../models/Whiskey');
// Get all ratings for a whiskey // Get all ratings for a whiskey
exports.getWhiskeyRatings = async (req, res) => { exports.getWhiskeyRatings = async (req, res) => {

View file

@ -1,4 +1,4 @@
const { Whiskey } = require('../models'); const { Whiskey } = require('../models/Whiskey');
const { Op } = require('sequelize'); const { Op } = require('sequelize');
// Get all whiskies // Get all whiskies

View file

@ -1,7 +1,7 @@
const { DataTypes } = require('sequelize'); const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/db');
module.exports = (sequelize) => { const Collection = sequelize.define('Collection', {
const Collection = sequelize.define('Collection', {
id: { id: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
primaryKey: true, primaryKey: true,
@ -20,7 +20,4 @@ module.exports = (sequelize) => {
type: DataTypes.ENUM('sealed', 'opened', 'empty'), type: DataTypes.ENUM('sealed', 'opened', 'empty'),
defaultValue: 'sealed' defaultValue: 'sealed'
} }
}); });
return Collection;
};

View file

@ -1,7 +1,7 @@
const { DataTypes } = require('sequelize'); const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/db');
module.exports = (sequelize) => { const Rating = sequelize.define('Rating', {
const Rating = sequelize.define('Rating', {
id: { id: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
primaryKey: true, primaryKey: true,
@ -39,7 +39,4 @@ module.exports = (sequelize) => {
max: 10 max: 10
} }
} }
}); });
return Rating;
};

View file

@ -1,7 +1,8 @@
const { DataTypes } = require('sequelize'); const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/db');
const bcrypt = require('bcrypt');
module.exports = (sequelize) => { const User = sequelize.define('User', {
const User = sequelize.define('User', {
id: { id: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
primaryKey: true, primaryKey: true,
@ -24,20 +25,15 @@ module.exports = (sequelize) => {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false allowNull: false
} }
}); }, {
hooks: {
// Add password hashing hook beforeCreate: async (user) => {
User.beforeCreate(async (user) => {
const bcrypt = require('bcrypt');
const salt = await bcrypt.genSalt(10); const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(user.password, salt); user.password = await bcrypt.hash(user.password, salt);
}); }
}
});
// Add password validation method User.prototype.validatePassword = async function(password) {
User.prototype.validatePassword = async function(password) {
const bcrypt = require('bcrypt');
return await bcrypt.compare(password, this.password); return await bcrypt.compare(password, this.password);
};
return User;
}; };

View file

@ -1,47 +0,0 @@
const { DataTypes } = require('sequelize');
module.exports = (sequelize) => {
const Whiskey = sequelize.define('Whiskey', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
distillery: {
type: DataTypes.STRING,
allowNull: false
},
type: {
type: DataTypes.STRING,
allowNull: false
},
country: {
type: DataTypes.STRING,
allowNull: false
},
region: {
type: DataTypes.STRING
},
age: {
type: DataTypes.INTEGER
},
abv: {
type: DataTypes.FLOAT
},
price: {
type: DataTypes.FLOAT
},
description: {
type: DataTypes.TEXT
},
imageUrl: {
type: DataTypes.STRING
}
});
return Whiskey;
};

View file

@ -0,0 +1,44 @@
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/db');
const Whiskey = sequelize.define('Whiskey', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
distillery: {
type: DataTypes.STRING,
allowNull: false
},
type: {
type: DataTypes.STRING,
allowNull: false
},
country: {
type: DataTypes.STRING,
allowNull: false
},
region: {
type: DataTypes.STRING
},
age: {
type: DataTypes.INTEGER
},
abv: {
type: DataTypes.FLOAT
},
price: {
type: DataTypes.FLOAT
},
description: {
type: DataTypes.TEXT
},
imageUrl: {
type: DataTypes.STRING
}
});

View file

@ -1,14 +1,11 @@
// src/models/index.js
const { sequelize } = require('../config/db'); const { sequelize } = require('../config/db');
const { DataTypes } = require('sequelize'); const User = require('./User');
const Whiskey = require('./Whiskey');
const Collection = require('./Collection');
const Rating = require('./Rating');
// Initialize models // Define relationships
const User = require('./User')(sequelize);
const Whiskey = require('./Whiskey')(sequelize);
const Collection = require('./Collection')(sequelize);
const Rating = require('./Rating')(sequelize);
// Define associations
User.hasMany(Collection); User.hasMany(Collection);
Collection.belongsTo(User); Collection.belongsTo(User);
@ -21,7 +18,8 @@ Rating.belongsTo(User);
Whiskey.hasMany(Rating); Whiskey.hasMany(Rating);
Rating.belongsTo(Whiskey); Rating.belongsTo(Whiskey);
// Export models // Exports
module.exports = { module.exports = {
User, User,
Whiskey, Whiskey,