mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore: updated Edge Functions examples (#18742)
* Removed the use of deprecated std/http in favor of Deno.serve * Use full import paths instead of using paths from import maps (less confusing, easy to copy examples) * Formatted all examples with `deno fmt`
This commit is contained in:
1 parent
3ef54467d9
commit
67367d7f4e
30 files changed
+125
-131
No files matched your search
@@ -2,12 +2,11 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
console.log(`Function "browser-with-cors" up and running!`)
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
// This is needed if you're planning to invoke your function from a browser.
|
||||
if (req.method === 'OPTIONS') {
|
||||
return new Response('ok', { headers: corsHeaders })
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
console.log(`Function "cloudflare-turnstile" up and running!`)
|
||||
@@ -11,7 +10,7 @@ function ips(req: Request) {
|
||||
return req.headers.get('x-forwarded-for')?.split(/\s*,\s*/)
|
||||
}
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
// This is needed if you're planning to invoke your function from a browser.
|
||||
if (req.method === 'OPTIONS') {
|
||||
return new Response('ok', { headers: corsHeaders })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Application, Router } from 'https://deno.land/x/oak@v11.1.0/mod.ts'
|
||||
import { Session, CookieStore } from 'https://deno.land/x/oak_sessions@v4.1.9/mod.ts'
|
||||
import { CookieStore, Session } from 'https://deno.land/x/oak_sessions@v4.1.9/mod.ts'
|
||||
import { OAuth2Client } from 'https://deno.land/x/oauth2_client@v1.0.2/mod.ts'
|
||||
import { SupabaseManagementAPI } from 'https://esm.sh/supabase-management-js@0.1.2'
|
||||
|
||||
|
||||
@@ -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 'sift'
|
||||
import { json, serve, validateRequest } from 'https://deno.land/x/sift@0.6.0/mod.ts'
|
||||
// TweetNaCl is a cryptography library that we use to verify requests
|
||||
// from Discord.
|
||||
import nacl from 'nacl'
|
||||
import nacl from 'https://cdn.skypack.dev/tweetnacl@v1.0.3?dts'
|
||||
|
||||
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 } from 'oak'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Application } from 'https://deno.land/x/oak@v11.1.0/mod.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.7.1'
|
||||
|
||||
const MB = 1024 * 1024
|
||||
|
||||
@@ -49,9 +49,10 @@ app.use(async (ctx) => {
|
||||
}
|
||||
|
||||
// insert record to messages table
|
||||
const { error } = await supabaseClient
|
||||
.from('comments')
|
||||
.insert({ message: formData.fields!.message || '', image_path: upload.path })
|
||||
const { error } = await supabaseClient.from('comments').insert({
|
||||
message: formData.fields!.message || '',
|
||||
image_path: upload.path,
|
||||
})
|
||||
if (error) {
|
||||
console.error(error)
|
||||
ctx.response.status = 500
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.7.1'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
console.log(`Function "get-tshirt-competition" up and running!`)
|
||||
@@ -23,7 +22,7 @@ function turnEmailToCount(email: string): string {
|
||||
)}`
|
||||
}
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
// This is needed if you're planning to invoke your function from a browser.
|
||||
if (req.method === 'OPTIONS') {
|
||||
return new Response('ok', { headers: corsHeaders })
|
||||
@@ -41,15 +40,17 @@ serve(async (req) => {
|
||||
!answer ||
|
||||
!twitter ||
|
||||
!size
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
`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 (answer !== countEmailSegments(email!))
|
||||
if (answer !== countEmailSegments(email!)) {
|
||||
throw new Error(
|
||||
`Sorry, that's wrong, please try again! HINT: https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts`
|
||||
)
|
||||
}
|
||||
|
||||
const supabaseAdminClient = createClient(
|
||||
// Supabase API URL - env var exported by default when deployed.
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
|
||||
console.log('Hello from Functions!')
|
||||
|
||||
serve((_req) => {
|
||||
Deno.serve((_req) => {
|
||||
const data = {
|
||||
message: `I was deployed via GitHub Actions!`,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
||||
import { HfInference } from 'https://esm.sh/@huggingface/inference@2.3.2'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.7.1'
|
||||
import { Database } from './types.ts'
|
||||
|
||||
console.log('Hello from `huggingface-image-captioning` function!')
|
||||
@@ -16,7 +15,7 @@ interface WebhookPayload {
|
||||
old_record: null | SoRecord
|
||||
}
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
const payload: WebhookPayload = await req.json()
|
||||
const soRecord = payload.record
|
||||
const supabaseAdminClient = createClient<Database>(
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { Pool } from 'postgres'
|
||||
import {
|
||||
Kysely,
|
||||
Generated,
|
||||
Kysely,
|
||||
PostgresAdapter,
|
||||
PostgresIntrospector,
|
||||
PostgresQueryCompiler,
|
||||
@@ -59,7 +58,7 @@ const db = new Kysely<Database>({
|
||||
},
|
||||
})
|
||||
|
||||
serve(async (_req) => {
|
||||
Deno.serve(async (_req) => {
|
||||
try {
|
||||
// Run a query
|
||||
const animals = await db.selectFrom('animals').select(['id', 'animal', 'created_at']).execute()
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
|
||||
function ips(req: Request) {
|
||||
return req.headers.get('x-forwarded-for')?.split(/\s*,\s*/)
|
||||
}
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
const clientIps = ips(req) || ['']
|
||||
const res = await fetch(
|
||||
`https://ipinfo.io/${clientIps[0]}?token=${Deno.env.get('IPINFO_TOKEN')}`,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Application, Router } from 'oak'
|
||||
import { Application, Router } from 'https://deno.land/x/oak@v11.1.0/mod.ts'
|
||||
|
||||
const router = new Router()
|
||||
router
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'React'
|
||||
import { ImageResponse } from 'og_edge'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import React from 'https://esm.sh/react@18.2.0?deno-std=0.177.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.7.1'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
const STORAGE_URL = 'https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/lw6'
|
||||
@@ -20,11 +20,12 @@ export async function handler(req: Request) {
|
||||
const name = url.searchParams.get('name') ?? url.searchParams.get('amp;name')
|
||||
const golden = url.searchParams.get('golden') ?? url.searchParams.get('amp;golden')
|
||||
|
||||
if (!username || !ticketNumber || !name)
|
||||
if (!username || !ticketNumber || !name) {
|
||||
return new Response(JSON.stringify({ error: 'missing params' }), {
|
||||
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
|
||||
status: 400,
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
// Try to get image from Supabase Storage CDN.
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
|
||||
import { handler } from './handler.tsx'
|
||||
|
||||
console.log(`Function "og-image-with-storage-cdn" up and running!`)
|
||||
|
||||
serve(handler)
|
||||
Deno.serve(handler)
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'xhr_polyfill'
|
||||
import { serve } from 'std/server'
|
||||
import { CreateCompletionRequest } from 'openai'
|
||||
import 'https://deno.land/x/xhr@0.3.0/mod.ts'
|
||||
import { CreateCompletionRequest } from 'https://esm.sh/openai@3.1.0'
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
const { query } = await req.json()
|
||||
|
||||
const completionConfig: CreateCompletionRequest = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'React'
|
||||
import { ImageResponse } from 'og_edge'
|
||||
import React from 'https://esm.sh/react@18.2.0?deno-std=0.177.0'
|
||||
import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts'
|
||||
|
||||
export function handler(req: Request) {
|
||||
return new ImageResponse(
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
|
||||
import { handler } from './handler.tsx'
|
||||
|
||||
console.log(`Function "opengraph" up and running!`)
|
||||
|
||||
serve(handler)
|
||||
Deno.serve(handler)
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Pool } from 'postgres'
|
||||
import { serve } from 'std/server'
|
||||
import { Pool } from 'https://deno.land/x/postgres@v0.17.0/mod.ts'
|
||||
|
||||
// Create a database pool with one connection.
|
||||
const pool = new Pool(
|
||||
@@ -14,7 +13,7 @@ const pool = new Pool(
|
||||
1
|
||||
)
|
||||
|
||||
serve(async (_req) => {
|
||||
Deno.serve(async (_req) => {
|
||||
try {
|
||||
// Grab a connection from the pool
|
||||
const connection = await pool.connect()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { serve } from 'std/server'
|
||||
import puppeteer from 'puppeteer'
|
||||
import puppeteer from 'https://deno.land/x/puppeteer@16.2.0/mod.ts'
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.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
|
||||
@@ -17,7 +16,9 @@ serve(async (req) => {
|
||||
await page.goto(url)
|
||||
const screenshot = await page.screenshot()
|
||||
|
||||
return new Response(screenshot, { headers: { 'Content-Type': 'image/png' } })
|
||||
return new Response(screenshot, {
|
||||
headers: { 'Content-Type': 'image/png' },
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return new Response(JSON.stringify({ error: e.message }), {
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.7.1'
|
||||
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey',
|
||||
}
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
// read a text file from storage and print its contents
|
||||
// This is needed if you're planning to invoke your function from a browser.
|
||||
if (req.method === 'OPTIONS') {
|
||||
@@ -26,7 +25,11 @@ serve(async (req) => {
|
||||
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.
|
||||
{ global: { headers: { Authorization: req.headers.get('Authorization')! } } }
|
||||
{
|
||||
global: {
|
||||
headers: { Authorization: req.headers.get('Authorization')! },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const { data, error } = await supabaseClient.storage.from('my-bucket').download('sample.txt')
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { createClient, SupabaseClient } from '@supabase/supabase-js'
|
||||
import { createClient, SupabaseClient } from 'https://esm.sh/@supabase/supabase-js@2.7.1'
|
||||
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
@@ -65,7 +64,7 @@ async function createTask(supabaseClient: SupabaseClient, task: Task) {
|
||||
})
|
||||
}
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
const { url, method } = req
|
||||
|
||||
// This is needed if you're planning to invoke your function from a browser.
|
||||
@@ -82,7 +81,11 @@ serve(async (req) => {
|
||||
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.
|
||||
{ global: { headers: { Authorization: req.headers.get('Authorization')! } } }
|
||||
{
|
||||
global: {
|
||||
headers: { Authorization: req.headers.get('Authorization')! },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// For more details on URLPattern, check https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.7.1'
|
||||
import { corsHeaders } from '../_shared/cors.ts'
|
||||
|
||||
console.log(`Function "select-from-table-with-auth-rls" up and running!`)
|
||||
|
||||
serve(async (req: Request) => {
|
||||
Deno.serve(async (req: Request) => {
|
||||
// This is needed if you're planning to invoke your function from a browser.
|
||||
if (req.method === 'OPTIONS') {
|
||||
return new Response('ok', { headers: corsHeaders })
|
||||
@@ -23,7 +22,11 @@ serve(async (req: Request) => {
|
||||
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.
|
||||
{ global: { headers: { Authorization: req.headers.get('Authorization')! } } }
|
||||
{
|
||||
global: {
|
||||
headers: { Authorization: req.headers.get('Authorization')! },
|
||||
},
|
||||
}
|
||||
)
|
||||
// Now we can get the session or user object
|
||||
const {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
||||
|
||||
const RESEND_API_KEY = Deno.env.get('RESEND_API_KEY')
|
||||
|
||||
const handler = async (_request: Request): Promise<Response> => {
|
||||
@@ -27,4 +25,4 @@ const handler = async (_request: Request): Promise<Response> => {
|
||||
})
|
||||
}
|
||||
|
||||
serve(handler)
|
||||
Deno.serve(handler)
|
||||
@@ -2,14 +2,13 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { SmtpClient } from 'denomailer'
|
||||
import { SmtpClient } from 'https://deno.land/x/denomailer@0.12.0/mod.ts'
|
||||
|
||||
const smtp = new SmtpClient()
|
||||
|
||||
console.log(`Function "send-email-smtp" up and running!`)
|
||||
|
||||
serve(async (_req) => {
|
||||
Deno.serve(async (_req) => {
|
||||
await smtp.connect({
|
||||
hostname: Deno.env.get('SMTP_HOSTNAME')!,
|
||||
port: Number(Deno.env.get('SMTP_PORT')!),
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
import { serve } from 'https://deno.land/std@0.197.0/http/server.ts';
|
||||
import { WebClient } from 'https://deno.land/x/slack_web_api@6.7.2/mod.js';
|
||||
import { WebClient } from 'https://deno.land/x/slack_web_api@6.7.2/mod.js'
|
||||
|
||||
const slackBotToken = Deno.env.get("SLACK_TOKEN") ?? "";
|
||||
const botClient = new WebClient(slackBotToken);
|
||||
const slackBotToken = Deno.env.get('SLACK_TOKEN') ?? ''
|
||||
const botClient = new WebClient(slackBotToken)
|
||||
|
||||
console.log(`Slack URL verification function up and running!`);
|
||||
serve(async (req) => {
|
||||
console.log(`Slack URL verification function up and running!`)
|
||||
Deno.serve(async (req) => {
|
||||
try {
|
||||
const { token, challenge, type, event } = await req.json();
|
||||
const { token, challenge, type, event } = await req.json()
|
||||
|
||||
if (type == 'url_verification') {
|
||||
return new Response(JSON.stringify({ challenge }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
status: 200,
|
||||
});
|
||||
})
|
||||
} else if (event.type == 'app_mention') {
|
||||
const { user, text, channel, ts } = event;
|
||||
const { user, text, channel, ts } = event
|
||||
// Here you should process the text received and return a response:
|
||||
const response = await botClient.chat.postMessage({
|
||||
channel: channel,
|
||||
text: `Hello <@${user}>!`,
|
||||
thread_ts: ts,
|
||||
});
|
||||
return new Response('ok', { status: 200 });
|
||||
})
|
||||
return new Response('ok', { status: 200 })
|
||||
}
|
||||
} catch (error) {
|
||||
return new Response(JSON.stringify({ error: error.message }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
status: 500,
|
||||
});
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
@@ -1,8 +1,6 @@
|
||||
import { serve } from 'std/server'
|
||||
|
||||
const msg = new TextEncoder().encode('data: hello\r\n\r\n')
|
||||
|
||||
serve((_) => {
|
||||
Deno.serve((_) => {
|
||||
let timerId: number | undefined
|
||||
|
||||
const body = new ReadableStream({
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
|
||||
// Import via bare specifier thanks to the import_map.json file.
|
||||
import Stripe from 'stripe'
|
||||
import Stripe from 'https://esm.sh/stripe@11.1.0?target=deno'
|
||||
|
||||
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
|
||||
@@ -18,7 +16,7 @@ const cryptoProvider = Stripe.createSubtleCryptoProvider()
|
||||
|
||||
console.log('Hello from Stripe Webhook!')
|
||||
|
||||
serve(async (request) => {
|
||||
Deno.serve(async (request) => {
|
||||
const signature = request.headers.get('Stripe-Signature')
|
||||
|
||||
// First step is to verify the event. The .text() method must be used as the
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
|
||||
console.log(`Function "telegram-bot" up and running!`)
|
||||
|
||||
import { Bot, webhookCallback } from 'grammy'
|
||||
import { Bot, webhookCallback } from 'https://deno.land/x/grammy@v1.8.3/mod.ts'
|
||||
|
||||
const bot = new Bot(Deno.env.get('TELEGRAM_BOT_TOKEN') || '')
|
||||
|
||||
@@ -16,11 +14,12 @@ bot.command('ping', (ctx) => ctx.reply(`Pong! ${new Date()} ${Date.now()}`))
|
||||
|
||||
const handleUpdate = webhookCallback(bot, 'std/http')
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
try {
|
||||
const url = new URL(req.url)
|
||||
if (url.searchParams.get('secret') !== Deno.env.get('FUNCTION_SECRET'))
|
||||
if (url.searchParams.get('secret') !== Deno.env.get('FUNCTION_SECRET')) {
|
||||
return new Response('not allowed', { status: 405 })
|
||||
}
|
||||
|
||||
return await handleUpdate(req)
|
||||
} catch (err) {
|
||||
|
||||
@@ -2,10 +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.140.0/http/server.ts'
|
||||
|
||||
import { handler } from './handler.tsx'
|
||||
|
||||
console.log(`Function "tweet-to-image" up and running!`)
|
||||
|
||||
serve(handler)
|
||||
Deno.serve(handler)
|
||||
@@ -2,12 +2,11 @@
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { Redis } from 'upstash_redis'
|
||||
import { Redis } from 'https://deno.land/x/upstash_redis@v1.19.3/mod.ts'
|
||||
|
||||
console.log(`Function "upstash-redis-counter" up and running!`)
|
||||
|
||||
serve(async (_req) => {
|
||||
Deno.serve(async (_req) => {
|
||||
try {
|
||||
const redis = new Redis({
|
||||
url: Deno.env.get('UPSTASH_REDIS_REST_URL')!,
|
||||
@@ -27,14 +26,22 @@ serve(async (_req) => {
|
||||
const counterHash: Record<string, number> | null = await redis.hgetall('supa-edge-counter')
|
||||
const counters = Object.entries(counterHash!)
|
||||
.sort(([, a], [, b]) => b - a) // sort desc
|
||||
.reduce((r, [k, v]) => ({ total: r.total + v, regions: { ...r.regions, [k]: v } }), {
|
||||
total: 0,
|
||||
regions: {},
|
||||
})
|
||||
.reduce(
|
||||
(r, [k, v]) => ({
|
||||
total: r.total + v,
|
||||
regions: { ...r.regions, [k]: v },
|
||||
}),
|
||||
{
|
||||
total: 0,
|
||||
regions: {},
|
||||
}
|
||||
)
|
||||
|
||||
return new Response(JSON.stringify({ counters }), { status: 200 })
|
||||
} catch (error) {
|
||||
return new Response(JSON.stringify({ error: error.message }), { status: 200 })
|
||||
return new Response(JSON.stringify({ error: error.message }), {
|
||||
status: 200,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,61 +1,60 @@
|
||||
import { serve } from "std/server";
|
||||
import { Redis } from "@upstash/redis";
|
||||
import { Ratelimit } from "@upstash/ratelimit";
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
import { Redis } from 'https://deno.land/x/upstash_redis@v1.19.3/mod.ts'
|
||||
import { Ratelimit } from 'https://cdn.skypack.dev/@upstash/ratelimit@0.4.4'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.7.1'
|
||||
|
||||
console.log(`Function "upstash-redis-counter" up and running!`);
|
||||
console.log(`Function "upstash-redis-counter" up and running!`)
|
||||
|
||||
serve(async (req) => {
|
||||
Deno.serve(async (req) => {
|
||||
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") ?? "",
|
||||
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') ?? '',
|
||||
// Create client with Auth context of the user that called the function.
|
||||
// This way your row-level-security (RLS) policies are applied.
|
||||
{
|
||||
global: {
|
||||
headers: { Authorization: req.headers.get("Authorization")! },
|
||||
headers: { Authorization: req.headers.get('Authorization')! },
|
||||
},
|
||||
}
|
||||
);
|
||||
)
|
||||
// Now we can get the session or user object
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabaseClient.auth.getUser();
|
||||
if (!user) throw new Error("no user");
|
||||
console.log(user.id);
|
||||
} = await supabaseClient.auth.getUser()
|
||||
if (!user) throw new Error('no user')
|
||||
console.log(user.id)
|
||||
|
||||
const redis = new Redis({
|
||||
url: Deno.env.get("UPSTASH_REDIS_REST_URL")!,
|
||||
token: Deno.env.get("UPSTASH_REDIS_REST_TOKEN")!,
|
||||
});
|
||||
url: Deno.env.get('UPSTASH_REDIS_REST_URL')!,
|
||||
token: Deno.env.get('UPSTASH_REDIS_REST_TOKEN')!,
|
||||
})
|
||||
|
||||
// Create a new ratelimiter, that allows 10 requests per 10 seconds
|
||||
const ratelimit = new Ratelimit({
|
||||
redis,
|
||||
limiter: Ratelimit.slidingWindow(2, "10 s"),
|
||||
limiter: Ratelimit.slidingWindow(2, '10 s'),
|
||||
analytics: true,
|
||||
});
|
||||
})
|
||||
|
||||
// Use a constant string to limit all requests with a single ratelimit
|
||||
// Or use a userID, apiKey or ip address for individual limits.
|
||||
const identifier = user.id;
|
||||
const { success } = await ratelimit.limit(identifier);
|
||||
const identifier = user.id
|
||||
const { success } = await ratelimit.limit(identifier)
|
||||
|
||||
if (!success) {
|
||||
throw new Error("limit exceeded");
|
||||
throw new Error('limit exceeded')
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({ success }), { status: 200 });
|
||||
return new Response(JSON.stringify({ success }), { status: 200 })
|
||||
} catch (error) {
|
||||
return new Response(JSON.stringify({ error: error.message }), {
|
||||
status: 200,
|
||||
});
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// curl -i --location --request POST 'http://localhost:54321/functions/v1/upstash-redis-ratelimit' \
|
||||
// --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjc4MDA4Mjk2LCJzdWIiOiJkZjQ3ZDU5My0zMjY1LTQ2OWEtOWI5OS1mZDk1OTdhOGU4YzciLCJlbWFpbCI6InRlc3RyQHRlc3Quc2ciLCJwaG9uZSI6IiIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6ImVtYWlsIiwicHJvdmlkZXJzIjpbImVtYWlsIl19LCJ1c2VyX21ldGFkYXRhIjp7fSwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJwYXNzd29yZCIsInRpbWVzdGFtcCI6MTY3ODAwNDY5Nn1dLCJzZXNzaW9uX2lkIjoiMDNjMmFlYjUtMjk5MC00ZWU0LWIxYTYtZmU1Y2IwMGFhMjU3In0.WwqggrX34j0NINiulC9rsj-cd6HzV55ySxJkJlVsU4o' \
|
||||
|
||||
Reference in new issue
Block a user