Definimos nuestros modelos
// app/models/category.model.ts
export interface Category {
id: number;
name: string;
image: string;
}
// app/models/product.model.ts
import { Category } from './category.model';
export interface Product {
id: number;
title: string;
price: number;
description: string;
category: Category;
images: string[];
}
// app/models/product-service.model.ts
import { CreateProductDto, UpdateProductDto } from "../dtos/product.dto";
import { Product } from "./product.model";
// Interface que define los métodos que debe implementar cada ProductService
// Por ejemplo product-HTTP.service o product-memory.service
export interface ProductService {
getAll(): Product[] | Promise<Product[]>;
update(id: Product['id'], changes: UpdateProductDto): Product | Promise<Product>;
create(dto: CreateProductDto): Product | Promise<Product>;
findOne(id: Product['id']): Product | undefined | Promise<Product | undefined>;
}
Definimos nuestros DTOs
// app/dtos/product.dto.ts
import { Product } from './../models/product.model';
import { Category } from './../models/category.model';
export interface CreateProductDto extends Omit<Product, 'id' | 'category'>{
categoryId: Category['id'];
}
export interface UpdateProductDto extends Partial<CreateProductDto> {}
Definiendo nuestros servicios
- product-memory.service: Para manejo en memoria
- prodyct-http.service: Para envios HTTP
// app/services/product-memory.service.ts
import faker from '@faker-js/faker';
import { Product } from '../models/product.model';
import { CreateProductDto, UpdateProductDto } from '../dtos/product.dto';
import { ProductService } from '../models/product-service.model';
export class ProductMemoryService implements ProductService {
private products: Product[] = [];
getAll() {
return this.products;
}
create(data: CreateProductDto): Product {
const newProduct = {
...data,
id: faker.datatype.number(),
category: {
id: data.categoryId,
name: faker.commerce.department(),
image: faker.image.imageUrl(),
}
}
return this.add(newProduct);
}
add(product: Product) {
this.products.push(product);
return product;
}
update (id: Product['id'], changes: UpdateProductDto ): Product {
const index = this.products.findIndex(item => item.id === id);
const prevData = this.products[index];
this.products[index] = {
...prevData,
...changes
}
return this.products[index];
}
findOne(id: Product['id']) {
return this.products.find(item => item.id === id);
}
}
// app/services/product-http.service.ts
import axios from 'axios';
import { UpdateProductDto, CreateProductDto } from "../dtos/product.dto";
import { ProductService } from "../models/product-service.model";
import { Product } from "../models/product.model";
export class ProductHttpService implements ProductService {
private url = 'https://api.escuelajs.co/api/v1/products';
async getAll() {
// <Product[]> para tipar el retorno de axios, un array de productos
const { data } = await axios.get<Product[]>(this.url);
return data;
}
async update(id: Product['id'], changes: UpdateProductDto) {
const { data } = await axios.put(`${this.url}/${id}`, changes);
return data;
}
async create(dto: CreateProductDto) {
const { data } = await axios.post(this.url, dto);
return data;
}
async findOne(id: Product['id']) {
const { data } = await axios.get(`${this.url}/${id}`);
return data;
}
}
Implementando el servicio product-memory.service
// app/main.ts
import { ProductMemoryService } from './services/product-memory.service';
const productService = new ProductMemoryService();
productService.create({
title: 'Producto 1',
price: 100,
description: 'bla bla bla',
categoryId: 12,
images: []
});
const products = productService.getAll();
const productId = products[0].id;
productService.update(productId, {
title: 'cambiar nombre'
});
const rta = productService.findOne(productId);
console.log(rta);
Implementando el servicio product-http.service
// // app/main.ts
import { ProductHttpService } from './services/product-http.service';
(async ()=> {
// TODO: ProductHttpService podria implementar Singleton
const productService = new ProductHttpService();
// Para manejar errores
try {
console.log('--'.repeat(10));
console.log('getAll');
const products = await productService.getAll();
console.log(products.length);
console.log(products.map(item => item.price));
const productId = products[0].id;
console.log('--'.repeat(10));
console.log('update');
await productService.update(productId, {
price: 10000,
title: 'new title',
description: 'new description'
});
console.log('--'.repeat(10));
console.log('findOne');
const product = await productService.findOne(productId);
console.log(product);
} catch (error) {
console.error(error);
}
})();
Ejemplo tomado de Curso de TypeScript: Programación Orientada a Objetos y Asincronismo