Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,427 changes: 2,427 additions & 0 deletions semana17/aula2/package-lock.json

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions semana17/aula2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "aula-back-arquitetura",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "ts-node-dev ./src/index.ts"
},
"author": "",
"license": "ISC",
"dependencies": {
"@types/express": "^4.17.3",
"@types/knex": "^0.16.1",
"@types/node": "^13.7.7",
"@types/uuid": "^7.0.0",
"express": "^4.17.1",
"knex": "^0.20.11",
"mysql": "^2.18.1",
"ts-node": "^8.6.2",
"ts-node-dev": "^1.0.0-pre.44",
"typescript": "^3.8.3",
"uuid": "^7.0.2"
}
}
87 changes: 87 additions & 0 deletions semana17/aula2/src/business/entities/post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { User } from "./user";
import { type } from "os";

export class Post {
constructor(
private id: string,
private title: string,
private content: string,
private type: PostType,
private userId: string,
private image?: string
) {}

public getId(): string {
return this.id;
}

public setId(id: string): void {
this.id = id;
}

public getTitle(): string {
return this.title;
}

public setTitle(title: string): void {
this.title = title;
}

public getContent(): string {
return this.content;
}

public setContent(content: string): void {
this.content = content;
}

public getType(): PostType {
return this.type;
}

public setType(type: PostType): void {
this.type = type;
}

public getUserId(): string {
return this.userId;
}

public setUserId(userId: string): void {
this.userId = userId;
}

public getImage(): string | undefined {
return this.image;
}

public setImage(image: string): void {
this.image = image;
}
}

export enum PostType {
normal = "normal",
event = "event"
}

export class PostWithUser extends Post {
constructor(
id: string,
title: string,
content: string,
type: PostType,
private user: User,
image?: string
) {
super(id, title, content, type, user.getId(), image);
}

public setUser(user: User): void {
this.user = user;
}

public getUser(): User {
return this.user;
}
}
40 changes: 40 additions & 0 deletions semana17/aula2/src/business/entities/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export class User {
constructor(
private id: string,
private name: string,
private email: string,
private birthDate: Date
) {}

public getEmail(): string {
return this.email;
}

public setEmail(email: string): void {
this.email = email;
}

public getName(): string {
return this.name;
}

public setName(name: string): void {
this.name = name;
}

public getId(): string {
return this.id;
}

public setId(id: string): void {
this.id = id;
}

public getBirthDate(): Date {
return this.birthDate;
}

public setBirthDate(birthDate: Date) {
this.birthDate = birthDate;
}
}
5 changes: 5 additions & 0 deletions semana17/aula2/src/business/error/BaseError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export abstract class BaseError extends Error {
constructor(public errorCode: number, message: string) {
super(message);
}
}
7 changes: 7 additions & 0 deletions semana17/aula2/src/business/error/InvalidParameterError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { BaseError } from "./BaseError";

export class InvalidParameterError extends BaseError {
constructor(message: string) {
super(401, message);
}
}
7 changes: 7 additions & 0 deletions semana17/aula2/src/business/error/NotFoundError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { BaseError } from "./BaseError";

export class NotFoundError extends BaseError {
constructor(message: string) {
super(404, message);
}
}
90 changes: 90 additions & 0 deletions semana17/aula2/src/business/usecase/posts/createPost.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { PostDB } from "../../../data/postDataBase";
import { Post, PostType } from "../../entities/post";
import { InvalidParameterError } from "../../error/InvalidParameterError";
import { v4 } from "uuid";

export class CreatePostUC {
constructor(private db: PostDB) {}

public async execute(input: CreatePostUCInput): Promise<CreatePostUCOutput> {
const id = v4();
let type = PostType.normal;
if (input.type === "event") {
type = PostType.event;
} else if (input.type !== "normal") {
throw new InvalidParameterError("Invalid type");
}

const post = new Post(
id,
input.title,
input.content,
type,
input.userId,
input.image
);

await this.db.createPost(post);

return {
message: "Post created successfully"
};
}
}

export interface CreatePostUCInput {
title: string;
content: string;
type: string;
userId: string;
image?: string;
}

export interface CreatePostUCOutput {
message: string;
}


// (i)
/**
* Os tipo de posts disponíveis são normal e event.
*/

// (ii)
/**
* A criação de posts verifica qual é o tipo do post a ser criado;
* caso ele não seja event ou normal, é exibida uma mensagem de erro.
*/

// (iii)
/**
* Porque não é esperado que seja criado nenhum objeto desta classe; ela serve apenas como modelo.
* Ela guarda todas as informações referentes ao banco de dados a ser acessado.
*/

// (iv)
/**
* Cria uma nova instância do CreatePostUC.
*/

// (v)
/**
* É necessário para organizar os dados que serão enviados ao banco de dados.
*/

// (vi)
/**
* O input são os dados passados pelo endpoint; mais precisamente, vem dos dados passados no body da requisição.
*/

// (vii)
/**
* Vem do CreatePostUC, que chama a função createPost, passando os dados do post.
*/

// (viii)
/**
* Porque o usuário pode ou não inserir uma imagem no post.
* Caso o ternário não existisse, haveria um erro ao incluir os dados no banco de dados,
* que reberia um undefined caso a imagem não fosse incluída no post.
*/
20 changes: 20 additions & 0 deletions semana17/aula2/src/business/usecase/posts/deletePost.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PostDB } from "../../../data/postDataBase";
import { NotFoundError } from "../../error/NotFoundError";

export class DeletePostUC {
constructor(private db: PostDB) {}

public async execute(input: DeletePostUCInput): Promise<void> {
const post = await this.db.getPost(input.id);

if (!post) {
throw new NotFoundError("Post not found");
}

await this.db.deletePost(input.id);
}
}

export interface DeletePostUCInput {
id: string;
}
62 changes: 62 additions & 0 deletions semana17/aula2/src/business/usecase/posts/editPost.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { PostDB } from "../../../data/postDataBase";
import { NotFoundError } from "../../error/NotFoundError";
import { PostType } from "../../entities/post";
import { InvalidParameterError } from "../../error/InvalidParameterError";

export class EditPostUC {
constructor(private db: PostDB) {}

public async execute(input: EditPostUCInput): Promise<EditPostUCOutput> {
const post = await this.db.getPost(input.id);

if (!post) {
throw new NotFoundError("Post not found");
}

if (input.title !== undefined) {
if (input.title === "") {
throw new InvalidParameterError("Name must not be an empty string");
} else {
post.setTitle(input.title);
}
}

if (input.content !== undefined) {
if (input.content === "") {
throw new InvalidParameterError("Name must not be an empty string");
} else {
post.setContent(input.content);
}
}

let type = post.getType();
if (input.type === "event") {
type = PostType.event;
} else if (input.type === "normal") {
type = PostType.normal;
} else {
throw new InvalidParameterError("Invalid type");
}
post.setType(type);

post.setImage(input.image);

await this.db.updatePost(post);

return {
message: "Post edited successfully"
};
}
}

export interface EditPostUCInput {
id: string;
title: string;
content: string;
type: string;
image: string;
}

export interface EditPostUCOutput {
message: string;
}
45 changes: 45 additions & 0 deletions semana17/aula2/src/business/usecase/posts/getPostById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { PostDB } from "../../../data/postDataBase";
import { PostType } from "../../entities/post";
import { NotFoundError } from "../../error/NotFoundError";

export class GetPostByIdUC {
constructor(private db: PostDB) {}

public async execute(input: GetPostByIdUCInput): Promise<GetPostByIdUCOutput> {
/**
* ISSUE 2
*
* Perceba que a Presentation e o DataBase já estão preparados,
* você deve terminar o UseCase (lembre-se de colcar a saída correta)
*/
const post = await this.db.getPost(input.id)

if (!post) {
throw new NotFoundError("Post not found");
}

return {
id: post.getId(),
title: post.getTitle(),
content: post.getContent(),
image: post.getImage(),
type: post.getType(),
userId: post.getUserId(),
userName: post.getUser().getName()
}
}
}

export interface GetPostByIdUCInput {
id: string;
}

export interface GetPostByIdUCOutput {
id: string;
title: string;
content: string;
image?: string;
type: PostType;
userId: string;
userName: string;
}
Loading