first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 22:11:03 +03:00
commit 031582ea2c
98 changed files with 13281 additions and 0 deletions

51
app/lib/api-key-utils.ts Normal file
View File

@@ -0,0 +1,51 @@
/** Kullanıcı/admin API key oluşturma ve güncelleme için ortak süre kuralları */
export const MAX_API_KEY_NAME_LEN = 120;
export const MAX_EXPIRES_DAYS = 3650;
export function expiresAtFromDays(days: number): Date {
return new Date(Date.now() + days * 86_400_000);
}
/**
* Body'den süre çıkarır: yok/null/0 = süresiz; 1..MAX_EXPIRES_DAYS = o kadar gün.
* Geçersiz sayıda null döner (çağıran 400 verebilir).
*/
export function parseExpiresInDaysOptional(
raw: unknown
): { ok: true; value: number | null } | { ok: false; error: string } {
if (raw === undefined || raw === null) {
return { ok: true, value: null };
}
if (typeof raw !== "number" || !Number.isFinite(raw)) {
return { ok: false, error: "expiresInDays sayı olmalıdır." };
}
const d = Math.floor(raw);
if (d === 0) {
return { ok: true, value: null };
}
if (d < 1 || d > MAX_EXPIRES_DAYS) {
return {
ok: false,
error: `expiresInDays 0 (süresiz) veya 1${MAX_EXPIRES_DAYS} arası olmalıdır.`,
};
}
return { ok: true, value: d };
}
/** Süresiz: daysRemaining null. Süreli: kalan tam gün sayısı (bitiş anına kadar; dolmuşsa 0). */
export function getDaysRemaining(expiresAt: Date | null | undefined): number | null {
if (expiresAt == null) return null;
const ms = expiresAt.getTime() - Date.now();
if (ms <= 0) return 0;
return Math.ceil(ms / 86_400_000);
}
/** Kullanıcı ve admin arayüzleri için kısa Türkçe ibare */
export function getExpiryRemainingLabel(expiresAt: Date | null | undefined): string {
if (expiresAt == null) return "Süresiz";
const d = getDaysRemaining(expiresAt);
if (d === 0) return "Süresi doldu";
if (d === 1) return "1 gün kaldı";
return `${d} gün kaldı`;
}