supabase client tool
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
|
||||
import type { Database } from '@/types/supabase';
|
||||
import { Select } from './Select';
|
||||
import { getSupabaseClient } from '../../utils/supabase';
|
||||
import { AuthChangeEvent, Session } from '@supabase/supabase-js';
|
||||
|
||||
type Team = Database['public']['Tables']['teams']['Row'];
|
||||
type Team = Database['limq']['Tables']['teams']['Row'];
|
||||
|
||||
interface TeamSelectorProps {
|
||||
value?: string;
|
||||
@@ -18,8 +19,6 @@ export function TeamSelector({ value, onChange, className }: TeamSelectorProps)
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const supabase = createClientComponentClient<Database>();
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
|
||||
@@ -31,6 +30,8 @@ export function TeamSelector({ value, onChange, className }: TeamSelectorProps)
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const supabase = getSupabaseClient();
|
||||
|
||||
// 获取用户的团队成员关系
|
||||
console.log('Fetching team memberships for user:', userId);
|
||||
const { data: memberships, error: membershipError } = await supabase
|
||||
@@ -84,8 +85,10 @@ export function TeamSelector({ value, onChange, className }: TeamSelectorProps)
|
||||
}
|
||||
};
|
||||
|
||||
const supabase = getSupabaseClient();
|
||||
|
||||
// 设置认证状态监听器
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => {
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange((event: AuthChangeEvent, session: Session | null) => {
|
||||
console.log('Auth state changed:', event, session?.user);
|
||||
if (event === 'SIGNED_IN' && session?.user?.id) {
|
||||
fetchTeams(session.user.id);
|
||||
@@ -96,7 +99,7 @@ export function TeamSelector({ value, onChange, className }: TeamSelectorProps)
|
||||
});
|
||||
|
||||
// 初始检查session
|
||||
supabase.auth.getSession().then(({ data: { session } }) => {
|
||||
supabase.auth.getSession().then(({ data: { session } }: { data: { session: Session | null } }) => {
|
||||
console.log('Initial session check:', session?.user);
|
||||
if (session?.user?.id) {
|
||||
fetchTeams(session.user.id);
|
||||
@@ -107,7 +110,7 @@ export function TeamSelector({ value, onChange, className }: TeamSelectorProps)
|
||||
isMounted = false;
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [supabase]);
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return <div className="animate-pulse h-10 bg-gray-200 rounded-md dark:bg-gray-700" />;
|
||||
|
||||
59
app/utils/supabase.ts
Normal file
59
app/utils/supabase.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { createClient, SupabaseClient } from "@supabase/supabase-js";
|
||||
import type { Database } from "@/types/supabase";
|
||||
|
||||
let supabase: SupabaseClient<Database> | null = null;
|
||||
|
||||
// 简单的存储适配器,使用localStorage
|
||||
const storageAdapter = {
|
||||
getItem: async (key: string) => {
|
||||
try {
|
||||
const item = localStorage.getItem(key);
|
||||
return item;
|
||||
} catch (error) {
|
||||
console.error("Storage get error:", error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
setItem: async (key: string, value: string) => {
|
||||
try {
|
||||
localStorage.setItem(key, value);
|
||||
} catch (error) {
|
||||
console.error("Storage set error:", error);
|
||||
}
|
||||
},
|
||||
|
||||
removeItem: async (key: string) => {
|
||||
try {
|
||||
localStorage.removeItem(key);
|
||||
} catch (error) {
|
||||
console.error("Storage remove error:", error);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const getSupabaseClient = (): SupabaseClient<Database> => {
|
||||
if (!supabase) {
|
||||
if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) {
|
||||
throw new Error('Missing Supabase environment variables');
|
||||
}
|
||||
|
||||
supabase = createClient<Database>(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
||||
{
|
||||
db: { schema: "limq" },
|
||||
auth: {
|
||||
storage: storageAdapter,
|
||||
persistSession: true,
|
||||
autoRefreshToken: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
return supabase;
|
||||
};
|
||||
|
||||
export const clearSupabaseInstance = () => {
|
||||
supabase = null;
|
||||
};
|
||||
@@ -78,4 +78,69 @@ export interface Database {
|
||||
[_ in never]: never
|
||||
}
|
||||
}
|
||||
limq: {
|
||||
Tables: {
|
||||
teams: {
|
||||
Row: {
|
||||
id: string
|
||||
name: string
|
||||
description: string | null
|
||||
avatar_url: string | null
|
||||
attributes: Json | null
|
||||
created_at: string
|
||||
updated_at: string
|
||||
deleted_at: string | null
|
||||
}
|
||||
Insert: {
|
||||
id?: string
|
||||
name: string
|
||||
description?: string | null
|
||||
avatar_url?: string | null
|
||||
attributes?: Json | null
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
deleted_at?: string | null
|
||||
}
|
||||
Update: {
|
||||
id?: string
|
||||
name?: string
|
||||
description?: string | null
|
||||
avatar_url?: string | null
|
||||
attributes?: Json | null
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
deleted_at?: string | null
|
||||
}
|
||||
}
|
||||
team_membership: {
|
||||
Row: {
|
||||
id: string
|
||||
team_id: string
|
||||
user_id: string
|
||||
role: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
deleted_at: string | null
|
||||
}
|
||||
Insert: {
|
||||
id?: string
|
||||
team_id: string
|
||||
user_id: string
|
||||
role: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
deleted_at?: string | null
|
||||
}
|
||||
Update: {
|
||||
id?: string
|
||||
team_id?: string
|
||||
user_id?: string
|
||||
role?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
deleted_at?: string | null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user