Skip to main content
Glama
supabase.md5.07 kB
```typescript 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