Skip to content

Commit bfac91a

Browse files
authored
Merge pull request #279 from dhruvi-16-me/web-auth-cors
Add CORS support to Supabase Edge Functions
2 parents 36cb2b8 + d41c063 commit bfac91a

6 files changed

Lines changed: 52 additions & 38 deletions

File tree

supabase/functions/_shared/cors.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const corsHeaders: Record<string, string> = {
2+
"Access-Control-Allow-Origin": "*",
3+
"Access-Control-Allow-Headers":
4+
"authorization, x-client-info, apikey, content-type",
5+
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
6+
};
7+
8+
export function handleCorsPreflight(req: Request): Response | null {
9+
if (req.method === "OPTIONS") {
10+
return new Response("ok", { headers: corsHeaders });
11+
}
12+
return null;
13+
}

supabase/functions/fetch-transcript/index.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
22
import { createClient } from "npm:@supabase/supabase-js@2";
3+
import { corsHeaders, handleCorsPreflight } from "../_shared/cors.ts";
34

45
const VEXA_API_KEY = Deno.env.get("VEXA_API_KEY");
56
const SUPABASE_URL = Deno.env.get("SUPABASE_URL");
67
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");
78

89
serve(async (req) => {
10+
const preflight = handleCorsPreflight(req);
11+
if (preflight) return preflight;
12+
913
console.log("Fetch-transcript function called");
1014

1115
// Handle GET requests for testing
@@ -14,7 +18,7 @@ serve(async (req) => {
1418
JSON.stringify({
1519
message: "This endpoint requires a POST request with meeting_url and meeting_id in the body"
1620
}),
17-
{ status: 400, headers: { "Content-Type": "application/json" } }
21+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
1822
);
1923
}
2024

@@ -24,15 +28,15 @@ serve(async (req) => {
2428
console.error("VEXA_API_KEY is not set");
2529
return new Response(
2630
JSON.stringify({ error: "VEXA_API_KEY is not set" }),
27-
{ status: 500, headers: { "Content-Type": "application/json" } }
31+
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
2832
);
2933
}
3034

3135
if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) {
3236
console.error("SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY is not set");
3337
return new Response(
3438
JSON.stringify({ error: "Database credentials are not set" }),
35-
{ status: 500, headers: { "Content-Type": "application/json" } }
39+
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
3640
);
3741
}
3842

@@ -45,7 +49,7 @@ serve(async (req) => {
4549
console.error("Error parsing request body:", e);
4650
return new Response(
4751
JSON.stringify({ error: "Invalid JSON body" }),
48-
{ status: 400, headers: { "Content-Type": "application/json" } }
52+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
4953
);
5054
}
5155

@@ -56,15 +60,15 @@ serve(async (req) => {
5660
console.error("Missing meeting_url in request");
5761
return new Response(
5862
JSON.stringify({ error: "Missing meeting_url in request" }),
59-
{ status: 400, headers: { "Content-Type": "application/json" } }
63+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
6064
);
6165
}
6266

6367
if (!meeting_id) {
6468
console.error("Missing meeting_id in request");
6569
return new Response(
6670
JSON.stringify({ error: "Missing meeting_id in request" }),
67-
{ status: 400, headers: { "Content-Type": "application/json" } }
71+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
6872
);
6973
}
7074

@@ -135,7 +139,7 @@ serve(async (req) => {
135139
transcript,
136140
message: "Transcript successfully fetched and saved"
137141
}), {
138-
headers: { "Content-Type": "application/json" },
142+
headers: { ...corsHeaders, "Content-Type": "application/json" },
139143
});
140144
} catch (error) {
141145
console.error("Error in transcript process:", error);
@@ -174,7 +178,7 @@ serve(async (req) => {
174178
: "Failed to fetch transcript",
175179
...(transcript && { transcript }) // Include transcript in response if available
176180
}),
177-
{ status: 500, headers: { "Content-Type": "application/json" } }
181+
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
178182
);
179183
}
180184
} catch (error) {
@@ -184,7 +188,7 @@ serve(async (req) => {
184188
error: error.message,
185189
details: "Internal server error"
186190
}),
187-
{ status: 500, headers: { "Content-Type": "application/json" } }
191+
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
188192
);
189193
}
190194
});

supabase/functions/generate-embeddings/index.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@
77
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
88
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.7.1";
99
import "https://deno.land/std@0.192.0/dotenv/load.ts";
10+
import { corsHeaders, handleCorsPreflight } from "../_shared/cors.ts";
1011

11-
const corsHeaders = {
12-
"Access-Control-Allow-Origin": "*",
13-
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
14-
};
1512
const GEMINI_API_KEY = Deno.env.get("GEMINI_API_KEY");
1613
const SUPABASE_URL = Deno.env.get("SUPABASE_URL");
1714
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");
@@ -21,9 +18,8 @@ console.log("SUPABASE_URL:", SUPABASE_URL ? "Loaded" : "Missing");
2118
console.log("SUPABASE_SERVICE_ROLE_KEY:", SUPABASE_SERVICE_ROLE_KEY ? "Loaded" : "Missing");
2219

2320
serve(async (req) => {
24-
if (req.method === "OPTIONS") {
25-
return new Response("ok", { headers: corsHeaders });
26-
}
21+
const preflight = handleCorsPreflight(req);
22+
if (preflight) return preflight;
2723

2824
try {
2925
const { meeting_id } = await req.json();
@@ -96,4 +92,3 @@ serve(async (req) => {
9692
);
9793
}
9894
});
99-

supabase/functions/get-embedding/index.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
// supabase/functions/get-embedding/index.ts
22
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
33
import "https://deno.land/std@0.192.0/dotenv/load.ts";
4-
5-
const corsHeaders = {
6-
"Access-Control-Allow-Origin": "*",
7-
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
8-
};
4+
import { corsHeaders, handleCorsPreflight } from "../_shared/cors.ts";
95

106
const GEMINI_API_KEY = Deno.env.get("GEMINI_API_KEY");
117

128
console.log("GEMINI_API_KEY:", GEMINI_API_KEY ? "Loaded" : "Missing");
139

1410
serve(async (req) => {
15-
if (req.method === "OPTIONS") {
16-
return new Response("ok", { headers: corsHeaders });
17-
}
11+
const preflight = handleCorsPreflight(req);
12+
if (preflight) return preflight;
1813

1914
try {
2015
const { text } = await req.json();
@@ -61,4 +56,3 @@ serve(async (req) => {
6156
);
6257
}
6358
});
64-

supabase/functions/start-bot/index.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
22
import { createClient } from "npm:@supabase/supabase-js@2";
3+
import { corsHeaders, handleCorsPreflight } from "../_shared/cors.ts";
34

45
const VEXA_API_KEY = Deno.env.get("VEXA_API_KEY");
56
const SUPABASE_URL = Deno.env.get("SUPABASE_URL");
67
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");
78

89
serve(async (req) => {
10+
const preflight = handleCorsPreflight(req);
11+
if (preflight) return preflight;
12+
913
console.log("Start-bot function called");
1014

1115
// Handle GET requests for testing
@@ -14,7 +18,7 @@ serve(async (req) => {
1418
JSON.stringify({
1519
message: "This endpoint requires a POST request with meeting_url and meeting_id in the body"
1620
}),
17-
{ status: 400, headers: { "Content-Type": "application/json" } }
21+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
1822
);
1923
}
2024

@@ -24,15 +28,15 @@ serve(async (req) => {
2428
console.error("VEXA_API_KEY is not set");
2529
return new Response(
2630
JSON.stringify({ error: "VEXA_API_KEY is not set" }),
27-
{ status: 500, headers: { "Content-Type": "application/json" } }
31+
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
2832
);
2933
}
3034

3135
if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) {
3236
console.error("SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY is not set");
3337
return new Response(
3438
JSON.stringify({ error: "Database credentials are not set" }),
35-
{ status: 500, headers: { "Content-Type": "application/json" } }
39+
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
3640
);
3741
}
3842

@@ -45,7 +49,7 @@ serve(async (req) => {
4549
console.error("Error parsing request body:", e);
4650
return new Response(
4751
JSON.stringify({ error: "Invalid JSON body" }),
48-
{ status: 400, headers: { "Content-Type": "application/json" } }
52+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
4953
);
5054
}
5155

@@ -56,15 +60,15 @@ serve(async (req) => {
5660
console.error("Missing meeting_url in request");
5761
return new Response(
5862
JSON.stringify({ error: "Missing meeting_url in request" }),
59-
{ status: 400, headers: { "Content-Type": "application/json" } }
63+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
6064
);
6165
}
6266

6367
if (!meeting_id) {
6468
console.error("Missing meeting_id in request");
6569
return new Response(
6670
JSON.stringify({ error: "Missing meeting_id in request" }),
67-
{ status: 400, headers: { "Content-Type": "application/json" } }
71+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
6872
);
6973
}
7074

@@ -73,7 +77,7 @@ serve(async (req) => {
7377
console.error("Only Google Meet URLs are supported");
7478
return new Response(
7579
JSON.stringify({ error: "Only Google Meet URLs are supported" }),
76-
{ status: 400, headers: { "Content-Type": "application/json" } }
80+
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
7781
);
7882
}
7983

@@ -114,20 +118,20 @@ serve(async (req) => {
114118
error: "Bot started but failed to update meeting record",
115119
details: updateError.message
116120
}),
117-
{ status: 500, headers: { "Content-Type": "application/json" } }
121+
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
118122
);
119123
}
120124

121125
console.log("Meeting record updated successfully");
122126

123127
return new Response(JSON.stringify(result), {
124-
headers: { "Content-Type": "application/json" },
128+
headers: { ...corsHeaders, "Content-Type": "application/json" },
125129
});
126130
} catch (error) {
127131
console.error("Error in start-bot function:", error);
128132
return new Response(
129133
JSON.stringify({ error: error instanceof Error ? error.message : "Unknown error" }),
130-
{ status: 500, headers: { "Content-Type": "application/json" } }
134+
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
131135
);
132136
}
133137
})

supabase/functions/summarize-transcription/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { serve } from "https://deno.land/std@0.192.0/http/server.ts";
22
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
3+
import { corsHeaders, handleCorsPreflight } from "../_shared/cors.ts";
34

45

56
// import "https://deno.land/std@0.192.0/dotenv/load.ts";
@@ -67,6 +68,9 @@ const meetingSummarySchema = {
6768

6869

6970
serve(async (req) => {
71+
const preflight = handleCorsPreflight(req);
72+
if (preflight) return preflight;
73+
7074
try {
7175
if (!GEMINI_API_KEY || !SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) {
7276
throw new Error("Missing environment variables");
@@ -170,12 +174,12 @@ serve(async (req) => {
170174
success: true,
171175
summary: structuredSummary
172176
}), {
173-
headers: { "Content-Type": "application/json" },
177+
headers: { ...corsHeaders, "Content-Type": "application/json" },
174178
});
175179
} catch (error) {
176180
return new Response(JSON.stringify({ error: error.message }), {
177181
status: 500,
178-
headers: { "Content-Type": "application/json" },
182+
headers: { ...corsHeaders, "Content-Type": "application/json" },
179183
});
180184
}
181185
});

0 commit comments

Comments
 (0)