Nestjs не видит модуль/сервис

Уже несколько дней пытаюсь решить проблему с тем, что Nest не видит у меня сервис/модуль, что видно по ошибке ниже, пробовал искать решение, даже спросил ChatGPT и он сказал что все реализовано правильно, вот и решил наконец спросить у вас совета, может кто из вас знает, что мне надо изменить, чтобы заработало и что я делаю не так?

Ошибка:

[Nest] 18316  - 24.04.2023, 15:35:59   ERROR [ExceptionHandler] Nest can't resolve dependencies of the MailService (MailerService, ?). Please make sure that the argument dependency at index [1] is available in the AuthModule context.

Potential solutions:
- Is AuthModule a valid NestJS module?
- If dependency is a provider, is it part of the current AuthModule?
- If dependency is exported from a separate @Module, is that module imported within AuthModule?
  @Module({
    imports: [ /* the Module containing dependency */ ]
  })

Код модуля авторизации:

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { HttpModule } from '@nestjs/axios';
import { JwtModule } from '@nestjs/jwt';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { GoogleStrategy } from './strategy/google.strategy';
import { FacebookStrategy } from './strategy/facebook.strategy';
import googleConfig from '../config/google.config';
import facebookConfig from '../config/facebook.config';
import { MailService } from './mail/mail.service';
import { MailModule } from './mail/mail.module';
import { UsersModule } from '../users/users.module';
import { User } from '../users/entities/user.entity';
import { Profile } from '../users/entities/profile.entity';

@Module({
  imports: [
    HttpModule,
    JwtModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => ({
        secret: configService.get('jwt.secretKet'),
        signOptions: { expiresIn: configService.get('jwt.expirationTime') },
      }),
    }),
    UsersModule,
    ConfigModule.forFeature(googleConfig),
    ConfigModule.forFeature(facebookConfig),
    TypeOrmModule.forFeature([User, Profile]),
    MailModule,
  ],
  controllers: [AuthController],
  providers: [
    AuthService,
    GoogleStrategy,
    FacebookStrategy,
    MailService,
  ],
  exports: [AuthService],
})
export class AuthModule {}

Код службы авторизации:

import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { UserService } from '../users/user.service';
import { MailService } from './mail/mail.service';
import { compare } from 'bcrypt';

@Injectable()
export class AuthService {
  constructor(
    private readonly userService: UserService,
    private readonly jwtService: JwtService,
    private readonly mailService: MailService,
  ) {}

  async login(user: any) {
    const socialUser = await this.userService.findOrCreateSocialUser(user);

    await this.mailService.sendMail({
      to: user.email,
      subject: 'Verify your email',
      template: 'email-verification',
      context: {
        name: user.name,
      },
    });
    return socialUser;
  }
}

Код почтового модуля:

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MailerModule, MailerService } from '@nestjs-modules/mailer';
import { MailService } from './mail.service';
import * as handlebars from 'handlebars';
import mailConfig from '../../config/mail.config';

@Module({
  imports: [
    ConfigModule.forFeature(mailConfig),
    MailerModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => ({
        transport: {
          host: configService.get('mail.host'),
          port: configService.get('mail.port'),
          secure: configService.get('mail.secure') === 'true',
          auth: {
            user: configService.get('mail.user'),
            pass: configService.get('mail.password'),
          },
        },
        defaults: {
          from: `"${configService.get('APP_NAME')}" <${configService.get(
            'mail.user',
          )}>`,
        },
        template: {
          dir: './templates',
          adapter: new HandlebarsAdapter(), // lub inny adapter szablonów
          options: {
            strict: true,
          },
        },
      }),
    }),
  ],
  controllers: [],
  providers: [MailService, MailerService],
  exports: [MailService, MailerService],
})
export class MailModule {}

export class HandlebarsAdapter {
  compile(mail: any, callback: any, mailerOptions: any) {
    const template = handlebars.compile(mail.data.html);
    const html = template(mail.data.context);
    mail.data.html = html;
    callback();
  }
}

Код почтового сервиса:

import { Injectable } from '@nestjs/common';
import { MailerService } from '@nestjs-modules/mailer';
import { ConfigType } from '@nestjs/config';
import mailConfig from '../../config/mail.config';

@Injectable()
export class MailService {
  constructor(
    private readonly mailerService: MailerService,
    private mailConf: ConfigType<typeof mailConfig>,
  ) {}

  async sendMail(options: {
    to: string;
    subject: string;
    template: string;
    context: Record<string, unknown>;
  }) {
    const { to, subject, template, context } = options;

    const mailOptions = {
      to,
      subject,
      template: `./${template}`,
      context,
    };

    await this.mailerService.sendMail(mailOptions);
  }
}

Код конфигурации почты:

import { registerAs } from '@nestjs/config';

export default registerAs('mail', () => ({
  host: process.env.mail_host,
  port: process.env.mail_port,
  secure: process.env.mail_secure,
  auth: {
    user: process.env.mail_user,
    pass: process.env.mail_password,
  },
}));

Потому что когда я импортировал, например, User to be visible in Auth, у меня все работало нормально, а когда я хочу импортировать из папки, которая находится в текущей папке, я получаю ошибку и мне кажется, что я все сделал верно.

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
1
0
139
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

ConfigType<typeof mailConfig> — это тип, а типы стираются компилятором машинописного текста во время компиляции. Чтобы обойти это ограничение, вы должны использовать декоратор параметров @Inject().

Я думаю, что вы должны сделать это:
@Inject(mailConfig.KEY) private mailConf: ConfigService<typeof mailConfig>

как показано в документации здесь: https://docs.nestjs.com/techniques/configuration

это потому, что этот провайдер недоступен для модуля AuthModule. Я только что увидел, что вы MailService зарегистрированы в AuthModule. Вам это не нужно, так как вы импортировали MailModule (который регистрирует и экспортирует MailService). Просто уберите MailService из AuthModule и все будет хорошо. Довольно простой модульный модуль Nestjs. Ознакомьтесь с документами.

Micael Levi 24.04.2023 16:49

Другие вопросы по теме