Skip to main content
Glama
supabase.ts5.78 kB
import { createClient, SupabaseClient } from '@supabase/supabase-js' // ============================================ // Types (Database definitions) // ============================================ export type Json = | string | number | boolean | null | { [key: string]: Json | undefined } | Json[] export interface Database { public: { Tables: { todos: { Row: { id: number user_id: string task: string is_completed: boolean inserted_at: string } Insert: { id?: number user_id: string task: string is_completed?: boolean inserted_at?: string } Update: { id?: number user_id?: string task?: string is_completed?: boolean inserted_at?: string } } profiles: { Row: { id: string username: string | null avatar_url: string | null updated_at: string | null } Insert: { id: string username?: string | null avatar_url?: string | null updated_at?: string | null } Update: { id?: string username?: string | null avatar_url?: string | null updated_at?: string | null } } } } } // ============================================ // Client Setup // ============================================ const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL! const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! // Simple client (client-side) export const supabase = createClient<Database>(supabaseUrl, supabaseAnonKey) // Service role client (server-side only - bypasses RLS) // export const supabaseAdmin = createClient<Database>( // supabaseUrl, // process.env.SUPABASE_SERVICE_ROLE_KEY! // ) // ============================================ // Auth Helpers // ============================================ export const authService = { async signInWithEmail(email: string) { // Magic link login const { data, error } = await supabase.auth.signInWithOtp({ email, options: { emailRedirectTo: 'http://localhost:3000/auth/callback', }, }) return { data, error } }, async signInWithGoogle() { const { data, error } = await supabase.auth.signInWithOAuth({ provider: 'google', }) return { data, error } }, async signOut() { const { error } = await supabase.auth.signOut() return { error } }, async getUser() { const { data: { user } } = await supabase.auth.getUser() return user }, } // ============================================ // Data Services // ============================================ export const todoService = { async getTodos() { const { data, error } = await supabase .from('todos') .select('*') .order('is_completed', { ascending: true }) .order('inserted_at', { ascending: false }) if (error) throw error return data }, async createTodo(task: string) { const user = await authService.getUser() if (!user) throw new Error('Not authenticated') const { data, error } = await supabase .from('todos') .insert({ task, user_id: user.id }) .select() .single() if (error) throw error return data }, async toggleTodo(id: number, isCompleted: boolean) { const { data, error } = await supabase .from('todos') .update({ is_completed: isCompleted }) .eq('id', id) .select() .single() if (error) throw error return data }, async deleteTodo(id: number) { const { error } = await supabase .from('todos') .delete() .eq('id', id) if (error) throw error return true } } // ============================================ // Real-time Subscriptions // ============================================ export function subscribeToTodos(callback: (payload: any) => void) { const subscription = supabase .channel('public:todos') .on( 'postgres_changes', { event: '*', schema: 'public', table: 'todos' }, callback ) .subscribe() return () => { supabase.removeChannel(subscription) } } // ============================================ // Storage Helpers // ============================================ export const storageService = { async uploadAvatar(file: File) { const user = await authService.getUser() if (!user) throw new Error('Not authenticated') const fileExt = file.name.split('.').pop() const filePath = `${user.id}.${fileExt}` const { error: uploadError } = await supabase.storage .from('avatars') .upload(filePath, file, { upsert: true }) if (uploadError) throw uploadError // Get public URL const { data } = supabase.storage .from('avatars') .getPublicUrl(filePath) return data.publicUrl } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/millsydotdev/Code-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server