No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

useValue y useClass

6/17
Recursos

NestJS posee diferentes formas de inyectar servicios en un m贸dulo seg煤n la necesidad. Exploremos algunas de ellas, sus diferencias y cu谩ndo utilizarlas.

C贸mo hacer la inyecci贸n con 鈥渦seClass鈥

Cuando realizas un import de un servicio en un m贸dulo:

import { AppService } from './app.service';

@Module({
  providers: [AppService],
})
export class AppModule {}

Internamente, NestJS realiza lo siguiente:

import { AppService } from './app.service';

@Module({
  providers: [
    {
      provide: AppService,
      useClass: AppService
    }
  ]
})
export class AppModule {}

Ambas sintaxis son equivalentes, useClass es el tipo de inyecci贸n por defecto. B谩sicamente, indica que un servicio debe utilizar X clase para funcionar. Si el d铆a de ma帽ana, por alg煤n motivo en tu aplicaci贸n, el servicio AppService queda obsoleto y tienes que reemplazarlo por uno nuevo, puedes realizar lo siguiente:

import { AppService2 } from './app.service';

@Module({
  providers: [
    {
      provide: AppService,
      useClass: AppService2
    }
  ]
})
export class AppModule {}

De este modo, no tienes necesidad de cambiar el nombre AppService en todos los controladores donde se utiliza, este ser谩 reemplazado por la nueva versi贸n del servicio.

C贸mo hacer la inyecci贸n con 鈥渦seValue鈥

Adem谩s de clases, puedes inyectar valores como un string o un n煤mero. useValue suele utilizarse para inyectar globalmente en tu aplicaci贸n la llave secreta de una API o alguna otra variable de entorno que tu app necesita.

Para esto, simplemente inyecta el valor de una constante en el providers.

const API_KEY = '1324567890';

@Module({
  providers: [
    {
      provide: 'API_KEY',
      useValue: API_KEY
    }
  ],
})
export class AppModule {}

Importa este valor en los controladores u otros servicios donde se necesite de la siguiente manera:

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

@Controller()
export class AppController {

  constructor(@Inject('API_KEY') private apiKey: string) {}
}

Ahora tienes a disposici贸n el valor de este dato en tu controlador para utilizarlo en lo que necesites.

Cuadro de c贸digos para inyecci贸n de servicios

// src/app.module.ts
...

const API_KEY = '12345634';
const API_KEY_PROD = 'PROD1212121SA';

@Module({
  imports: [UsersModule, ProductsModule],
  controllers: [AppController],
  providers: [
    AppService,
    {
      provide: 'API_KEY',
      useValue: process.env.NODE_ENV === 'prod' ? API_KEY_PROD : API_KEY,
    },
  ],
})
export class AppModule {}
// src/app.service.ts
import { Injectable, Inject } from '@nestjs/common';

@Injectable()
export class AppService {
  constructor(@Inject('API_KEY') private apiKey: string) {} // 馃憟 Inject API_KEY
  getHello(): string {
    return `Hello World! ${this.apiKey}`;
  }
}
// src/app.controller.ts

@Controller()
export class AppController {

  @Get()
  getHello(): string { // 馃憟 new enpoint
    return this.appService.getHello();
  }

}

Contribuci贸n creada por: Kevin Fiorentino.

Aportes 12

Preguntas 3

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Para los que usan windows y powershell una manera de setear la variable antes del comando es as铆:

$env:NODE_ENV = 'prod'; npm run start:dev

Dependiendo del sistema operativo y la terminal la manera de hacerlo cambio, hay paquetes en npm que nos ayudan a setear variables sin importar la plataforma, como por ejemplo

cross-env

Resumen

Introducci贸n

Cuando queremos que la instancia de una clase se comparta por todo un modulo debemos hacer 2 cosas.

  1. Le colocamos el decorador @Inyectable a la clase
@Injectable() // <-- El decorador
export class ProductsService {
	// ...
}
  1. Y lo declaramos dentro del modulo correspondiente usando la sintaxis resumida
@Module({
  ...
  providers: [..., ProductsService], // Aqui por ejemplo
  ...
})

useClass

Internamente, nest js rescribe esta sintaxis de la siguiente forma:

@Module({
  ...
  providers: [..., 
		{
			provide: ProducsService, // Nombre con el que haremos referencia a ella
			useClass: ProducsService // Nombre de la clase que se usara
		}
	], // Aqui por ejemplo
  ...
})

useValues

Adem谩s de poder inyectar clases tambi茅n podemos inyectar valores. Esto es util para compartir valores que globales de la aplicaci贸n y evita que estos se guarden en memoria cada vez que se requieran.

const API_KEY = '12345634';
const API_KEY_PROD = 'PROD1212121SA';

@Module({
  imports: [...],
  controllers: [..],
  providers: [
    AppService,
    {
      provide: 'API_KEY', // Nombre con el que se hara referencia
      useValue: process.env.NODE_ENV === 'prod' ? API_KEY_PROD : API_KEY, // El valor
    },
  ],
})
export class AppModule {}

Para usar el valor solo debemos inyectarlo.

// src/app.service.ts
import { Injectable, Inject } from '@nestjs/common';

@Injectable()
export class AppService {
  constructor(@Inject('API_KEY') private apiKey: string) {} // 馃憟 Inject API_KEY
  getHello(): string {
    return `Hello World! ${this.apiKey}`;
  }
}

Por si quieren manejar variables de entorno de otra manera
https://docs.nestjs.com/techniques/configuration

No recomendar铆a usar if鈥lse o ternary operators sobre NODE_ENV en el c贸digo como tal, usualmente en un ambiente productivo tendr铆as un .env por cada ambiente, o en el caso de NestJS, @nestjs/config, y que eso cargue las variables acorde al entorno.

No creo que sea buena practica dejar quemado en c贸digo los datos de conexi贸n a una base de datos.
.
Todas estas variables que se utilizan con useValue vendrian a ser las variables de entorno que en aplicaciones con express se almacenan en un archivo .env

Aunque en el curso no se toca esta parte, el uso de los provide useClass y useValue se usan mucho en los test unitarios

Cuando se va a hacer el test unitario de un controller se debe usar una dumy class del servicio porque el objetivo del test es comprobar solo los metodos del controller y en este caso se remplaza la clase original por otra que tiene una implementaci贸n falsa para el caso de un UsersService seria algo asi

proviers:[
	{
		provide: UsersService, 
		useClass: DummyUsersService
	}
]

y nuestra DummyUsersService tendria metodos mockeados con valores fijos

Tambien podr铆as o pueden crear un archivo .env y definir la variable de manera global. Eso les permitiria usarlo en cualquiera modulo

Utilizando el valor en un controlador o servicio. Decorador @Inject

Use Value

Use Class

Use Value

Hola 馃憢
Para los usuarios de yarn, solo cambia un poco el comandos.

NODE_ENV=prod yarn start:dev

Espero haberles aportado algo 馃殌