glebbash / nestjs-fireorm

Nest.js Fireorm module
https://glebbash.github.io/nestjs-fireorm
MIT License
15 stars 10 forks source link

Some weird dependency issue (expecting UserRepository but it's not defined?) #14

Open Rhig opened 1 month ago

Rhig commented 1 month ago

I get the following dependency error: `Error: Nest can't resolve dependencies of the UserService (?). Please make sure that the argument "UserRepository" at index [0] is available in the AppModule context.

Potential solutions:

I'm sure that I did something wrong/stupid but I can't figure out what it is.

My user.module.ts file:

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { FireormModule } from 'nestjs-fireorm';
import { User } from './entities/user.entity';

@Module({
  imports: [FireormModule.forFeature([User])],
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService],
})
export class UserModule {}

My User entity:

import { Timestamp } from '@google-cloud/firestore';
import { Collection } from 'fireorm';

@Collection()
export class User {
  id!: string;

  displayName: string;

  email!: string;

  createdAt!: Timestamp;
}

My app.module.ts file:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AuthModule } from './auth/auth.module';
import { FireormModule } from 'nestjs-fireorm';
import * as admin from 'firebase-admin';
import { FirebaseStrategy } from './auth/firebase.auth.strategy';
import { AuthService } from './auth/auth.service';
import { UserService } from './user/user.service';
import { UserController } from './user/user.controller';
import { FirebaseAppService } from './firebase-app/firebase-app.service';
import { FirebaseAppModule } from './firebase-app/firebase-app.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: '.env',
    }),
    FireormModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => {
        const firebase_params = {
          type: process.env.FIREBASE_ADMIN_TYPE,
          project_id: config.get('FIRESTORE_PROJECT_ID'),
          private_key_id: config.get('FIREBASE_PRIVATE_KEY_ID'),
          private_key: config.get('FIREBASE_PRIVATE_KEY'),
          client_email: config.get('FIREBASE_CLIENT_EMAIL'),
          client_id: config.get('FIREBASE_CLIENT_ID'),
          auth_uri: config.get('FIREBASE_AUTH_URI'),
          token_uri: config.get('FIREBASE_TOKEN_URI'),
          auth_provider_x509_cert_url: config.get(
            'FIREBASE_AUTH_PROVIDER_X509_CERT_URL',
          ),
          client_x509_cert_url: config.get('FIREBASE_CLIENT_X509_CERT_URL'),
        };
        const firebaseServiceAccount = {
          project_id: firebase_params.project_id,
          clientEmail: firebase_params.client_email,
          privateKey: firebase_params.private_key,
        };
        const creds = admin.credential.cert(firebaseServiceAccount);
        const app = admin.initializeApp(
          {
            credential: creds,
          },
          'firestore',
        );
        const firestore = admin.firestore(app);
        return {
          firestore: firestore,
        };
      },
    }),
    UserModule,
    AuthModule,
    FirebaseAppModule,
  ],
  controllers: [AppController, UserController],
  providers: [
    AppService,
    AuthService,
    FirebaseAppService,
    FirebaseStrategy,
    UserService,
  ],
})
export class AppModule {}

Is it because I used forRootAsync? When I try to use console.log from inside the useFactory function in the AppModule I don't see the text being printed to the terminal, so it might hint that the FireormModule isn't initialized properly?

glebbash commented 1 month ago

I'm not sure if firebase-admin's firestore is compatible with @google-cloud/firestore. Also I can't help finding the issue without seeing what's in UserService as the error originates there.

Rhig commented 1 month ago

Here's UserService:

import { Injectable, Logger } from '@nestjs/common';
import { BaseFirestoreRepository } from 'fireorm';
import { InjectRepository } from 'nestjs-fireorm';
import { User } from './entities/user.entity';
import { Timestamp } from '@google-cloud/firestore';

@Injectable()
export class UserService {
  private logger: Logger = new Logger(UserService.name);

  constructor(
    @InjectRepository(User)
    private users: BaseFirestoreRepository<User>,
  ) {}

  async create({ username, email }): Promise<User> {
    const displayName = username;
    return this.users.create({
      displayName,
      email,
      createdAt: Timestamp.now(), // Use server-side timestamp
    });
  }

  async findOne(email: string): Promise<User | null> {
    return await this.users.whereEqualTo('email', email).findOne();
  }

  async getOrCreateUser(email: string, displayName: string): Promise<User> {
    const user = await this.findOne(email);

    if (user) {
      this.logger.log(`User with email ${email} already exists`);
      return user;
    }

    this.logger.log(`User with email ${email} not found, creating a new user`);

    const newUser = await this.create({
      username: displayName,
      email,
    });

    return newUser;
  }

  async findAll(): Promise<User[]> {
    return this.users.find();
  }
}
glebbash commented 1 month ago

Yeah, not sure what the problem is here. Have you tried running the example but using your firestore instance?