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 “useClass”

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 “useValue”

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 13

Preguntas 5

Ordenar por:

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

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}`;
  }
}

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

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

No recomendaría usar if…else 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.

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

Si están usando Ubuntu, tiene que exportar la variable:export NODE\_ENV=development```js export NODE_ENV=prod ```Y para reiniciarlo ```js unset NODE_ENV ```

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 🚀