All files / src/users user.repository.ts

92.59% Statements 25/27
75% Branches 6/8
100% Functions 9/9
92% Lines 23/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 1007x 7x 7x   7x     7x 33x     33x       2x                           6x                           1x       1x                       2x           2x                   2x       1x 1x       2x 2x   2x 1x     1x       2x 2x      
import { Injectable } from "@nestjs/common";
import { User } from "./user.entity";
import { RedisService } from "../redis/redis.service";
import type { RedisPipeline } from "../common/types/redis.types";
import { BaseRedisRepository } from "../common/repositories/base-redis.repository";
 
@Injectable()
export class UserRepository extends BaseRedisRepository<User> {
  protected entityName = "user";
 
  constructor(redisService: RedisService) {
    super(redisService);
  }
 
  protected serialize(user: User): Record<string, string> {
    return {
      id: user.id,
      email: user.email,
      name: user.name || "",
      passwordHash: user.passwordHash,
      profileImage: user.profileImage || "",
      emailVerified: user.emailVerified.toString(),
      isActive: user.isActive.toString(),
      createdAt: user.createdAt.toISOString(),
      updatedAt: user.updatedAt.toISOString(),
    };
  }
 
  protected deserialize(data: Record<string, string>): User {
    return new User({
      id: data.id,
      email: data.email,
      name: data.name,
      passwordHash: data.passwordHash,
      profileImage: data.profileImage,
      emailVerified: data.emailVerified === "true",
      isActive: data.isActive === "true",
      createdAt: new Date(data.createdAt),
      updatedAt: new Date(data.updatedAt),
    });
  }
 
  protected createEntity(data: Partial<User>): User {
    return new User(data);
  }
 
  protected updateEntity(existing: User, updates: Partial<User>): User {
    return new User({
      ...existing,
      ...updates,
      updatedAt: new Date(),
    });
  }
 
  protected updateIndexes(
    pipeline: RedisPipeline,
    newUser: User,
    oldUser: User | null,
  ): void {
    const emailKey = this.redisService.generateKey(
      "user",
      "email",
      newUser.email,
    );
 
    Iif (oldUser && oldUser.email !== newUser.email) {
      // 이메일이 변경된 경우 기존 인덱스 제거
      const oldEmailKey = this.redisService.generateKey(
        "user",
        "email",
        oldUser.email,
      );
      pipeline.del(oldEmailKey);
    }
 
    pipeline.set(emailKey, newUser.id);
  }
 
  protected removeFromIndexes(pipeline: RedisPipeline, user: User): void {
    const emailKey = this.redisService.generateKey("user", "email", user.email);
    pipeline.del(emailKey);
  }
 
  async findByEmail(email: string): Promise<User | null> {
    const emailKey = this.redisService.generateKey("user", "email", email);
    const userId = await this.redisService.get(emailKey);
 
    if (!userId) {
      return null;
    }
 
    return await this.findById(userId);
  }
 
  async existsByEmail(email: string): Promise<boolean> {
    const emailKey = this.redisService.generateKey("user", "email", email);
    return await this.redisService.exists(emailKey);
  }
}