Skip to content

Commit 308715b

Browse files
authored
Added supabase database operations and new snippet (#1359)
* Added supabase database examples * Copy updates * More copy updates * Added comment about generating the typescript types * Updated intro table * Improved title * Added supabase-docs-cards to go at the bottom of the examples and guides * merge main * Link fix * Fix more links
1 parent 5fe2bab commit 308715b

8 files changed

+274
-86
lines changed

docs/guides/examples/intro.mdx

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ sidebarTitle: "Introduction"
44
description: "Learn how to use Trigger.dev with these practical task examples."
55
---
66

7-
| Example task | Description |
8-
| :------------------------------------------------------------ | :-------------------------------------------------------------------------- |
9-
| [DALL·E 3 image generation](/guides/examples/dall-e3-generate-image) | Use OpenAI's GPT-4o and DALL·E 3 to generate an image and text. |
10-
| [FFmpeg video processing](/guides/examples/ffmpeg-video-processing) | Use FFmpeg to process a video in various ways and save it to Cloudflare R2. |
11-
| [OpenAI with retrying](/guides/examples/open-ai-with-retrying) | Create a reusable OpenAI task with custom retry options. |
12-
| [PDF to image](/guides/examples/pdf-to-image) | Use `MuPDF` to turn a PDF into images and save them to Cloudflare R2. |
13-
| [React to PDF](/guides/examples/react-pdf) | Use `react-pdf` to generate a PDF and save it to Cloudflare R2. |
14-
| [Puppeteer](/guides/examples/puppeteer) | Use Puppeteer to generate a PDF or scrape a webpage. |
15-
| [Resend email sequence](/guides/examples/resend-email-sequence) | Send a sequence of emails over several days using Resend with Trigger.dev. |
16-
| [Sharp image processing](/guides/examples/sharp-image-processing) | Use Sharp to process an image and save it to Cloudflare R2. |
17-
| [Stripe webhook](/guides/examples/stripe-webhook) | Trigger a task from Stripe webhook events. |
18-
| [Supabase Storage upload](/guides/examples/supabase-storage-upload) | Download a video from a URL and upload it to Supabase Storage using S3. |
19-
| [Vercel AI SDK](/guides/examples/vercel-ai-sdk) | Use Vercel AI SDK to generate text using OpenAI. |
7+
| Example task | Description |
8+
| :---------------------------------------------------------------------------- | :----------------------------------------------------------------------------- |
9+
| [DALL·E 3 image generation](/guides/examples/dall-e3-generate-image) | Use OpenAI's GPT-4o and DALL·E 3 to generate an image and text. |
10+
| [FFmpeg video processing](/guides/examples/ffmpeg-video-processing) | Use FFmpeg to process a video in various ways and save it to Cloudflare R2. |
11+
| [OpenAI with retrying](/guides/examples/open-ai-with-retrying) | Create a reusable OpenAI task with custom retry options. |
12+
| [PDF to image](/guides/examples/pdf-to-image) | Use `MuPDF` to turn a PDF into images and save them to Cloudflare R2. |
13+
| [React to PDF](/guides/examples/react-pdf) | Use `react-pdf` to generate a PDF and save it to Cloudflare R2. |
14+
| [Puppeteer](/guides/examples/puppeteer) | Use Puppeteer to generate a PDF or scrape a webpage. |
15+
| [Resend email sequence](/guides/examples/resend-email-sequence) | Send a sequence of emails over several days using Resend with Trigger.dev. |
16+
| [Sharp image processing](/guides/examples/sharp-image-processing) | Use Sharp to process an image and save it to Cloudflare R2. |
17+
| [Stripe webhook](/guides/examples/stripe-webhook) | Trigger a task from Stripe webhook events. |
18+
| [Supabase database operations](/guides/examples/supabase-database-operations) | Run basic CRUD operations on a table in a Supabase database using Trigger.dev. |
19+
| [Supabase Storage upload](/guides/examples/supabase-storage-upload) | Download a video from a URL and upload it to Supabase Storage using S3. |
20+
| [Vercel AI SDK](/guides/examples/vercel-ai-sdk) | Use Vercel AI SDK to generate text using OpenAI. |
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
---
2+
title: "Supabase database operations using Trigger.dev"
3+
sidebarTitle: "Supabase database operations"
4+
description: "These examples demonstrate how to run basic CRUD operations on a table in a Supabase database using Trigger.dev."
5+
---
6+
7+
import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx";
8+
9+
## Add a new user to a table in a Supabase database
10+
11+
This is a basic task which inserts a new row into a table from a Trigger.dev task.
12+
13+
### Key features
14+
15+
- Shows how to set up a Supabase client using the `@supabase/supabase-js` library
16+
- Shows how to add a new row to a table using `insert`
17+
18+
### Prerequisites
19+
20+
- A [Supabase account](https://supabase.com/dashboard/) and a project set up
21+
- In your Supabase project, create a table called `user_subscriptions`.
22+
- In your `user_subscriptions` table, create a new column:
23+
- `user_id`, with the data type: `text`
24+
25+
### Task code
26+
27+
```ts trigger/supabase-database-insert.ts
28+
import { createClient } from "@supabase/supabase-js";
29+
import { task } from "@trigger.dev/sdk/v3";
30+
// Generate the Typescript types using the Supabase CLI: https://supabase.com/docs/guides/api/rest/generating-types
31+
import { Database } from "database.types";
32+
33+
// Create a single Supabase client for interacting with your database
34+
// 'Database' supplies the type definitions to supabase-js
35+
const supabase = createClient<Database>(
36+
// These details can be found in your Supabase project settings under `API`
37+
process.env.SUPABASE_PROJECT_URL as string, // e.g. https://abc123.supabase.co - replace 'abc123' with your project ID
38+
process.env.SUPABASE_SERVICE_ROLE_KEY as string // Your service role secret key
39+
);
40+
41+
export const supabaseDatabaseInsert = task({
42+
id: "add-new-user",
43+
run: async (payload: { userId: string }) => {
44+
const { userId } = payload;
45+
46+
// Insert a new row into the user_subscriptions table with the provided userId
47+
const { error } = await supabase.from("user_subscriptions").insert({
48+
user_id: userId,
49+
});
50+
51+
// If there was an error inserting the new user, throw an error
52+
if (error) {
53+
throw new Error(`Failed to insert new user: ${error.message}`);
54+
}
55+
56+
return {
57+
message: `New user added successfully: ${userId}`,
58+
};
59+
},
60+
});
61+
```
62+
63+
<Note>
64+
This task uses your service role secret key to bypass Row Level Security. There are different ways
65+
of configuring your [RLS
66+
policies](https://supabase.com/docs/guides/database/postgres/row-level-security), so always make
67+
sure you have the correct permissions set up for your project.
68+
</Note>
69+
70+
### Testing your task
71+
72+
To test this task in the [Trigger.dev dashboard](https://cloud.trigger.dev), you can use the following payload:
73+
74+
```json
75+
{
76+
"userId": "user_12345"
77+
}
78+
```
79+
80+
If the task completes successfully, you will see a new row in your `user_subscriptions` table with the `user_id` set to `user_12345`.
81+
82+
## Update a user's subscription on a table in a Supabase database
83+
84+
This task shows how to update a user's subscription on a table. It checks if the user already has a subscription and either inserts a new row or updates an existing row with the new plan.
85+
86+
This type of task is useful for managing user subscriptions, updating user details, or performing other operations you might need to do on a database table.
87+
88+
### Key features
89+
90+
- Shows how to set up a Supabase client using the `@supabase/supabase-js` library
91+
- Adds a new row to the table if the user doesn't exist using `insert`
92+
- Checks if the user already has a plan, and if they do updates the existing row using `update`
93+
- Demonstrates how to use [AbortTaskRunError](https://trigger.dev/docs/errors-retrying#using-aborttaskrunerror) to stop the task run without retrying if an invalid plan type is provided
94+
95+
### Prerequisites
96+
97+
- A [Supabase account](https://supabase.com/dashboard/) and a project set up
98+
- In your Supabase project, create a table called `user_subscriptions` (if you haven't already)
99+
- In your `user_subscriptions` table, create these columns (if they don't already exist):
100+
101+
- `user_id`, with the data type: `text`
102+
- `plan`, with the data type: `text`
103+
- `updated_at`, with the data type: `timestamptz`
104+
105+
### Task code
106+
107+
```ts trigger/supabase-update-user-subscription.ts
108+
import { createClient } from "@supabase/supabase-js";
109+
import { AbortTaskRunError, task } from "@trigger.dev/sdk/v3";
110+
// Generate the Typescript types using the Supabase CLI: https://supabase.com/docs/guides/api/rest/generating-types
111+
import { Database } from "database.types";
112+
113+
// Define the allowed plan types
114+
type PlanType = "hobby" | "pro" | "enterprise";
115+
116+
// Create a single Supabase client for interacting with your database
117+
// 'Database' supplies the type definitions to supabase-js
118+
const supabase = createClient<Database>(
119+
// These details can be found in your Supabase project settings under `API`
120+
process.env.SUPABASE_PROJECT_URL as string, // e.g. https://abc123.supabase.co - replace 'abc123' with your project ID
121+
process.env.SUPABASE_SERVICE_ROLE_KEY as string // Your service role secret key
122+
);
123+
124+
export const supabaseUpdateUserSubscription = task({
125+
id: "update-user-subscription",
126+
run: async (payload: { userId: string; newPlan: PlanType }) => {
127+
const { userId, newPlan } = payload;
128+
129+
// Abort the task run without retrying if the new plan type is invalid
130+
if (!["hobby", "pro", "enterprise"].includes(newPlan)) {
131+
throw new AbortTaskRunError(
132+
`Invalid plan type: ${newPlan}. Allowed types are 'hobby', 'pro', or 'enterprise'.`
133+
);
134+
}
135+
136+
// Query the user_subscriptions table to check if the user already has a subscription
137+
const { data: existingSubscriptions } = await supabase
138+
.from("user_subscriptions")
139+
.select("user_id")
140+
.eq("user_id", userId);
141+
142+
if (!existingSubscriptions || existingSubscriptions.length === 0) {
143+
// If there are no existing users with the provided userId and plan, insert a new row
144+
const { error: insertError } = await supabase.from("user_subscriptions").insert({
145+
user_id: userId,
146+
plan: newPlan,
147+
updated_at: new Date().toISOString(),
148+
});
149+
150+
// If there was an error inserting the new subscription, throw an error
151+
if (insertError) {
152+
throw new Error(`Failed to insert user subscription: ${insertError.message}`);
153+
}
154+
} else {
155+
// If the user already has a subscription, update their existing row
156+
const { error: updateError } = await supabase
157+
.from("user_subscriptions")
158+
// Set the plan to the new plan and update the timestamp
159+
.update({ plan: newPlan, updated_at: new Date().toISOString() })
160+
.eq("user_id", userId);
161+
162+
// If there was an error updating the subscription, throw an error
163+
if (updateError) {
164+
throw new Error(`Failed to update user subscription: ${updateError.message}`);
165+
}
166+
}
167+
168+
// Return an object with the userId and newPlan
169+
return {
170+
userId,
171+
newPlan,
172+
};
173+
},
174+
});
175+
```
176+
177+
<Note>
178+
This task uses your service role secret key to bypass Row Level Security. There are different ways
179+
of configuring your [RLS
180+
policies](https://supabase.com/docs/guides/database/postgres/row-level-security), so always make
181+
sure you have the correct permissions set up for your project.
182+
</Note>
183+
184+
## Testing your task
185+
186+
To test this task in the [Trigger.dev dashboard](https://cloud.trigger.dev), you can use the following payload:
187+
188+
```json
189+
{
190+
"userId": "user_12345",
191+
"newPlan": "pro"
192+
}
193+
```
194+
195+
If the task completes successfully, you will see a new row in your `user_subscriptions` table with the `user_id` set to `user_12345`, the `plan` set to `pro`, and the `updated_at` timestamp updated to the current time.
196+
197+
<SupabaseDocsCards />

docs/guides/examples/supabase-storage-upload.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ sidebarTitle: "Supabase Storage upload"
44
description: "This example demonstrates how to download a video from a URL and upload it to Supabase Storage using Trigger.dev."
55
---
66

7+
import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx";
8+
79
## Overview
810

911
This task downloads a video from a provided URL, saves it to a temporary file, and then uploads the video file to Supabase Storage using S3.
@@ -72,3 +74,5 @@ To test this task in the dashboard, you can use the following payload:
7274
"videoUrl": "<a-video-url>" // Replace <a-video-url> with the URL of the video you want to upload
7375
}
7476
```
77+
78+
<SupabaseDocsCards />

docs/guides/frameworks/supabase-edge-functions-basic.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import TriggerTaskNextjs from "/snippets/trigger-tasks-nextjs.mdx";
1515
import NextjsTroubleshootingMissingApiKey from "/snippets/nextjs-missing-api-key.mdx";
1616
import NextjsTroubleshootingButtonSyntax from "/snippets/nextjs-button-syntax.mdx";
1717
import WorkerFailedToStartWhenRunningDevCommand from "/snippets/worker-failed-to-start.mdx";
18+
import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx";
1819

1920
## Overview
2021

@@ -177,4 +178,4 @@ Check your [cloud.trigger.dev](http://cloud.trigger.dev) dashboard and you shoul
177178
</Step>
178179
</Steps>
179180

180-
<UsefulNextSteps />
181+
<SupabaseDocsCards />

docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Triggering tasks from Supabase database webhooks"
33
sidebarTitle: "Database webhooks"
4-
description: "This guide will show you how to trigger a task when a row is added to a table using Supabase database webhooks."
4+
description: "This guide will show you how to trigger a task when a row is added to a table using a Supabase database webhook and edge function."
55
---
66

77
import Prerequisites from "/snippets/framework-prerequisites.mdx";
@@ -15,6 +15,7 @@ import TriggerTaskNextjs from "/snippets/trigger-tasks-nextjs.mdx";
1515
import NextjsTroubleshootingMissingApiKey from "/snippets/nextjs-missing-api-key.mdx";
1616
import NextjsTroubleshootingButtonSyntax from "/snippets/nextjs-button-syntax.mdx";
1717
import WorkerFailedToStartWhenRunningDevCommand from "/snippets/worker-failed-to-start.mdx";
18+
import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx";
1819

1920
## Overview
2021

@@ -233,4 +234,4 @@ Inside that run you will see the payload that was sent from the database webhook
233234

234235
</Steps>
235236

236-
<UsefulNextSteps />
237+
<SupabaseDocsCards />
Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,9 @@
11
---
2-
title: "Supabase guides"
2+
title: "Supabase overview"
33
sidebarTitle: "Overview"
4-
description: "Guides for using Supabase with Trigger.dev."
4+
description: "Guides and examples for using Supabase with Trigger.dev."
55
---
66

7-
<CardGroup cols={2}>
8-
<Card
9-
title="Edge function hello world"
10-
icon="bolt"
11-
href="/guides/frameworks/supabase-edge-functions-basic"
12-
>
13-
Learn how to trigger a task from a Supabase edge function when a URL is visited.
14-
</Card>
15-
<Card
16-
title="Edge function database webhooks"
17-
icon="bolt"
18-
href="/guides/frameworks/supabase-edge-functions-database-webhooks"
19-
>
20-
Learn how to trigger a task from a Supabase edge function when an event occurs in your database.
21-
</Card>
22-
</CardGroup>
7+
import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx";
8+
9+
<SupabaseDocsCards />

0 commit comments

Comments
 (0)