97 lines
2.8 KiB
TypeScript
97 lines
2.8 KiB
TypeScript
// Follow this setup guide to integrate the Deno language server with your editor:
|
|
// https://deno.land/manual/getting_started/setup_your_environment
|
|
// This enables autocomplete, go to definition, etc.
|
|
|
|
// Setup type definitions for built-in Supabase Runtime APIs
|
|
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
|
|
import React from 'npm:react@18.3.1'
|
|
import { Webhook } from 'https://esm.sh/standardwebhooks@1.0.0'
|
|
import { Resend } from 'npm:resend@4.0.0'
|
|
import { renderAsync } from 'npm:@react-email/components@0.0.22'
|
|
import { MagicLinkEmail } from './_templates/magic-link.tsx'
|
|
|
|
const resend = new Resend(Deno.env.get('RESEND_API_KEY') as string)
|
|
const hookSecret = Deno.env.get('SEND_EMAIL_HOOK_SECRET') as string
|
|
|
|
Deno.serve(async (req) => {
|
|
if (req.method !== 'POST') {
|
|
return new Response('not allowed', { status: 400 })
|
|
}
|
|
|
|
const payload = await req.text()
|
|
const headers = Object.fromEntries(req.headers)
|
|
const wh = new Webhook(hookSecret)
|
|
try {
|
|
const {
|
|
user,
|
|
email_data: { token, token_hash, redirect_to, email_action_type },
|
|
} = wh.verify(payload, headers) as {
|
|
user: {
|
|
email: string
|
|
}
|
|
email_data: {
|
|
token: string
|
|
token_hash: string
|
|
redirect_to: string
|
|
email_action_type: string
|
|
site_url: string
|
|
token_new: string
|
|
token_hash_new: string
|
|
}
|
|
}
|
|
|
|
const html = await renderAsync(
|
|
React.createElement(MagicLinkEmail, {
|
|
supabase_url: Deno.env.get('SUPABASE_URL') ?? '',
|
|
token,
|
|
token_hash,
|
|
redirect_to,
|
|
email_action_type,
|
|
})
|
|
)
|
|
|
|
const { error } = await resend.emails.send({
|
|
from: 'welcome <onboarding@resend.dev>',
|
|
to: [user.email],
|
|
subject: 'Supa Custom MagicLink!',
|
|
html,
|
|
})
|
|
if (error) {
|
|
throw error
|
|
}
|
|
} catch (error) {
|
|
console.log(error)
|
|
return new Response(
|
|
JSON.stringify({
|
|
error: {
|
|
http_code: error.code,
|
|
message: error.message,
|
|
},
|
|
}),
|
|
{
|
|
status: 401,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
}
|
|
)
|
|
}
|
|
|
|
const responseHeaders = new Headers()
|
|
responseHeaders.set('Content-Type', 'application/json')
|
|
return new Response(JSON.stringify({}), {
|
|
status: 200,
|
|
headers: responseHeaders,
|
|
})
|
|
})
|
|
|
|
/* To invoke locally:
|
|
|
|
1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start)
|
|
2. Make an HTTP request:
|
|
|
|
curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/send-email' \
|
|
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
|
|
--header 'Content-Type: application/json' \
|
|
--data '{"name":"Functions"}'
|
|
|
|
*/
|