fix(danisman): H1 — aynı adımda iki profil_guncelle birbirini ezmesin

profilAlanYaz oku → değiştir → yaz yerine tek SQL ifadesiyle yazar
(json_set / json_remove); eşzamanlı iki alan yazımı artık ikisini de tutar.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-05 01:03:37 +03:00
parent 3e4886e0d9
commit 4e2470e713

View File

@@ -1,7 +1,8 @@
import "server-only"; import "server-only";
import { eq } from "drizzle-orm"; import { eq, sql } from "drizzle-orm";
import { appDb, schema } from "@/lib/appdb"; import { appDb, schema } from "@/lib/appdb";
import { import {
PROFIL_ALANLARI,
PROFIL_SEMASI, PROFIL_SEMASI,
profilTemizle, profilTemizle,
type DanismanProfili, type DanismanProfili,
@@ -20,33 +21,38 @@ export async function profilGetir(userId: string): Promise<DanismanProfili> {
/** /**
* Tek alanı yazar (deger null → alan silinir). Değer şemadan geçmezse hata * Tek alanı yazar (deger null → alan silinir). Değer şemadan geçmezse hata
* fırlatır; çağıran taraf (araç) bunu modele "kaydedilmedi" diye döner. * fırlatır; çağıran taraf (araç) bunu modele "kaydedilmedi" diye döner.
*
* Yazım tek SQL ifadesidir (json_set / json_remove): model aynı adımda iki
* alanı birden kaydedince oku → değiştir → yaz sırası birbirini eziyordu.
*/ */
export async function profilAlanYaz( export async function profilAlanYaz(
userId: string, userId: string,
alan: ProfilAlani, alan: ProfilAlani,
deger: unknown, deger: unknown,
): Promise<DanismanProfili> { ): Promise<DanismanProfili> {
const mevcut = await profilGetir(userId); if (!PROFIL_ALANLARI.includes(alan)) throw new Error(`Bilinmeyen alan: ${alan}`);
const yeni: Record<string, unknown> = { ...mevcut }; const kolon = schema.danismanProfil.alanlar;
const yol = `$.${alan}`;
const now = new Date();
if (deger === null || deger === undefined) { if (deger === null || deger === undefined) {
delete yeni[alan]; await appDb
.update(schema.danismanProfil)
.set({ alanlar: sql`json_remove(${kolon}, ${yol})`, updatedAt: now })
.where(eq(schema.danismanProfil.userId, userId));
} else { } else {
const dogrulama = PROFIL_SEMASI.shape[alan].safeParse(deger); const dogrulama = PROFIL_SEMASI.shape[alan].safeParse(deger);
if (!dogrulama.success) { if (!dogrulama.success) {
throw new Error(`Geçersiz değer: ${alan}`); throw new Error(`Geçersiz değer: ${alan}`);
} }
yeni[alan] = dogrulama.data; await appDb
.insert(schema.danismanProfil)
.values({ userId, alanlar: { [alan]: dogrulama.data }, updatedAt: now })
.onConflictDoUpdate({
target: schema.danismanProfil.userId,
set: { alanlar: sql`json_set(${kolon}, ${yol}, ${dogrulama.data})`, updatedAt: now },
});
} }
const alanlar = PROFIL_SEMASI.parse(yeni); return profilGetir(userId);
const now = new Date();
await appDb
.insert(schema.danismanProfil)
.values({ userId, alanlar, updatedAt: now })
.onConflictDoUpdate({
target: schema.danismanProfil.userId,
set: { alanlar, updatedAt: now },
});
return alanlar;
} }
export async function profilSil(userId: string): Promise<void> { export async function profilSil(userId: string): Promise<void> {