Ajout de la base de données MySQL
This commit is contained in:
+19
@@ -0,0 +1,19 @@
|
||||
//import express to use express methods and properties
|
||||
const express = require('express');
|
||||
const routes = require('./routes');
|
||||
|
||||
//create an instance of express
|
||||
const app = express();
|
||||
|
||||
//use express.json() to parse incoming requests with JSON payloads
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true })); //parse incoming requests with urlencoded payloads
|
||||
|
||||
app.use('/api/v1', routes);
|
||||
|
||||
//catch all routes that are not defined to avoid running into errors when a route is not defined
|
||||
app.use('*', (req, res) => {
|
||||
res.status(404).json({ error: 'Path does not found, try again' });
|
||||
});
|
||||
|
||||
module.exports = app; //export app to be used in other files
|
||||
@@ -0,0 +1,42 @@
|
||||
const { ArticleService } = require('../services/article.service');
|
||||
|
||||
const createArticle = async (req, res) => {
|
||||
try {
|
||||
const { name, description, userId } = req.body;
|
||||
|
||||
const article = await ArticleService.createArticle({
|
||||
name,
|
||||
description,
|
||||
userId,
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
message: 'Article created successfully',
|
||||
data: article,
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).json({
|
||||
message: 'something went wrong while creating article',
|
||||
error: err.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const getArticlesByUserId = async (req, res) => {
|
||||
try {
|
||||
const { userId } = req.params;
|
||||
|
||||
const articles = await ArticleService.getArticlesByUserId(userId);
|
||||
|
||||
res.status(200).json({
|
||||
data: articles,
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).json({
|
||||
message: 'something went wrong while fetching articles',
|
||||
error: err.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { createArticle, getArticlesByUserId };
|
||||
@@ -0,0 +1,36 @@
|
||||
const { UserService } = require('../services/user.service');
|
||||
|
||||
const createUser = async (req, res) => {
|
||||
try {
|
||||
const { name, email } = req.body;
|
||||
|
||||
const user = await UserService.createUser({ name, email });
|
||||
|
||||
res.status(201).json({
|
||||
message: 'User created successfully',
|
||||
data: user,
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).json({
|
||||
message: 'something went wrong while creating user',
|
||||
error: err.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const getAllUsers = async (req, res) => {
|
||||
try {
|
||||
const users = await UserService.getAllUsers();
|
||||
|
||||
res.status(200).json({
|
||||
data: users,
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).json({
|
||||
message: 'something went wrong while fetching users',
|
||||
error: err.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { createUser, getAllUsers };
|
||||
@@ -0,0 +1,33 @@
|
||||
module.exports = {
|
||||
"development": {
|
||||
"username": process.env.MYSQL_DBUSER,
|
||||
"password": process.env.MYSQL_DBPASS,
|
||||
"database": process.env.MYSQL_DBNAME,
|
||||
"host": process.env.MYSQL_DBHOST,
|
||||
"port": process.env.MYSQL_DBPORT,
|
||||
"dialect": process.env.MYSQL_DBTYPE
|
||||
},
|
||||
"test": {
|
||||
"username": process.env.MYSQL_DBUSER,
|
||||
"password": process.env.MYSQL_DBPASS,
|
||||
"database": process.env.MYSQL_DBNAME,
|
||||
"host": process.env.MYSQL_DBHOST,
|
||||
"port": process.env.MYSQL_DBPORT,
|
||||
"dialect": process.env.MYSQL_DBTYPE
|
||||
},
|
||||
"production": {
|
||||
"username": process.env.MYSQL_DBUSER,
|
||||
"password": process.env.MYSQL_DBPASS,
|
||||
"database": process.env.MYSQL_DBNAME,
|
||||
"host": process.env.MYSQL_DBHOST,
|
||||
"port": process.env.MYSQL_DBPORT,
|
||||
"dialect": process.env.MYSQL_DBTYPE,
|
||||
"dialectOptions": {
|
||||
"ssl": {
|
||||
// enable this for production environment only if using a secure connection
|
||||
"require": true,
|
||||
"rejectUnauthorized": false
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
const { Sequelize } = require('sequelize');
|
||||
|
||||
const Op = Sequelize.Op;
|
||||
const sequelize = new Sequelize(
|
||||
process.env.MYSQL_DBNAME,
|
||||
process.env.MYSQL_DBUSER,
|
||||
process.env.MYSQL_DBPASS,
|
||||
{
|
||||
host: process.env.MYSQL_DBHOST,
|
||||
port: process.env.MYSQL_DBPORT,
|
||||
dialect: process.env.MYSQL_DBTYPE,
|
||||
$like: Op.like,
|
||||
$not: Op.not,
|
||||
timezone: '+02:00',
|
||||
define: {
|
||||
charset: 'utf8mb4',
|
||||
collate: 'utf8mb4_general_ci',
|
||||
underscored: false,
|
||||
freezeTableName: true,
|
||||
},
|
||||
pool: {
|
||||
//explain this line of code? this means that the connection pool will have a minimum of 0 connections and a maximum of 5 connections
|
||||
min: 0,
|
||||
max: 5,
|
||||
},
|
||||
logQueryParameters: process.env.APP_ENV === 'development', // this line of code will log the query parameters if the environment is development
|
||||
benchmark: true,
|
||||
});
|
||||
|
||||
/*
|
||||
const checkConnection = async () => {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log(`DB Connected`.cyan.underline.bold);
|
||||
} catch (error) {
|
||||
console.error("Unable to connect to the database:".red.bold, error);
|
||||
}
|
||||
};
|
||||
|
||||
checkConnection();
|
||||
*/
|
||||
|
||||
module.exports = sequelize;
|
||||
@@ -0,0 +1,11 @@
|
||||
const sequelize = require('./config/sequelize');
|
||||
const ArticleModel = require('./models/article');
|
||||
const UserModel = require('./models/user');
|
||||
|
||||
const DB = {
|
||||
sequelize,
|
||||
User: UserModel(sequelize),
|
||||
Article: ArticleModel(sequelize),
|
||||
};
|
||||
|
||||
module.exports = DB;
|
||||
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
/** @type {import('sequelize-cli').Migration} */
|
||||
module.exports = {
|
||||
async up(queryInterface, Sequelize) {
|
||||
await queryInterface.createTable('Users', {
|
||||
id: {
|
||||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
type: Sequelize.INTEGER,
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
email: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
createdAt: {
|
||||
allowNull: false,
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
allowNull: false,
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
},
|
||||
async down(queryInterface, Sequelize) {
|
||||
await queryInterface.dropTable('Users');
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
'use strict';
|
||||
/** @type {import('sequelize-cli').Migration} */
|
||||
module.exports = {
|
||||
async up(queryInterface, Sequelize) {
|
||||
await queryInterface.createTable('article', {
|
||||
id: {
|
||||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
type: Sequelize.INTEGER,
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
description: {
|
||||
type: Sequelize.TEXT,
|
||||
},
|
||||
userId: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: 'User',
|
||||
key: 'id',
|
||||
},
|
||||
},
|
||||
createdAt: {
|
||||
allowNull: false,
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
updatedAt: {
|
||||
allowNull: false,
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
},
|
||||
async down(queryInterface, Sequelize) {
|
||||
await queryInterface.dropTable('article');
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
const { DataTypes, Model } = require("sequelize");
|
||||
const sequelize = require("../config/sequelize");
|
||||
const slug = require("slug");
|
||||
|
||||
class Article extends Model { }
|
||||
|
||||
const ArticleModel = () => {
|
||||
Article.init(
|
||||
{
|
||||
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
||||
slug: { type: DataTypes.STRING, allowNull: false },
|
||||
title: { type: DataTypes.STRING, allowNull: false },
|
||||
description: { type: DataTypes.TEXT },
|
||||
body: { type: DataTypes.TEXT, allowNull: false }
|
||||
},
|
||||
{
|
||||
sequelize,
|
||||
modelName: 'Article',
|
||||
tableName: 'article',
|
||||
timestamps: true,
|
||||
createdAt: true,
|
||||
updatedAt: true
|
||||
}
|
||||
);
|
||||
|
||||
Article.beforeValidate((article) => {
|
||||
article.slug =slug(`${article.title}`) + '-' + (Math.random() * Math.pow(36, 6) | 0).toString(36);
|
||||
});
|
||||
|
||||
Article.prototype.toJSONFor = function () {
|
||||
return {
|
||||
id: this.id,
|
||||
slug: this.slug,
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
body: this.body
|
||||
};
|
||||
};
|
||||
|
||||
return Article;
|
||||
};
|
||||
|
||||
module.exports = ArticleModel;
|
||||
@@ -0,0 +1,60 @@
|
||||
const { DataTypes, Model } = require("sequelize");
|
||||
const sequelize = require("../config/sequelize");
|
||||
const bcrypt = require("bcrypt");
|
||||
|
||||
class User extends Model { }
|
||||
|
||||
const UserModel = () => {
|
||||
User.init(
|
||||
{
|
||||
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
||||
email: { type: DataTypes.STRING, allowNull: false, unique: true },
|
||||
username: { type: DataTypes.STRING, allowNull: false, unique: true },
|
||||
firstname: { type: DataTypes.STRING },
|
||||
lastname: { type: DataTypes.STRING },
|
||||
bio: { type: DataTypes.TEXT, allowNull: true },
|
||||
image: { type: DataTypes.TEXT, allowNull: true },
|
||||
role: { type: DataTypes.STRING },
|
||||
password: { type: DataTypes.STRING, allowNull: false }
|
||||
},
|
||||
{
|
||||
sequelize,
|
||||
modelName: 'User',
|
||||
tableName: 'user',
|
||||
timestamps: false,
|
||||
createdAt: true,
|
||||
updatedAt: true
|
||||
}
|
||||
);
|
||||
|
||||
Model.prototype.matchPassword = async function (enteredPassword) {
|
||||
return await bcrypt.compare(enteredPassword, this.password);
|
||||
};
|
||||
|
||||
const DEFAULT_SALT_ROUNDS = 10;
|
||||
|
||||
User.addHook("beforeCreate", async (user) => {
|
||||
const encryptedPassword = await bcrypt.hash(
|
||||
user.password,
|
||||
DEFAULT_SALT_ROUNDS
|
||||
);
|
||||
user.password = encryptedPassword;
|
||||
});
|
||||
|
||||
User.prototype.toJSONFor = function () {
|
||||
return {
|
||||
id: this.id,
|
||||
email: this.email,
|
||||
username: this.username,
|
||||
firstname: this.firstname,
|
||||
lastname: this.lastname,
|
||||
bio: this.bio,
|
||||
image: this.image,
|
||||
role: this.role
|
||||
};
|
||||
};
|
||||
|
||||
return User;
|
||||
};
|
||||
|
||||
module.exports = UserModel;
|
||||
@@ -0,0 +1,29 @@
|
||||
const DB = require('../index');
|
||||
|
||||
const associate = () => {
|
||||
DB.User.hasMany(DB.Article, {
|
||||
foreignKey: 'userId',
|
||||
as: 'projects',
|
||||
});
|
||||
|
||||
DB.Article.belongsTo(DB.User, {
|
||||
foreignKey: 'userId',
|
||||
as: 'user',
|
||||
});
|
||||
/*
|
||||
DB.User.belongsToMany(DB.User, { as: "followers", through: "Followers", foreignKey: "userId", timestamps: false });
|
||||
DB.User.belongsToMany(DB.User, { as: "following", through: "Followers", foreignKey: "followerId", timestamps: false });
|
||||
DB.User.hasMany(DB.Article, { foreignKey: "authorId", onDelete: "CASCADE" });
|
||||
DB.Article.belongsTo(DB.User, { as: "author", foreignKey: "authorId" });
|
||||
DB.User.hasMany(DB.Comment, { foreignKey: "authorId", onDelete: "CASCADE" });
|
||||
DB.Comment.belongsTo(DB.User, { as: "author", foreignKey: "authorId" });
|
||||
DB.Article.hasMany(DB.omment, { foreignKey: "articleId", onDelete: "CASCADE" });
|
||||
DB.Comment.belongsTo(DB.Article, { foreignKey: "articleId" });
|
||||
DB.User.belongsToMany(DB.Article, { as: "favorites", through: "Favorites", timestamps: false });
|
||||
DB.Article.belongsToMany(DB.User, { through: "Favorites", foreignKey: "articleId", timestamps: false });
|
||||
DB.Article.belongsToMany(DB.Tag, { through: "TagLists", as: "tagLists", foreignKey: "articleId", timestamps: false, onDelete: "CASCADE" });
|
||||
DB.Tag.belongsToMany(DB.Article, { through: "ArticleTags", uniqueKey: false, timestamps: false });
|
||||
*/
|
||||
};
|
||||
|
||||
module.exports = associate;
|
||||
@@ -0,0 +1 @@
|
||||
console.log('this is placeholder for models');
|
||||
@@ -0,0 +1,9 @@
|
||||
const express = require('express');
|
||||
const { createProject, getProjectsByUserId } = require('../../controllers/article.controller');
|
||||
|
||||
const projectRouter = express.Router();
|
||||
|
||||
projectRouter.post('/', createProject);
|
||||
projectRouter.get('/:userId', getProjectsByUserId);
|
||||
|
||||
module.exports = projectRouter;
|
||||
@@ -0,0 +1,9 @@
|
||||
const express = require('express');
|
||||
const { createUser, getAllUsers } = require('../../controllers/user.controller');
|
||||
|
||||
const userRouter = express.Router();
|
||||
|
||||
userRouter.post('/register', createUser);
|
||||
userRouter.get('/', getAllUsers);
|
||||
|
||||
module.exports = userRouter;
|
||||
@@ -0,0 +1,10 @@
|
||||
const express = require('express');
|
||||
const articleRouter = require('./api/article.routes');
|
||||
const userRouter = require('./api/user.routes');
|
||||
|
||||
const routes = express.Router();
|
||||
|
||||
routes.use('/user', userRouter);
|
||||
routes.use('/article', articleRouter);
|
||||
|
||||
module.exports = routes;
|
||||
@@ -0,0 +1,24 @@
|
||||
const http = require('http'); // import the http module from node.js core to create a server instance
|
||||
const app = require('./app'); // import the express app from the app.js file
|
||||
const connectDB = require('./services/connectDB');
|
||||
|
||||
const PORT = process.env.PORT || 3000; // set the port number to be used by the server instance
|
||||
|
||||
/* create a server instance using the http.createServer method
|
||||
* there is no right or wrong way to create a server instance weather using the http.createServer method or the app.listen method
|
||||
* I usualy use the http.createServer method because it gives me more control over the server instance like adding a socket.io instance to the server instance
|
||||
*/
|
||||
const server = http.createServer(app);
|
||||
|
||||
// Adding server instance inside a callback function also gives a flexibility to add more logic before starting the server
|
||||
const startServer = () => {
|
||||
// Listen to the server instance on the specified port number
|
||||
connectDB(); // connect to the database before starting the server
|
||||
server.listen(PORT, () => {
|
||||
console.log(
|
||||
`Server is running on port ${PORT} AND NODE_ENV is ${process.env.NODE_ENV}`
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
startServer(); // start the server instance
|
||||
@@ -0,0 +1,23 @@
|
||||
const DB = require('../database');
|
||||
|
||||
const { Projects } = DB;
|
||||
|
||||
module.exports = class ProjectService {
|
||||
static async createProject(data) {
|
||||
return Projects.create(data);
|
||||
}
|
||||
|
||||
static async getProjectsByUserId(userId) {
|
||||
return Projects.findAll({
|
||||
where: { userId },
|
||||
include: [
|
||||
{
|
||||
model: DB.Users,
|
||||
as: 'user',
|
||||
attributes: ['name', 'email'],
|
||||
},
|
||||
],
|
||||
order: [['createdAt', 'DESC']],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
const DB = require('../database');
|
||||
const sequelize = require('../database/config/sequelize');
|
||||
const associate = require('../database/relationships');
|
||||
|
||||
// Connect to the database and log a message to the console
|
||||
const connectDB = async () => {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log('Connection has been established successfully🔥');
|
||||
|
||||
// Synchronize the database with the models without need of dropping the tables
|
||||
await DB.sequelize.sync({
|
||||
force: false,
|
||||
});
|
||||
|
||||
associate(); // Call the associate function to create the relationships between the models
|
||||
} catch (error) {
|
||||
console.error('Unable to connect to the database:', error);
|
||||
process.exit(1); // Exit the process if the connection is not successful
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = connectDB;
|
||||
@@ -0,0 +1,21 @@
|
||||
const DB = require('../database');
|
||||
|
||||
const { Users } = DB;
|
||||
|
||||
module.exports = class UserService {
|
||||
static async createUser(data) {
|
||||
return Users.create(data);
|
||||
}
|
||||
|
||||
static async getAllUsers() {
|
||||
return Users.findAll({
|
||||
order: [['createdAt', 'DESC']],
|
||||
});
|
||||
}
|
||||
|
||||
static async getUserById(id) {
|
||||
return Users.findByPk(id);
|
||||
}
|
||||
}
|
||||
|
||||
//module.exports = userService;
|
||||
@@ -0,0 +1 @@
|
||||
console.log('this is placeholder for routes');
|
||||
Reference in New Issue
Block a user