imagen

Servicio Básico con TS

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