diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8ece3ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules +package-lock.json +build +.env \ No newline at end of file diff --git a/README.md b/README.md index 49352af..f6e00f7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,64 @@ -# labook-template -Repositório do projeto Labook +##

📇 Labook

+ +## :memo: Descrição +Projeto desenvolvido como didática de back-end para as turmas JBL LABENU com conteúdos que englobam o universo da criação de APIs com a temática de um rede social. + +## Link Documentação Postman +[Doc_Postman](https://documenter.getpostman.com/view/22363157/2s935mtRKC) + +## Link Deploy Render +https://labook4.onrender.com + +## 👩🏾Pessoa Desenvolvedora do Projeto + + [
Byron Smith](https://github.com/byron-smith-nobrega) + +## :books: Funcionalidades +* Criar Usuário: Método voltado para a criação de usuários. +* Criar Post: Método voltado para a criação de postagens. +* Buscar Post: Método voltado para a consulta de uma postagem. +* Criar Amizade: Método voltado para a criação de amizade entre usuários. +* Deletar Amizade: Método voltado para a exclusão de uma amizade. +* Criar Curtida: Método voltado para a criação de vínculo entre usuário e postagem. +* Deletar Curtida: Método voltado para a exclusão de vínculo entre usuário e postagem. +* Criar Comentário : Método voltado para a criação de comentário nas postagens. +* Buscar Feeds Amigos : Método voltado para a consulta de postagens dos amigos. +* Buscar Feeds: Método voltado para a consulta de postagens. + +## :wrench: Tecnologias utilizadas +* VS Code +* nodeJS +* expressJS +* axios +* cors +* dotenv +* uuid +* MySQL + + +## :rocket: Rodando o projeto +Para rodar o repositório é necessário clonar o mesmo, dar o seguinte comando para instalar as dependências: +``` +npm install +``` +Após instaladas as dependências, configure o arquivo .env: +``` +DB_HOST = +DB_USER = "" +DB_PASS = "" +DB_NAME = "" +``` +Após configuração do .env, dê o comando seguinte para rodar a aplicação: +``` +npm run start +``` +Após o start, dê o comando seguinte para criar as tabelas no banco de dados: +``` +npm run migrations +``` + +Use o Postman ou o Insomnia para realizar as requisições desejadas. + +## :dart: Status do projeto +O projeto está em andamento. + diff --git a/package.json b/package.json new file mode 100644 index 0000000..20a6081 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "revisao-full-stack", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "tsc && node ./build/index.js", + "dev": "ts-node-dev ./src/index.ts", + "migrations": "tsc && node ./build/data/migrations.js" + }, + "author": "Byron", + "license": "ISC", + "dependencies": { + "@types/node": "^18.11.18", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "knex": "^2.4.0", + "mysql": "^2.18.1", + "typescript": "^4.9.4", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@types/cors": "^2.8.13", + "@types/express": "^4.17.15", + "@types/knex": "^0.16.1", + "@types/uuid": "^9.0.0", + "cors": "^2.8.5", + "ts-node-dev": "^2.0.0" + } +} diff --git a/request.rest b/request.rest new file mode 100644 index 0000000..c86d229 --- /dev/null +++ b/request.rest @@ -0,0 +1,89 @@ + +### Create a new User +POST http://localhost:3003/user/create +Content-Type: application/json + +{ + "name":"Bianca Smith", + "email":"biancasmith@gmail.com", + "password": "1234567" +} + +### Return post +GET http://localhost:3003/post/getpost +Content-Type: application/json + +{ + "id":"1675379034720" +} + +### Create a new Post +POST http://localhost:3003/post/create +Content-Type: application/json +Authorization: 1675001631299 + +{ + "photo" : "Foto", + "description": "foto da viagem", + "type": "normal", + "createdAt": "08/02/2023" +} + +### Create a new Friendship +POST http://localhost:3003/friendship/create +Content-Type: application/json +Authorization: 1675001631299 + +{ + "friendId":"1675019596015" +} + +### Delete Friendship +DELETE http://localhost:3003/friendship +Content-Type: application/json +Authorization: 1675001631299 + +{ + "friendId":"1675019596015" +} + +### Return Feeds freands +GET http://localhost:3003/post/getfeedsfreands +Content-Type: application/json +Authorization: fde08a25-cb5c-4948-bb59-693eb726721d + +### return feed by type +GET http://localhost:3003/post/getfeeds +Content-Type: application/json + +{ + "type":"normal" +} + +### Like Post +POST http://localhost:3003/like/create +Content-Type: application/json +Authorization: 1675001631299 + +{ + "postId":"1675379034720" +} + +### Delete Like Post +DELETE http://localhost:3003/like +Content-Type: application/json +Authorization: 1675001631299 + +{ + "postId":"1675379034720" +} + +### Comment Post +POST http://localhost:3003/comments +Content-Type: application/json +Authorization: 1675001631299 + +{ + "comment":"Linda foto", + "postId":"1675379034720" +} \ No newline at end of file diff --git a/src/business/CommentsBusiness.ts b/src/business/CommentsBusiness.ts new file mode 100644 index 0000000..1eb1501 --- /dev/null +++ b/src/business/CommentsBusiness.ts @@ -0,0 +1,53 @@ +import { CommentDatabase } from "../data/CommentsDatabase"; +import { PostDatabase } from "../data/PostDatabase"; +import { UserDatabase } from "../data/UserDatabase"; +import { InputCommentControllerDTO } from "../model/Comments"; +import { IdGenerator } from "../service/IdGenerator"; + +const commentDatabase = new CommentDatabase(); +const userDatabase = new UserDatabase(); +const postDatabase = new PostDatabase(); +const idGenerator = new IdGenerator(); + +export class CommentsBusiness { + createComment = async (input: InputCommentControllerDTO): Promise => { + try { + const { comment, postId, authorId } = input; + + + if (!comment || !postId || !authorId) { + throw new Error( + 'Fill in the fields "comment", "postId" and "authorId"' + ); + } + + const userBase = await userDatabase.findUser(); + const existUser = userBase.findIndex((user)=>user.id === authorId); + + if(existUser === -1) { + throw new Error("User not exist."); + } + const postBase = await postDatabase.findPost(postId); + const existPost = postBase.findIndex((post)=>post.id === postId); + + if(existPost === -1) { + throw new Error("Post not exist."); + } + + const id: string = idGenerator.generateId(); + + + await commentDatabase.insertcomment({ + id, + comment, + postId, + authorId, + }); + } catch (error:any) { + throw new Error(error.message) + } + }; + + findComment = () => {}; + deleteComment = () => {}; +} \ No newline at end of file diff --git a/src/business/FriendshipBusiness.ts b/src/business/FriendshipBusiness.ts new file mode 100644 index 0000000..010a6b5 --- /dev/null +++ b/src/business/FriendshipBusiness.ts @@ -0,0 +1,104 @@ +import { FriendshipDatabase } from "../data/FriendshipDatabase"; +import { UserDatabase } from "../data/UserDatabase"; +import { FriendInputDTO } from "../model/friends"; +import { DeleteFriendshipInputDTO, FriendshipInputDTO} from "../model/Friendship"; +import { IdGenerator } from "../service/IdGenerator"; + +const friendshipDatabase = new FriendshipDatabase(); +const userDatabase = new UserDatabase(); +const idGenerator = new IdGenerator(); + +export class FriendshipBusiness { + createFriendship = async (input: FriendInputDTO): Promise => { + try { + const { friendId, authorId } = input; + + if (!friendId || !authorId) { + throw new Error("Fill in the friendId, authorId fields"); + } + + const queryUser = await userDatabase.findUser(); + const existFriend = queryUser.findIndex((user) => { + return user.id === friendId; + }); + + if (existFriend === -1) { + throw new Error("Friend id does not exist."); + } + + const existauthorId = queryUser.findIndex((user) => { + return user.id === authorId; + }); + + if (existauthorId === -1) { + throw new Error("User id does not exist."); + } + + const id: string = idGenerator.generateId(); + + const queryResult: FriendshipInputDTO[] = + await friendshipDatabase.findFriendship(authorId); + + const existFriendship = queryResult.findIndex((user) => { + return user.friend_id === friendId; + }); + + if (existFriendship != -1) { + throw new Error("friendship already exists!"); + } + const idFriend: string = idGenerator.generateId(); + + await friendshipDatabase.insertPost({ + id, + idRows: idFriend, + friendId, + authorId, + }); + } catch (error: any) { + throw new Error(error.message); + } + }; + + findFriendship = () => {}; + + deleteFriendship = async (input: DeleteFriendshipInputDTO): Promise => { + try { + const { friendId, authorId } = input; + + if (!friendId || !authorId) { + throw new Error("Fill in the friendId, authorId fields"); + } + + const queryUser = await userDatabase.findUser(); + const existFriend = queryUser.findIndex((user) => { + return user.id === friendId; + }); + + if (existFriend === -1) { + throw new Error("Friend id does not exist."); + } + + const existauthorId = queryUser.findIndex((user) => { + return user.id === authorId; + }); + + if (existauthorId === -1) { + throw new Error("User id does not exist."); + } + + const queryResult: FriendshipInputDTO[] = await friendshipDatabase.findFriendship(authorId); + + const existFriendship = queryResult.findIndex((user) => { + return user.friend_id === friendId; + }); + + if (existFriendship === -1) { + throw new Error("friendship does not exist!"); + } + + await friendshipDatabase.deletePost(input); + } catch (error: any) { + throw new Error(error.message); + } + }; +} diff --git a/src/business/LikeBusiness.ts b/src/business/LikeBusiness.ts new file mode 100644 index 0000000..3e047c7 --- /dev/null +++ b/src/business/LikeBusiness.ts @@ -0,0 +1,108 @@ +import { LikeDatabase } from "../data/LikeDatabase"; +import { PostDatabase } from "../data/PostDatabase"; +import { UserDatabase } from "../data/UserDatabase"; +import { LikeInputControllerDTO, LikeInputDTO } from "../model/likes"; +import { IdGenerator } from "../service/IdGenerator"; + +const likeDatabase = new LikeDatabase(); +const userDatabase = new UserDatabase(); +const postDatabase = new PostDatabase(); +const idGenerator = new IdGenerator(); + +export class LikeBusiness { + createLike = async (input: LikeInputControllerDTO): Promise => { + try { + const { postId, authorId } = input; + + if (!postId || !authorId) { + throw new Error("Fill in the postId, authorId."); + } + + const queryUser = await userDatabase.findUser(); + const queryPost = await postDatabase.findPost(postId); + const existPost = queryPost.findIndex((post) => { + return post.id === postId; + }); + + if (existPost === -1) { + throw new Error("Post id does not exist."); + } + + const existauthorId = queryUser.findIndex((user) => { + return user.id === authorId; + }); + + if (existauthorId === -1) { + throw new Error("User id does not exist."); + } + + const queryResult: LikeInputDTO[] = await likeDatabase.findLike(input); + + const existLike = queryResult.findIndex((like) => { + return like.post_id === postId; + }); + + if (existLike !== -1) { + throw new Error("You already liked this post!"); + } + + + const id: string = idGenerator.generateId(); + + await likeDatabase.insertLike({ + id, + postId, + authorId, + }); + } catch (error: any) { + throw new Error(error.message); + } + }; + + findLike = () => {}; + + deleteLike = async (input: LikeInputControllerDTO): Promise => { + try { + const { postId, authorId } = input; + + if (!postId || !authorId) { + throw new Error("Fill in the postId, authorId"); + } + + const queryUser = await userDatabase.findUser(); + const queryPost = await postDatabase.findPost(postId); + + const existPost = queryPost.findIndex((post) => { + return post.id === postId; + }); + + if (existPost === -1) { + throw new Error("Post id does not exist."); + } + + const existauthorId = queryUser.findIndex((user) => { + return user.id === authorId; + }); + + if (existauthorId === -1) { + throw new Error("User id does not exist."); + } + + const queryResult: LikeInputDTO[] = await likeDatabase.findLike(input); + + const existLike = queryResult.findIndex((like) => { + return like.post_id === postId; + }); + + if (existLike === -1) { + throw new Error("You didn't like this post!"); + } + + const idLike:string = queryResult[0].id + + await likeDatabase.deleteLike(idLike); + } catch (error: any) { + throw new Error(error.message); + } + }; +} diff --git a/src/business/PostBusiness.ts b/src/business/PostBusiness.ts new file mode 100644 index 0000000..7229e29 --- /dev/null +++ b/src/business/PostBusiness.ts @@ -0,0 +1,164 @@ +import { FriendshipDatabase } from "../data/FriendshipDatabase"; +import { PostDatabase } from "../data/PostDatabase"; +import { UserDatabase } from "../data/UserDatabase"; +import { FriendshipInputDTO } from "../model/Friendship"; +import { FeedPostDBDTO, FeedPostDTO, InpultPostDTO, PostIdDTO, PostTypeDTO, TPost } from "../model/Posts"; +import { dateFormat, dateFormatBr } from "../service/formatDate"; +import { IdGenerator } from "../service/IdGenerator"; + +const postDatabase = new PostDatabase(); +const userDatabase = new UserDatabase(); +const friendshipDatabase = new FriendshipDatabase(); +const idGenerator = new IdGenerator(); + +export class PostBusiness { + createPost = async (input: InpultPostDTO): Promise => { + try { + const { photo, description, type, createdAt, authorId } = input; + + if (!photo || !description || !type || !createdAt || !authorId) { + throw new Error( + 'Fill in the fields photo, description, type, authorId' + ); + } + + + if(type.toUpperCase() !== "normal".toUpperCase() && type.toUpperCase() !== "event".toUpperCase()){ + throw new Error( + 'Fill in the fields type: normal or event' + ); + } + + const queryUser = await userDatabase.findUser(); + const existUser = queryUser.findIndex((user)=>{ + return user.id === authorId + }) + + if(existUser === -1){ + throw new Error("User id does not exist.") + } + + const formatDate:any= dateFormat(createdAt.toString()) + + const id: string = idGenerator.generateId(); + + await postDatabase.insertPost({ + id, + photo, + description, + type, + createdAt:formatDate, + authorId + }) + + } catch (error:any) { + throw new Error(error.message) + } + }; + + findPost = async(input:PostIdDTO):Promise=> { + try { + + const { id } = input; + + if(!id){ + throw new Error('Pass the id params'); + } + + const result:TPost[] = await postDatabase.findPost(id) + if (!result[0]) { + throw new Error("Post not found"); + } + return result; + + } catch (error:any) { + throw new Error(error.message) + } + }; + + feedPost = async(input:PostIdDTO):Promise => { + try { + const {id} = input; + + const queryUser = await userDatabase.findUser(); + const existUser = queryUser.findIndex((user)=>{ + return user.id === id + }) + + if(existUser === -1){ + throw new Error("User id does not exist.") + } + + const queryFriends: FriendshipInputDTO[] = await friendshipDatabase.findFriendship(id); + const existFriendship = queryFriends.findIndex((user) => { + return user.author_id === id; + }); + + if (existFriendship === -1) { + throw new Error("friendship already exists!"); + } + + const friends:string[] = [] + + for (let i = 0; i < queryFriends.length; i++) { + friends.push(queryFriends[i].friend_id); + } + const posts: FeedPostDTO[] = []; + const result:FeedPostDBDTO[] = await postDatabase.feedPost(friends) + result.map((item:any)=>{ + item.created_at = dateFormatBr(item.created_at.toString()) + return result + }) + for (let i = 0; i < result.length; i++) { + posts.push({ + id: result[i].id, + photo: result[i].photo, + description: result[i].description, + type: result[i].type, + createdAt: result[i].created_at, + authorId: result[i].author_id} + ) + + } + + return posts + } catch (error:any) { + throw new Error(error.message) + } + }; + feedPostAll = async(input:PostTypeDTO) => { + try { + + const{type} = input; + + if(type.toUpperCase() !== "normal".toUpperCase() && type.toUpperCase() !== "event".toUpperCase()){ + throw new Error( + 'Fill in the field type: normal or event' + ); + } + const posts: FeedPostDTO[] = []; + const result:FeedPostDBDTO[] = await postDatabase.feedPostAll(input) + result.map((item:any)=>{ + item.created_at = dateFormatBr(item.created_at.toString()) + return result + }) + + for (let i = 0; i < result.length; i++) { + posts.push({ + id: result[i].id, + photo: result[i].photo, + description: result[i].description, + type: result[i].type, + createdAt: result[i].created_at, + authorId: result[i].author_id} + ) + + } + + return posts + } catch (error:any) { + throw new Error(error.message) + } + }; + deletePost = () => {}; +} \ No newline at end of file diff --git a/src/business/UserBusiness.ts b/src/business/UserBusiness.ts new file mode 100644 index 0000000..f37b5a3 --- /dev/null +++ b/src/business/UserBusiness.ts @@ -0,0 +1,45 @@ +import { UserDatabase } from "../data/UserDatabase"; +import { InputControllerDTO } from "../model/User"; +import { IdGenerator } from "../service/IdGenerator"; +const idGenerator = new IdGenerator(); + +export class UserBusiness { + createUser = async (input: InputControllerDTO): Promise => { + try { + const { name, email, password } = input; + + const userDatabase = new UserDatabase(); + + if (!name || !email || !password) { + throw new Error( + 'Fill in the fields "name", "email" e "password"' + ); + } + + if (password.length < 6) { + throw new Error("Password too short minimum 6 characters"); + } + + const userBase = await userDatabase.findUser(); + const existUser = userBase.findIndex((user)=>user.email === email) + + if(existUser != -1) { + throw new Error("User already registered"); + } + const id: string = idGenerator.generateId(); + + + await userDatabase.insertUser({ + id, + name, + email, + password, + }); + } catch (error:any) { + throw new Error(error.message) + } + }; + + findUser = () => {}; + deleteUser = () => {}; +} \ No newline at end of file diff --git a/src/controller/CommentsController.ts b/src/controller/CommentsController.ts new file mode 100644 index 0000000..f3e8358 --- /dev/null +++ b/src/controller/CommentsController.ts @@ -0,0 +1,25 @@ +import { Request, Response } from "express"; +import { CommentsBusiness} from "../business/CommentsBusiness"; +import { InputCommentControllerDTO } from "../model/Comments"; + +export class CommentController { + createComment = async (req: Request, res: Response): Promise => { + try { + const input: InputCommentControllerDTO = { + comment: req.body.comment, + postId: req.body.postId, + authorId: req.headers.authorization as string + }; + + const commentBusiness = new CommentsBusiness() + await commentBusiness.createComment(input) + + res.status(201).send({ message: "Comment created!" }); + } catch (error: any) { + res.status(400).send(error.message); + } + }; + + findComment = () => {}; + deleteComment = () => {}; +} \ No newline at end of file diff --git a/src/controller/FriendshipController.ts b/src/controller/FriendshipController.ts new file mode 100644 index 0000000..1b45a8a --- /dev/null +++ b/src/controller/FriendshipController.ts @@ -0,0 +1,37 @@ +import { Request, Response } from "express"; +import { FriendshipBusiness } from "../business/FriendshipBusiness"; +import { FriendInputDTO } from "../model/friends"; +import { DeleteFriendshipInputDTO } from "../model/Friendship"; +const friendshipBusiness = new FriendshipBusiness(); +export class FriendshipController { + createFriendship = async (req: Request, res: Response): Promise => { + try { + const input: FriendInputDTO = { + friendId: req.body.friendId, + authorId: req.headers.authorization as string + }; + + await friendshipBusiness.createFriendship(input) + + res.status(201).send({ message: "Friendship created!" }); + } catch (error: any) { + res.status(400).send(error.message); + } + }; + + findFriendship = () => {}; + + deleteFriendship = async(req:Request, res:Response):Promise => { + try { + const input: DeleteFriendshipInputDTO = { + friendId: req.body.friendId, + authorId: req.headers.authorization as string + }; + + await friendshipBusiness.deleteFriendship(input) + res.status(201).send({ message: "deleted from friendship!" }); + } catch (error:any) { + res.status(400).send(error.message); + } + }; +} diff --git a/src/controller/LikeController.ts b/src/controller/LikeController.ts new file mode 100644 index 0000000..88eb9b4 --- /dev/null +++ b/src/controller/LikeController.ts @@ -0,0 +1,37 @@ +import { Request, Response } from "express"; +import { LikeBusiness } from "../business/LikeBusiness"; +import { LikeInputControllerDTO } from "../model/likes"; + +const likeBusiness = new LikeBusiness(); +export class LikeController { + createLike = async (req: Request, res: Response): Promise => { + try { + const input: LikeInputControllerDTO = { + postId: req.body.postId, + authorId: req.headers.authorization as string + }; + + await likeBusiness.createLike(input) + + res.status(201).send({ message: "Like success!" }); + } catch (error: any) { + res.status(400).send(error.message); + } + }; + + findLike = () => {}; + + deleteLike = async(req:Request, res:Response):Promise => { + try { + const input: LikeInputControllerDTO = { + postId: req.body.postId, + authorId: req.headers.authorization as string + }; + + await likeBusiness.deleteLike(input) + res.status(201).send({ message: "deleted from Like!" }); + } catch (error:any) { + res.status(400).send(error.message); + } + }; +} \ No newline at end of file diff --git a/src/controller/PostController.ts b/src/controller/PostController.ts new file mode 100644 index 0000000..ee059ac --- /dev/null +++ b/src/controller/PostController.ts @@ -0,0 +1,69 @@ +import { Request, Response } from "express"; +import { PostBusiness } from "../business/PostBusiness"; +import { InpultPostDTO, PostIdDTO, PostTypeDTO } from "../model/Posts"; + +const postBusiness = new PostBusiness() + +export class PostController { + createPost = async (req: Request, res: Response): Promise => { + try { + const input: InpultPostDTO = { + photo: req.body.photo, + description:req.body.description, + type: req.body.type, + createdAt: req.body.createdAt, + authorId: req.headers.authorization as string + }; + + await postBusiness.createPost(input) + + res.status(201).send({ message: "Post created!" }); + } catch (error: any) { + res.status(400).send(error.message); + } + }; + + findPost = async (req: Request, res: Response): Promise => { + try { + const input: PostIdDTO = { + id: req.body.id + }; + + const posts = await postBusiness.findPost(input) + + res.status(200).send({ posts }); + } catch (error: any) { + res.status(400).send(error.message); + } + }; + + feedPost = async(req: Request, res: Response) => { + try { + const input: PostIdDTO = { + id: req.headers.authorization as string + }; + + const posts = await postBusiness.feedPost(input) + + res.status(200).send({ posts }); + } catch (error: any) { + res.status(400).send(error.message); + } + }; + + feedPostAll = async(req: Request, res: Response) => { + try { + const input: PostTypeDTO = { + type: req.body.type + }; + + const posts = await postBusiness.feedPostAll(input) + + res.status(200).send({ posts }); + } catch (error: any) { + res.status(400).send(error.message); + } + }; + deletePost = () => {}; + +} \ No newline at end of file diff --git a/src/controller/UserController.ts b/src/controller/UserController.ts new file mode 100644 index 0000000..b3ce7d5 --- /dev/null +++ b/src/controller/UserController.ts @@ -0,0 +1,25 @@ +import { Request, Response } from "express"; +import { UserBusiness } from "../business/UserBusiness"; +import { InputControllerDTO } from "../model/User"; + +export class UserController { + createUser = async (req: Request, res: Response): Promise => { + try { + const input: InputControllerDTO = { + name: req.body.name, + email: req.body.email, + password: req.body.password, + }; + + const userBusiness = new UserBusiness() + await userBusiness.createUser(input) + + res.status(201).send({ message: "User created!" }); + } catch (error: any) { + res.status(400).send(error.message); + } + }; + + findUser = () => {}; + deleteUser = () => {}; +} \ No newline at end of file diff --git a/src/controller/app.ts b/src/controller/app.ts new file mode 100644 index 0000000..32e736f --- /dev/null +++ b/src/controller/app.ts @@ -0,0 +1,13 @@ +import express from 'express' +import cors from 'cors' + +const app = express() + +app.use(express.json()) +app.use(cors()) + +app.listen(3003, ()=>{ + console.log('Servidor rodando na porta 3003') +}) + +export default app \ No newline at end of file diff --git a/src/controller/router/FriendshipRouter.ts b/src/controller/router/FriendshipRouter.ts new file mode 100644 index 0000000..a43c44b --- /dev/null +++ b/src/controller/router/FriendshipRouter.ts @@ -0,0 +1,11 @@ +import express from "express"; + +import { FriendshipController } from "../FriendshipController"; + +export const friendshipRouter = express.Router() + +const friendshipController = new FriendshipController(); + +friendshipRouter.post('/create',friendshipController.createFriendship); +friendshipRouter.delete('/',friendshipController.deleteFriendship); + diff --git a/src/controller/router/commentsRouter.ts b/src/controller/router/commentsRouter.ts new file mode 100644 index 0000000..3c238db --- /dev/null +++ b/src/controller/router/commentsRouter.ts @@ -0,0 +1,10 @@ +import express from "express"; + +import { CommentController } from "../CommentsController"; + +export const commentsRouter = express.Router() + +const commentController = new CommentController(); + +commentsRouter.post('/', commentController.createComment); + diff --git a/src/controller/router/likeRouter.ts b/src/controller/router/likeRouter.ts new file mode 100644 index 0000000..8f58943 --- /dev/null +++ b/src/controller/router/likeRouter.ts @@ -0,0 +1,11 @@ +import express from "express"; + +import { LikeController } from "../LikeController"; + +export const likeRouter = express.Router() + +const likeController = new LikeController(); + +likeRouter.post('/create',likeController.createLike); +likeRouter.delete('/',likeController.deleteLike); + diff --git a/src/controller/router/postRouter.ts b/src/controller/router/postRouter.ts new file mode 100644 index 0000000..d4d4df1 --- /dev/null +++ b/src/controller/router/postRouter.ts @@ -0,0 +1,13 @@ +import express from "express"; + +import { PostController } from "../PostController"; + +export const postRouter = express.Router() + +const postController = new PostController(); + +postRouter.post('/create',postController.createPost); +postRouter.get('/getpost',postController.findPost); +postRouter.get('/getfeedsfreands',postController.feedPost); +postRouter.get('/getfeeds',postController.feedPostAll); + diff --git a/src/controller/router/userRouter.ts b/src/controller/router/userRouter.ts new file mode 100644 index 0000000..7d47b43 --- /dev/null +++ b/src/controller/router/userRouter.ts @@ -0,0 +1,10 @@ +import express from "express"; + +import { UserController } from "../UserController"; + +export const userRouter = express.Router() + +const userController = new UserController(); + +userRouter.post('/create', userController.createUser); + diff --git a/src/data/BaseDatabase.ts b/src/data/BaseDatabase.ts new file mode 100644 index 0000000..2663d9c --- /dev/null +++ b/src/data/BaseDatabase.ts @@ -0,0 +1,17 @@ +import knex from "knex" +import dotenv from "dotenv"; + +dotenv.config(); +export abstract class BaseDatabase { + protected static connection = knex({ + client: "mysql", + connection: { + host: process.env.DB_HOST, + port: 3306, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_DATABASE, + multipleStatements: true + }, +}); +} \ No newline at end of file diff --git a/src/data/CommentsDatabase.ts b/src/data/CommentsDatabase.ts new file mode 100644 index 0000000..056eb40 --- /dev/null +++ b/src/data/CommentsDatabase.ts @@ -0,0 +1,42 @@ +import { BaseDatabase } from "./BaseDatabase"; +import { CommentInputBDTO, InputCommentDTO } from "../model/Comments"; + +export class CommentDatabase extends BaseDatabase { + private static TABLE_NAME ="labook_comments"; + insertcomment = async (comment: InputCommentDTO): Promise => { + try { + await CommentDatabase.connection + .insert({ + id: comment.id, + comment: comment.comment, + post_id: comment.postId, + author_id: comment.authorId + }) + .into(CommentDatabase.TABLE_NAME); + } catch (error: any) { + throw new Error(error.message); + } + }; + + findcomment = async (input:string): Promise => { + try { + const comments: CommentInputBDTO[] = []; + + const result = await CommentDatabase.connection + .select("*") + .from(CommentDatabase.TABLE_NAME) + .where({input}); + + + for (let comment of result) { + comments.push(comment); + } + + return comments; + + } catch (error: any) { + throw new Error(error.message); + } + }; + deletecomment = () => {}; +} diff --git a/src/data/FriendshipDatabase.ts b/src/data/FriendshipDatabase.ts new file mode 100644 index 0000000..e37f5c6 --- /dev/null +++ b/src/data/FriendshipDatabase.ts @@ -0,0 +1,67 @@ +import { BaseDatabase } from "./BaseDatabase"; +import { + DeleteFriendshipInputDTO, + FriendshipInputDataDTO, + FriendshipInputDTO + } from "../model/Friendship"; + +export class FriendshipDatabase extends BaseDatabase { + private static TABLE_NAME = "labook_friendship"; + insertPost = async (friend: FriendshipInputDataDTO): Promise => { + try { + await FriendshipDatabase.connection + .insert({ + id: friend.id, + friend_id: friend.friendId, + author_id: friend.authorId, + }) + .into(FriendshipDatabase.TABLE_NAME); + + await FriendshipDatabase.connection + .insert({ + id: friend.idRows, + friend_id: friend.authorId, + author_id: friend.friendId, + }) + .into(FriendshipDatabase.TABLE_NAME); + } catch (error: any) { + throw new Error(error.message); + } + }; + + findFriendship = async (userid: string): Promise => { + try { + const friends: FriendshipInputDTO[] = []; + + const result = await FriendshipDatabase.connection + .select("*") + .from(FriendshipDatabase.TABLE_NAME) + .where({ author_id: userid }); + + for (let friend of result) { + friends.push(friend); + } + + return friends; + } catch (error: any) { + throw new Error(error.message); + } + }; + deletePost = async (input: DeleteFriendshipInputDTO): Promise => { + try { + const { friendId, authorId } = input; + + await FriendshipDatabase.connection + .from(FriendshipDatabase.TABLE_NAME) + .where({ author_id: authorId, friend_id: friendId }) + .delete(); + + await FriendshipDatabase.connection + .from(FriendshipDatabase.TABLE_NAME) + .where({ author_id: friendId, friend_id: authorId }) + .delete(); + } catch (error: any) { + throw new Error(error.message); + } + }; +} diff --git a/src/data/LikeDatabase.ts b/src/data/LikeDatabase.ts new file mode 100644 index 0000000..e2ee473 --- /dev/null +++ b/src/data/LikeDatabase.ts @@ -0,0 +1,46 @@ +import { BaseDatabase } from "./BaseDatabase"; +import { LikeInputControllerDTO, LikeInputDataDTO, LikeInputDTO } from "../model/likes"; + +export class LikeDatabase extends BaseDatabase { + private static TABLE_NAME = "labook_likes"; + insertLike = async (input: LikeInputDataDTO): Promise => { + try { + await LikeDatabase.connection + .insert({ + id: input.id, + post_id: input.postId, + author_id: input.authorId, + }) + .into(LikeDatabase.TABLE_NAME); + } catch (error: any) { + throw new Error(error.message); + } + }; + + findLike = async (input: LikeInputControllerDTO): Promise => { + try { + + const {postId,authorId}= input; + + const result = await LikeDatabase.connection + .select("*") + .from(LikeDatabase.TABLE_NAME) + .where({ post_id: postId, author_id: authorId }); + + return result; + } catch (error: any) { + throw new Error(error.message); + } + }; + + deleteLike = async (input: string): Promise => { + try { + await LikeDatabase.connection + .from(LikeDatabase.TABLE_NAME) + .where({ id: input }) + .delete(); + } catch (error: any) { + throw new Error(error.message); + } + }; +} diff --git a/src/data/PostDatabase.ts b/src/data/PostDatabase.ts new file mode 100644 index 0000000..4a30b00 --- /dev/null +++ b/src/data/PostDatabase.ts @@ -0,0 +1,59 @@ +import { BaseDatabase } from "./BaseDatabase"; +import { FeedPostDBDTO, PostTypeDTO, TPost } from "../model/Posts"; + +export class PostDatabase extends BaseDatabase { + private static TABLE_NAME = "labook_posts"; + insertPost = async (post: TPost): Promise => { + try { + await PostDatabase.connection + .insert({ + id: post.id, + photo: post.photo, + description: post.description, + type: post.type, + created_at: post.createdAt, + author_id: post.authorId, + }) + .into(PostDatabase.TABLE_NAME); + } catch (error: any) { + throw new Error(error.message); + } + }; + + findPost = async (postid: string): Promise => { + try { + + const result = await PostDatabase.connection + .select("*") + .from(PostDatabase.TABLE_NAME) + .where({ id: postid }); + + return result; + } catch (error: any) { + throw new Error(error.message); + } + }; + + feedPost = async (input: string[]): Promise => { + try { + const [result] = await PostDatabase.connection.raw( + `select * from ${PostDatabase.TABLE_NAME} where author_id in ('${input}') order by created_at desc;` + ); + return result; + } catch (error: any) { + throw new Error(error.message); + } + }; + + feedPostAll = async (input: PostTypeDTO): Promise => { + try { + const [result] = await PostDatabase.connection.raw( + `select * from ${PostDatabase.TABLE_NAME} where type = "${input.type}" order by created_at desc;` + ); + return result; + } catch (error: any) { + throw new Error(error.message); + } + }; + deletePost = () => {}; +} diff --git a/src/data/TableDataBase.ts b/src/data/TableDataBase.ts new file mode 100644 index 0000000..ea1c1c8 --- /dev/null +++ b/src/data/TableDataBase.ts @@ -0,0 +1,55 @@ +import { BaseDatabase } from "./BaseDatabase"; + +export class Migration extends BaseDatabase { + createTables = async () => { + try { + await Migration.connection + .raw(` + CREATE TABLE IF NOT EXISTS labook_users( + id VARCHAR(255) PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) UNIQUE NOT NULL, + password VARCHAR(255) NOT NULL + ); + CREATE TABLE IF NOT EXISTS labook_posts( + id VARCHAR(255) PRIMARY KEY, + photo VARCHAR(255) NOT NULL, + description VARCHAR(255) NOT NULL, + type ENUM("normal","event") DEFAULT "normal", + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + author_id VARCHAR(255), + FOREIGN KEY (author_id) REFERENCES labook_users (id) + ); + CREATE TABLE IF NOT EXISTS labook_friendship( + id VARCHAR(255) PRIMARY KEY, + friend_id VARCHAR(255) NOT NULL, + author_id VARCHAR(255) NOT NULL, + FOREIGN KEY (author_id) REFERENCES labook_users (id), + FOREIGN KEY (friend_id) REFERENCES labook_users (id) + ); + CREATE TABLE IF NOT EXISTS labook_likes( + id VARCHAR(255) PRIMARY KEY, + post_id VARCHAR(255) NOT NULL, + author_id VARCHAR(255) NOT NULL, + FOREIGN KEY (author_id) REFERENCES labook_users (id), + FOREIGN KEY (post_id) REFERENCES labook_posts (id) + ); + CREATE TABLE IF NOT EXISTS labook_comments( + id VARCHAR(255) PRIMARY KEY, + comment TEXT(500) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + post_id VARCHAR(255) NOT NULL, + author_id VARCHAR(255) NOT NULL, + FOREIGN KEY (author_id) REFERENCES labook_users (id), + FOREIGN KEY (post_id) REFERENCES labook_posts (id) + ); + `) + } catch (error: any) { + throw new Error(error.message); + } + }; +} + +const printError = (error: any) => { + console.log(error.sqlMessage || error.message); +}; diff --git a/src/data/UserDatabase.ts b/src/data/UserDatabase.ts new file mode 100644 index 0000000..0630728 --- /dev/null +++ b/src/data/UserDatabase.ts @@ -0,0 +1,41 @@ +import { BaseDatabase } from "./BaseDatabase"; +import { UserDTO } from "../model/User"; + +export class UserDatabase extends BaseDatabase { + private static TABLE_NAME = "labook_users"; + insertUser = async (user: UserDTO): Promise => { + try { + await UserDatabase.connection + .insert({ + id: user.id, + name: user.name, + email: user.email, + password: user.password, + }) + .into(UserDatabase.TABLE_NAME); + } catch (error: any) { + throw new Error(error.message); + } + }; + + findUser = async (): Promise => { + try { + const users: UserDTO[] = []; + + const result = await UserDatabase.connection + .select("*") + .from(UserDatabase.TABLE_NAME); + + + for (let user of result) { + users.push(user); + } + + return users; + + } catch (error: any) { + throw new Error(error.message); + } + }; + deleteUser = () => {}; +} diff --git a/src/data/migrations.ts b/src/data/migrations.ts new file mode 100644 index 0000000..a7b0a5f --- /dev/null +++ b/src/data/migrations.ts @@ -0,0 +1,10 @@ +import { Migration } from "./TableDataBase" +const migration = new Migration(); + +const queryMigrations = ()=>{ + migration.createTables(); + console.log("Tabelas criadas!!"); + +} + +queryMigrations(); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..9c90076 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,17 @@ +import app from "./controller/app" +import { userRouter } from "./controller/router/userRouter" +import { postRouter } from "./controller/router/postRouter" +import { friendshipRouter } from "./controller/router/FriendshipRouter" +import { likeRouter } from "./controller/router/likeRouter" +import { commentsRouter } from "./controller/router/commentsRouter" + + + +/**************************** ENDPOINTS ******************************/ +app.use('/user', userRouter) +app.use('/post', postRouter); +app.use('/friendship', friendshipRouter); +app.use('/like', likeRouter); +app.use('/comments', commentsRouter); + + diff --git a/src/model/Comments.ts b/src/model/Comments.ts new file mode 100644 index 0000000..a9ea19e --- /dev/null +++ b/src/model/Comments.ts @@ -0,0 +1,22 @@ +export interface InputCommentDTO{ + id: string, + comment: string, + postId: string, + authorId: string + } + export interface CommentInputBDTO{ + id: string, + comment: string, + created_at: Date, + post_id: string, + author_id: string + } + export interface InputCommentControllerDTO{ + comment: string, + postId: string, + authorId: string + } + + export interface CommentIdDTO{ + id: string, + } diff --git a/src/model/Friendship.ts b/src/model/Friendship.ts new file mode 100644 index 0000000..c97dda7 --- /dev/null +++ b/src/model/Friendship.ts @@ -0,0 +1,24 @@ +export type TFriendship = { + id: string, + friendId: string, + authorId: string + +} +export interface FriendshipInputDTO{ + id: string, + friend_id: string, + author_id: string + +} +export interface FriendshipInputDataDTO{ + id: string, + idRows: string, + friendId: string, + authorId: string + +} +export interface DeleteFriendshipInputDTO{ + friendId: string, + authorId: string + +} \ No newline at end of file diff --git a/src/model/Posts.ts b/src/model/Posts.ts new file mode 100644 index 0000000..85947ee --- /dev/null +++ b/src/model/Posts.ts @@ -0,0 +1,45 @@ +enum TPOST_TYPES { + NORMAL = "normal", + EVENT = "event" + } + + export type TPost = { + id: string, + photo: string, + description: string, + type: TPOST_TYPES, + createdAt: Date, + authorId: string + } + + export interface FeedPostDTO{ + id: string, + photo: string, + description: string, + type: TPOST_TYPES, + createdAt: Date, + authorId: string + } + export interface FeedPostDBDTO{ + id: string, + photo: string, + description: string, + type: TPOST_TYPES, + created_at: Date, + author_id: string + } + export interface InpultPostDTO{ + photo: string, + description: string, + type: TPOST_TYPES, + createdAt: Date, + authorId: string + } + + export interface PostIdDTO{ + id: string, + } + + export interface PostTypeDTO{ + type: TPOST_TYPES + } \ No newline at end of file diff --git a/src/model/User.ts b/src/model/User.ts new file mode 100644 index 0000000..2b98e0e --- /dev/null +++ b/src/model/User.ts @@ -0,0 +1,16 @@ +export type authenticationData = { + id: string + } + +export interface UserDTO{ + id: string, + name: string, + email: string, + password: string + } +export interface InputControllerDTO{ + name: string, + email: string, + password: string + } + \ No newline at end of file diff --git a/src/model/friends.ts b/src/model/friends.ts new file mode 100644 index 0000000..2009adc --- /dev/null +++ b/src/model/friends.ts @@ -0,0 +1,10 @@ +export type TFriends = { + friend_id: string, + name: string + +} + +export interface FriendInputDTO{ + friendId: string, + authorId: string +} \ No newline at end of file diff --git a/src/model/likes.ts b/src/model/likes.ts new file mode 100644 index 0000000..fe2deed --- /dev/null +++ b/src/model/likes.ts @@ -0,0 +1,18 @@ +export interface LikeInputDTO{ + id: string, + post_id: string, + author_id: string + +} +export interface LikeInputDataDTO{ + id: string, + postId: string, + authorId: string +} +export interface LikeInputControllerDTO{ + postId: string, + authorId: string +} +export interface DeleteLikeInputDTO{ + id: string, +} \ No newline at end of file diff --git a/src/service/IdGenerator.ts b/src/service/IdGenerator.ts new file mode 100644 index 0000000..b36379b --- /dev/null +++ b/src/service/IdGenerator.ts @@ -0,0 +1,6 @@ +import { v4 } from "uuid"; + +export class IdGenerator { + + public generateId = () => v4() +} \ No newline at end of file diff --git a/src/service/formatDate.ts b/src/service/formatDate.ts new file mode 100644 index 0000000..02677c1 --- /dev/null +++ b/src/service/formatDate.ts @@ -0,0 +1,13 @@ +export const dateFormat = (dateAccount: string): string => { + let parts = dateAccount.split("/"); + dateAccount = `${parts[2]}-${parts[1]}-${parts[0]}`; + return dateAccount; +}; +export const dateFormatBr = (dateAccount: string): string => { + let data = new Date(dateAccount); + let date = String(data.getDate()).padStart(2, "0"); + let month = String(data.getMonth() + 1).padStart(2, "0"); + let fullYear = data.getFullYear(); + let dataAtual = date + "/" + month + "/" + fullYear; + return dataAtual; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a9ee948 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, + "outDir": "./build" /* Redirect output structure to the directory. */, + "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, + "strict": true /* Enable all strict type-checking options. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +} \ No newline at end of file