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
3 changes: 3 additions & 0 deletions semana23/case-amaro/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
build
.env
1,138 changes: 1,138 additions & 0 deletions semana23/case-amaro/package-lock.json

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions semana23/case-amaro/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "case-amaro",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "ts-node-dev ./src/index.ts",
"start": "tsc && node ./build/index.js",
"migrations": "tsnd ./src/data/Migrations.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^15.0.0",
"express": "^4.17.2",
"knex": "^1.0.1",
"mysql": "^2.18.1",
"uuid": "^8.3.2"
},
"devDependencies": {
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/knex": "^0.16.1",
"@types/node": "^17.0.13",
"@types/uuid": "^8.3.4",
"ts-node-dev": "^1.1.8",
"typescript": "^4.5.5"
}
}
17 changes: 17 additions & 0 deletions semana23/case-amaro/src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import express, { Express } from "express"
import cors from "cors"
import { AddressInfo } from "net"

export const app: Express = express()

app.use(express.json())
app.use(cors())

const server = app.listen(process.env.PORT || 3003, () => {
if (server) {
const address = server.address() as AddressInfo;
console.log(`Server is running in http://localhost:${address.port}`)
} else {
console.error(`Failure upon starting server.`)
}
})
18 changes: 18 additions & 0 deletions semana23/case-amaro/src/data/BaseDataBase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import knex, { Knex } from "knex"
import dotenv from "dotenv"

dotenv.config()

export class BaseDataBase {
protected static connection: Knex = knex({
client: "mysql",
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_SCHEMA,
port: 3306,
multipleStatements: true
}
})
}
29 changes: 29 additions & 0 deletions semana23/case-amaro/src/data/Migrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { BaseDataBase } from "./BaseDataBase"

class Migrations extends BaseDataBase {
async createTable() {
await BaseDataBase.connection.raw(`
create table if not exists Amaro_Product(
id VARCHAR(255) PRIMARY KEY,
name VARCHAR(255) NOT NULL
);

create table if not exists Amaro_Tag(
id VARCHAR(255) PRIMARY KEY,
name VARCHAR(255) NOT NULL
);

create table if not exists Amaro_Product_Tag(
id_product VARCHAR(255),
id_tag VARCHAR(255),
primary key(id_product , id_tag),
foreign key (id_product) references Amaro_Product(id),
foreign key (id_tag) references Amaro_Tag(id)
);
`)
console.log("Tables created successfully!")
}
}

const createTableMigrations = new Migrations()
createTableMigrations.createTable()
100 changes: 100 additions & 0 deletions semana23/case-amaro/src/data/ProductDataBase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { BaseDataBase } from "./BaseDataBase"
import { Product } from "../model/Product"
import { IdGenerator } from "../services/IdGenerator"

export class ProductDataBase extends BaseDataBase {

public async createProduct(product: Product): Promise<void> {

try {
await BaseDataBase.connection("Amaro_Product").insert({
id: product.getId(),
name: product.getName()
})

for (let tag of product.getTags()) {

const idGenerator = new IdGenerator()

const idTag = idGenerator.generate()

await BaseDataBase.connection("Amaro_Tag").insert({
id: idTag,
name: tag
})

await BaseDataBase.connection("Amaro_Product_Tag").insert({
id_product: product.getId(),
id_tag: idTag
})
}
} catch (error: any) {
throw new Error(error.sqlMessage || error.message)
}
}

public async findProductById(id: string): Promise<Product> {

try {
const product = await BaseDataBase.connection("Amaro_Product")
.select()
.where({ id })

return product[0] && Product.toProductModel(product[0])

} catch (error: any) {
throw new Error(error.sqlMessage || error.message)
}
}

public async findProductByIdForQuery(id: string): Promise<any> {

try {
const product = await BaseDataBase.connection("Amaro_Product")
.select("Amaro_Product.id as id", "Amaro_Product.name as name", "Amaro_Tag.name as tags")
.from("Amaro_Product_Tag")
.innerJoin("Amaro_Product", "Amaro_Product_Tag.id_product", "Amaro_Product.id")
.innerJoin("Amaro_Tag", "Amaro_Product_Tag.id_tag", "Amaro_Tag.id")
.where({ "Amaro_Product.id": id })

return product[0]

} catch (error: any) {
throw new Error(error.sqlMessage || error.message)
}
}

public async findProductByName(name: string): Promise<any> {

try {
const product = await BaseDataBase.connection("Amaro_Product")
.select("Amaro_Product.id as id", "Amaro_Product.name as name", "Amaro_Tag.name as tags")
.innerJoin("Amaro_Product", "Amaro_Product_Tag.id_product", "Amaro_Product.id")
.innerJoin("Amaro_Tag", "Amaro_Product_Tag.id_tag", "Amaro_Tag.id")
.from("Amaro_Product_Tag")
.where({ "Amaro_Product.name": name })

return product[0]

} catch (error: any) {
throw new Error(error.sqlMessage || error.message)
}
}

public async findProductByTag(tag: string): Promise<Product> {

try {
const product = await BaseDataBase.connection("Amaro_Tag")
.select("Amaro_Product.id as id", "Amaro_Product.name as name", "Amaro_Tag.name as tags")
.innerJoin("Amaro_Product", "Amaro_Product_Tag.id_product", "Amaro_Product.id")
.innerJoin("Amaro_Tag", "Amaro_Product_Tag.id_tag", "Amaro_Tag.id")
.from("Amaro_Product_Tag")
.where({ "Amaro_Tag.name": tag })

return product[0]

} catch (error: any) {
throw new Error(error.sqlMessage || error.message)
}
}
}
34 changes: 34 additions & 0 deletions semana23/case-amaro/src/endpoints/getProductById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Request, Response } from "express"
import { ProductDataBase } from "../data/ProductDataBase"

export async function getProductById(req: Request, res: Response) {

try {
const { id } = req.params

if (!id) {
res.status(422).send("Id not informed!")
return
}

const productDataBase = new ProductDataBase()

const product = await productDataBase.findProductByIdForQuery(id)

if (!product) {
res.status(404).send("Product not found!")
return
}

const result = {
id: product.id,
name: product.name,
tags: product.tags
}

res.status(200).send(result)

} catch (error: any) {
res.status(400).send(error.message)
}
}
34 changes: 34 additions & 0 deletions semana23/case-amaro/src/endpoints/getProductByName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Request, Response } from "express"
import { ProductDataBase } from "../data/ProductDataBase"

export async function getProductByName(req: Request, res: Response) {

try {
const { name } = req.params

if (!name) {
res.status(422).send("Name not informed!")
return
}

const productDataBase = new ProductDataBase()

const product = await productDataBase.findProductByName(name)

if (!product) {
res.status(404).send("Product not found!")
return
}

const result = {
id: product.id,
name: product.name,
tags: product.tags
}

res.status(200).send(result)

} catch (error: any) {
res.status(400).send(error.message)
}
}
34 changes: 34 additions & 0 deletions semana23/case-amaro/src/endpoints/getProductByTag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Request, Response } from "express"
import { ProductDataBase } from "../data/ProductDataBase"

export async function getProductByTag(req: Request, res: Response) {

try {
const { tag } = req.params

if (!tag) {
res.status(422).send("Tag not informed!")
return
}

const productDataBase = new ProductDataBase()

const product: any = await productDataBase.findProductByTag(tag)

if (!product) {
res.status(404).send("No products match the indicated tag!")
return
}

const result = {
id: product.id,
name: product.name,
tags: product.tags
}

res.status(200).send(result)

} catch (error: any) {
res.status(400).send(error.message)
}
}
33 changes: 33 additions & 0 deletions semana23/case-amaro/src/endpoints/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Request, Response } from "express"
import { ProductDataBase } from "../data/ProductDataBase"
import { Product } from "../model/Product"

export async function register(req: Request, res: Response) {

try {
const { id, name, tags } = req.body

if (!id || !name || !tags) {
res.status(422).send("Enter the 'id', 'name' and 'tags' information correctly!")
return
}

const productDataBase = new ProductDataBase()

const product = await productDataBase.findProductById(id)

if (product) {
res.status(409).send("Product has already been registered!")
return
}

const newProduct = new Product(id, name, tags)

await productDataBase.createProduct(newProduct)

res.status(200).send("Product registered successfully!")

} catch (error: any) {
res.status(400).send(error.message)
}
}
10 changes: 10 additions & 0 deletions semana23/case-amaro/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { app } from "./app"
import { register } from "./endpoints/register"
import { getProductById } from "./endpoints/getProductById"
import { getProductByName } from "./endpoints/getProductByName"
import { getProductByTag } from "./endpoints/getProductByTag"

app.post("/register", register)
app.get("/product/id/:id", getProductById)
app.get("/product/name/:name", getProductByName)
app.get("/product/tag/:tag", getProductByTag)
23 changes: 23 additions & 0 deletions semana23/case-amaro/src/model/Product.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export class Product {
constructor(
private id: number,
private name: string,
private tags: string[]
) {}

static toProductModel(data: any): Product {
return new Product(data.id, data.name, data.tags)
}

public getId() {
return this.id
}

public getName() {
return this.name
}

public getTags() {
return this.tags
}
}
Loading