I'm new to nest, can't figure out what is wrong.
- I created an abstract base repository
- extended users repository from base
- implemented auth logic:
- controller
- service
- module
- auth service contains method
registerwhich creates user in mysql but first it make request to db to find users(do not look for the logic, it's just for testing purposes)
The problems are the following:
- when the findAll method is called, I get the error that .findAll is not a function(update: I think I understood why this happens, it's because @InjectRepository(User) injects the an instance of Repository and not my actually class UsersRepository and since Repository has no findAll method, it gives the error. Because it works fine with .find() which is present in Repository)
- if I comment findAll method and allow the code to call .create(), there is no error but it looks like nothing happens, on debugger it's not event entering the .create() method.(update: again, it seems like the issue is I'm working here with Repository and not my custom UsersRepository)
//base repo
import { Repository, DeleteResult, FindOptionsWhere } from 'typeorm';
import { Base } from './base.entity';
import { BaseInterfaceRepository } from 'models/base/base.interface.repository';
export abstract class BaseRepository<T extends Base> implements BaseInterfaceRepository<T> {
private repository: Repository<T>;
protected constructor(repository: Repository<T>) {
this.repository = repository;
}
public async create(entity: T): Promise<T> {
return await this.repository.save(entity);
}
public async update(entity: T): Promise<T> {
return await this.repository.save(entity);
}
public async findById(id: string): Promise<T> {
return await this.repository.findOneBy({ id } as FindOptionsWhere<T>);
}
public async findOne(criteria: any): Promise<T> {
return await this.repository.findOne(criteria);
}
public async findAll(): Promise<T[]> {
return await this.repository.find();
}
public async delete(id: string): Promise<DeleteResult> {
return await this.repository.delete(id);
}
}
// base entity
import { CreateDateColumn, UpdateDateColumn, PrimaryGeneratedColumn } from 'typeorm';
import { IBase } from './base.interface';
export abstract class Base implements IBase {
@PrimaryGeneratedColumn('uuid')
public id: string;
@CreateDateColumn({ type: 'timestamp' })
public createdAt: Date;
@UpdateDateColumn({ type: 'timestamp' })
public updatedAt: Date;
}
//users repository
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { BaseRepository } from '../base/base.repository';
import { InjectRepository } from '@nestjs/typeorm';
import { UserInterfaceRepository } from './users.interface.repository';
@Injectable()
export class UsersRepository extends BaseRepository<User> implements UserInterfaceRepository {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {
super(userRepository);
}
}
// user entity
import { Entity, Column, OneToMany } from 'typeorm';
import { UserInterface } from '../interfaces/user.interface';
import { Base } from 'models/base/base.entity';
@Entity({ name: 'Users' })
export class User extends Base implements UserInterface {
@Column()
authToken: string;
@Column()
coins: number;
@Column()
paidCoins: number;
}
// users module
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {
}
all my models are in the models namespace, thus here is my models.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
import { LinkedAccountsModule } from 'models/linked-accounts/linked-accounts.module';
import { LinkedAccountsService } from 'models/linked-accounts/linked-accounts.service';
@Module({
imports: [UsersModule, LinkedAccountsModule],
providers: [LinkedAccountsService],
})
export class ModelsModule {
}
// auth service
import { Inject, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { LoginDto, RegisterResponseDto } from './dto/auth.dto';
import { argumentsAssert } from 'common/errors';
import { User } from 'models/users/entities/user.entity';
import { AuthHelper } from './auth.helper';
import { UsersRepository } from 'models/users/users.repository';
import { Repository } from 'typeorm';
@Injectable()
export class AuthService {
@InjectRepository(User)
private readonly userRepository: Repository<User>;
@Inject(AuthHelper)
private readonly authHelper: AuthHelper;
private generateAccessToken(user: User): string {
const payload = { id: user.id, authToken: user.authToken };
const shouldExpire = true;
return this.authHelper.encode(payload, shouldExpire);
}
async register(): Promise<RegisterResponseDto> {
const res = await this.userRepository.findAll();
const user = new User();
const registeredUser = await this.userRepository.create(user);
user.authToken = this.authHelper.encode(registeredUser.id);
user.id = registeredUser.id;
await this.userRepository.update(user);
return Object.assign(user, { accessToken: this.generateAccessToken(user) });
}
}
// auth module
import { Module } from '@nestjs/common';
import { JwtModule, JwtService } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { getRepositoryToken, TypeOrmModule } from '@nestjs/typeorm';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { JwtStrategy } from './jwt.strategy';
import { AuthHelper } from './auth.helper';
import { AppConfigModule } from 'config/app/config.module';
import { AppConfigService } from 'config/app/config.service';
import { User } from 'models/users/entities/user.entity';
import { UsersRepository } from 'models/users/users.repository';
import { Repository } from 'typeorm';
@Module({
imports: [
AppConfigModule,
TypeOrmModule.forFeature([User]),
PassportModule.register({ defaultStrategy: 'jwt', property: 'user' }),
JwtModule.registerAsync({
inject: [AppConfigService],
imports: [AppConfigModule],
useFactory: (appConfigService: AppConfigService) => ({
secret: appConfigService.jwtSecret,
signOptions: { expiresIn: appConfigService.jwtExpiresIn },
}),
}),
],
providers: [
UsersRepository,
AuthService,
JwtStrategy,
{
provide: AuthHelper,
useFactory: (userRepository: UsersRepository, jwtService: JwtService, appConfigService: AppConfigService) =>
new AuthHelper(userRepository, jwtService, appConfigService.jwtSecret),
inject: [getRepositoryToken(User), JwtService, AppConfigService, UsersRepository],
},
],
controllers: [AuthController],
})
export class AuthModule {
}
my app module
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from 'app.controller';
import { AppService } from 'app.service';
import { CommonModule } from 'common/common.module';
import { DatabaseModule } from 'database/database.module';
import { AppConfigModule } from 'config/app/config.module';
import { AuthModule } from 'authentication/auth.module';
import { ModelsModule } from 'models/models.module';
import { ProvidersModule } from 'providers/providers.module';
import { MysqlDatabaseProviderModule } from 'providers/database/mysql/provider.module';
@Module({
imports: [
ConfigModule.forRoot(),
CommonModule,
DatabaseModule,
AppConfigModule,
AuthModule,
ModelsModule,
ProvidersModule,
MysqlDatabaseProviderModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
}
please help me, I spent two days of googling...no results.