From 0a3aca7cbc9bd66e117f0b1472f8f5b0d4e43657 Mon Sep 17 00:00:00 2001 From: dwindown Date: Tue, 23 Dec 2025 10:26:06 +0700 Subject: [PATCH] Add deployment helpers and environment config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add manual deployment instructions for self-hosted Supabase - Add schema refresh SQL scripts - Add deployment helper scripts - Add Supabase environment configuration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- bypass-schema-cache.ts | 55 ++++++++++++++++ deploy-google-meet-function.sh | 74 +++++++++++++++++++++ deploy-with-env.sh | 24 +++++++ force-schema-refresh.sql | 11 ++++ manual-deploy-instructions.md | 114 +++++++++++++++++++++++++++++++++ supabase/.env | 2 + 6 files changed, 280 insertions(+) create mode 100644 bypass-schema-cache.ts create mode 100755 deploy-google-meet-function.sh create mode 100755 deploy-with-env.sh create mode 100644 force-schema-refresh.sql create mode 100644 manual-deploy-instructions.md create mode 100644 supabase/.env diff --git a/bypass-schema-cache.ts b/bypass-schema-cache.ts new file mode 100644 index 0000000..226b756 --- /dev/null +++ b/bypass-schema-cache.ts @@ -0,0 +1,55 @@ +// Temporary workaround to bypass PostgREST schema cache +// Add this function to IntegrasiTab.tsx + +async function saveGoogleServiceAccountJSON(supabase: any, jsonValue: string) { + try { + // Use raw SQL to bypass PostgREST schema cache + const { data, error } = await supabase.rpc('exec', { + sql: ` + UPDATE platform_settings + SET google_service_account_json = $1 + WHERE id = (SELECT id FROM platform_settings LIMIT 1) + `, + params: [jsonValue] + }); + + if (error) throw error; + return { success: true }; + } catch (error) { + console.error('Error saving service account:', error); + return { error }; + } +} + +// Alternative: Create a temporary edge function to handle the save +// Add to supabase/functions/save-service-account/index.ts + +/* +import { serve } from "https://deno.land/std@0.190.0/http/server.ts"; +import { createClient } from "https://esm.sh/@supabase/supabase-js@2"; + +serve(async (req: Request) => { + const supabaseUrl = Deno.env.get("SUPABASE_URL")!; + const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!; + const supabase = createClient(supabaseUrl, supabaseServiceKey); + + const { json_value } = await req.json(); + + const { data, error } = await supabase + .from('platform_settings') + .update({ google_service_account_json: json_value }) + .neq('id', ''); + + if (error) { + return new Response( + JSON.stringify({ success: false, error: error.message }), + { status: 500, headers: { "Content-Type": "application/json" } } + ); + } + + return new Response( + JSON.stringify({ success: true }), + { headers: { "Content-Type": "application/json" } } + ); +}); +*/ diff --git a/deploy-google-meet-function.sh b/deploy-google-meet-function.sh new file mode 100755 index 0000000..dc66d85 --- /dev/null +++ b/deploy-google-meet-function.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +# Deploy create-google-meet-event function directly + +SUPABASE_URL="https://lovable.backoffice.biz.id" +SERVICE_ROLE_KEY="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsImlhdCI6MTc2NjAzNzEyMCwiZXhwIjo0OTIxNzEwNzIwLCJyb2xlIjoic2VydmljZV9yb2xlIn0.t6D9VwaukYGq4c_VbW1bkd3ZkKgldpCKRR13nN14XXc" + +FUNCTION_NAME="create-google-meet-event" +FUNCTION_PATH="supabase/functions/$FUNCTION_NAME/index.ts" + +echo "🚀 Deploying $FUNCTION_NAME..." +echo "" + +# Check if function file exists +if [ ! -f "$FUNCTION_PATH" ]; then + echo "❌ Error: Function file not found at $FUNCTION_PATH" + exit 1 +fi + +# Read function content +FUNCTION_CONTENT=$(cat "$FUNCTION_PATH") + +echo "📄 Function file found, size: $(echo "$FUNCTION_CONTENT" | wc -c) bytes" +echo "" + +# Create/update function via Supabase Management API +echo "📤 Uploading to Supabase..." +RESPONSE=$(curl -s -w "\n%{http_code}" \ + -X POST "$SUPABASE_URL/rest/v1/functions" \ + -H "Authorization: Bearer $SERVICE_ROLE_KEY" \ + -H "apikey: $SERVICE_ROLE_KEY" \ + -H "Content-Type: application/json" \ + -d "{ + \"name\": \"$FUNCTION_NAME\", + \"verify_jwt\": true + }") + +# Extract status code +HTTP_CODE=$(echo "$RESPONSE" | tail -n1) +RESPONSE_BODY=$(echo "$RESPONSE" | sed '$d') + +echo "HTTP Status: $HTTP_CODE" +echo "Response: $RESPONSE_BODY" +echo "" + +if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "201" ]; then + echo "✅ Function metadata created successfully" + + # Now upload the actual function code + echo "📤 Uploading function code..." + CODE_RESPONSE=$(curl -s -w "\n%{http_code}" \ + -X PUT "$SUPABASE_URL/rest/v1/functions/$FUNCTION_NAME/body" \ + -H "Authorization: Bearer $SERVICE_ROLE_KEY" \ + -H "apikey: $SERVICE_ROLE_KEY" \ + -H "Content-Type: text/plain" \ + --data-binary @"$FUNCTION_PATH") + + CODE_HTTP=$(echo "$CODE_RESPONSE" | tail -n1) + + if [ "$CODE_HTTP" = "200" ] || [ "$CODE_HTTP" = "204" ]; then + echo "✅ Function code uploaded successfully!" + echo "" + echo "🌐 Function URL: $SUPABASE_URL/functions/v1/$FUNCTION_NAME" + else + echo "❌ Failed to upload function code (HTTP $CODE_HTTP)" + echo "Response: $(echo "$CODE_RESPONSE" | sed '$d')" + fi +else + echo "❌ Failed to create function metadata (HTTP $HTTP_CODE)" + echo "Response: $RESPONSE_BODY" +fi + +echo "" +echo "✨ Deployment attempt complete!" diff --git a/deploy-with-env.sh b/deploy-with-env.sh new file mode 100755 index 0000000..4219b09 --- /dev/null +++ b/deploy-with-env.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Deploy to self-hosted Supabase using environment variables + +# Set Supabase environment variables +export SUPABASE_URL="https://lovable.backoffice.biz.id" +export SUPABASE_SERVICE_ROLE_KEY="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsImlhdCI6MTc2NjAzNzEyMCwiZXhwIjo0OTIxNzEwNzIwLCJyb2xlIjoic2VydmljZV9yb2xlIn0.t6D9VwaukYGq4c_VbW1bkd3ZkKgldpCKRR13nN14XXc" + +FUNCTION_NAME="create-google-meet-event" +FUNCTION_FILE="supabase/functions/$FUNCTION_NAME/index.ts" + +echo "🚀 Deploying $FUNCTION_NAME to self-hosted Supabase..." +echo "" + +if [ ! -f "$FUNCTION_FILE" ]; then + echo "❌ Function file not found: $FUNCTION_FILE" + exit 1 +fi + +echo "📤 Deploying via Supabase CLI..." +supabase functions deploy "$FUNCTION_NAME" --project-ref "lovable-backoffice" --verify-jwt + +echo "" +echo "✨ Deployment complete!" diff --git a/force-schema-refresh.sql b/force-schema-refresh.sql new file mode 100644 index 0000000..2b68e26 --- /dev/null +++ b/force-schema-refresh.sql @@ -0,0 +1,11 @@ +-- Force schema cache refresh by selecting from the table +SELECT * FROM platform_settings LIMIT 1; + +-- Verify the column exists +SELECT column_name, data_type, is_nullable +FROM information_schema.columns +WHERE table_name = 'platform_settings' +AND column_name = 'google_service_account_json'; + +-- Update the table to trigger cache refresh (safe operation, just sets same value) +UPDATE platform_settings SET id = id WHERE 1=1 LIMIT 1; diff --git a/manual-deploy-instructions.md b/manual-deploy-instructions.md new file mode 100644 index 0000000..78272d3 --- /dev/null +++ b/manual-deploy-instructions.md @@ -0,0 +1,114 @@ +# Manual Deployment Instructions for Self-Hosted Supabase + +Since you're using self-hosted Supabase, here's how to deploy the edge function: + +## Option 1: Via Supabase CLI (Recommended) + +If you have Supabase CLI installed: + +```bash +# Link to your self-hosted instance +supabase link --project-ref your-project-id + +# Deploy the function +supabase functions deploy create-google-meet-event --verify-jwt +``` + +## Option 2: Direct File Upload to Supabase Container + +For self-hosted Supabase, you need to: + +1. **SSH into your Supabase container** or access via dashboard + +2. **Copy the function file** to the correct location: + ```bash + # Path in Supabase: /var/lib/postgresql/functions/create-google-meet-event/index.ts + # Or wherever your functions are stored + ``` + +3. **Restart the Supabase functions service** + +## Option 3: Use Docker Exec (If running in Docker) + +```bash +# Find the Supabase container +docker ps | grep supabase + +# Copy function file into container +docker cp supabase/functions/create-google-meet-event/index.ts \ + :/home/deno/functions/create-google-meet-event/index.ts + +# Restart the functions service +docker exec supervisorctl restart functions:* +``` + +## Option 4: Update via Supabase Dashboard (If Available) + +1. Access your Supabase dashboard at `https://lovable.backoffice.biz.id` +2. Navigate to **Edge Functions** +3. Click **New Function** or edit existing +4. Paste the code from `supabase/functions/create-google-meet-event/index.ts` +5. Set **Verify JWT** to `true` +6. Save + +## Quick Test to Verify Function Exists + +```bash +curl -X GET "https://lovable.backoffice.biz.id/functions/v1/create-google-meet-event" \ + -H "Authorization: Bearer YOUR_ANON_KEY" +``` + +Expected: Should get a method not allowed error (which means function exists) + +--- + +## Schema Cache Fix + +For the schema cache issue with the `google_service_account_json` column: + +### Run this in Supabase SQL Editor: + +```sql +-- Step 1: Verify column exists +SELECT column_name, data_type +FROM information_schema.columns +WHERE table_name = 'platform_settings' +AND column_name = 'google_service_account_json'; + +-- Step 2: Force cache refresh +NOTIFY pgrst, 'reload schema'; + +-- Step 3: Test query +SELECT google_service_account_json FROM platform_settings; +``` + +### Or restart PostgREST: + +If you have access: +```bash +# In Supabase container/system +supervisorctl restart postgrest +``` + +### Frontend workaround: + +If the schema cache persists, you can bypass the type-safe client and use raw SQL: + +```typescript +// In IntegrasiTab.tsx, temporary bypass +const { data } = await supabase + .rpc('exec_sql', { + sql: `UPDATE platform_settings SET google_service_account_json = '${JSON.stringify(settings.integration_google_service_account_json)}'::jsonb` + }); +``` + +--- + +## Next Steps + +1. Deploy the function using one of the methods above +2. Run the schema refresh SQL +3. Try saving the settings again +4. Test the connection + +Let me know which deployment method works for your setup! diff --git a/supabase/.env b/supabase/.env new file mode 100644 index 0000000..7652f57 --- /dev/null +++ b/supabase/.env @@ -0,0 +1,2 @@ +SUPABASE_URL=https://lovable.backoffice.biz.id +SUPABASE_SERVICE_ROLE_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsImlhdCI6MTc2NjAzNzEyMCwiZXhwIjo0OTIxNzEwNzIwLCJyb2xlIjoic2VydmljZV9yb2xlIn0.t6D9VwaukYGq4c_VbW1bkd3ZkKgldpCKRR13nN14XXc