Insert row
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Netlify Function (Node runtime).
|
||||
*
|
||||
* Inserts a row into the Supabase `funder_data_submissions` table
|
||||
* when the user submits the funder discovery form. Runs in parallel
|
||||
* with the Anthropic agent stream and is intentionally independent of
|
||||
* it — a Supabase failure must never block (or be observed by) the
|
||||
* streaming brief.
|
||||
*
|
||||
* Environment variables (set in .env.local for local `netlify dev`,
|
||||
* and in the Netlify UI for production):
|
||||
* - SUPABASE_URL e.g. https://<project>.supabase.co
|
||||
* - SUPABASE_SERVICE_ROLE_KEY service role key (server-side only)
|
||||
*
|
||||
* The service role key bypasses RLS, so this function must only be
|
||||
* called from trusted server-side code (which it is — this endpoint
|
||||
* is the only caller). Do NOT expose this key to the browser.
|
||||
*/
|
||||
|
||||
export const handler = async (event) => {
|
||||
if (event.httpMethod !== 'POST') {
|
||||
return {
|
||||
statusCode: 405,
|
||||
body: JSON.stringify({ error: 'Method not allowed' }),
|
||||
}
|
||||
}
|
||||
|
||||
const SUPABASE_URL = process.env.SUPABASE_URL
|
||||
const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY
|
||||
|
||||
if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) {
|
||||
return {
|
||||
statusCode: 500,
|
||||
body: JSON.stringify({
|
||||
error: 'Server is missing SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY',
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
let payload
|
||||
try {
|
||||
payload = JSON.parse(event.body || '{}')
|
||||
} catch {
|
||||
return {
|
||||
statusCode: 400,
|
||||
body: JSON.stringify({ error: 'Invalid JSON body' }),
|
||||
}
|
||||
}
|
||||
|
||||
const row = {
|
||||
name: payload.userName ?? null,
|
||||
email: payload.userEmail ?? null,
|
||||
station_name: payload.stationName ?? null,
|
||||
station_location: payload.stationLocation ?? null,
|
||||
station_website: payload.stationWebsite ?? null,
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(
|
||||
`${SUPABASE_URL.replace(/\/$/, '')}/rest/v1/funder_data_submissions`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
apikey: SUPABASE_SERVICE_ROLE_KEY,
|
||||
Authorization: `Bearer ${SUPABASE_SERVICE_ROLE_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
Prefer: 'return=minimal',
|
||||
},
|
||||
body: JSON.stringify(row),
|
||||
},
|
||||
)
|
||||
|
||||
if (!res.ok) {
|
||||
const text = await res.text()
|
||||
console.error('Supabase insert failed', res.status, text)
|
||||
return {
|
||||
statusCode: 502,
|
||||
body: JSON.stringify({
|
||||
error: `Supabase insert failed: ${res.status} ${text}`,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
statusCode: 204,
|
||||
body: '',
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Supabase request errored', err)
|
||||
return {
|
||||
statusCode: 500,
|
||||
body: JSON.stringify({
|
||||
error: `Supabase request errored: ${err?.message || String(err)}`,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -174,6 +174,17 @@ export default function App() {
|
||||
setIsThinking(true)
|
||||
setIsStreaming(false)
|
||||
|
||||
// Fire-and-forget: save the submission to Supabase in parallel
|
||||
// with the Anthropic agent stream. Any failure is logged but must
|
||||
// never block or surface in the streaming UX.
|
||||
fetch('/.netlify/functions/save-submission', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(form),
|
||||
}).catch((err) => {
|
||||
console.error('Failed to save submission to Supabase', err)
|
||||
})
|
||||
|
||||
try {
|
||||
let resume = null
|
||||
// Loop across segments. Each iteration is one HTTP request;
|
||||
|
||||
Reference in New Issue
Block a user