Add deployment helpers and environment config
- 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 <noreply@anthropic.com>
This commit is contained in:
55
bypass-schema-cache.ts
Normal file
55
bypass-schema-cache.ts
Normal file
@@ -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" } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
*/
|
||||||
74
deploy-google-meet-function.sh
Executable file
74
deploy-google-meet-function.sh
Executable file
@@ -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!"
|
||||||
24
deploy-with-env.sh
Executable file
24
deploy-with-env.sh
Executable file
@@ -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!"
|
||||||
11
force-schema-refresh.sql
Normal file
11
force-schema-refresh.sql
Normal file
@@ -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;
|
||||||
114
manual-deploy-instructions.md
Normal file
114
manual-deploy-instructions.md
Normal file
@@ -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 \
|
||||||
|
<container-id>:/home/deno/functions/create-google-meet-event/index.ts
|
||||||
|
|
||||||
|
# Restart the functions service
|
||||||
|
docker exec <container-id> 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!
|
||||||
2
supabase/.env
Normal file
2
supabase/.env
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
SUPABASE_URL=https://lovable.backoffice.biz.id
|
||||||
|
SUPABASE_SERVICE_ROLE_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsImlhdCI6MTc2NjAzNzEyMCwiZXhwIjo0OTIxNzEwNzIwLCJyb2xlIjoic2VydmljZV9yb2xlIn0.t6D9VwaukYGq4c_VbW1bkd3ZkKgldpCKRR13nN14XXc
|
||||||
Reference in New Issue
Block a user