feat: Upgrade to Next.js 16.1 & React 19.2, migrate to Supabase SSR with async client handling

This commit is contained in:
2025-12-19 20:31:46 +01:00
parent d9b44a0ec5
commit 24e243fff8
49 changed files with 942 additions and 852 deletions

View File

@@ -1,9 +1,9 @@
'use server';
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { createClient } from '@/lib/supabase/server';
import { checkIsAdmin } from './track-api-usage';
import { addCredits, getUserCredits } from './credit-service';
import { AdminCreditUpdateSchema, AdminSettingsSchema } from '@/types/whisky';
interface UserWithCredits {
id: string;
@@ -23,7 +23,7 @@ interface UserWithCredits {
*/
export async function getAllUsersWithCredits(): Promise<UserWithCredits[]> {
try {
const supabase = createServerComponentClient({ cookies });
const supabase = await createClient();
// Check if current user is admin
const { data: { user } } = await supabase.auth.getUser();
@@ -97,7 +97,8 @@ export async function updateUserCredits(
reason: string
): Promise<{ success: boolean; error?: string }> {
try {
const supabase = createServerComponentClient({ cookies });
const validated = AdminCreditUpdateSchema.parse({ userId, newBalance, reason });
const supabase = await createClient();
// Check if current user is admin
const { data: { user } } = await supabase.auth.getUser();
@@ -107,20 +108,20 @@ export async function updateUserCredits(
if (!isAdmin) return { success: false, error: 'Not authorized' };
// Get current credits
const currentCredits = await getUserCredits(userId);
const currentCredits = await getUserCredits(validated.userId);
if (!currentCredits) {
return { success: false, error: 'User credits not found' };
}
const difference = newBalance - currentCredits.balance;
const difference = validated.newBalance - currentCredits.balance;
// Use addCredits which handles the transaction logging
const result = await addCredits(userId, difference, reason, user.id);
const result = await addCredits(validated.userId, difference, validated.reason, user.id);
return result;
} catch (err) {
console.error('Error in updateUserCredits:', err);
return { success: false, error: 'Failed to update credits' };
return { success: false, error: err instanceof Error ? err.message : 'Failed to update credits' };
}
}
@@ -132,7 +133,8 @@ export async function setUserDailyLimit(
dailyLimit: number | null
): Promise<{ success: boolean; error?: string }> {
try {
const supabase = createServerComponentClient({ cookies });
const validated = AdminSettingsSchema.parse({ userId, dailyLimit });
const supabase = await createClient();
// Check if current user is admin
const { data: { user } } = await supabase.auth.getUser();
@@ -143,8 +145,8 @@ export async function setUserDailyLimit(
const { error } = await supabase
.from('user_credits')
.update({ daily_limit: dailyLimit })
.eq('user_id', userId);
.update({ daily_limit: validated.dailyLimit })
.eq('user_id', validated.userId);
if (error) {
console.error('Error setting daily limit:', error);
@@ -154,7 +156,7 @@ export async function setUserDailyLimit(
return { success: true };
} catch (err) {
console.error('Error in setUserDailyLimit:', err);
return { success: false, error: 'Failed to set daily limit' };
return { success: false, error: err instanceof Error ? err.message : 'Failed to set daily limit' };
}
}
@@ -167,7 +169,8 @@ export async function setUserApiCosts(
geminiAiCost: number
): Promise<{ success: boolean; error?: string }> {
try {
const supabase = createServerComponentClient({ cookies });
const validated = AdminSettingsSchema.parse({ userId, googleSearchCost, geminiAiCost });
const supabase = await createClient();
// Check if current user is admin
const { data: { user } } = await supabase.auth.getUser();
@@ -179,10 +182,10 @@ export async function setUserApiCosts(
const { error } = await supabase
.from('user_credits')
.update({
google_search_cost: googleSearchCost,
gemini_ai_cost: geminiAiCost
google_search_cost: validated.googleSearchCost,
gemini_ai_cost: validated.geminiAiCost
})
.eq('user_id', userId);
.eq('user_id', validated.userId);
if (error) {
console.error('Error setting API costs:', error);
@@ -192,7 +195,7 @@ export async function setUserApiCosts(
return { success: true };
} catch (err) {
console.error('Error in setUserApiCosts:', err);
return { success: false, error: 'Failed to set API costs' };
return { success: false, error: err instanceof Error ? err.message : 'Failed to set API costs' };
}
}
@@ -205,7 +208,7 @@ export async function bulkAddCredits(
reason: string
): Promise<{ success: boolean; processed: number; failed: number; error?: string }> {
try {
const supabase = createServerComponentClient({ cookies });
const supabase = await createClient();
// Check if current user is admin
const { data: { user } } = await supabase.auth.getUser();