No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Ejemplo de CRUD

16/22
Recursos

Implementaremos un pequeño programa básico que realice operaciones CRUD en un conjunto de usuarios. Este proyecto tocará varios conceptos importantes de TypeScript como enums, interfaces, clases, entre otros.

Recuerda que necesitas tener Node.js instalado. Puedes descargarlo desde el sitio web oficial de Node.js.

Configurando nuestro entorno de trabajo

Haciendo empleo de la terminal y un editor de código (utilizaremos Visual Studio Code) realizaremos las configuraciones básicas para poder ejecutar de manera sencilla nuestro código en TypeScript:

  1. Crea una carpeta para el proyecto
  2. Abre la carpeta del proyecto en tu editor de código de preferencia. En esta ocasión usaremos Visual Studio Code y para abrirlo usando la consola, nos ubicamos en la ruta de la carpeta y ejecutamos lo siguiente:
code .
  1. Generaremos 2 archivos con los nombres .editorconfig y .gitignore dentro de la carpeta de nuestro proyecto
  2. Para autogenerar el código necesario en el archivo .gitignore nos dirigiremos a la web gitignore.io. Como parámetros colocamos Windows, macOS, Node y Linux. Luego damos en el botón “Crear” o “Create” para generar el código.
  3. El código generado por esta página web lo copiaremos y lo pegaremos en nuestro archivo .gitignore
  4. En el archivo .editorconfig pega la siguiente configuración:
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false> 
  1. Ahora, empecemos con la configuración básica de Node. Ejecutamos lo siguiente en la ruta raíz de nuestra carpeta:
npm init -y
  1. Instalemos TypeScript:
npm i typescript --save-dev
  1. Generemos la configuración básica para TypeScript en nuestro proyecto:
npx tsc --init
  1. Instalaremos la librería ts-node para ejecutar TypeScript directamente en Node:
npm install -D ts-node
  1. En la ruta raíz del proyecto, crea un archivo main.ts. Este archivo tendrá la lógica de nuestro CRUD
  2. Para ejecutar el proyecto, una vez implementado, ejecutamos el siguiente comando para probarlo en la consola:
npx ts-node main.ts

Proyecto CRUD de usuarios

Ahora sí, codifiquemos paso a paso este proyecto:

  1. Nuestros usuarios pueden tener los siguientes roles, los cuales los definiremos con un enum:
// Enum para roles de usuario
enum UserRole {
    Admin = 'ADMIN',
    User = 'USER'
}
  1. Definimos qué estructura debería tener un usuario, para ello usaremos una interfaz:
// Interfaz para la estructura de los usuarios
interface User {
    id: number;
    name: string;
    email: string;
    role: UserRole;
    phoneNumber?: string; // Opcional
}
  1. Implementamos la clase que tendrá la funcionalidad CRUD y de la cual crearemos nuevos usuarios:
class UserCRUD {
    private users: User[] = []; // Lista de usuarios

    // Crear
    createUser(id: number, name: string, email: string, role: UserRole, phoneNumber?: string): User {
        const newUser: User = { id, name, email, role, phoneNumber };
        this.users.push(newUser);
        return newUser;
    }

    // Leer
    getUser(id: number): User | undefined {
        return this.users.find(user => user.id === id);
    }

    // Actualizar
    updateUser(id: number, fieldsToUpdate: Partial): User | 'Usuario no encontrado' {
        const user = this.users.find(user => user.id === id);

        if (!user) return 'Usuario no encontrado';

        Object.assign(user, fieldsToUpdate);
        return user;
    }

    // Borrar
    deleteUser(id: number): 'Usuario eliminado' | 'Usuario no encontrado' {
        const index = this.users.findIndex(user => user.id === id);

        if (index === -1) return 'Usuario no encontrado';

        this.users.splice(index, 1);
        return 'Usuario eliminado';
    }
}
  1. Finalmente, podemos hacer uso de nuestra clase UserCRUD:
// Uso de la clase UserCRUD
const userCRUD = new UserCRUD();

console.log("Usuario Creado:\n",userCRUD.createUser(1, 'Javier Paz', '[email protected]', UserRole.Admin, '333-111-888'));
console.log("Usuario Obtenido:\n",userCRUD.getUser(1));
console.log("Usuario Actualizado:\n",userCRUD.updateUser(1, { name: 'Elena Díaz' }));
console.log(userCRUD.deleteUser(1));

El código final sería el siguiente:

// Enum para roles de usuario
enum UserRole {
    Admin = 'ADMIN',
    User = 'USER'
}

// Interfaz para la estructura de los usuarios
interface User {
    id: number;
    name: string;
    email: string;
    role: UserRole;
    phoneNumber?: string; // Opcional
}

class UserCRUD {
    private users: User[] = []; // Lista de usuarios

    // Crear
    createUser(id: number, name: string, email: string, role: UserRole, phoneNumber?: string): User {
        const newUser: User = { id, name, email, role, phoneNumber };
        this.users.push(newUser);
        return newUser;
    }

    // Leer
    getUser(id: number): User | undefined {
        return this.users.find(user => user.id === id);
    }

    // Actualizar
    updateUser(id: number, fieldsToUpdate: Partial): User | 'Usuario no encontrado' {
        const user = this.users.find(user => user.id === id);

        if (!user) return 'Usuario no encontrado';

        Object.assign(user, fieldsToUpdate);
        return user;
    }

    // Borrar
    deleteUser(id: number): 'Usuario eliminado' | 'Usuario no encontrado' {
        const index = this.users.findIndex(user => user.id === id);

        if (index === -1) return 'Usuario no encontrado';

        this.users.splice(index, 1);
        return 'Usuario eliminado';
    }
}

// Uso de la clase UserCRUD
const userCRUD = new UserCRUD();

console.log("Usuario Creado:\n",userCRUD.createUser(1, 'Javier Paz', '[email protected]', UserRole.Admin, '333-111-888'));
console.log("Usuario Obtenido:\n",userCRUD.getUser(1));
console.log("Usuario Actualizado:\n",userCRUD.updateUser(1, { name: 'Elena Díaz' }));
console.log(userCRUD.deleteUser(1));

Contribución creada por: Martín Álvarez (Platzi Contributor).

Aportes 58

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

tuve problema con la libreria de faker, y lo solucione de la siguiente manera:

el import entre corchetes, (ya no es default):

import {faker} from '@faker-js/faker';

y algunas props ahora estan en otros lados:

color: faker.color.human(),
tags: faker.helpers.arrayElements(),
size: faker.helpers.arrayElement(['M', 'S', 'XL', 'L']),

Para los que tuvieron errores en la implementacion de faker, yo lo resolvi de esta forma:

import {faker} from '@faker-js/faker';
import { addProduct, products } from "./products/product.service";

for (let index = 0; index < 50; index++) {
    addProduct({
        id: faker.datatype.uuid(),
        title: faker.commerce.productName(),
        description: faker.commerce.productDescription(),
        image: faker.image.imageUrl(),
        size: faker.helpers.arrayElement(['M','S','L', 'XL']),
        color: faker.commerce.color(),
        isNew: faker.datatype.boolean(),
        tags: faker.helpers.arrayElement(),
        price: parseInt(faker.commerce.price()),
        createAt: faker.date.recent(),
        updateAt: faker.date.recent(),
        stock: faker.datatype.number({min: 10, max: 100}),
        category: {
            id: faker.datatype.uuid(),
            name: faker.commerce.department(),
            createAt: faker.date.recent(),
            updateAt: faker.date.recent(),
        }
    })   
}

console.log(products)

De nada XD

ahora array elements y array element estan dentro de helpers.

faker.helpers.arrayElements(),

Enero de 2024, código actualizado. Les dejo los cambios que le hice a mi código guiandome de las actualizaciones de faker

import { addProduct, products } from "./products/product.services";
import { faker } from '@faker-js/faker';

for (let index = 0; index < 50; index++) {
  addProduct({
    id: faker.string.uuid(),
    description: faker.commerce.productDescription(),
    title: faker.commerce.productName(),
    image: faker.image.url(),
    createdAt: faker.date.recent(),
    updatedAt: faker.date.recent(),
    stock: faker.datatype.number({ min: 10, max: 100 }),
    color: faker.color.human(), // Corregido el método para obtener un color
    size: faker.helpers.arrayElement(['M', 'S', 'XL', 'L']), // Corregido el método para obtener un elemento aleatorio de un array
    price: parseFloat(faker.commerce.price()), // Corregido el método para obtener un precio y parsearlo a float
    isNew: faker.datatype.boolean(),
    tags: [faker.lorem.word(), faker.lorem.word(), faker.lorem.word()], // Ejemplo de tres palabras aleatorias como tags
    category: {
      id: faker.string.uuid(),
      name: faker.commerce.department(),
      createdAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
    },
  });
}

console.log(products);

En caso de que se les dificulte crear la funcion de Update, Read y Delete del CRUD, acá les dejo mi aporte.

Para no repetir codigo, cree el tipo Id en el archivo Base.model para mantener ese tipado mejor.

export type Id = string | number

También cree una funcion que retorna el index y otro que lanza un error. en el archivo product.service

const getIndex = (id: Id) => products.findIndex(product => product.id === id)
const throwError = (error: string) => new Error(error)

Acá la funcion update: updateProduct

export const updateProduct = (id: Id, changes: object) => {
  const index: number = getIndex(id)
  const product: Product = products[index]
 index === -1 && throwError('Product not Found')

  products[index] = {
    ...product,
    ...changes
  }
  return products[index]
}

Acá la función delete: deleteProduct

export const deleteProduct = (id: Id) => {
  const index: number = getIndex(id)
  index === -1 && throwError('Product not Found')
  products.splice(index, 1)
  return id
}

finalemnte la funcion Find: findProduct

export const findProduct = (id: Id) => {
  const index: number = getIndex(id)
  index === -1 && throwError('Product not Found')
  return products[index]
}

Espero les sirva.

Les dejo mis soluciones para las funciones getProduct(), updateProduct() y deleteProduct()
Decidí hacerlas por mi cuenta para ver cómo me iba. Primero les doy un poco de contexto de lo que usé y algo que cambié:
.

<h5>Overloading</h5>

Utilicé en todas las funciones overloading, ya que quise que getProduct() retornara un string si no encontraba el producto con el ID indicado.
Y las demás tienen overloading ya que utilizan a getProduct()
.

<h5>Cambios en product.model.ts</h5>

Concretamente modifiqué Product interface, ya que al utilizar updateProduct() no quería modificar el id ni tampoco createdAt; no tenía sentido hacer esas modificaciones.
Entonces, Product interface cambió por ProductEdit interface.
Y creé un nuevo Product interface que extiende de BaseModel interface y de ProductEdit interface. Al hacer esto tuve que agregar updatedAt en ProductEdit interface y funciona todo perfecto.
.
Ahora sí, les dejo cada función:

let products: Product[] = []; // cambié el `const` por `let`


// getProduct()
function getProduct(id: string): Product;
function getProduct(id: string): string;

function getProduct(id: string): unknown {
  const product = products.find(product => product.id === id);

  return product ?? `Product with ID '${id}' does not exist.`;
}


// updateProduct()
function updateProduct(id: string, changes: ProductEdit): Product;
function updateProduct(id: string, changes: ProductEdit): string;

function updateProduct(id: string, changes: ProductEdit):unknown {
  const product = getProduct(id);

  if (product) {
    products.map(product => {
      product.id === id && Object.assign(product, changes);
    });
  }

  return product;
}


// deleteProduct()
function deleteProduct(id: string):Product;
function deleteProduct(id: string):string;

function deleteProduct(id: string):unknown {
  const product = getProduct(id);

  if (product) {
    products = products.filter(product => product.id !== id);
  }

  return product;
}

Espero les sirva😁

Hey soporte ! el orden de los videos está mal, hay clases invertidas de posición. Por favor revisen el orden de los videos.

AQUI TE DEJO EL CODIGO PARA 2023 POR SI SE TE PRESENTA ALGUN PROBLEMA CON FAKER

import { addProduct, products } from './products/products.service'
import { faker } from '@faker-js/faker';


for (let i = 0; i < 10; i++) {
  addProduct({
    id: faker.datatype.uuid(),
    title: faker.commerce.productName(),
    description: faker.commerce.productDescription(),
    imagen: faker.image.imageUrl(),
    sizes: faker.helpers.arrayElement(['S', 'M', 'L',]),
    color: faker.color.human(),
    isNew: faker.datatype.boolean(),
    tags: faker.helpers.arrayElement(),
    precio: parseInt(faker.commerce.price()),
    createdAt: faker.date.recent(),
    updatedAt: faker.date.recent(),
    stock: faker.datatype.number({ min: 10, max: 100 }),

    category: {
      id: faker.datatype.uuid(),
      name: faker.commerce.department(),
      createdAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
    }

  });
}

console.log(products);


Algunos métodos han cambiado de ruta en la librería de faker.

En la API Reference pueden buscar cada método que no sea accesible como lo señala la clase.

A fecha 19/ago/2023 hay varios modules que estan por ser obsoletos o ya lo son.

Resolví de esta manera el código

import { faker } from '@faker-js/faker';

import { addProduct, products } from './products/product.service';

for (let i = 0; i < 50; i++) {
  faker.seed(i); // semilla para obtener datos consistentes

  addProduct({
    id: faker.string.uuid(),
    title: faker.commerce.productName(),
    description: faker.commerce.productDescription(),
    image: faker.image.url(),
    color: faker.color.human(),
    isNew: faker.datatype.boolean(),
    tags: faker.helpers.multiple(faker.commerce.productAdjective, {
      count: { min: 1, max: 5 },
    }),
    // Posible solución usando arrayElements
    // tags: faker.helpers.arrayElements(
    //   [
    //     faker.commerce.productAdjective(),
    //     faker.commerce.productAdjective(),
    //     faker.commerce.productAdjective(),
    //     faker.commerce.productAdjective(),
    //     faker.commerce.productAdjective(),
    //   ],
    //   { min: 1, max: 5 }
    // ),
    price: parseInt(faker.commerce.price({ min: 0, max: 150 }), 10),
    createdAt: faker.date.past(),
    updatedAt: faker.date.recent(),
    stock: faker.number.int({ min: 0, max: 100 }),
    size: faker.helpers.arrayElement(['S', 'M', 'L', 'XL']),
    category: {
      id: 1,
      name: faker.commerce.department(),
      createdAt: faker.date.past(),
      updatedAt: faker.date.recent(),
    },
  });
}

console.log(products);

Les dejo como quedó mi main.ts, más que nada por si alguno también tuvo problemas con ciertas funciones que estaban deprecadas o que no existían en la propiedad usada.
/


/
Primero que nada el import no tiene que ser default, debería ser así:

import { faker } from '@faker-js/faker';

/


/
Ya para el producto que vamos a crear usando faker-js hay algunas funciones que fueron colocadas en otras propiedades.

  • color, por ejemplo:
addProduct({
	...
	color: faker.commerce.color(),
	...
})

Ya no se encuentra en la propiedad commerce, sino que tiene su propia propiedad color con varias funciones. Para la clase usé human(), que es la misma función que tenía commerce.

addProduct({
	...
	color: faker.color.human(),
	...

/


/
Y así con otras propiedades y/o funciones. Les dejo mi addProduct({…}) a continuación:

addProduct({
    id: faker.datatype.uuid(),
    title: faker.commerce.productName(),
    category: {
      id: faker.datatype.uuid(),
      name: faker.commerce.department(),
      createdAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
    },
    price: parseFloat(faker.commerce.price()),
    stock: faker.datatype.number({min: 10, max: 100}),
    isNew: faker.datatype.boolean(),
    image: faker.image.imageUrl(),
    description: faker.commerce.productDescription(),
    tags: faker.helpers.arrayElements(),
    size: faker.helpers.arrayElement(['S', 'M', 'L', 'XL']),
    color: faker.color.human(),
    createdAt: faker.date.recent(),
    updatedAt: faker.date.recent(),
  });

Espero les sirva 😄

corregido en abril 2024 ```js import { faker } from '@faker-js/faker'; import { addProduct, product } from './products/product.service'; for (let index = 0; index < 50; index++) { addProduct({ id: faker.string.uuid(), description: faker.commerce.productDescription(), image: faker.image.url(), color: faker.color.human(), price: parseInt(faker.commerce.price(), 10), isNew: faker.datatype.boolean(), tags: [faker.lorem.word(), faker.lorem.word(), faker.lorem.word()], size: faker.helpers.arrayElement(['S', 'L', 'M', 'XL']), title: faker.commerce.productName(), createdAt: faker.date.recent(), updateAt: faker.date.recent(), stock: faker.datatype.number({ min: 10, max: 100 }), category: { id: faker.string.uuid(), name: faker.commerce.department(), createdAt: faker.date.recent(), updateAt: faker.date.recent(), }, }); } console.log(product); ```import { faker } from '@faker-js/faker';import { addProduct, product } from './products/product.service'; for (let index = 0; index < 50; index++) { addProduct({ id: faker.string.uuid(), description: faker.commerce.productDescription(), image: faker.image.url(), color: faker.color.human(), price: parseInt(faker.commerce.price(), 10), isNew: faker.datatype.boolean(), tags: \[faker.lorem.word(), faker.lorem.word(), faker.lorem.word()], size: faker.helpers.arrayElement(\['S', 'L', 'M', 'XL']), title: faker.commerce.productName(), createdAt: faker.date.recent(), updateAt: faker.date.recent(), stock: faker.datatype.number({ min: 10, max: 100 }), category: { id: faker.string.uuid(), name: faker.commerce.department(), createdAt: faker.date.recent(), updateAt: faker.date.recent(), }, });} console.log(product);

Faker cambio la forma de utilizar arrayElement a:

faker.helpers.arrayElement(['16','S','M','L','XL'])

Con color lo mismo:

faker.color.human()
`import { addProduct, products } from './products/product.service';import { simpleFaker, faker } from '@faker-js/faker';import { Sizes } from './products/product.model'; for (let index = 0; index < 10; index++) { addProduct({ id: simpleFaker.string.uuid(), title: faker.commerce.productName(), color: faker.color.human(), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), description: faker.commerce.productDescription(), image: faker.image.url(), isNew: faker.datatype.boolean(), price: parseFloat(faker.commerce.price()), size: faker.helpers.arrayElement([Sizes.L, Sizes.M, Sizes.S, Sizes.XL]), stock: faker.number.int(), tags: faker.helpers.arrayElements([faker.commerce.department()]), category: { createdAt: faker.date.recent(), updatedAt: faker.date.recent(), id: simpleFaker.string.uuid(), name: faker.commerce.department() }, });} console.log('products:', products);`
Para hoy 10 Enero 2025 algunas de las propiedades son diferentes les coloco por aqui mi main.ts para que puedan verlo. `import {faker} from '@faker-js/faker';import { addProduct, products } from './products/products.service';` `for (let index = 0; index < 50; index++) {addProduct({    id: faker.number.bigInt().toString(),    description: faker.commerce.productDescription(),    image: faker.image.url(),    color: faker.color.rgb(),    sizes: faker.helpers.arrayElement(['M', 'S', 'XL', 'L']),    price: parseInt(faker.commerce.price(), 10),    isNew: faker.datatype.boolean(),    tags: faker.helpers.arrayElements(['new', 'sale', 'hot', 'winter', 'summer', 'spring', 'autumn']),    title: faker.commerce.productName(),    createdAt: faker.date.recent(),    updatedAt: faker.date.recent(),    stock: faker.number.float({min: 1, max: 100}),    category: {      id: faker.number.bigInt().toString(),      name: faker.commerce.department(),      createdAt: faker.date.recent(),      updatedAt: faker.date.recent(),    }  });}` `console.log(products);`
Con las actualizaciones de faker tuve que usarlo de la siguiene manera: ```ts addProduct({ id: faker.string.uuid(), description: faker.commerce.productDescription(), image: faker.image.url(), color: faker.color.human(), size: faker.helpers.arrayElement(['M', 'S', 'XL', 'L']), price: parseInt(faker.commerce.price(), 10), isNew: faker.datatype.boolean(), tags: faker.helpers.arrayElements(['tag1', 'tag2', 'tag3', 'tag4', 'tag5']), title: faker.commerce.productName(), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), stock: faker.number.int({min: 10, max: 100}), category: { id: faker.string.uuid(), name: faker.commerce.department(), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), } }) ```
Por favor revise alguien el curso y ordene los video correctamente.
Voy a dejar la página de Road Map, para que puedan ver el recorrido en typescript (aprender). Road Map: <https://roadmap.sh/typescript>

Les dejo como lo resolví con la versión actual de faker:

import { faker } from '@faker-js/faker';
import { addProduct } from './products/product.service';

const randomTags = Array.from({ length: 5 }, () => faker.lorem.word());

for (let i = 0; i < 50; i++) {
  addProduct({
    id: faker.string.uuid(),
    title: faker.commerce.productName(),
    description: faker.commerce.productDescription(),
    image: faker.image.url(),
    size: faker.helpers.arrayElement(['M', 'S', 'L', 'XL']),
    color: faker.color.human(),
    isNew: faker.datatype.boolean(),
    tags: faker.helpers.arrayElements(randomTags),
    price: parseInt(faker.commerce.price()),
    createdAt: faker.date.recent(),
    updatedAt: faker.date.recent(),
    stock: faker.number.int({ min: 10, max: 100 }),
    category: {
      id: faker.string.uuid(),
      name: faker.commerce.department(),
      createdAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
    },
  });
}

Actualmente faker esta en la v9.0

   addProduct({
    id: faker.datatype.uuid(),
    title: faker.commerce.productName(),
    image: faker.image.url(),
    description: faker.commerce.productDescription(),
    createAt: faker.date.recent(),
    updatedAt: faker.date.recent(),
    size: faker.helpers.arrayElement(['S', 'M', 'L', 'XL']),
    stock: faker.number.int(),
    color: faker.commerce.productMaterial(),
    price: parseInt(faker.commerce.price()),
    category:{
      id: faker.commerce.productName(),
      createAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
      name: faker.commerce.productName(),
    },
    isNew: faker.datatype.boolean(),
    tags: faker.helpers.arrayElements(['new', 'used', 'N/A', 'refurbished'])
  })

Asi arregle para como se ve la libreria faker actualizada
import { addProduct, products } from “./products/product.service”;

import { faker } from ‘@faker-js/faker’;

for (let index = 0; index < 50; index++) {
addProduct({
id: faker.string.uuid(),
descripton: faker.commerce.productName(),
image: faker.image.url(),
color: faker.color.human(),
size: faker.helpers.arrayElement([“S”, “M”, “L”, “XL”]),
price: parseInt(faker.commerce.price(), 10),
isNew: faker.datatype.boolean(),
tags: faker.helpers.arrayElements([]),
title: faker.commerce.productName(),
createdAt: faker.date.recent(),
updatedAt: faker.date.recent(),
stock: faker.number.int({
min: 10,
max: 100
}),
category: {
id: faker.string.uuid(),
name: faker.commerce.department(),
createdAt: faker.date.recent(),
updatedAt: faker.date.recent(),
}
});
}

console.log(products);
OBS: -> falto poner un generador randon en tags

Dejo la mi versión con los cambios que tuve que hacer, ya que varias funciones de faker fueron depreciadas.
.
Versión de Faker: "^8.0.2"
Fecha: 2023-06-19
.

import { faker } from '@faker-js/faker';

addProduct({
    id: faker.string.uuid(),
    description: faker.commerce.productDescription(),
    title: faker.commerce.productName(),
    image: faker.image.url(),
    stock: faker.number.int({ min: 10, max: 100 }),
    size: faker.helpers.arrayElement(['S', 'M', 'L', 'XL']),
    color: faker.color.human(),
    price: parseInt(faker.commerce.price(), 10),
    isNew: faker.datatype.boolean(),
    tags: faker.helpers.arrayElements(['new', 'white', 'tshirt', 'clothes']),
    createdAt: faker.date.recent(),
    updatedAt: faker.date.recent(),
    category: {
      id: faker.datatype.uuid.toString(),
      name: faker.commerce.department(),
      createdAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
    },
  });

Para la versión actual 8.0.2 de faker , me funcionó de esta manera:

addProduct({
    id: faker.datatype.uuid(),
    title: faker.commerce.productName(),
    image: faker.image.imageUrl(),
    color: faker.color.human(),
    price: parseInt(faker.commerce.price(), 10),
    isNew: faker.datatype.boolean(),
    size: faker.string.fromCharacters(["S","M","L","XL"]),
    tags: faker.random.words(5).split(" "),
    description: faker.commerce.productDescription(),
    createAt: faker.date.recent(),
    updateAt: faker.date.recent(),
    stock: faker.datatype.number({ min: 10, max: 100 }),
    category: {
      id: faker.datatype.uuid(),
      createAt: faker.date.recent(),
      updateAt: faker.date.recent(),
      name: faker.commerce.department()
    }
  });

Tuve que cambiar solamente el tipo de size ya que el tipado no me funcionaba con la opción que utilice:
export interface Product extends BaseModel {
title: string;
image: string;
description: string;
stock: number;
size?: string | Size;
color: string;
price: number;
category: Category;
isNew: boolean;
tags: string[];
}

Mis metodos CRUD, me corrigen si algo esta mal, recibo retroalimentaciones 😃


import { Product } from './product.model';

export let products: Product[] = [];

export const addProduct = (data: Product) => {
  products.push(data);
}

export const getAllProducts =()=>{
  return products;
}
export const getProductById=(id:string)=>{
  const response =products.find(item=>item.id===id)
  return response
}
export const updateProduct = (id: string, changes: Product ) => {
  let actual=getProductById(id);
  if (actual) {
      actual.title=changes.title;
      actual.image=changes.image;
      actual.description=changes.description;
      actual.stock=changes.stock;
      actual.size=changes.size;
      actual.color=changes.color;
      actual.price=changes.price;
      actual.category=changes.category;
      actual.isNew=changes.isNew;
      actual.tags=changes.tags;
  }
  return changes;
}

export const deleteProduct=(id:string)=>{
  const product = getProductById(id);
  if(product){
    const index=products.findIndex(item=>item.id===id);
    products.splice(index,1);

  }
}

Así creo que podría ser para delete y get (en get podemos buscar un producto por su ID o por su título):

import { Product } from "./product.model"

export const products: Product[] = []

export const addProduct = (data: Product) => {
  products.push(data)
}

export const updateProduct = (id: string | number, changes: Product) => {

}

export const deleteProduct = (id: string | number) => {

}

export const getProduct = (id?: string | number, title?: string) => {

}

import { addProduct, products } from './products/product.service';import { simpleFaker, faker } from '@faker-js/faker';import { Sizes } from './products/product.model'; for (let index = 0; index < 10; index++) {  addProduct({    id: simpleFaker.string.uuid(),    title: faker.commerce.productName(),    color: faker.color.human(),    createdAt: faker.date.recent(),    updatedAt: faker.date.recent(),    description: faker.commerce.productDescription(),    image: faker.image.url(),    isNew: faker.datatype.boolean(),    price: parseFloat(faker.commerce.price()),    size: faker.helpers.arrayElement(\[Sizes.L, Sizes.M, Sizes.S, Sizes.XL]),    stock: faker.number.int(),    tags: faker.helpers.arrayElements(\[faker.commerce.department()]),    category: {      createdAt: faker.date.recent(),      updatedAt: faker.date.recent(),      id: simpleFaker.string.uuid(),      name: faker.commerce.department()    },  });} console.log('products:', products);
Con las actualizaciones de faker tuve que usarlo de esta manera: `addProduct({    id: faker.string.uuid(),    description: faker.commerce.productDescription(),    image: faker.image.url(),    color: faker.color.human(),    size: faker.helpers.arrayElement(['M', 'S', 'XL', 'L']),    price: parseInt(faker.commerce.price(), 10),    isNew: faker.datatype.boolean(),    tags: faker.helpers.arrayElements(['tag1', 'tag2', 'tag3', 'tag4', 'tag5']),    title: faker.commerce.productName(),    createdAt: faker.date.recent(),    updatedAt: faker.date.recent(),    stock: faker.number.int({min: 10, max: 100}),    category: {      id: faker.string.uuid(),      name: faker.commerce.department(),      createdAt: faker.date.recent(),      updatedAt: faker.date.recent(),    }})`
Asi quedo mi código ya que han cambiado cosas con la librería faker: ```ts import { faker } from '@faker-js/faker'; import { addProduct, products } from './products/product.service'; for (let index = 0; index < 50; index++) { addProduct({ id: faker.string.uuid(), description: faker.commerce.productDescription(), image: faker.image.url(), color: faker.color.human(), size: faker.helpers.arrayElement(['M', 'S', 'XL', 'L']), price: parseInt(faker.commerce.price(), 10), isNew: faker.datatype.boolean(), tags: faker.helpers.arrayElements(['tag1', 'tag2', 'tag3']), title: faker.commerce.productName(), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), stock: faker.number.int({ min: 10, max: 100 }), category: { id: faker.string.uuid(), name: faker.commerce.department(), createdAt: faker.date.recent(), updatedAt: faker.date.recent() } }) } console.log(products) ```import { faker } from '@faker-js/faker';import { addProduct, products } from './products/product.service'; for (let index = 0; index < 50; index++) { addProduct({ id: faker.string.uuid(), description: faker.commerce.productDescription(), image: faker.image.url(), color: faker.color.human(), size: faker.helpers.arrayElement(\['M', 'S', 'XL', 'L']), price: parseInt(faker.commerce.price(), 10), isNew: faker.datatype.boolean(), tags: faker.helpers.arrayElements(\['tag1', 'tag2', 'tag3']), title: faker.commerce.productName(), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), stock: faker.number.int({ min: 10, max: 100 }), category: { id: faker.string.uuid(), name: faker.commerce.department(), createdAt: faker.date.recent(), updatedAt: faker.date.recent() } })} console.log(products)
```ts import { Product } from './product.model'; export const products: Product[] = []; export const findProduct = (id: string) => { return products.find((product) => product.id === id); }; export const addProduct = (data: Product) => { products.push(data); }; export const updateProduct = (id: string, changes: Product) => { const index = products.findIndex((product) => product.id === id); products[index] = { ...products[index], ...changes }; }; export const deleteProduct = (id: string) => { const index = products.findIndex((product) => product.id === id); products.splice(index, 1); }; ```Asi quedaron mis servicios al al menos por ahora
Hola, dejo mi código de cómo lo hice yo: ```js import { addProduct, products } from "./products/product.service"; import { simpleFaker , faker } from '@faker-js/faker'; for(let index = 0; index < 50; index++){ addProduct({ id: simpleFaker.string.uuid(), title: faker.commerce.productName(), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), image: faker.image.url(), price: parseInt(faker.commerce.price(), 10), color: faker.color.human(), size: faker.helpers.arrayElement(['M', 'S', 'XL', 'L']), isNew: faker.datatype.boolean(), tags: faker.helpers.arrayElements([faker.commerce.productAdjective(), faker.commerce.productAdjective(), faker.commerce.productAdjective()], { min: 2, max: 3}), description: faker.commerce.productDescription(), stock: faker.number.int({min:10, max: 100}), category: { id: simpleFaker.string.uuid(), name: faker.commerce.department(), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), } }) } console.log(products); ```
Actualización Septiembre 2024: ![](https://static.platzi.com/media/user_upload/Captura%20de%20Pantalla%202024-09-17%20a%20las%2015.37.28-ef68b4c8-1c2f-4dbc-9f07-1dddedcfde14.jpg) Han sacado tambien el objeto number de datatype.
Platziiii las clases 16 y 17 estan invertidas
Para resolver el lío reciente con faker-js, preferí utilizar una librería totalmente implementada en Typescript, esta es falso`npm i @ngneat/falso` ```js npm i @ngneat/falso ```Y ya luego importas la librería: ```js import { randColor } from '@ngneat/falso' ```Ya luego tienes muchas opciones para sacar un valor aleatorio de lo que sea, nombres, palabras, números etc.
Comentario de ejemplo.
Dejo mi aporte del 25 de Octubre del 2023, muchas cosas han cambiado y es mejor buscar en la documentacion, dejo lo mas actual al momento. ```js id: faker.string.uuid(), stock: faker.number.int({ min: 1, max: 100 }), title: faker.commerce.productName(), description: faker.commerce.productDescription(), image: faker.image.urlPicsumPhotos(), color: faker.internet.color(), sizes: faker.helpers.arrayElement(['S', 'M', 'L', 'XL', 'XXL']), price: parseInt(faker.commerce.price()), isNew: faker.datatype.boolean(), tags: faker.commerce.productMaterial().split(' '), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), category: { id: faker.string.uuid(), name: faker.commerce.department(), createdAt: faker.date.recent(), updatedAt: faker.date.recent() } ```

para faker V8, donde muchos metodos y propiedades cambiaron

const data : productInterface =  {
      id: faker.number.int({max: 9999,}),
      title: faker.commerce.productName(),
      image: faker.image.urlLoremFlickr(),
      description: faker.commerce.productDescription(),
      price: parseInt(faker.commerce.price()),
      color: faker.color.human(),
      isNew: faker.datatype.boolean(),
      size: faker.helpers.arrayElement(['S' , 'M' , 'L' , 'XL']),
      tags: faker.helpers.multiple(faker.person.jobArea, {count:3}),
      stock: faker.number.int({min:3, max:2000}),
      createdAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
      category: {
        id : faker.number.int({max: 9999,}),
        name: faker.commerce.department(),
        createdAt: faker.date.recent(),
        updatedAt: faker.date.recent(),
      }
    }
    addProduct(data);

Como ya lo mencionaron, la API de Faker ha tenido algunos cambios, aquí está mi addProduct y un addTags:

const addTags = () => {
  const tags: string[] = [];
  tags.push(faker.commerce.productAdjective());
  tags.push(faker.commerce.productAdjective());
  tags.push(faker.commerce.productAdjective());

  return tags;
}

//removeAllProducts()

addProduct({
  id: faker.string.uuid(),
  title: faker.commerce.productName(),
  description: faker.commerce.productDescription(),
  price: parseInt(faker.commerce.price()), //convert from string to number
  color: faker.color.human(),
  size: faker.helpers.arrayElement(['M', 'L', 'XL']),
  image: faker.image.urlLoremFlickr({category: 'commerce'}),
  createdAt: faker.date.recent(),
  updatedAt: faker.date.recent(),
  isNew: faker.datatype.boolean(0.5),
  stock: faker.number.int({min: 0, max: 99}),
  tags: addTags(),
  category: {
    id: faker.string.uuid(),
    name: faker.commerce.department(),
    createdAt: faker.date.recent(),
    updatedAt: faker.date.recent(),
  }
})

Agrego mi solución para el CRUD de la lista de Products, agregando las funciones de findProduct, updateProduct y removeProduct:

import { Product } from "./product.model";

export const products:Product[] = [];

export const addProduct = (data:Product) => {
  products.push(data);
}

export const updateProduct = (update:Product): boolean => {
  const index = products.findIndex(product => product.id === update.id)
  if(index >= 0){
    products[index] = update;
    return true;
  }
  return false;
}

export const removeProduct = (id: string | number): unknown => {
  const index = products.findIndex(product => product.id === id);
    if(index >= 0){
      let productRemoved = products[index];
      products.splice(index, 1);
      return productRemoved;
    }
  return undefined;
}

export const findProduct = (id:string | number) => {
  return products.find(product => product.id === id);
}

Actualmente aparece como deprecado datatype.uuid()
En su lugar usar :

faker.string.uuid()

Si desean que la librería les genere resultados en español pueden importarla así:
import { faker } from ‘@faker-js/faker/locale/es’

En lo personal cree una funcion para generar los tags:

const genTags = (): string[] => {
  const length = faker.number.int({ max: 20 });
  const tags: string[] = [];

  for (let i = 0; i < length; i++) {
    tags.push(faker.word.noun())
  }

  return tags;
};

hola hasta el momento algunas funciones de la libreria faker se sustituyeron por otras aqui por si las necesitan en este junio 2023


import { faker } from '@faker-js/faker';
import {addProduct, products} from './products/product.service';
import { Sizes } from './products/product.model';

for (let index = 0; index < 50; index++) {

	addProduct({
		id: faker.string.uuid(),
		description: faker.commerce.productDescription(),
		image: faker.image.urlLoremFlickr({ category: 'abstract' }),
		color: faker.color.human(),
		price: parseInt(faker.commerce.price()),
		isNew: faker.datatype.boolean(),
		tags: faker.helpers.arrayElements(['apple', 'banana', 'orange', 'grape', 'kiwi']),
		title: faker.commerce.productName(),
		createdAt: faker.date.recent(),
		updateAt: faker.date.recent(),
		stock: faker.number.int({min: 10, max: 100}),
		sizes: faker.helpers.arrayElement(['M','XL','S','L',]) as Sizes,
		category: {
			id: faker.string.uuid(),
			name: faker.commerce.department(),
			createdAt: faker.date.recent(),
			updateAt: faker.date.recent(),
		},
	});
}

console.log(products);

Para que faker les funcione tal cual con el código que genera el profesor, pueden trabajar con la misma versión que él utilizó en su momento. Ejecutan el comando npm install @faker-js/faker@^6.0.0-alpha.5 para esto.

Es necesario aclarar que si ya instalaron faker pueden desinstalarlo con npm uninstall faker y luego intentar instalarla con el comando anterior.

product.service.ts

import { Product } from './product.model';

export const products: Product[] = [];

export const addProduct = (data: Product) => {
  products.push(data);
};

export const updateProduct = (id: string, newData: Product) => {
  const index = products.findIndex((product) => product.id === id);
  if (index !== -1) {
    products[index] = { ...products[index], ...newData };
  }
};

export const deleteProduct = (id: string) => {
  const index = products.findIndex((product) => product.id === id);
  if (index !== -1) {
    products.splice(index, 1);
  }
};

export const getProduct = (id: string) => {
  return products.find((product) => product.id === id);
};

export const getAllProducts = () => {
  return products;
};

Sugiero ir probando las funcionalidades con un json. Lo hace todavía más claro. Ejemplo de product.service.ts:

import { ProductInterface } from ‘./product.model’;
const fs = require(‘fs’);

export const products: ProductInterface[] = [];

export const addProduct = (input: ProductInterface) => {
products.push(input);

fs.writeFileSync(
’./src/app/products.json’,
JSON.stringify(products, null, 2)
);
};

npm install --save-dev @faker-js/faker

Acá esta mi solución para el CRUD, espero que a alguien le sirva

export const addProduct = (data: Product): void => {
    products.push(data);
}
export const getProduct = (productID: string): any => {
    let product = products.filter(product => product.id === productID)
    return product
}
export const uploadProduct = (productID: string, data: object): void => {
    let newData = {...data, updatedAt: new Date() }
    let productIndex = products.findIndex(product => product.id === productID)
    Object.assign(products[productIndex], newData) 
}
export const deleadProduct = (productID: string): void => {
    let productIndex = products.findIndex(product => product.id === productID)
    products.splice(productIndex, 1)
}

En enero del 2022 paso algo curioso con el creador de la lib
Faker.js, saboteo su propio repositorio en simbolo protesta, dejo de funcionar y muchas big companies tambien se vieron afectadas, les dejo mi articulo acerca de ello, tiene muucho que ver con los ideales del opensource…

https://cr0wg4n.medium.com/es-un-buen-momento-para-hablar-de-ideales-en-el-mundo-del-software-f8f618a6bfb6

en las nuevas versiones usar:

faker.color.human()

en vez de: faker.commerce.color()

Aquí les dejo mi función para el update:

export const updateProduct = (id: string, changes: Product) => {
  let index = products.findIndex(item => {
    id === item.id
  })

  products.splice(index, 1, changes)
}

A

OLD

faker.random.arrayElements()

NEW

faker.helpers.arrayElements()

Pocos entenderán:

Para los tags lo implemente asi: le di un array de opciones… el toma el random en cantidades y tipos y los asigna:

tags: faker.helpers.arrayElements(['perro','gato','raton','pajaro','culebra','peces','pollito']),

Por alguna razón la nueva versión de faker no encontre la manera de hacer un array de string, ya que el método está en dataType y retorna, (string | number)[] así que hice un pequeño método para rellenar los tags, de una manera más natural… este fue el código que utilice

const productTagsArray = (times: number): string[] => {
  let productsArray: string[] = [];
  for(let i=0; i<times; i++){
    productsArray.push(faker.commerce.productAdjective());
  }
  return productsArray;
}

Lo agregue a product service.ts y lo importe a main.ts este es un resultado de ejemplo:

 tags: [
      'Small',      'Generic',
      'Luxurious',  'Awesome',
      'Gorgeous',   'Tasty',
      'Recycled',   'Luxurious',
      'Electronic', 'Rustic'
    ]

Librería Faker

Instalación
npm install @faker-js/faker --save-dev

Importando Librería
import faker from '@faker-js/faker';

Los otros templates que faltan son delete y get.

const deleteProduct = (id: string): void => {
  //code
}

const getProduct = (id: string): void => {
  //code
}
Si estas mirando este curso a día de hoy te hare un gran **favor** para que evites leer la documentación a las 3:40 am buscando cuales de las cosas que coloco nico no estan deprecadas o eliminadas a día de hoy **("No culpo a nico es algo habitual en el sector IT que renueven siempre las cosas y otras queden deprecadas")** ```ts addProduct({ id: faker.string.uuid(), title: faker.commerce.productName(), description: faker.commerce.productDescription(), image: faker.image.url(), price: parseInt(faker.commerce.price(), 10), isNew: faker.datatype.boolean(), tags: faker.helpers.arrayElements(faker.lorem.words({ min: 5, max: 10 }).split(' '), {min: 1, max: 10}), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), stock: faker.number.int({min: 10, max: 100}), category: { id: faker.string.uuid(), createdAt: faker.date.recent(), updatedAt: faker.date.recent(), name: faker.commerce.department(), }, }) ```