mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
Merge pull request #9493 from supabase/chore/functions-updates-2210122
Chore/functions updates 2210122
This commit is contained in:
6 files changed
+128
-49
No files matched your search
@@ -7,29 +7,6 @@ sidebar_label: Overview
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
import ButtonCard from '@site/src/components/ButtonCard'
|
||||
const examples = [
|
||||
{
|
||||
name: 'With supabase-js',
|
||||
description: 'Use the Supabase client inside your Edge Function.',
|
||||
href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts',
|
||||
},
|
||||
{
|
||||
name: 'With CORS headers',
|
||||
description: 'Send CORS headers for invoking from the browser.',
|
||||
href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/browser-with-cors/index.ts',
|
||||
},
|
||||
{
|
||||
name: 'React Native with Stripe',
|
||||
description: 'Full example for using Supabase and Stripe, with Expo.',
|
||||
href: 'https://github.com/supabase-community/expo-stripe-payments-with-supabase-functions',
|
||||
},
|
||||
{
|
||||
name: 'Flutter with Stripe',
|
||||
description: 'Full example for using Supabase and Stripe, with Flutter.',
|
||||
href: 'https://github.com/supabase-community/flutter-stripe-payments-with-supabase-functions',
|
||||
},
|
||||
]
|
||||
|
||||
Edge Functions are server-side TypeScript functions, distributed globally at the edge—close to your users. They can be used for listening to webhooks or integrating your Supabase project with third-parties [like Stripe](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/stripe-webhooks).
|
||||
|
||||
@@ -235,26 +212,6 @@ To see all the secrets which you have set remotely, use [`supabase secrets list`
|
||||
supabase secrets list
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
You can find a list of useful [Edge Function Examples](https://github.com/supabase/supabase/tree/master/examples/edge-functions) in our GitHub repository.
|
||||
|
||||
<div class="container" style={{ padding: 0 }}>
|
||||
<div class="row is-multiline">
|
||||
{examples.map((x) => (
|
||||
<div class="col col--6">
|
||||
<ButtonCard
|
||||
class="card"
|
||||
to={x.href}
|
||||
title={x.name}
|
||||
description={x.description}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Suggestions
|
||||
|
||||
### Database Functions vs Edge Functions
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
id: auth
|
||||
title: Auth
|
||||
description: Supabase Edge Functions and Auth.
|
||||
---
|
||||
|
||||
Edge Functions work seamlessly with [Supabase Auth](/docs/guides/auth), allowing you to identify which user called your function.
|
||||
|
||||
When [invoking](/docs/reference/javascript/invoke) a function with one of the [client libraries](/docs/reference), the logged in user's JWT is automatically attached to the function call and becomes accessible within your function.
|
||||
|
||||
This is important, for example, to identify which customer's credit card should be charged. You can see this concept end-to-end in our [Stripe example app](https://github.com/supabase-community/expo-stripe-payments-with-supabase-functions).
|
||||
|
||||
## Auth Context & RLS
|
||||
|
||||
By creating a supabase client with the auth context from the function, you can do two things:
|
||||
|
||||
1. Get the user object.
|
||||
2. Run queries in the context of the user with [Row Level Security (RLS)](http://localhost:3010/docs/guides/auth/row-level-security) policies enforced.
|
||||
|
||||
```js title="supabase/functions/select-from-table-with-auth-rls/index.ts"
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.0.0-rc.12'
|
||||
|
||||
serve(async (req: Request) => {
|
||||
try {
|
||||
// Create a Supabase client with the Auth context of the logged in user.
|
||||
const supabaseClient = createClient(
|
||||
// Supabase API URL - env var exported by default.
|
||||
Deno.env.get('SUPABASE_URL') ?? '',
|
||||
// Supabase API ANON KEY - env var exported by default.
|
||||
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
|
||||
// Create client with Auth context of the user that called the function.
|
||||
// This way your row-level-security (RLS) policies are applied.
|
||||
// highlight-next-line
|
||||
{ global: { headers: { Authorization: req.headers.get('Authorization')! } } }
|
||||
)
|
||||
// Now we can get the session or user object
|
||||
// highlight-start
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabaseClient.auth.getUser()
|
||||
// highlight-end
|
||||
|
||||
// And we can run queries in the context of our authenticated user
|
||||
// highlight-start
|
||||
const { data, error } = await supabaseClient.from('users').select('*')
|
||||
if (error) throw error
|
||||
// highlight-end
|
||||
|
||||
return new Response(JSON.stringify({ user, data }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
status: 200,
|
||||
})
|
||||
} catch (error) {
|
||||
return new Response(JSON.stringify({ error: error.message }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
status: 400,
|
||||
})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
See the [example on GitHub](https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts).
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
id: examples
|
||||
title: Examples
|
||||
description: Useful Supabase Edge Functions Examples.
|
||||
---
|
||||
|
||||
import ButtonCard from '@site/src/components/ButtonCard'
|
||||
const examples = [
|
||||
{
|
||||
name: 'With supabase-js',
|
||||
description: 'Use the Supabase client inside your Edge Function.',
|
||||
href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts',
|
||||
},
|
||||
{
|
||||
name: 'With CORS headers',
|
||||
description: 'Send CORS headers for invoking from the browser.',
|
||||
href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/browser-with-cors/index.ts',
|
||||
},
|
||||
{
|
||||
name: 'React Native with Stripe',
|
||||
description: 'Full example for using Supabase and Stripe, with Expo.',
|
||||
href: 'https://github.com/supabase-community/expo-stripe-payments-with-supabase-functions',
|
||||
},
|
||||
{
|
||||
name: 'Flutter with Stripe',
|
||||
description: 'Full example for using Supabase and Stripe, with Flutter.',
|
||||
href: 'https://github.com/supabase-community/flutter-stripe-payments-with-supabase-functions',
|
||||
},
|
||||
]
|
||||
|
||||
You can find a list of useful [Edge Function Examples](https://github.com/supabase/supabase/tree/master/examples/edge-functions) in our GitHub repository.
|
||||
|
||||
<div class="container" style={{ padding: 0 }}>
|
||||
<div class="row is-multiline">
|
||||
{examples.map((x) => (
|
||||
<div class="col col--6">
|
||||
<ButtonCard
|
||||
class="card"
|
||||
to={x.href}
|
||||
title={x.name}
|
||||
description={x.description}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,7 +156,12 @@ const sidebars = {
|
||||
type: 'category',
|
||||
label: 'Edge Functions',
|
||||
collapsed: true,
|
||||
items: ['guides/functions', 'guides/functions/cicd-workflow'],
|
||||
items: [
|
||||
'guides/functions',
|
||||
'guides/functions/auth',
|
||||
'guides/functions/examples',
|
||||
'guides/functions/cicd-workflow',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
To celebrate the support of GET requests in Supabase Edge Functions we're giving away some limited edition Functions Shirts!
|
||||
|
||||
To win a Supabase Edge Functions T-Shirt, make a GET request to https://obuldanrptloktxcffvn.functions.supabase.co/get-tshirt-competition with your email address, your Twitter handle (optional), and the correct answer, e.g.
|
||||
To win a Supabase Edge Functions T-Shirt, make a GET request to https://obuldanrptloktxcffvn.functions.supabase.co/get-tshirt-competition with your email address, your Twitter handle (optional), your t-shirt size (S-2XL) and the correct answer, e.g.
|
||||
|
||||
```text
|
||||
https://obuldanrptloktxcffvn.functions.supabase.co/get-tshirt-competition?email=testr@test.de&twitter=thorwebdev&answer=20
|
||||
https://obuldanrptloktxcffvn.functions.supabase.co/get-tshirt-competition?email=testr@test.de&twitter=thorwebdev&size=2XL&answer=20
|
||||
```
|
||||
|
||||
You can read the functions source code to figure out the answer ;)
|
||||
|
||||
@@ -27,11 +27,17 @@ serve(async (req) => {
|
||||
const url = new URL(req.url)
|
||||
const email = url.searchParams.get('email')
|
||||
const twitter = url.searchParams.get('twitter')
|
||||
const size = url.searchParams.get('size')
|
||||
const answer = url.searchParams.get('answer')
|
||||
|
||||
if (!/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email ?? '') || !answer)
|
||||
if (
|
||||
!/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email ?? '') ||
|
||||
!answer ||
|
||||
!twitter ||
|
||||
!size
|
||||
)
|
||||
throw new Error(
|
||||
`You're missing either a valid 'email' and/or 'answer' param(s). HINT: https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts`
|
||||
`Please provide valid 'email', 'twitter', 'size', and 'answer' params. HINT: https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts`
|
||||
)
|
||||
|
||||
if (Number(answer) !== positionInAlphabet(email!))
|
||||
@@ -50,6 +56,7 @@ serve(async (req) => {
|
||||
{
|
||||
email,
|
||||
twitter,
|
||||
size,
|
||||
},
|
||||
{ onConflict: 'email' }
|
||||
)
|
||||
@@ -71,4 +78,4 @@ serve(async (req) => {
|
||||
})
|
||||
|
||||
// To invoke:
|
||||
// curl -i --location --request GET 'http://localhost:54321/functions/v1/get-tshirt-competition?email=testr@test.de&answer=20'
|
||||
// curl -i --location --request GET 'http://localhost:54321/functions/v1/get-tshirt-competition?email=testr@test.de&twitter=thorwebdev&size=2XL&answer=20'
|
||||
Reference in new issue
Block a user