0

When user registers, I want to him to send his account name, so I will have "Accounts" table with reference to the user entity. I'm using Nest.js. I'm looking for alternative to the following logic in my users.service.ts Register method:

  1. Find Account by Name
  2. If Account not found, Create It
  3. Create User with the Account found above

Here is my Account Entity:

  @Entity()
  export class Account extends BaseEntity {
    @PrimaryGeneratedColumn('uuid')
    id: string;
  
    @Column({ unique: true })
    name: string;
  
    @Column()
    @CreateDateColumn()
    createdAt: Date;
  }

And my User Entity:

@Entity() 
export class User extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ unique: true })
  email: string;

  @Column()
  password: string;

  @ManyToOne(() => Account, (Account) => Account.name, { cascade:true })
  @JoinColumn({name: 'name'})
  account: Account;
}

My CreateUserDTO:

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsNotEmpty()
  password: string;

  @IsNotEmpty()
  account: string;
}

And this is the error when I try to do User.create(dto): Type 'string' is not assignable to type 'Account | DeepPartial<Account>'.

In addition, for some reason, the User.create(dto) returns array of users and not single user, and I don't understand why.

1 Answer 1

1

You can proceed like this :

// create-user.dto.ts

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsString()
  @IsNotEmpty()
  password: string;

  @IsString()
  @IsNotEmpty()
  accountName: string;
}

@Entity()
export class User extends BaseEntity {
    @PrimaryGeneratedColumn('uuid')
    id: string;

    @Column({ unique: true })
    email: string;

    @Column()
    password: string;

    @Column()
    name: string; // This is your relations between user and account defined in JoinColumn decorator

    @ManyToOne(() => Account, (Account) => Account.name, { cascade: true })
    @JoinColumn({ name: 'name' })
    account: Account;
}

// user.service.ts

// user.service.ts
@Injectable()
export class UserService {
    constructor(
        @InjectRepository(Account)
        private readonly accountRepository: Repository<Account>, // Or your custom repository
        @InjectRepository(User)
        private readonly userRepository: Repository<User> // Or your custom repository
    ) {}

    public async register(dto: CreateUserDto): Promise<void> {
        let accountToSaveWithUser: Account;
        // First check if account exist
        const account = await this.accountRepository.findOne({
            where: {
                name: dto.accountName,
            },
        });

        if (isNil(account)) {
            const accountToSave = this.accountRepository.create({
                name: dto.accountName,
            });
            accountToSaveWithUser = await this.accountRepository.save(accountToSave);
        } else {
            accountToSaveWithUser = account;
        }

        await this.userRepository.save({
            email: dto.email,
            password: hash(dto.password), // Use your package for hash password
            name: accountToSaveWithUser.name,
        });
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I was hoping for a way without developing the creation/finding of the account. Sounds like a pretty common use case (When you want to have a table with id + value only)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.