mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 18:05:11 +03:00
62 files changed
+311
-167
No files matched your search
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code.
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v3
|
||||
- name: misspell
|
||||
uses: reviewdog/action-misspell@v1
|
||||
with:
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Run prettier
|
||||
run: |-
|
||||
npx prettier -c 'apps/**/*.{js,jsx,ts,tsx,css,md,json}'
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Run prettier
|
||||
run: |-
|
||||
npx prettier -c 'i18n/**/*.{js,jsx,ts,tsx,css,md,json}'
|
||||
|
||||
@@ -18,9 +18,9 @@ jobs:
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
@@ -24,9 +24,9 @@ jobs:
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
@@ -43,6 +43,12 @@ Supabase supports a suite of social providers. Follow these guides to configure
|
||||
))}
|
||||
|
||||
</div>
|
||||
|
||||
## Provider Tokens
|
||||
|
||||
Once the OAuth flow completes, Supabase Auth will sign your user in. You will receive a copy of the provider token used in the OAuth flow in case you need to use it further. For example, you can use the Google provider token to access Google APIs on behalf of your user.
|
||||
|
||||
Provider tokens are intentionally not stored in your project's database, however. This is because provider tokens give access to potentially sensitive user data in third-party systems. Different applications have different needs, and one application's OAuth scopes may be significantly more permissive than another. If you do want to use the provider token outside of the browser that completed the OAuth flow, you will have to send it manually to a secure server under your control.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ serve(async (_req) => {
|
||||
|
||||
```bash
|
||||
supabase start
|
||||
supabase functions serve upstash-redis-counter --no-verify-jwt --env-file supabase/functions/upstash-redis-counter/.env
|
||||
supabase functions serve --no-verify-jwt --env-file supabase/functions/upstash-redis-counter/.env
|
||||
```
|
||||
|
||||
Navigate to http://localhost:54321/functions/v1/upstash-redis-counter.
|
||||
|
||||
@@ -10,7 +10,7 @@ You can run your Edge Function locally using [`supabase functions serve`](/docs/
|
||||
|
||||
```bash
|
||||
supabase start # start the supabase stack
|
||||
supabase functions serve hello-world # start the Function watcher
|
||||
supabase functions serve # start the Functions watcher
|
||||
```
|
||||
|
||||
The `functions serve` command has hot-reloading capabilities. It will watch for any changes to your files and restart the Deno server.
|
||||
@@ -20,7 +20,7 @@ The `functions serve` command has hot-reloading capabilities. It will watch for
|
||||
While serving your local Edge Function, you can invoke it using curl:
|
||||
|
||||
```bash
|
||||
curl --request POST 'http://localhost:54321/functions/v1/hello-world' \
|
||||
curl --request POST 'http://localhost:54321/functions/v1/function-name' \
|
||||
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{ "name":"Functions" }'
|
||||
@@ -37,7 +37,7 @@ const supabase = createClient(
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0'
|
||||
)
|
||||
|
||||
const { data, error } = await supabase.functions.invoke('hello-world', {
|
||||
const { data, error } = await supabase.functions.invoke('function-name', {
|
||||
body: { name: 'Functions' },
|
||||
})
|
||||
```
|
||||
|
||||
@@ -46,7 +46,7 @@ console.log(Deno.env.get('MY_NAME'))
|
||||
Now we can invoke our function locally, by serving it with our new `.env.local` file:
|
||||
|
||||
```bash
|
||||
supabase functions serve hello-world --env-file ./supabase/.env.local
|
||||
supabase functions serve --env-file ./supabase/.env.local
|
||||
```
|
||||
|
||||
When the function starts you should see the name “Yoda” output to the terminal.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: HappyTeams unlocks better performance and reduces cost with Supabase
|
||||
description: How a bootstrapped startup migrated from Heroku to Supabase in 30 minutes and never looked back
|
||||
author: rory_wilding
|
||||
image: 2023-02-16-case-study-happyteams/case-study-happyteams.png
|
||||
thumb: 2023-02-16-case-study-happyteams/case-study-happyteams.png
|
||||
tags:
|
||||
- case-study
|
||||
date: '2023-02-16'
|
||||
toc_depth: 3
|
||||
---
|
||||
|
||||
## The Challenge
|
||||
|
||||
> Finding a painless and hands-free database experience to support growth
|
||||
|
||||
[HappyTeams](https://happyteams.io/) is a growing startup with an ambitious vision. The company is bootstrapped, so technical resources are scarce. Devs need to do more with less. This means staying laser-focused on delivering features, rather than database timeouts or performance issues.
|
||||
|
||||
The company launched its app on Heroku Postgres. But one year in, they were experiencing scaling issues. They needed to handle thousands of users while also shipping new features and building out integrations. Issues with database slowness and concurrent connections were holding them back.
|
||||
|
||||
Michael Dever, the founder and CTO of HappyTeams, realized it was time for a change. A large overhaul of the app in early 2022 presented the opportunity to do so: "When you're in that first sprint of building a product, you're kind of locked with that first database decision you make. When we did a rebuild, it was time to look at something like Supabase."
|
||||
|
||||

|
||||
|
||||
## Why Supabase?
|
||||
|
||||
There were four main factors that led HappyTeams to switch from Heroku Postgres to Supabase:
|
||||
|
||||
1. **Better performance**. The team was experiencing uneven performance with Heroku, which was sluggish at times. Supabase was consistently fast.
|
||||
|
||||
2. **Enabling a large number of direct connections and connection pooling with PgBouncer**. HappyTeams was constantly hitting limits on the number of database connections. They could solve this problem with Supabase's [flexible plans](https://supabase.com/pricing) and [support for PgBouncer](https://supabase.com/blog/supabase-pgbouncer).
|
||||
|
||||
3. **Quality of support, documentation, and onboarding**: While Heroku provided no support at the tier they were on, the Supabase team was readily available: "Responses were powerful and they answered all my questions, even on a Sunday. That just further sold the product for me." He was also impressed with the [documentation](https://supabase.com/docs) on the Supabase website and the onboarding process.
|
||||
|
||||
4. **Lower costs**. Moving to Supabase reduced HappyTeams's costs: The base plan comes with everything they need to scale the product.
|
||||
|
||||
<Quote img="michael-dever-happyteams.jpeg" caption="Michael Dever - CTO of HappyTeams">
|
||||
Great documentation, great product, great pricing. It sells itself, really.
|
||||
</Quote>
|
||||
|
||||
## Supabase provides a fast and reliable production database
|
||||
|
||||
After a 30 minute migration, HappyTeams can iterate quickly, add new features, and improve their product based on customer feedback
|
||||
|
||||
Once they made the decision, migrating from Heroku to Supabase was simple. HappyTeams completed their database migration in less than an hour using pg_dump and pg_restore.
|
||||
|
||||
Performance is no longer an issue. "Supabase just worked", says Michael. Pooling connections using PgBouncer was effortless - solving a recurring pain point for HappyTeams.
|
||||
|
||||
"Supabase is so fast. Way, way, way faster than our Heroku Postgres database, which I think was located in the same region."
|
||||
|
||||
Today, Supabase is an integral part of HappyTeams's tech stack. It has allowed the company to move fast and rapidly release new features - with minimal tech resources devoted to their backend infrastructure.
|
||||
|
||||
Thanks to Supabase's ease of use and reliability, HappyTeams can iterate quickly based on feature requests and deliver more value to their user base. They are planning to expand their usage, exploring functionality such as [Edge Functions](https://supabase.com/edge-functions) and the [API client](https://supabase.com/docs/guides/api).
|
||||
|
||||
<Quote img="michael-dever-happyteams.jpeg" caption="Michael Dever - CTO of HappyTeams">
|
||||
When we needed to add a comments feature to our app, we could get it done in just two days.
|
||||
Supabase is really like a dream come true for a developer.
|
||||
</Quote>
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 712 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 529 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@@ -5,9 +5,16 @@
|
||||
<link>https://supabase.com</link>
|
||||
<description>Latest news from Supabase</description>
|
||||
<language>en</language>
|
||||
<lastBuildDate>Mon, 13 Feb 2023 16:04:00 +0000</lastBuildDate>
|
||||
<lastBuildDate>Wed, 15 Feb 2023 16:04:00 +0000</lastBuildDate>
|
||||
<atom:link href="https://supabase.com/rss.xml" rel="self" type="application/rss+xml"/>
|
||||
<item>
|
||||
<guid>https://supabase.com/blog/case-study-happyteams</guid>
|
||||
<title>HappyTeams unlocks better performance and reduces cost with Supabase</title>
|
||||
<link>https://supabase.com/blog/case-study-happyteams</link>
|
||||
<description>How a bootstrapped startup migrated from Heroku to Supabase in 30 minutes and never looked back</description>
|
||||
<pubDate>Wed, 15 Feb 2023 16:04:00 +0000</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<guid>https://supabase.com/blog/flutter-real-time-multiplayer-game</guid>
|
||||
<title>How to build a real-time multiplayer game with Flutter Flame</title>
|
||||
<link>https://supabase.com/blog/flutter-real-time-multiplayer-game</link>
|
||||
|
||||
@@ -2,3 +2,4 @@ volumes/db/data
|
||||
volumes/storage
|
||||
.env
|
||||
test.http
|
||||
docker-compose.override.yml
|
||||
@@ -6,23 +6,17 @@
|
||||
|
||||
## Example Functions
|
||||
|
||||
The function examples are located in [`./supabase/functions`](./supabase/functions):
|
||||
|
||||
- [`browser-with-cors`](./supabase/functions/browser-with-cors/index.ts): Handle CORS headers for function invocations from browser environments.
|
||||
- [`select-from-table-with-auth-rls`](./supabase/functions/select-from-table-with-auth-rls/index.ts): Retrieve data from an authenticated user via RLS.
|
||||
- [`send-email-smtp`](./supabase/functions/send-email-smtp/index.ts): Send an email using SMTP credentials.
|
||||
- [`stripe-webhooks`](./supabase/functions/stripe-webhooks/index.ts): Handle Stripe Webhooks.
|
||||
- [`telegram-bot`](./supabase/functions/telegram-bot/index.ts): Webhook handler for Telegram bots using [grammY](https://grammy.dev/).
|
||||
We're constantly adding new Function Examples, [check our docs](https://supabase.com/docs/guides/functions#examples) for a complete list!
|
||||
|
||||
## Develop locally
|
||||
|
||||
- Run `supabase start` (make sure your Docker daemon is running.)
|
||||
- Run `mv ./supabase/.env.local.example ./supabase/.env.local` to rename the local `.env` file.
|
||||
- Set the required variables to run the desired edge functions in the `.env.local` file.
|
||||
- Run `supabase functions serve your-function-name --env-file ./supabase/.env.local`
|
||||
- Run `cp ./supabase/.env.local.example ./supabase/.env.local` to create your local `.env` file.
|
||||
- Set the required variables for the corresponding edge functions in the `.env.local` file.
|
||||
- Run `supabase functions serve --env-file ./supabase/.env.local --no-verify-jwt`
|
||||
- Run the CURL command in the example function, or use the [invoke method](https://supabase.com/docs/reference/javascript/invoke) on the Supabase client or use the test client [app](./app/).
|
||||
|
||||
## Test
|
||||
## Test Client
|
||||
|
||||
This example includes a create-react-app in the [`./app/`](./app/) directory which you can use as a sort of postman to make test requests both locally and to your deployed functions.
|
||||
|
||||
@@ -45,10 +39,13 @@ Note: when testing locally, the select dropdown doesn't have any effect, and inv
|
||||
- Link your project
|
||||
- Within your project root run `supabase link --project-ref your-project-ref`
|
||||
- Set up your secrets
|
||||
|
||||
- Run `supabase secrets set --env-file ./supabase/.env.local` to set the environment variables.
|
||||
|
||||
|
||||
(This is assuming your local and production secrets are the same. The recommended way is to create a separate `.env` file for storing production secrets, and then use it to set the environment variables while deploying.)
|
||||
|
||||
- You can run `supabase secrets list` to check that it worked and also to see what other env vars are set by default.
|
||||
|
||||
- Deploy the function
|
||||
- Within your project root run `supabase functions deploy your-function-name`
|
||||
- In your [`./app/.env`](./app/.env) file remove the `SUPA_FUNCTION_LOCALHOST` variable and restart your Expo app.
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"node_modules/": true,
|
||||
"app/": true,
|
||||
"supabase/functions/": true
|
||||
}
|
||||
},
|
||||
"deno.importMap": "./supabase/functions/import_map.json"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,21 @@
|
||||
# cloudflare-turnstile
|
||||
CLOUDFLARE_TURNSTILE_SECRET_KEY=your_secret_key
|
||||
|
||||
# discord-bot
|
||||
DISCORD_PUBLIC_KEY=
|
||||
|
||||
# location
|
||||
IPINFO_TOKEN="your https://ipinfo.io token"
|
||||
|
||||
# openai
|
||||
OPENAI_API_KEY="<YOUR API KEY HERE>"
|
||||
|
||||
# postgres-on-the-edge
|
||||
DATABASE_URL=
|
||||
|
||||
# puppeteer
|
||||
PUPPETEER_BROWSERLESS_IO_TOKEN=
|
||||
|
||||
# send-email-smtp
|
||||
SMTP_HOSTNAME="your.hostname.com"
|
||||
SMTP_PORT="2587"
|
||||
@@ -5,13 +23,14 @@ SMTP_USERNAME="your_username"
|
||||
SMTP_PASSWORD="your_password"
|
||||
SMTP_FROM="no-reply@example.com"
|
||||
|
||||
# telegram-bot
|
||||
TELEGRAM_BOT_TOKEN="get it from https://t.me/BotFather"
|
||||
FUNCTION_SECRET="random secret"
|
||||
|
||||
# stripe-webhooks
|
||||
STRIPE_API_KEY="<YOUR API KEY HERE>"
|
||||
STRIPE_WEBHOOK_SIGNING_SECRET="<YOUR WEBHOOK SIGNING HERE>"
|
||||
|
||||
# openai
|
||||
OPENAI_API_KEY="<YOUR API KEY HERE>"
|
||||
# telegram-bot
|
||||
TELEGRAM_BOT_TOKEN="get it from https://t.me/BotFather"
|
||||
FUNCTION_SECRET="random secret"
|
||||
|
||||
# upstash-redis-counter
|
||||
UPSTASH_REDIS_REST_URL=
|
||||
UPSTASH_REDIS_REST_TOKEN=
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"deno.enable": true,
|
||||
"deno.lint": true,
|
||||
"deno.unstable": true
|
||||
"deno.unstable": true,
|
||||
"deno.importMap": "./import_map.json"
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import { serve } from 'std/server'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
console.log(`Function "browser-with-cors" up and running!`)
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
Turnstile is Cloudflare's CAPTCHA alternative: https://developers.cloudflare.com/turnstile/get-started/
|
||||
|
||||
## Watch the Video Tutorial
|
||||
|
||||
[](https://www.youtube.com/watch?v=OwW0znboh60)
|
||||
|
||||
## Setup
|
||||
|
||||
- Follow these steps to set up a new site: https://developers.cloudflare.com/turnstile/get-started/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import { serve } from 'std/server'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
console.log(`Function "cloudflare-turnstile" up and running!`)
|
||||
@@ -55,7 +55,7 @@ serve(async (req) => {
|
||||
})
|
||||
|
||||
// To invoke:
|
||||
// curl -i --location --request POST 'http://localhost:54321/functions/v1/' \
|
||||
// curl -i --location --request POST 'http://localhost:54321/functions/v1/cloudflare-turnstile' \
|
||||
// --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
|
||||
// --header 'Content-Type: application/json' \
|
||||
// --data '{"token":"cf-turnstile-response"}'
|
||||
@@ -5,6 +5,10 @@
|
||||
- https://deno.com/deploy/docs/tutorial-discord-slash
|
||||
- https://discord.com/developers/docs/interactions/application-commands#slash-commands
|
||||
|
||||
## Watch the Video Tutorial
|
||||
|
||||
[](https://www.youtube.com/watch?v=J24Bvo_m7DM)
|
||||
|
||||
## Create an application on Discord Developer Portal
|
||||
|
||||
1. Go to [https://discord.com/developers/applications](https://discord.com/developers/applications) (login using your discord account if required).
|
||||
@@ -59,6 +63,6 @@ Open Discord, type `/Promise` and press **Enter**.
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
supabase functions serve discord-bot --no-verify-jwt --env-file ./supabase/functions/discord-bot/.env
|
||||
supabase functions serve discord-bot --no-verify-jwt --env-file ./supabase/.env.local
|
||||
ngrok http 54321
|
||||
```
|
||||
@@ -5,10 +5,10 @@
|
||||
// Sift is a small routing library that abstracts away details like starting a
|
||||
// listener on a port, and provides a simple function (serve) that has an API
|
||||
// to invoke a function for a specific path.
|
||||
import { json, serve, validateRequest } from 'https://deno.land/x/sift@0.6.0/mod.ts'
|
||||
import { json, serve, validateRequest } from 'sift'
|
||||
// TweetNaCl is a cryptography library that we use to verify requests
|
||||
// from Discord.
|
||||
import nacl from 'https://cdn.skypack.dev/tweetnacl@v1.0.3?dts'
|
||||
import nacl from 'nacl'
|
||||
|
||||
enum DiscordCommandType {
|
||||
Ping = 1,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// This example shows how to use Edge Functions to read incoming multipart/form-data request,
|
||||
// and write files to Supabase Storage and other fields to a database table.
|
||||
|
||||
import { Application, Router } from 'https://deno.land/x/oak/mod.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
import { Application } from 'oak'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const MB = 1024 * 1024
|
||||
|
||||
@@ -25,9 +25,9 @@ app.use(async (ctx) => {
|
||||
|
||||
const supabaseClient = createClient(
|
||||
// Supabase API URL - env var exported by default.
|
||||
Deno.env.get('SUPABASE_URL') ?? '',
|
||||
Deno.env.get('SUPABASE_URL')!,
|
||||
// Supabase API ANON KEY - env var exported by default.
|
||||
Deno.env.get('SUPABASE_ANON_KEY') ?? ''
|
||||
Deno.env.get('SUPABASE_ANON_KEY')!
|
||||
)
|
||||
|
||||
//upload image to Storage
|
||||
|
||||
@@ -15,9 +15,11 @@ Good luck trying to GET a T-Shirt!
|
||||
### Serve this function locally
|
||||
|
||||
```bash
|
||||
supabase functions serve --no-verify-jwt get-tshirt-competition
|
||||
supabase functions serve --no-verify-jwt
|
||||
```
|
||||
|
||||
Navigate to http://localhost:54321/functions/v1/get-tshirt-competition?email=testr@test.de&twitter=thorwebdev&size=2XL&answer=20
|
||||
|
||||
### Deploy this function
|
||||
|
||||
```bash
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
import { serve } from 'std/server'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
console.log(`Function "get-tshirt-competition" up and running!`)
|
||||
|
||||
@@ -2,23 +2,18 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from "https://deno.land/std@0.131.0/http/server.ts";
|
||||
import { serve } from 'std/server'
|
||||
|
||||
console.log("Hello from Functions!");
|
||||
console.log('Hello from Functions!')
|
||||
|
||||
serve(async (req) => {
|
||||
const { name } = await req.json();
|
||||
serve((_req) => {
|
||||
const data = {
|
||||
message: `I was deployed via GitHub Actions!`,
|
||||
};
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify(data), {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
});
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
})
|
||||
|
||||
// To invoke:
|
||||
// curl -i --location --request POST 'http://localhost:54321/functions/v1/' \
|
||||
// --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs' \
|
||||
// --header 'Content-Type: application/json' \
|
||||
// --data '{"name":"Functions"}'
|
||||
// To invoke: http://localhost:54321/functions/v1/github-action-deploy
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"imports": {
|
||||
"denomailer": "https://deno.land/x/denomailer@0.12.0/mod.ts",
|
||||
"nacl": "https://cdn.skypack.dev/tweetnacl@v1.0.3?dts",
|
||||
"oak": "https://deno.land/x/oak@v11.1.0/mod.ts",
|
||||
"og_edge": "https://deno.land/x/og_edge@0.0.4/mod.ts",
|
||||
"openai": "https://esm.sh/openai@3.1.0",
|
||||
"grammy": "https://deno.land/x/grammy@v1.8.3/mod.ts",
|
||||
"react": "https://esm.sh/react@18.2.0",
|
||||
"std/server": "https://deno.land/std@0.177.0/http/server.ts",
|
||||
"stripe": "https://esm.sh/stripe@11.1.0?target=deno",
|
||||
"sift": "https://deno.land/x/sift@0.6.0/mod.ts",
|
||||
"@supabase/supabase-js": "https://esm.sh/@supabase/supabase-js@2.7.1",
|
||||
"postgres": "https://deno.land/x/postgres@v0.14.2/mod.ts",
|
||||
"puppeteer": "https://deno.land/x/puppeteer@16.2.0/mod.ts",
|
||||
"React": "https://esm.sh/react@18.2.0?deno-std=0.177.0",
|
||||
"upstash_redis": "https://deno.land/x/upstash_redis@v1.19.3/mod.ts",
|
||||
"xhr_polyfill": "https://deno.land/x/xhr@0.3.0/mod.ts"
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,14 @@ This example shows how you can get user location based on the IP provided in X-F
|
||||
|
||||
You will need to signup for an account in https://ipinfo.io and provide it as `IPINFO_TOKEN` environment variable ([learn how to set environment variables to your functions](https://supabase.com/docs/guides/functions#secrets-and-environment-variables)).
|
||||
|
||||
## Develop locally
|
||||
|
||||
```bash
|
||||
supabase functions serve --env-file ./supabase/.env.local --no-verify-jwt
|
||||
```
|
||||
|
||||
Navigate to http://localhost:54321/functions/v1/location
|
||||
|
||||
## Deploy
|
||||
|
||||
```bash
|
||||
|
||||
@@ -2,20 +2,29 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from "https://deno.land/std@0.131.0/http/server.ts"
|
||||
import { serve } from 'std/server'
|
||||
|
||||
function ips(req: Request) {
|
||||
return req.headers.get("x-forwarded-for")?.split(/\s*,\s*/);
|
||||
return req.headers.get('x-forwarded-for')?.split(/\s*,\s*/)
|
||||
}
|
||||
|
||||
serve(async (req) => {
|
||||
const clientIps = ips(req) || [''];
|
||||
const res = await fetch(`https://ipinfo.io/${clientIps[0]}?token=${Deno.env.get('IPINFO_TOKEN')}`, {
|
||||
headers: { 'Content-Type': 'application/json'}});
|
||||
const { city, country } = await res.json();
|
||||
|
||||
return new Response(
|
||||
JSON.stringify(`You're accessing from ${city}, ${country}`),
|
||||
{ headers: { "Content-Type": "application/json" } },
|
||||
const clientIps = ips(req) || ['']
|
||||
const res = await fetch(
|
||||
`https://ipinfo.io/${clientIps[0]}?token=${Deno.env.get('IPINFO_TOKEN')}`,
|
||||
{
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
}
|
||||
)
|
||||
if (res.ok) {
|
||||
const { city, country } = await res.json()
|
||||
|
||||
return new Response(JSON.stringify(`You're accessing from ${city}, ${country}`), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
} else {
|
||||
return new Response(await res.text(), {
|
||||
status: 400,
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -5,7 +5,7 @@ This example shows how you can write functions using Oak server middleware (http
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
supabase functions serve oak-server
|
||||
supabase functions serve --no-verify-jwt
|
||||
```
|
||||
|
||||
Use cURL or Postman to make a POST request to http://localhost:54321/functions/v1/oak-server.
|
||||
@@ -20,5 +20,5 @@ Use cURL or Postman to make a POST request to http://localhost:54321/functions/v
|
||||
## Deploy
|
||||
|
||||
```bash
|
||||
supabase functions deploy oak-server
|
||||
supabase functions deploy oak-server --no-verify-jwt
|
||||
```
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Application, Router } from 'https://deno.land/x/oak/mod.ts'
|
||||
import { Application, Router } from 'oak'
|
||||
|
||||
const router = new Router()
|
||||
router
|
||||
|
||||
@@ -9,7 +9,7 @@ Generate Open Graph images with Deno and Supabase Edge Functions and cache the g
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
supabase functions serve og-image-with-storage-cdn --no-verify-jwt
|
||||
supabase functions serve --no-verify-jwt
|
||||
```
|
||||
|
||||
Navigate to http://localhost:54321/functions/v1/og-image-with-storage-cdn?ticketNumber=3524&username=thorwebdev&name=Thor%20%E9%9B%B7%E7%A5%9E%20Schaeff
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0'
|
||||
import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
import React from 'React'
|
||||
import { ImageResponse } from 'og_edge'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
const STORAGE_URL = 'https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/lw6'
|
||||
@@ -213,7 +213,7 @@ export async function handler(req: Request) {
|
||||
})
|
||||
if (error) throw error
|
||||
|
||||
return generatedImage
|
||||
return await fetch(`${STORAGE_URL}/tickets/${username}.png?v=3`)
|
||||
} catch (error) {
|
||||
return new Response(JSON.stringify({ error: error.message }), {
|
||||
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.140.0/http/server.ts'
|
||||
import { serve } from 'std/server'
|
||||
|
||||
import { handler } from './handler.tsx'
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ cp supabase/.env.local.example supabase/.env.local
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
supabase functions serve --no-verify-jwt --env-file ./supabase/.env.local openai
|
||||
supabase functions serve --env-file ./supabase/.env.local --no-verify-jwt
|
||||
```
|
||||
|
||||
Use cURL or Postman to make a POST request to http://localhost:54321/functions/v1/openai.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'https://deno.land/x/xhr@0.3.0/mod.ts'
|
||||
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
||||
import { CreateCompletionRequest } from 'https://esm.sh/openai@3.1.0'
|
||||
import 'xhr_polyfill'
|
||||
import { serve } from 'std/server'
|
||||
import { CreateCompletionRequest } from 'openai'
|
||||
|
||||
serve(async (req) => {
|
||||
const { query } = await req.json()
|
||||
|
||||
@@ -8,7 +8,7 @@ Generate Open Graph images with Deno and Supabase Edge Functions, no framework n
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
supabase functions serve opengraph --no-verify-jwt
|
||||
supabase functions serve --no-verify-jwt
|
||||
```
|
||||
|
||||
Navigate to http://localhost:54321/functions/v1/opengraph
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0'
|
||||
import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts'
|
||||
import React from 'React'
|
||||
import { ImageResponse } from 'og_edge'
|
||||
|
||||
export function handler(req: Request) {
|
||||
return new ImageResponse(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.140.0/http/server.ts'
|
||||
import { serve } from 'std/server'
|
||||
|
||||
import { handler } from './handler.tsx'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as postgres from 'https://deno.land/x/postgres@v0.14.2/mod.ts'
|
||||
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
||||
import * as postgres from 'postgres'
|
||||
import { serve } from 'std/server'
|
||||
|
||||
// Get the connection string from the environment variable "DATABASE_URL"
|
||||
const databaseUrl = Deno.env.get('DATABASE_URL')!
|
||||
|
||||
@@ -4,6 +4,14 @@ This example shows how you can use Puppeteer and a headless-browser to generate
|
||||
|
||||
Since Edge Functions cannot run a Headless Browser instance due to resource constraints, you will need to use a hosted browser service like https://browserless.io.
|
||||
|
||||
## Develop locally
|
||||
|
||||
```bash
|
||||
supabase functions serve --env-file ./supabase/.env.local --no-verify-jwt
|
||||
```
|
||||
|
||||
Navigate to http://localhost:54321/functions/v1/puppeteer
|
||||
|
||||
## Deploy
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import puppeteer from 'https://deno.land/x/puppeteer@16.2.0/mod.ts'
|
||||
import { serve } from 'std/server'
|
||||
import puppeteer from 'puppeteer'
|
||||
|
||||
serve(async (req) => {
|
||||
try {
|
||||
console.log(`wss://chrome.browserless.io?token=${Deno.env.get('PUPPETEER_BROWSERLESS_IO_KEY')}`)
|
||||
// Visit browserless.io to get your free API token
|
||||
const browser = await puppeteer.connect({
|
||||
browserWSEndpoint: 'wss://chrome.browserless.io?token=YOUR_API_TOKEN',
|
||||
browserWSEndpoint: `wss://chrome.browserless.io?token=${Deno.env.get(
|
||||
'PUPPETEER_BROWSERLESS_IO_KEY'
|
||||
)}`,
|
||||
})
|
||||
const page = await browser.newPage()
|
||||
|
||||
@@ -17,7 +20,7 @@ serve(async (req) => {
|
||||
return new Response(screenshot, { headers: { 'Content-Type': 'image/png' } })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return new Response(JSON.stringify(`Error occurred when generating the screenshot`), {
|
||||
return new Response(JSON.stringify({ error: e.message }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
status: 500,
|
||||
})
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
import { serve } from 'std/server'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import { createClient, SupabaseClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
import { serve } from 'std/server'
|
||||
import { createClient, SupabaseClient } from '@supabase/supabase-js'
|
||||
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
import { serve } from 'std/server'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
console.log(`Function "select-from-table-with-auth-rls" up and running!`)
|
||||
|
||||
@@ -13,4 +13,4 @@ Note: `SMTP_PORT` must be a port other than `25`, `465`, and `587` as Deno Deplo
|
||||
## Test locally
|
||||
|
||||
- `cp ./supabase/.env.local.example ./supabase/.env.local`
|
||||
- `supabase functions serve send-email-smtp --env-file ./supabase/.env.local`
|
||||
- `supabase functions serve --env-file ./supabase/.env.local`
|
||||
@@ -2,14 +2,14 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'
|
||||
import { SmtpClient } from 'https://deno.land/x/denomailer@0.12.0/mod.ts'
|
||||
import { serve } from 'std/server'
|
||||
import { SmtpClient } from 'denomailer'
|
||||
|
||||
const smtp = new SmtpClient()
|
||||
|
||||
console.log(`Function "send-email-smtp" up and running!`)
|
||||
|
||||
serve(async (req) => {
|
||||
serve(async (_req) => {
|
||||
await smtp.connect({
|
||||
hostname: Deno.env.get('SMTP_HOSTNAME')!,
|
||||
port: Number(Deno.env.get('SMTP_PORT')!),
|
||||
@@ -24,7 +24,7 @@ serve(async (req) => {
|
||||
subject: `Hello from Supabase Edge Functions`,
|
||||
content: `Hello Functions \o/`,
|
||||
})
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
return new Response(error.message, { status: 500 })
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ serve(async (req) => {
|
||||
})
|
||||
|
||||
// To invoke:
|
||||
// curl -i --location --request POST 'http://localhost:54321/functions/v1/' \
|
||||
// curl -i --location --request POST 'http://localhost:54321/functions/v1/send-email-smtp' \
|
||||
// --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs' \
|
||||
// --header 'Content-Type: application/json' \
|
||||
// --data '{"name":"Functions"}'
|
||||
@@ -3,7 +3,7 @@
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
supabase functions serve --no-verify-jwt streams
|
||||
supabase functions serve --no-verify-jwt
|
||||
```
|
||||
|
||||
Use cURL or Postman to make a GET request to http://localhost:54321/functions/v1/streams.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
||||
import { serve } from 'std/server'
|
||||
|
||||
const msg = new TextEncoder().encode('data: hello\r\n\r\n')
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Also check out our full Stripe Payments examples for [React Native (Expo)](https
|
||||
## Test locally
|
||||
|
||||
- Terminal 1:
|
||||
- `supabase functions serve --no-verify-jwt stripe-webhooks --env-file ./supabase/.env.local`
|
||||
- `supabase functions serve --no-verify-jwt --env-file ./supabase/.env.local`
|
||||
- Terminal 2:
|
||||
- `stripe listen --forward-to localhost:54321/functions/v1/`
|
||||
- Terminal 3 (optional):
|
||||
|
||||
@@ -2,20 +2,21 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.132.0/http/server.ts'
|
||||
import { serve } from 'std/server'
|
||||
|
||||
// esm.sh is used to compile stripe-node to be compatible with ES modules.
|
||||
import Stripe from 'https://esm.sh/stripe@10.13.0?target=deno&no-check&deno-std=0.132.0'
|
||||
// Import via bare specifier thanks to the import_map.json file.
|
||||
import Stripe from 'stripe'
|
||||
|
||||
const stripe = Stripe(Deno.env.get('STRIPE_API_KEY'), {
|
||||
const stripe = new Stripe(Deno.env.get('STRIPE_API_KEY') as string, {
|
||||
// This is needed to use the Fetch API rather than relying on the Node http
|
||||
// package.
|
||||
apiVersion: '2022-11-15',
|
||||
httpClient: Stripe.createFetchHttpClient(),
|
||||
})
|
||||
// This is needed in order to use the Web Crypto API in Deno.
|
||||
const cryptoProvider = Stripe.createSubtleCryptoProvider()
|
||||
|
||||
console.log(`Function "stripe-webhooks" up and running!`)
|
||||
console.log('Hello from Stripe Webhook!')
|
||||
|
||||
serve(async (request) => {
|
||||
const signature = request.headers.get('Stripe-Signature')
|
||||
@@ -27,8 +28,8 @@ serve(async (request) => {
|
||||
try {
|
||||
receivedEvent = await stripe.webhooks.constructEventAsync(
|
||||
body,
|
||||
signature,
|
||||
Deno.env.get('STRIPE_WEBHOOK_SIGNING_SECRET'),
|
||||
signature!,
|
||||
Deno.env.get('STRIPE_WEBHOOK_SIGNING_SECRET')!,
|
||||
undefined,
|
||||
cryptoProvider
|
||||
)
|
||||
@@ -36,25 +37,5 @@ serve(async (request) => {
|
||||
return new Response(err.message, { status: 400 })
|
||||
}
|
||||
console.log(`🔔 Event received: ${receivedEvent.id}`)
|
||||
|
||||
// Secondly, we use this event to query the Stripe API in order to avoid
|
||||
// handling any forged event. If available, we use the idempotency key.
|
||||
const requestOptions =
|
||||
receivedEvent.request && receivedEvent.request.idempotency_key
|
||||
? {
|
||||
idempotencyKey: receivedEvent.request.idempotency_key,
|
||||
}
|
||||
: {}
|
||||
|
||||
let retrievedEvent
|
||||
try {
|
||||
retrievedEvent = await stripe.events.retrieve(receivedEvent.id, requestOptions)
|
||||
} catch (err) {
|
||||
return new Response(err.message, { status: 400 })
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({ id: retrievedEvent.id, status: 'ok' }), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
return new Response(JSON.stringify({ ok: true }), { status: 200 })
|
||||
})
|
||||
@@ -2,34 +2,28 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from "https://deno.land/std@0.131.0/http/server.ts"
|
||||
import { serve } from 'std/server'
|
||||
|
||||
console.log(`Function "telegram-bot" up and running!`)
|
||||
|
||||
import { Bot, webhookCallback } from "https://deno.land/x/grammy@v1.8.3/mod.ts";
|
||||
import { Bot, webhookCallback } from 'grammy'
|
||||
|
||||
const bot = new Bot(Deno.env.get('TELEGRAM_BOT_TOKEN') || '');
|
||||
const bot = new Bot(Deno.env.get('TELEGRAM_BOT_TOKEN') || '')
|
||||
|
||||
bot.command("start", (ctx) => ctx.reply("Welcome! Up and running."));
|
||||
bot.command('start', (ctx) => ctx.reply('Welcome! Up and running.'))
|
||||
|
||||
bot.command('ping', (ctx) => ctx.reply(`Pong! ${new Date()} ${Date.now()}`))
|
||||
|
||||
const handleUpdate = webhookCallback(bot, "std/http");
|
||||
const handleUpdate = webhookCallback(bot, 'std/http')
|
||||
|
||||
serve(async (req) => {
|
||||
try {
|
||||
const url = new URL(req.url);
|
||||
if (url.searchParams.get('secret') !== Deno.env.get('FUNCTION_SECRET'))
|
||||
const url = new URL(req.url)
|
||||
if (url.searchParams.get('secret') !== Deno.env.get('FUNCTION_SECRET'))
|
||||
return new Response('not allowed', { status: 405 })
|
||||
|
||||
return await handleUpdate(req);
|
||||
return await handleUpdate(req)
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
|
||||
// To invoke:
|
||||
// curl -i --location --request POST 'http://localhost:54321/functions/v1/' \
|
||||
// --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs' \
|
||||
// --header 'Content-Type: application/json' \
|
||||
// --data '{"name":"Functions"}'
|
||||
@@ -1,2 +0,0 @@
|
||||
UPSTASH_REDIS_REST_URL=
|
||||
UPSTASH_REDIS_REST_TOKEN=
|
||||
@@ -9,7 +9,7 @@ Create a Redis database using the [Upstash Console](https://console.upstash.com/
|
||||
Select the `Global` type to minimize the latency from all edge locations. Copy the `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` to your .env file. You'll find them under **Details > REST API > .env**.
|
||||
|
||||
```bash
|
||||
cp supabase/functions/upstash-redis-counter/.env.example supabase/functions/upstash-redis-counter/.env
|
||||
cp supabase/.env.local.example supabase/.env.local
|
||||
```
|
||||
|
||||
## Run locally
|
||||
@@ -18,7 +18,7 @@ Make sure you have the latest version of the [Supabase CLI installed](https://su
|
||||
|
||||
```bash
|
||||
supabase start
|
||||
supabase functions serve upstash-redis-counter --no-verify-jwt --env-file supabase/functions/upstash-redis-counter/.env
|
||||
supabase functions serve --no-verify-jwt --env-file supabase/.env.local
|
||||
```
|
||||
|
||||
Navigate to http://localhost:54321/functions/v1/upstash-redis-counter.
|
||||
@@ -27,5 +27,5 @@ Navigate to http://localhost:54321/functions/v1/upstash-redis-counter.
|
||||
|
||||
```bash
|
||||
supabase functions deploy upstash-redis-counter --no-verify-jwt
|
||||
supabase secrets set --env-file supabase/functions/upstash-redis-counter/.env
|
||||
supabase secrets set --env-file supabase/.env.local
|
||||
```
|
||||
@@ -2,8 +2,8 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'https://deno.land/std@0.177.0/http/server.ts'
|
||||
import { Redis } from 'https://deno.land/x/upstash_redis@v1.19.3/mod.ts'
|
||||
import { serve } from 'std/server'
|
||||
import { Redis } from 'upstash_redis'
|
||||
|
||||
console.log(`Function "upstash-redis-counter" up and running!`)
|
||||
|
||||
|
||||
Generated
+1
-2
@@ -5,7 +5,6 @@
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "supabase",
|
||||
"version": "0.0.0",
|
||||
"license": "Apache-2.0",
|
||||
"workspaces": [
|
||||
@@ -46167,7 +46166,7 @@
|
||||
"@sinclair/typebox": "^0.25.1",
|
||||
"pg": "^8.7.1",
|
||||
"pg-format": "^1.0.4",
|
||||
"pgsql-parser": "13.4.0",
|
||||
"pgsql-parser": "^13.3.0",
|
||||
"postgres-array": "^3.0.1",
|
||||
"prettier": "^2.6.0",
|
||||
"prettier-plugin-sql": "^0.12.1"
|
||||
|
||||
@@ -380,12 +380,12 @@ commands:
|
||||
```
|
||||
- id: supabase-functions-serve
|
||||
title: supabase functions serve
|
||||
summary: Serve a Function locally
|
||||
summary: Serve Functions locally
|
||||
tags: []
|
||||
links: []
|
||||
usage: |-
|
||||
```sh
|
||||
supabase functions serve <Function name> [flags]
|
||||
supabase functions serve [flags]
|
||||
```
|
||||
subcommands: []
|
||||
options: |-
|
||||
|
||||
@@ -761,10 +761,10 @@ commands:
|
||||
flags: []
|
||||
- id: supabase-functions-serve
|
||||
title: supabase functions serve
|
||||
summary: Serve a Function locally
|
||||
summary: Serve all functions locally
|
||||
tags: []
|
||||
links: []
|
||||
usage: supabase functions serve <Function name> [flags]
|
||||
usage: supabase functions serve [flags]
|
||||
subcommands: []
|
||||
flags:
|
||||
- id: env-file
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
},
|
||||
{
|
||||
"id": "supabase-functions-serve",
|
||||
"title": "Serve a function",
|
||||
"title": "Serve functions locally",
|
||||
"slug": "supabase-functions-serve",
|
||||
"type": "cli-command"
|
||||
},
|
||||
|
||||
@@ -2258,6 +2258,9 @@ functions:
|
||||
```
|
||||
hideCodeBlock: true
|
||||
isSpotlight: true
|
||||
description: |
|
||||
When using [reserved words](https://www.postgresql.org/docs/current/sql-keywords-appendix.html) for column names you need
|
||||
to add double quotes e.g. `.gt('"order"', 2)`
|
||||
- id: gte
|
||||
title: gte()
|
||||
$ref: '@supabase/postgrest-js.PostgrestFilterBuilder.gte'
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import dayjs from 'dayjs'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { IconArrowRight } from 'ui'
|
||||
import { Badge, Button, IconArrowRight, IconExternalLink } from 'ui'
|
||||
|
||||
import { useParams, useStore } from 'hooks'
|
||||
import { TIME_PERIODS_INFRA, USAGE_APPROACHING_THRESHOLD } from 'lib/constants'
|
||||
import {
|
||||
PRICING_TIER_PRODUCT_IDS,
|
||||
TIME_PERIODS_INFRA,
|
||||
USAGE_APPROACHING_THRESHOLD,
|
||||
} from 'lib/constants'
|
||||
import { formatBytes } from 'lib/helpers'
|
||||
import { NextPageWithLayout } from 'types'
|
||||
|
||||
@@ -71,6 +75,10 @@ const DatabaseUsage: FC<any> = () => {
|
||||
const egressIsApproaching = databaseSizeUsageRatio >= USAGE_APPROACHING_THRESHOLD
|
||||
const egressIsExceeded = databaseSizeUsageRatio >= 1
|
||||
|
||||
const subscriptionTier = ui.selectedProject?.subscription_tier
|
||||
|
||||
const isPaidTier = subscriptionTier !== PRICING_TIER_PRODUCT_IDS.FREE
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
@@ -94,6 +102,25 @@ const DatabaseUsage: FC<any> = () => {
|
||||
labelTop={databaseSizeLimit > 0 ? formatBytes(databaseSizeLimit) : ''}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center mt-3">
|
||||
<div className="flex flex-row space-x-3 text-scale-1000 text-sm">
|
||||
{usage?.disk_volume_size_gb && (
|
||||
<span>Disk Size: {usage.disk_volume_size_gb} GB</span>
|
||||
)}
|
||||
|
||||
{isPaidTier && <Badge>Auto-Scaling</Badge>}
|
||||
</div>
|
||||
|
||||
<Button type="default" icon={<IconExternalLink size={14} strokeWidth={1.5} />}>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://supabase.com/docs/guides/platform/database-usage"
|
||||
>
|
||||
What is disk size?
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</Panel.Content>
|
||||
<Panel.Content>
|
||||
<div className="space-y-1">
|
||||
|
||||
Reference in new issue
Block a user