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": {
"start": "node src/app.js",
"dev": "nodemon src/app.js",
"prod": "NODE_ENV=production node src/app.js",
"test": "NODE_ENV=test jest --forceExit",
"test:watch": "NODE_ENV=test jest --watch",
"start:test": "NODE_ENV=test node src/app.js"
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"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 dotenv = require('dotenv');
const path = require('path');
// Load environment-specific variables
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);
dotenv.config();
const sequelize = new Sequelize(
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 { User } = require('../models');
const { User } = require('../models/User');
const { Op } = require('sequelize');
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
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
exports.getWhiskeyRatings = async (req, res) => {

View file

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

View file

@ -1,26 +1,23 @@
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/db');
module.exports = (sequelize) => {
const Collection = sequelize.define('Collection', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
purchaseDate: {
type: DataTypes.DATE
},
purchasePrice: {
type: DataTypes.FLOAT
},
notes: {
type: DataTypes.TEXT
},
bottleStatus: {
type: DataTypes.ENUM('sealed', 'opened', 'empty'),
defaultValue: 'sealed'
}
});
return Collection;
};
const Collection = sequelize.define('Collection', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
purchaseDate: {
type: DataTypes.DATE
},
purchasePrice: {
type: DataTypes.FLOAT
},
notes: {
type: DataTypes.TEXT
},
bottleStatus: {
type: DataTypes.ENUM('sealed', 'opened', 'empty'),
defaultValue: 'sealed'
}
});

View file

@ -1,45 +1,42 @@
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/db');
module.exports = (sequelize) => {
const Rating = sequelize.define('Rating', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
score: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
min: 0,
max: 100
}
},
notes: {
type: DataTypes.TEXT
},
nose: {
type: DataTypes.INTEGER,
validate: {
min: 0,
max: 10
}
},
taste: {
type: DataTypes.INTEGER,
validate: {
min: 0,
max: 10
}
},
finish: {
type: DataTypes.INTEGER,
validate: {
min: 0,
max: 10
}
const Rating = sequelize.define('Rating', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
score: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
min: 0,
max: 100
}
});
return Rating;
};
},
notes: {
type: DataTypes.TEXT
},
nose: {
type: DataTypes.INTEGER,
validate: {
min: 0,
max: 10
}
},
taste: {
type: DataTypes.INTEGER,
validate: {
min: 0,
max: 10
}
},
finish: {
type: DataTypes.INTEGER,
validate: {
min: 0,
max: 10
}
}
});

View file

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

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 { DataTypes } = require('sequelize');
const User = require('./User');
const Whiskey = require('./Whiskey');
const Collection = require('./Collection');
const Rating = require('./Rating');
// Initialize models
const User = require('./User')(sequelize);
const Whiskey = require('./Whiskey')(sequelize);
const Collection = require('./Collection')(sequelize);
const Rating = require('./Rating')(sequelize);
// Define relationships
// Define associations
User.hasMany(Collection);
Collection.belongsTo(User);
@ -21,11 +18,12 @@ Rating.belongsTo(User);
Whiskey.hasMany(Rating);
Rating.belongsTo(Whiskey);
// Export models
// Exports
module.exports = {
User,
Whiskey,
Collection,
Rating,
sequelize
};
};