patch 메소드로 구현하므로, service 단위부터 if문으로 분기처리해 함수를 하나만 제작. if (!isRegistered) ... else ...async function update(
req: Request<{}, {}, ClientProfileRegisterDto>,
res: Response,
next: NextFunction,
) {
try {
const { userId } = req.auth!;
// 프로필 등록 vs 수정 판단
const existingProfile = await profileClientRepository.findById(userId);
const mode = existingProfile?.isProfileCompleted === true ? "update" : "create";
// 유형별 parse
let parsedData;
if (mode === "create") {
parsedData = profileClientSchema("create").parse(req.body) as ClientProfileRegisterDto;
} else {
parsedData = profileClientSchema("update").parse(req.body) as ClientProfileUpdateDto;
}
const newProfile = await profileClientService.update(userId, parsedData);
res.status(200).json({
message: `일반 프로필 ${mode === "create" ? "등록" : "수정"} 성공`,
data: newProfile,
});
} catch (error) {
next(error);
}
}
export function profileClientSchema(mode: "create" | "update") {
// 프로필 생성
const create = z.object({
profileImage: profileImageSchema,
serviceType: serviceTypeSchema,
livingArea: livingAreaSchema,
});
// 프로필 수정
const update = z
.object({ ... })
.superRefine((data, ctx) => {
const { newPassword, newPasswordConfirmation } = data;
// 1. 새 비밀번호를 설정하면 확인도 해야 함
const eitherPasswordExists = !!newPassword || !!newPasswordConfirmation;
...
isProfileCompleted// 프로필 생성
async function create(userId: Client["id"], profile: ClientProfileRegister) {
// 배열1: serviceType. [user.serviceType]가 안 먹혀서 돌려씀
const serviceTypes: MoveType[] | undefined = profile.serviceType
? profile.serviceType.map((type) => MoveType[type as keyof typeof MoveType])
: undefined;
// 배열2: 지역
const livingAreaName = profile.livingArea
? {
connect: profile.livingArea.map((regionName) => ({
regionName,
})),
}
: undefined;
// Client 반환
const newProfile = await prisma.client.update({
where: { id: userId }, // 조건: 로그인한 사용자
data: {
profileImage: profile.profileImage,
serviceType: serviceTypes,
livingArea: livingAreaName,
isProfileCompleted: true,
},
});
zod의 superRefine과 addIssue 함수로 구현. 하지만 스스로 구현하는 쪽이 더 직관적이었을 듯함.
const basicPasswordSchema = z
.string()
.min(8, "기존 비밀번호를 입력해주세요.")
.max(16, ErrorMessage.PASSWORD_LENGTH_LIMIT)
.regex(
/^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*(),.?":{}|<>])[A-Za-z\\d!@#$%^&*(),.?":{}|<>]{8,16}$/,
ErrorMessage.PASSWORD_REGEX,
)
.optional();
const passwordSchema = z
.string()
.min(8, ErrorMessage.PASSWORD_LENGTH_LIMIT)
.max(16, ErrorMessage.PASSWORD_LENGTH_LIMIT)
.regex(
/^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*(),.?":{}|<>])[A-Za-z\\d!@#$%^&*(),.?":{}|<>]{8,16}$/,
ErrorMessage.PASSWORD_REGEX,
)
.optional()
.or(z.literal(""));