UNPKG

sourabhrealtime

Version:

ROBUST RICH TEXT EDITOR: Single-pane contentEditable with direct text selection formatting, speech features, undo/redo, professional UI - Perfect TipTap alternative

292 lines (265 loc) 9.21 kB
// Simple Supabase API with automatic table creation const SUPABASE_URL = "https://supabase.merai.app"; const SERVICE_ROLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"; const simpleSupabase = { async init() { try { // Create projects table await fetch(`${SUPABASE_URL}/rest/v1/rpc/exec_sql`, { method: 'POST', headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ sql: ` CREATE TABLE IF NOT EXISTS projects ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, name VARCHAR(255) NOT NULL, description TEXT, content TEXT DEFAULT '<p>Start typing...</p>', created_by UUID NOT NULL, updated_by UUID, members TEXT[] DEFAULT '{}', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS approval_requests ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, project_id UUID NOT NULL, project_name VARCHAR(255) NOT NULL, content TEXT NOT NULL, user_id UUID NOT NULL, user_name VARCHAR(255) NOT NULL, user_email VARCHAR(255) NOT NULL, status VARCHAR(20) DEFAULT 'pending', reviewed_by UUID, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), reviewed_at TIMESTAMP WITH TIME ZONE ); ` }) }); } catch (error) { // Tables may already exist } }, async authenticateUser(email, password) { try { await this.init(); const response = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=password`, { method: 'POST', headers: { 'apikey': SERVICE_ROLE_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); if (response.ok) { const data = await response.json(); return { success: true, user: { id: data.user.id, email: data.user.email, name: data.user.user_metadata?.name || data.user.email.split('@')[0], role: data.user.user_metadata?.role || 'user' }, token: data.access_token }; } return { success: false, message: 'Invalid credentials' }; } catch (error) { return { success: false, message: 'Authentication failed' }; } }, async getProjects(userId, userRole) { try { await this.init(); const response = await fetch(`${SUPABASE_URL}/rest/v1/projects?select=*`, { headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json' } }); if (response.ok) { const projects = await response.json(); return { success: true, projects }; } return { success: true, projects: [] }; } catch (error) { return { success: true, projects: [] }; } }, async createProject(projectData, creatorId) { try { await this.init(); const response = await fetch(`${SUPABASE_URL}/rest/v1/projects`, { method: 'POST', headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json', 'Prefer': 'return=representation' }, body: JSON.stringify({ name: projectData.name, description: projectData.description || '', content: '<p>Start typing...</p>', created_by: creatorId, members: [creatorId], created_at: new Date().toISOString(), updated_at: new Date().toISOString() }) }); if (response.ok) { const projects = await response.json(); const project = Array.isArray(projects) ? projects[0] : projects; return { success: true, project }; } return { success: false, message: 'Failed to create project' }; } catch (error) { return { success: false, message: error.message }; } }, async updateProjectContent(projectId, content, userId) { try { const response = await fetch(`${SUPABASE_URL}/rest/v1/projects?id=eq.${projectId}`, { method: 'PATCH', headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ content, updated_at: new Date().toISOString(), updated_by: userId }) }); return { success: response.ok }; } catch (error) { return { success: false }; } }, async getApprovalRequests() { try { await this.init(); const response = await fetch(`${SUPABASE_URL}/rest/v1/approval_requests?status=eq.pending&select=*`, { headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json' } }); if (response.ok) { const requests = await response.json(); return { success: true, requests }; } return { success: true, requests: [] }; } catch (error) { return { success: true, requests: [] }; } }, async createApprovalRequest(requestData) { try { await this.init(); const response = await fetch(`${SUPABASE_URL}/rest/v1/approval_requests`, { method: 'POST', headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json', 'Prefer': 'return=representation' }, body: JSON.stringify({ project_id: requestData.projectId, project_name: requestData.projectName, content: requestData.content, user_id: requestData.user.id, user_name: requestData.user.name, user_email: requestData.user.email, status: 'pending', created_at: new Date().toISOString() }) }); if (response.ok) { const requests = await response.json(); const request = Array.isArray(requests) ? requests[0] : requests; return { success: true, request }; } return { success: false, message: 'Failed to create approval request' }; } catch (error) { return { success: false, message: error.message }; } }, async updateApprovalRequest(requestId, status, adminId) { try { const response = await fetch(`${SUPABASE_URL}/rest/v1/approval_requests?id=eq.${requestId}`, { method: 'PATCH', headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status, reviewed_by: adminId, reviewed_at: new Date().toISOString() }) }); return { success: response.ok }; } catch (error) { return { success: false }; } }, async getAllUsers() { try { const response = await fetch(`${SUPABASE_URL}/auth/v1/admin/users`, { headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); const users = data.users?.map(user => ({ id: user.id, email: user.email, name: user.user_metadata?.name || user.email.split('@')[0], role: user.user_metadata?.role || 'user', created_at: user.created_at })) || []; return { success: true, users }; } return { success: true, users: [] }; } catch (error) { return { success: true, users: [] }; } }, async inviteUserToProject(projectId, userId, invitedBy) { try { await this.init(); // Add user to project members const projectResponse = await fetch(`${SUPABASE_URL}/rest/v1/projects?id=eq.${projectId}`, { method: 'PATCH', headers: { 'apikey': SERVICE_ROLE_KEY, 'Authorization': `Bearer ${SERVICE_ROLE_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ members: `{${userId}}`, updated_at: new Date().toISOString() }) }); return { success: projectResponse.ok }; } catch (error) { return { success: false, message: error.message }; } } }; export default simpleSupabase;