Importante

lunes, 15 de mayo de 2023

proyecto nuevo config module


creo un nuevo proyecto.

 Lo primero que haremos es acomodar la configuración, para el lo crearemos un modulo congfig desde el cual gestionaremos las variables de entorno.

nest generate module config

esto creará 

PS C:\Users\Usuario\Desktop\pro\proyecto> nest generate module config

CREATE src/config/config.module.ts (83 bytes)

UPDATE src/app.module.ts (316 bytes)


se crea un nuevo modulo llamado config y se agrega al modulo peincipal app.module.  Desde ahora todos los cambios que hagamos en config.module se veran reflejados a nievel global.

ahora crearemos en la base del proyectro un archivo .env que contendrá las variables de entorno que usaremos. El archivo ,env lucirá así

#puerto a usar
PORT=8081
#ambiente de trabajo
NODE_ENV=development
#bases de datos
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=1234
DB_NAME=ejemplo

esto permitiria usar el puerto 808 en vez del 3000 que viene por defecto, además contiene los valores de la base de datos que ya hemos creado en nuestro mysql llemadas ejemplo.

ahora descargaremos en el proyecto el typeorm, y mysql2 

npm install --save @nestjs/typeorm typeorm mysql2

el resultado será

PS C:\Users\Usuario\Desktop\pro\proyecto> npm install --save @nestjs/typeorm typeorm mysql2


added 39 packages in 11m

PS C:\Users\Usuario\Desktop\pro\proyecto> 








 

sábado, 13 de mayo de 2023

creacion de servicios y controladores dentro de los modulos

 Los controladores son los que han de recibir los llamados enrutado por la api y ustos usarán los servicios que les sena injectados y son estos servicios los que tendrán la lógica de negocio , los que unirán con la base de datos  y permitirán que se haga el crud.

hasta ahora hemos construido dos modelos ahora dentro de cada modelos formaremos sus controladores y servicios usando en la terminal con el comando:

 nest g co user/user

nest g s user/user

 nest g co task/task

 nest g co task/task

lo cual generaá los siguiente: 

PS C:\Users\Usuario\Desktop\pro> nest generate module user

CREATE src/user/user.module.ts (81 bytes)

PS C:\Users\Usuario\Desktop\pro> nest generate module task

CREATE src/task/task.module.ts (81 bytes)

UPDATE src/app.module.ts (520 bytes)

CREATE src/user/user/user.controller.ts (97 bytes)

CREATE src/user/user/user.controller.spec.ts (478 bytes)

UPDATE src/user/user.module.ts (171 bytes)

CREATE src/user/user/user.service.ts (88 bytes)

UPDATE src/user/user.module.ts (250 bytes)

PS C:\Users\Usuario\Desktop\pro>  nest g co task/task

CREATE src/task/task/task.controller.ts (97 bytes)

CREATE src/task/task/task.controller.spec.ts (478 bytes)

UPDATE src/task/task.module.ts (171 bytes)

PS C:\Users\Usuario\Desktop\pro> nest g s task/task

CREATE src/task/task/task.service.ts (88 bytes)

CREATE src/task/task/task.service.spec.ts (446 bytes)

UPDATE src/task/task.module.ts (250 bytes)

PS C:\Users\Usuario\Desktop\pro> 

ya se vcrearon los controladores y servicios para cada modelo y estos fueron automáticamente incluido dentro de sus respectivos modelos.


el servicio creado tendrá la siguiente forma

import { Injectable } from '@nestjs/common';

@Injectable()
export class TaskService {}

y los controladores

import { Controller } from '@nestjs/common';

@Controller('task')
export class TaskController {}

y el modulo quedaria así

import { Module } from '@nestjs/common';
import { TaskController } from './task/task.controller';
import { TaskService } from './task/task.service';

@Module({
  controllers: [TaskController],
  providers: [TaskService],
})
export class TaskModule {}


nest creacion de modulos

 es buena práctica crear un modulo aparte por cada entidad. y cargarlo en el modulo principal esto ayuda al mantenimiento y escalabilidad de la aplicación.

en el presente ejemplo crearemos dos modulos cuyas tablas estarán relacionadas con una relación uno a muchos, donde un user podrá escribir multiples tareas.  

lo primero que haremos es crear los Modulos con 

nest generate module user

nest generate module task

Los resultadros serán: en consolo los siguientes:

PS C:\Users\Usuario\Desktop\pro> nest generate module user

CREATE src/user/user.module.ts (81 bytes)

UPDATE src/app.module.ts (459 bytes)

PS C:\Users\Usuario\Desktop\pro> nest generate module task

CREATE src/task/task.module.ts (81 bytes)

UPDATE src/app.module.ts (520 bytes)

PS C:\Users\Usuario\Desktop\pro> 


Como notarás en ambos caso se genera una nueva a carpeta dentro de src, dentro de la cual se genra el modulo user y task. además se modifica el modulp principal app.module agregando los modulos creados.

Si abrimos los modulos creados tendrán los siguientes aspectos:

import { Module } from '@nestjs/common';

@Module({})
export class UserModule {}

import { Module } from '@nestjs/common';

@Module({})
export class TaskModule {}


observa que los modulos son son más que un @module y una clase exportable

el app.module ahora lucirá así

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
//importo el moduloconfigMOdule

import { AppConfigModule } from './config.module';
import { UserModule } from './user/user.module';
import { TaskModule } from './task/task.module';

@Module({
  imports: [AppConfigModule, UserModule, TaskModule],

  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}


observa que los modelos ya han sido incorporados dentro de este modulo dentro de imports:[],

desde ahora todo lo que se genere dentro de los modelos app.modulo lo porá usar.

nest dotenv

 

esta librerai sirve para facilitar el proceso de cargar variables de entorno así si desea lo primero que debe de hacer es tener en la raiz del proyecto una carpeta .env con las variables de entorno por ejemplo

PORT=3000
NODE_ENV=development
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=1234

DB_NAME=ejemplo


ahora descargue dotenv usando en la terminal el comando 

npm install --save dotenv

ahora agregue a la carpeta main.ts la configuración de dotenv

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as dotenv from 'dotenv';

async function bootstrap() {
  dotenv.config(); // Carga las variables de entorno
  const app = await NestFactory.create(AppModule);
  await app.listen(process.env.PORT);
}
bootstrap();


ya tiene de forma global las variables de estado, escritas en .env. ahora para usar esas variables de estado solo las deberás llamar usando process.env._variable escogida  por ejemplo :

process.env.PORT

para asegurarte de que todo quedó bien instalado puede hacer un console.log en el swerrvicio principal, y cada vez que este servciio sea llamado debe imprinir en consola por ejemplo en appservice:

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'es gersom el que escribe';
  }
}


pues coorer la aplicacion con nest start en la consola y luego llamar desde el buscador a localhost:3000

 y deberá imprimir en la terminal

3000

development

3306






viernes, 12 de mayo de 2023

nest configuracion


$ npm i --save @nestjs/config
creo el arcivo .env para cargar las variables de entornos en la base del proyecto

se crea la primera variable de entorno PORT:3000

#confiuracion de la aplicacion
PORT =3000
ahora vamos al appModule para configurar
import { Module } from '@nestjs/common';
// importo el type Ormmodule para hacer las base de datos
import { TypeOrmModule } from '@nestjs/typeorm';
// mis modulos
import { TwitsModule } from './modules/twits/twits.module';
import { UsersModule } from './modules/users/users.module';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    // importo el modulo para poder usarlo
    ConfigModule.forRoot({
      //paso un argumento
      isGlobal: true, // sirve para hacer de uso global las variabkles
    }),


ahora en appmodule hago un cosntructor
export class AppModule {
  constructor(){}
}

Ahora en el constructor injecto el confit serve para usarlo
export class AppModule {
  constructor(private readonly configService: ConfigService) {}
}


es importamte tener mportado 

import { ConfigModule, ConfigService } from '@nestjs/config';

hagamos una propiedad estática port de tipo number
export class AppModule {
  static port:number;
  constructor(private readonly configService: ConfigService) {
   
  }
}
 ahola le asigno a esta propiedad estática un valor 

export class AppModule {
  static port: number;
  constructor(private readonly configService: ConfigService) {
    //PORT viene del archivo .env creado
    AppModule.port = this.configService.get('PORT');
  }
}

ahora agrego un signo de + delante de this. para garantizar que el valor sea castiado a number
export class AppModule {
  static port: number;
  constructor(private readonly configService: ConfigService) {
    //PORT viene del archivo .env creado
    AppModule.port = +this.configService.get('PORT');
  }
}




ahora vamos al main.ts ys sutituir 3000 por port

 antes 

  await app.listen(3000);

ahora debe quedar asi
  await app.listen(AppModule.port);



nest insercion en cascada

 voy al dto de createtwit

que se ve asi por ahora

import { IsString } from 'class-validator';

export class CreateTwitDto {
  @IsString() // la propiedad debe existeir y ser de tipo strint
  readonly menssage: string;
 
}


lo arreglo asi

import { IsObject, IsString } from 'class-validator';
import { User } from 'src/modules/users/entities';

export class CreateTwitDto {
  @IsString() // la propiedad debe existeir y ser de tipo strint
  readonly menssage: string;
  // insercion en cascada
  @IsObject()
  readonly user: Partial<User>;
}

ahora en el servicio de twit deberé injectar el repository de usuario

quedando asi

import { Injectable, NotFoundException } from '@nestjs/common';
import { Twits } from './twits.entity';
import { CreateTwitDto } from './dto/create-twit.dto/create-twit.dto';
import { UddateTwitDto } from './dto/uddate-twit.dto/uddate-twit.dto';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { PaginationQueryDto } from './dto';
import { User } from '../users/entities';

@Injectable()
export class TwitsService {
  constructor(
    @InjectRepository(Twits)
    private readonly twitsRepository: Repository<Twits>,
    @InjectRepository(User)
    private readonly usersRepository: Repository<User>,
  ) {}


ahora modificaremos el metodo create

añado user como parametro tambien

async createTwit({ menssage, user }: CreateTwitDto): Promise<Twits> {
    const twit: Twits = this.twitsRepository.create({ menssage, user });
    return this.twitsRepository.save(twit);
  }


ahora voy al modelo twit einserto la propiedad  user

import { Module } from '@nestjs/common';
import { TwitsController } from './twits.controller';
import { TwitsService } from './twits.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Twits } from './twits.entity';
import { User } from '../users/entities';

@Module({
  imports: [TypeOrmModule.forFeature([Twits, User])],
  controllers: [TwitsController],
  providers: [TwitsService],
})
export class TwitsModule {}



nest paginacion

 en la carpeta dto dentro de twits

debo crear una nueva pagina llamada paginacion-query.dto.ts

/* eslint-disable prettier/prettier */
import { IsNumber, IsOptional, IsPositive } from 'class-validator';

export class PaginationQueryDto {
  @IsNumber()
  @IsPositive()
  @IsOptional()
  limit?: number;

  @IsNumber()
  @IsPositive()
  @IsOptional()
  offset?: number;
}

voy a servicio twit

  async getTwits(pagination: PaginationQueryDto): Promise<Twits[]> {
    const { limit, offset } = pagination;
    return await this.twitsRepository.find({
      relations: ['user'],
      skip: offset,
      take: limit,
    });
  }

incorporo como parametro la painationquerydto y lo desestructuro en limit y offset.

 luego agrego esto ami busqueda en find() donde ship; representa los campos a saltar y take la cantidad a buscar

ahora debo cambiar el contrlador

   @Get()
  async getTwitsFilter(
    @Query() pagination: PaginationQueryDto,
  ): Promise<Twits[]> {
    return await this.twitService.getTwits(pagination);
  }


ahora como nuestro dto require los parametros en numero y llegarn en string debo castiarlo a si que en main debo agregar una funcionalidad que lo castee de string a number, para ello usaremos    transformOptions: {

              enableImplicitConversion: true, 
  app.useGlobalPipes(
    new ValidationPipe({
      //lo que se envia sera de un objeto de la dto
      transform: true,
      // whitelist filtra la data maliciosa dejando sólo la que corresponda al dto
      whitelist: true,
      // cualquier propiedad adicionalo a la que necesita nuestro medto crea un
      //error 404
      forbidNonWhitelisted: true,
      //castean de string a number
      transformOptions: {
        //con esto nos aseguramos que los tipos de type
        //que entran siempre rseran correctos
        enableImplicitConversion: true,
      },
    }),
  );