es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Inyección de dependencia de modelos Nest.js con Mongoose sin constructor

Necesito integrar una API de CRM con mi servicio en Nest.js. Desafortunadamente, requieren que implemente su interfaz para usar una capa de persistencia personalizada, en mi caso, Mongo. Dado que necesito instanciar la clase resultante, no puedo inyectar el modelo como normalmente lo haría, así que intenté usar esto en la variable miembro de la clase en su lugar. Sin embargo, esto resulta en un error que indica que la variable miembro no está definida.

Este es mi modelo Mongoose:

export type ZohoTokenDocument = ZohoToken & Document;

@Schema({ timestamps: true })
export class ZohoToken {
  @Prop()
  name: string;

  @Prop({ type: String, length: 255, unique: true })
  user_mail: string;

  @Prop({ type: String, length: 255, unique: true })
  client_id: string;

  @Prop({ type: String, length: 255 })
  refresh_token: string;

  @Prop({ type: String, length: 255 })
  access_token: string;

  @Prop({ type: String, length: 255 })
  grant_token: string;

  @Prop({ type: String, length: 20 })
  expiry_time: string;
}

export const ZohoTokenSchema = SchemaFactory.createForClass(ZohoToken);

Esta es la clase personalizada que estoy creando según lo requerido por la API de terceros:

export class ZohoStore implements TokenStore {
  @InjectModel(ZohoToken.name)
  private readonly tokenModel: Model<zohotokendocument>;

  async getToken(user, token): Promise<any> {
    const result = await this.tokenModel.findOne({ grant_token: token });
    return result;
  }
  ...

Y en mi servicio, simplemente estoy instanciando esta clase como new ZohoStore(), lo cual funciona bien hasta que se llama al método getToken() más tarde.

El error resultante es: "TypeError: Cannot read property 'findOne' of undefined", lo que significa que el tokenModel no se está instanciando. ¿Alguna idea de cómo puedo inyectar mi modelo en esta clase sin colocarlo en el constructor? De lo contrario, no puedo instanciarlo con un constructor sin argumentos desde mi servicio.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para inyectar el modelo en la clase ZohoStore, puedes usar el decorador @InjectModel() de @nestjs/mongoose. Has utilizado esto correctamente dentro de tu clase ZohoStore. Sin embargo, como estás instanciando la clase ZohoStore utilizando el operador new, la inyección del modelo no se está produciendo automáticamente.

    Para resolver este problema, puedes utilizar ClassProvider para inyectar el modelo en la clase ZohoStore. Aquí tienes los pasos que puedes seguir:

    1. Crea un proveedor para la clase ZohoStore:
      import { ZohoStore } from './zoho.store'; // importa la clase ZohoStore
      
      export const ZOHO_STORE_PROVIDER = {
       provide: ZohoStore,
       useClass: ZohoStore,
      };
      
    2. Crea otro proveedor para el modelo inyectado Model<zohotokendocument>:
      import { getModelToken } from '@nestjs/mongoose';
      import { ZohoToken, ZohoTokenDocument } from './zoho.token'; // importa el modelo ZohoToken
      
      export const ZOHO_TOKEN_MODEL_PROVIDER = {
       provide: getModelToken(ZohoToken.name),
       useFactory: (connection: Connection) => connection.model(ZohoToken.name),
       inject: [Connection],
      };
      
    3. En tu módulo, importa MongooseModule y la clase ZohoStore, y añádelas al array de providers del módulo:
      import { Module } from '@nestjs/common';
      import { MongooseModule } from '@nestjs/mongoose';
      import { Connection } from 'mongoose';
      import { ZohoStore } from './zoho.store';
      import { ZohoToken, ZohoTokenSchema } from './zoho.token';
      import { ZOHO_STORE_PROVIDER, ZOHO_TOKEN_MODEL_PROVIDER } from './zoho.providers';
      
      @Module({
       imports: [MongooseModule.forFeature([{ name: ZohoToken.name, schema: ZohoTokenSchema }])],
       providers: [ZOHO_TOKEN_MODEL_PROVIDER, ZohoStore, ZOHO_STORE_PROVIDER],
      })
      export class AppModule {}
      
    4. Por último, en tu servicio que utiliza la clase ZohoStore, inyéctala utilizando el decorador @Inject():
      import { Inject } from '@nestjs/common';
      import { ZohoStore } from './zoho.store';
      
      export class MyService {
       constructor(@Inject(ZohoStore) private readonly zohoStore: ZohoStore) {}
      
       // utiliza this.zohoStore.getToken() según sea necesario
      }
      

    Al hacer esto, la clase ZohoStore recibirá automáticamente el Model<zohotokendocument> inyectado, sin necesidad de instanciarlo directamente. Esto debería resolver el error undefined que estás viendo actualmente.

Comments are closed.