changed all models to typescript

This commit is contained in:
canove
2020-09-19 08:15:47 -03:00
parent b04c0b878e
commit 99fa2cea61
22 changed files with 629 additions and 162 deletions

View File

@@ -20,6 +20,7 @@
"error",
{ "argsIgnorePattern": "_" }
],
"import/prefer-default-export": "off",
"no-console": "off",
"no-param-reassign": "off",
"prettier/prettier": "error",

View File

@@ -2,15 +2,13 @@ import { Request, Response } from "express";
import AuthUserService from "../services/UserServices/AuthUserSerice";
const store = async (req: Request, res: Response): Promise<Response> => {
export const store = async (req: Request, res: Response): Promise<Response> => {
const { email, password } = req.body;
const { user, token } = await AuthUserService({ email, password });
const { token, user } = await AuthUserService({ email, password });
return res.status(200).json({
user,
token
});
};
export default store;

View File

@@ -0,0 +1,174 @@
import { Request, Response } from "express";
import ListTicketsService from "../services/TicketServices/ListTicketsService";
// const Sequelize = require("sequelize");
// const { startOfDay, endOfDay, parseISO } = require("date-fns");
// const Ticket = require("../models/Ticket");
// const Contact = require("../models/Contact");
// const Message = require("../models/Message");
// const Whatsapp = require("../models/Whatsapp");
// const { getIO } = require("../libs/socket");
import Whatsapp from "../models/Whatsapp";
import Ticket from "../models/Ticket";
import Whatsapp from "../models/Whatsapp";
type RequestQuery = {
searchParam: string;
pageNumber: string;
status: string;
date: string;
showAll: string;
};
export const index = async (req: Request, res: Response): Promise<Response> => {
const {
pageNumber,
status,
date,
searchParam,
showAll
} = req.query as RequestQuery;
const userId = req.user.id;
// let includeCondition = [
// {
// model: Contact,
// as: "contact",
// attributes: ["name", "number", "profilePicUrl"]
// }
// ];
// if (searchParam) {
// includeCondition = [
// ...includeCondition,
// {
// model: Message,
// as: "messages",
// attributes: ["id", "body"],
// where: {
// body: Sequelize.where(
// Sequelize.fn("LOWER", Sequelize.col("body")),
// "LIKE",
// "%" + searchParam.toLowerCase() + "%"
// )
// },
// required: false,
// duplicating: false
// }
// ];
// whereCondition = {
// [Sequelize.Op.or]: [
// {
// "$contact.name$": Sequelize.where(
// Sequelize.fn("LOWER", Sequelize.col("name")),
// "LIKE",
// "%" + searchParam.toLowerCase() + "%"
// )
// },
// { "$contact.number$": { [Sequelize.Op.like]: `%${searchParam}%` } },
// {
// "$message.body$": Sequelize.where(
// Sequelize.fn("LOWER", Sequelize.col("body")),
// "LIKE",
// "%" + searchParam.toLowerCase() + "%"
// )
// }
// ]
// };
// }
const { tickets, count, hasMore } = await ListTicketsService({
searchParam,
pageNumber,
status,
date,
showAll,
userId
});
return res.status(200).json({ tickets, count, hasMore });
};
export const store = async (req: Request, res: Response): Promise<Response> => {
// const io = getIO();
const defaultWhatsapp = await Whatsapp.findOne({
where: { default: true }
});
const ticketData = req.body;
if (!defaultWhatsapp) {
return res
.status(404)
.json({ error: "No default WhatsApp found. Check Connection page." });
}
const ticket: Ticket = await defaultWhatsapp.$create("ticket", req.body);
const contact = await ticket.$get("contact");
const wapp = await ticket.$get("whatsapp");
const tickets = await wapp?.$get("tickets");
// const serializaedTicket = { ...ticket.dataValues, contact: contact };
// io.to("notification").emit("ticket", {
// action: "create",
// ticket: serializaedTicket
// });
return res.status(200).json({ ticket, contact, wapp, tickets });
};
// export const update = (req: Request, res: Response): Promise<Response> => {
// const io = getIO();
// const { ticketId } = req.params;
// const ticket = await Ticket.findByPk(ticketId, {
// include: [
// {
// model: Contact,
// as: "contact",
// attributes: ["name", "number", "profilePicUrl"]
// }
// ]
// });
// if (!ticket) {
// return res.status(404).json({ error: "No ticket found with this ID" });
// }
// await ticket.update(req.body);
// io.to("notification").emit("ticket", {
// action: "updateStatus",
// ticket: ticket
// });
// return res.status(200).json(ticket);
// };
// export const remove = (req: Request, res: Response): Promise<Response> => {
// const io = getIO();
// const { ticketId } = req.params;
// const ticket = await Ticket.findByPk(ticketId);
// if (!ticket) {
// return res.status(400).json({ error: "No ticket found with this ID" });
// }
// await ticket.destroy();
// io.to("notification").emit("ticket", {
// action: "delete",
// ticketId: ticket.id
// });
// return res.status(200).json({ message: "ticket deleted" });
// };

View File

@@ -1,32 +1,32 @@
const jwt = require("jsonwebtoken");
const authConfig = require("../config/auth");
const User = require("../models/User");
exports.store = async (req, res, next) => {
const { email, password } = req.body;
const user = await User.findOne({ where: { email: email } });
if (!user) {
return res.status(404).json({ error: "No user found with this email" });
}
if (!(await user.checkPassword(password))) {
return res.status(401).json({ error: "Password does not match" });
}
const token = jwt.sign(
{ email: user.email, userId: user.id },
authConfig.secret,
{
expiresIn: authConfig.expiresIn,
}
);
return res.status(200).json({
token: token,
username: user.name,
profile: user.profile,
userId: user.id,
});
};
const jwt = require("jsonwebtoken");
const authConfig = require("../config/auth");
const User = require("../models/User");
exports.store = async (req, res, next) => {
const { email, password } = req.body;
const user = await User.findOne({ where: { email: email } });
if (!user) {
return res.status(404).json({ error: "No user found with this email" });
}
if (!(await user.checkPassword(password))) {
return res.status(401).json({ error: "Password does not match" });
}
const token = jwt.sign(
{ email: user.email, userId: user.id },
authConfig.secret,
{
expiresIn: authConfig.expiresIn
}
);
return res.status(200).json({
token: token,
username: user.name,
profile: user.profile,
userId: user.id
});
};

View File

@@ -3,24 +3,23 @@ import User from "../models/User";
import Setting from "../models/Setting";
import Contact from "../models/Contact";
import Ticket from "../models/Ticket";
import Whatsapp from "../models/Whatsapp";
import ContactCustomField from "../models/ContactCustomField";
import Message from "../models/Message";
// eslint-disable-next-line
const dbConfig = require("../config/database");
// import dbConfig from "../config/database";
// const Message = require("../models/Message");
// const Whatsapp = require("../models/Whatsapp");
// const ContactCustomField = require("../models/ContactCustomField");
const sequelize = new Sequelize(dbConfig);
const models = [
User,
Contact,
Ticket,
// Message,
// Whatsapp,
// ContactCustomField,
Message,
Whatsapp,
ContactCustomField,
Setting
];

View File

@@ -4,13 +4,15 @@ import {
CreatedAt,
UpdatedAt,
Model,
DataType,
PrimaryKey,
AutoIncrement,
AllowNull,
Unique,
Default
Default,
HasMany
} from "sequelize-typescript";
import ContactCustomField from "./ContactCustomField";
import Ticket from "./Ticket";
@Table
class Contact extends Model<Contact> {
@@ -19,7 +21,7 @@ class Contact extends Model<Contact> {
@Column
id: number;
@Column(DataType.STRING)
@Column
name: string;
@AllowNull(false)
@@ -40,6 +42,12 @@ class Contact extends Model<Contact> {
@UpdatedAt
updatedAt: Date;
@HasMany(() => Ticket)
tickets: Ticket[];
@HasMany(() => ContactCustomField)
extraInfo: ContactCustomField[];
}
export default Contact;

View File

@@ -0,0 +1,41 @@
import {
Table,
Column,
CreatedAt,
UpdatedAt,
Model,
PrimaryKey,
AutoIncrement,
ForeignKey,
BelongsTo
} from "sequelize-typescript";
import Contact from "./Contact";
@Table
class ContactCustomField extends Model<ContactCustomField> {
@PrimaryKey
@AutoIncrement
@Column
id: number;
@Column
name: string;
@Column
value: string;
@ForeignKey(() => Contact)
@Column
contactId: number;
@BelongsTo(() => Contact)
contact: Contact;
@CreatedAt
createdAt: Date;
@UpdatedAt
updatedAt: Date;
}
export default ContactCustomField;

View File

@@ -0,0 +1,60 @@
import {
Table,
Column,
CreatedAt,
UpdatedAt,
Model,
DataType,
PrimaryKey,
AutoIncrement,
Default,
BelongsTo,
ForeignKey
} from "sequelize-typescript";
import Ticket from "./Ticket";
@Table
class Message extends Model<Message> {
@PrimaryKey
@AutoIncrement
@Column
id: number;
@Default(0)
@Column
ack: number;
@Default(false)
@Column
read: boolean;
@Default(false)
@Column
fromMe: boolean;
@Column(DataType.TEXT)
body: string;
@Column
mediaUrl: string;
@Column
mediaType: string;
@CreatedAt
@Column(DataType.DATE(6))
createdAt: Date;
@UpdatedAt
@Column(DataType.DATE(6))
updatedAt: Date;
@ForeignKey(() => Ticket)
@Column
ticketId: number;
@BelongsTo(() => Ticket)
ticket: Ticket;
}
export default Message;

View File

@@ -4,17 +4,16 @@ import {
CreatedAt,
UpdatedAt,
Model,
DataType,
PrimaryKey
} from "sequelize-typescript";
@Table
class Setting extends Model<Setting> {
@PrimaryKey
@Column(DataType.STRING)
@Column
key: string;
@Column(DataType.STRING)
@Column
value: string;
@CreatedAt

View File

@@ -5,25 +5,32 @@ import {
UpdatedAt,
Model,
DataType,
PrimaryKey
PrimaryKey,
ForeignKey,
BelongsTo,
HasMany,
AutoIncrement
} from "sequelize-typescript";
import Contact from "./Contact";
import Message from "./Message";
import User from "./User";
import Whatsapp from "./Whatsapp";
@Table
class Ticket extends Model<Ticket> {
@PrimaryKey
@Column(DataType.NUMBER)
@AutoIncrement
@Column
id: number;
@Column({ defaultValue: "pending" })
status: string;
// @Column({ allowNull: false, unique: true })
// userId: string;
@Column(DataType.VIRTUAL)
unreadMessages: string;
@Column(DataType.STRING)
@Column
lastMessage: string;
@CreatedAt
@@ -31,6 +38,30 @@ class Ticket extends Model<Ticket> {
@UpdatedAt
updatedAt: Date;
@ForeignKey(() => User)
@Column
userId: number;
@BelongsTo(() => User)
user: User;
@ForeignKey(() => Contact)
@Column
contactId: number;
@BelongsTo(() => Contact)
contact: Contact;
@ForeignKey(() => Whatsapp)
@Column
whatsappId: number;
@BelongsTo(() => Whatsapp)
whatsapp: Whatsapp;
@HasMany(() => Message)
messages: Message[];
}
export default Ticket;

View File

@@ -9,9 +9,11 @@ import {
BeforeUpdate,
PrimaryKey,
AutoIncrement,
Default
Default,
HasMany
} from "sequelize-typescript";
import { hash, compare } from "bcryptjs";
import Ticket from "./Ticket";
@Table
class User extends Model<User> {
@@ -42,6 +44,9 @@ class User extends Model<User> {
@UpdatedAt
updatedAt: Date;
@HasMany(() => Ticket)
tickets: Ticket[];
@BeforeUpdate
@BeforeCreate
static hashPassword = async (instance: User): Promise<void> => {

View File

@@ -0,0 +1,53 @@
import {
Table,
Column,
CreatedAt,
UpdatedAt,
Model,
DataType,
PrimaryKey,
AutoIncrement,
Default,
AllowNull,
HasMany
} from "sequelize-typescript";
import Ticket from "./Ticket";
@Table
class Whatsapp extends Model<Whatsapp> {
@PrimaryKey
@AutoIncrement
@Column
id: number;
@Column(DataType.TEXT)
session: string;
@Column(DataType.TEXT)
qrcode: string;
@Column
status: string;
@Column
battery: string;
@Column
plugged: boolean;
@Default(false)
@AllowNull
@Column
default: boolean;
@CreatedAt
createdAt: Date;
@UpdatedAt
updatedAt: Date;
@HasMany(() => Ticket)
tickets: Ticket[];
}
export default Whatsapp;

View File

@@ -1,26 +1,26 @@
const Sequelize = require("sequelize");
class ContactCustomField extends Sequelize.Model {
static init(sequelize) {
super.init(
{
name: { type: Sequelize.STRING },
value: { type: Sequelize.STRING },
},
{
sequelize,
}
);
static init(sequelize) {
super.init(
{
name: { type: Sequelize.STRING },
value: { type: Sequelize.STRING }
},
{
sequelize
}
);
return this;
}
return this;
}
static associate(models) {
this.belongsTo(models.Contact, {
foreignKey: "contactId",
as: "extraInfo",
});
}
static associate(models) {
this.belongsTo(models.Contact, {
foreignKey: "contactId",
as: "extraInfo"
});
}
}
module.exports = ContactCustomField;

View File

@@ -1,35 +1,35 @@
const Sequelize = require("sequelize");
class Message extends Sequelize.Model {
static init(sequelize) {
super.init(
{
ack: { type: Sequelize.INTEGER, defaultValue: 0 },
read: { type: Sequelize.BOOLEAN, defaultValue: false },
fromMe: { type: Sequelize.BOOLEAN, defaultValue: false },
body: { type: Sequelize.TEXT },
mediaUrl: { type: Sequelize.STRING },
mediaType: { type: Sequelize.STRING },
createdAt: {
type: Sequelize.DATE(6),
allowNull: false,
},
updatedAt: {
type: Sequelize.DATE(6),
allowNull: false,
},
},
{
sequelize,
}
);
return this;
}
static associate(models) {
this.belongsTo(models.Ticket, { foreignKey: "ticketId", as: "messages" });
}
}
module.exports = Message;
const Sequelize = require("sequelize");
class Message extends Sequelize.Model {
static init(sequelize) {
super.init(
{
ack: { type: Sequelize.INTEGER, defaultValue: 0 },
read: { type: Sequelize.BOOLEAN, defaultValue: false },
fromMe: { type: Sequelize.BOOLEAN, defaultValue: false },
body: { type: Sequelize.TEXT },
mediaUrl: { type: Sequelize.STRING },
mediaType: { type: Sequelize.STRING },
createdAt: {
type: Sequelize.DATE(6),
allowNull: false
},
updatedAt: {
type: Sequelize.DATE(6),
allowNull: false
}
},
{
sequelize
}
);
return this;
}
static associate(models) {
this.belongsTo(models.Ticket, { foreignKey: "ticketId", as: "messages" });
}
}
module.exports = Message;

View File

@@ -1,32 +1,32 @@
const Sequelize = require("sequelize");
class Whatsapp extends Sequelize.Model {
static init(sequelize) {
super.init(
{
session: { type: Sequelize.TEXT },
qrcode: { type: Sequelize.TEXT },
name: { type: Sequelize.STRING, unique: true, allowNull: false },
status: { type: Sequelize.STRING },
battery: { type: Sequelize.STRING },
plugged: { type: Sequelize.BOOLEAN },
default: {
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNull: false,
},
},
{
sequelize,
}
);
return this;
}
static associate(models) {
this.hasMany(models.Ticket, { foreignKey: "whatsappId", as: "tickets" });
}
}
module.exports = Whatsapp;
const Sequelize = require("sequelize");
class Whatsapp extends Sequelize.Model {
static init(sequelize) {
super.init(
{
session: { type: Sequelize.TEXT },
qrcode: { type: Sequelize.TEXT },
name: { type: Sequelize.STRING, unique: true, allowNull: false },
status: { type: Sequelize.STRING },
battery: { type: Sequelize.STRING },
plugged: { type: Sequelize.BOOLEAN },
default: {
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNull: false
}
},
{
sequelize
}
);
return this;
}
static associate(models) {
this.hasMany(models.Ticket, { foreignKey: "whatsappId", as: "tickets" });
}
}
module.exports = Whatsapp;

View File

@@ -1,5 +1,5 @@
import { Router, Request, Response } from "express";
import SessionController from "../controllers/SessionController";
import * as SessionController from "../controllers/SessionController";
import isAuth from "../middleware/isAuth";
import * as UserController from "../controllers/UserController";
@@ -7,7 +7,7 @@ const authRoutes = Router();
authRoutes.post("/signup", UserController.store);
authRoutes.post("/login", SessionController);
authRoutes.post("/login", SessionController.store);
authRoutes.get("/check", isAuth, (req: Request, res: Response) => {
res.status(200).json({ authenticated: true });

View File

@@ -4,8 +4,8 @@ import userRoutes from "./userRoutes";
import authRoutes from "./authRoutes";
import settingRoutes from "./settingRoutes";
import contactRoutes from "./contactRoutes";
import ticketRoutes from "./ticketRoutes";
// const TicketsRoutes = require("./routes/tickets");
// const MessagesRoutes = require("./routes/messages");
// const WhatsRoutes = require("./routes/whatsapp");
// const UsersRoutes = require("./routes/users");
@@ -16,7 +16,7 @@ routes.use(userRoutes);
routes.use("/auth", authRoutes);
routes.use(settingRoutes);
routes.use(contactRoutes);
// routes.use(TicketsRoutes);
routes.use(ticketRoutes);
// routes.use(MessagesRoutes);
// routes.use(WhatsRoutes);

View File

@@ -1,16 +0,0 @@
const express = require("express");
const isAuth = require("../../middleware/is-auth");
const TicketController = require("../../controllers/TicketController");
const routes = express.Router();
routes.get("/tickets", isAuth, TicketController.index);
routes.post("/tickets", isAuth, TicketController.store);
routes.put("/tickets/:ticketId", isAuth, TicketController.update);
routes.delete("/tickets/:ticketId", isAuth, TicketController.delete);
module.exports = routes;

View File

@@ -0,0 +1,16 @@
import express from "express";
import isAuth from "../middleware/isAuth";
import * as TicketController from "../controllers/TicketController";
const ticketRoutes = express.Router();
ticketRoutes.get("/tickets", isAuth, TicketController.index);
ticketRoutes.post("/tickets", isAuth, TicketController.store);
// ticketRoutes.put("/tickets/:ticketId", isAuth, TicketController.update);
// ticketRoutes.delete("/tickets/:ticketId", isAuth, TicketController.remove);
export default ticketRoutes;

View File

@@ -0,0 +1,24 @@
import * as Yup from "yup";
import AppError from "../../errors/AppError";
import User from "../../models/User";
interface Request {
email: string;
password: string;
name: string;
profile?: string;
}
interface Response {
email: string;
name: string;
id: number;
profile: string;
}
const CreateTicketService = async (): Promise<boolean> => {
return true;
};
export default CreateTicketService;

View File

@@ -0,0 +1,74 @@
import { Op } from "sequelize";
import { startOfDay, endOfDay, parseISO } from "date-fns";
import Ticket from "../../models/Ticket";
interface Request {
searchParam?: string;
pageNumber?: string;
status?: string;
date?: string;
showAll?: string;
userId: string;
}
interface Response {
tickets: Ticket[];
count: number;
hasMore: boolean;
}
const ListTicketsService = async ({
searchParam = "",
pageNumber = "1",
status,
date,
showAll,
userId
}: Request): Promise<Response> => {
let whereCondition = {};
if (showAll === "true") {
whereCondition = {};
} else {
whereCondition = { userId };
}
if (status) {
whereCondition = {
...whereCondition,
status
};
}
if (date) {
whereCondition = {
...whereCondition,
createdAt: {
[Op.between]: [startOfDay(parseISO(date)), endOfDay(parseISO(date))]
}
};
}
const limit = 20;
const offset = limit * (+pageNumber - 1);
const { count, rows: tickets } = await Ticket.findAndCountAll({
where: whereCondition,
// distinct: true,
// include: includeCondition,
limit,
offset,
order: [["updatedAt", "DESC"]]
});
const hasMore = count > offset + tickets.length;
return {
tickets,
count,
hasMore
};
};
export default ListTicketsService;

View File

@@ -28,7 +28,7 @@ const ListUsersService = async ({
{ email: { [Op.like]: `%${searchParam.toLowerCase()}%` } }
]
};
const limit = 10;
const limit = 20;
const offset = limit * (+pageNumber - 1);
const { count, rows: users } = await User.findAndCountAll({