Skip to content

Commit a28e347

Browse files
committed
Added supabase database examples
1 parent 3af8ae5 commit a28e347

File tree

2 files changed

+202
-52
lines changed

2 files changed

+202
-52
lines changed
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
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 Supabase database using Trigger.dev."
5+
---
6+
7+
## Add a new user to a Supabase database
8+
9+
This is a basic task which inserts a new user into a Supabase database by adding a row to the `user_subscriptions` table with the provided `userId`.
10+
11+
### Key features
12+
13+
- Shows how to set up a Supabase client using the `@supabase/supabase-js` library
14+
- Shows how to add a new row to a table using `insert`
15+
16+
### Prerequisites
17+
18+
- A [Supabase account](https://supabase.com/dashboard/) and a project set up
19+
- In your Supabase project, create a table called `user_subscriptions`.
20+
- In your `user_subscriptions` table, create a new column:
21+
- `user_id`, with the data type: `text`
22+
23+
### Task code
24+
25+
```ts trigger/supabase-database-insert.ts
26+
import { createClient } from "@supabase/supabase-js";
27+
import { task } from "@trigger.dev/sdk/v3";
28+
import { Database } from "database.types";
29+
30+
// Create a single Supabase client for interacting with your database
31+
const supabase = createClient<Database>(
32+
// These details can be found in your Supabase project settings under `API`
33+
process.env.SUPABASE_PROJECT_URL as string, // e.g. https://abc123.supabase.co - replace 'abc123' with your project ID
34+
process.env.SUPABASE_SERVICE_ROLE_KEY as string // Your service role secret key
35+
);
36+
37+
export const supabaseDatabaseInsert = task({
38+
id: "add-new-user",
39+
run: async (payload: { userId: string }) => {
40+
const { userId } = payload;
41+
42+
// Insert a new row into the user_subscriptions table with the provided userId
43+
const { error } = await supabase.from("user_subscriptions").insert({
44+
user_id: userId,
45+
});
46+
47+
// If there was an error inserting the new user, throw an error
48+
if (error) {
49+
throw new Error(`Failed to insert new user: ${error.message}`);
50+
}
51+
52+
return {
53+
message: `New user added successfully: ${userId}`,
54+
};
55+
},
56+
});
57+
```
58+
59+
<Note>
60+
This task uses your service role secret key to bypass Row Level Security. There are different ways
61+
of configuring your [RLS
62+
policies](https://supabase.com/docs/guides/database/postgres/row-level-security), so always make
63+
sure you have the correct permissions set up for your Supabase database.
64+
</Note>
65+
66+
### Testing your task
67+
68+
To test this task in the [Trigger.dev dashboard](https://cloud.trigger.dev), you can use the following payload:
69+
70+
```json
71+
{
72+
"userId": "user_12345"
73+
}
74+
```
75+
76+
If the task completes successfully, you will see a new row in your `user_subscriptions` table with the `user_id` set to `user_12345`.
77+
78+
## Update a user's subscription in a Supabase database
79+
80+
This task shows how to update a user's subscription. It checks if the user already has a subscription and either inserts a new row or updates an existing row with the new plan.
81+
82+
This type of task is useful for managing user subscriptions, updating user details, or performing other operations on a Supabase database.
83+
84+
### Key features
85+
86+
- Shows how to set up a Supabase client using the `@supabase/supabase-js` library
87+
- Adds a new row to the table if the user doesn't exist using `insert`
88+
- Checks if the user already has a plan, and if they do updates the existing row using `update`
89+
- 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
90+
91+
### Prerequisites
92+
93+
- A [Supabase account](https://supabase.com/dashboard/) and a project set up
94+
- In your Supabase project, create a table called `user_subscriptions` (if you haven't already)
95+
- In your `user_subscriptions` table, create these columns (if they don't already exist):
96+
- `user_id`, with the data type: `text`
97+
- `plan`, with the data type: `text`
98+
- `updated_at`, with the data type: `timestamptz`
99+
100+
### Task code
101+
102+
```ts trigger/supabase-update-user-subscription.ts
103+
import { createClient } from "@supabase/supabase-js";
104+
import { AbortTaskRunError, task } from "@trigger.dev/sdk/v3";
105+
import { Database } from "database.types";
106+
107+
// Define the allowed plan types
108+
type PlanType = "hobby" | "pro" | "enterprise";
109+
110+
// Create a single Supabase client for interacting with your database
111+
const supabase = createClient<Database>(
112+
// These details can be found in your Supabase project settings under `API`
113+
process.env.SUPABASE_PROJECT_URL as string, // e.g. https://abc123.supabase.co - replace 'abc123' with your project ID
114+
process.env.SUPABASE_SERVICE_ROLE_KEY as string // Your service role secret key
115+
);
116+
117+
export const supabaseUpdateUserSubscription = task({
118+
id: "update-user-subscription",
119+
run: async (payload: { userId: string; newPlan: PlanType }) => {
120+
const { userId, newPlan } = payload;
121+
122+
// Abort the task run without retrying if the new plan type is invalid
123+
if (!["hobby", "pro", "enterprise"].includes(newPlan)) {
124+
throw new AbortTaskRunError(
125+
`Invalid plan type: ${newPlan}. Allowed types are 'hobby', 'pro', or 'enterprise'.`
126+
);
127+
}
128+
129+
// Query the user_subscriptions table to check if the user already has a subscription
130+
const { data: existingSubscriptions } = await supabase
131+
.from("user_subscriptions")
132+
.select("user_id")
133+
.eq("user_id", userId);
134+
135+
if (!existingSubscriptions || existingSubscriptions.length === 0) {
136+
// If there are no existing users with the provided userId and plan, insert a new row
137+
const { error: insertError } = await supabase.from("user_subscriptions").insert({
138+
user_id: userId,
139+
plan: newPlan,
140+
updated_at: new Date().toISOString(),
141+
});
142+
143+
// If there was an error inserting the new subscription, throw an error
144+
if (insertError) {
145+
throw new Error(`Failed to insert user subscription: ${insertError.message}`);
146+
}
147+
} else {
148+
// If the user already has a subscription, update their existing row
149+
const { error: updateError } = await supabase
150+
.from("user_subscriptions")
151+
// Set the plan to the new plan and update the timestamp
152+
.update({ plan: newPlan, updated_at: new Date().toISOString() })
153+
.eq("user_id", userId);
154+
155+
// If there was an error updating the subscription, throw an error
156+
if (updateError) {
157+
throw new Error(`Failed to update user subscription: ${updateError.message}`);
158+
}
159+
}
160+
161+
// Return an object with the userId and newPlan
162+
return {
163+
userId,
164+
newPlan,
165+
};
166+
},
167+
});
168+
```
169+
170+
<Note>
171+
This task uses your service role secret key to bypass Row Level Security. There are different ways
172+
of configuring your [RLS
173+
policies](https://supabase.com/docs/guides/database/postgres/row-level-security), so always make
174+
sure you have the correct permissions set up for your Supabase database.
175+
</Note>
176+
177+
## Testing your task
178+
179+
To test this task in the [Trigger.dev dashboard](https://cloud.trigger.dev), you can use the following payload:
180+
181+
```json
182+
{
183+
"userId": "user_12345",
184+
"newPlan": "pro"
185+
}
186+
```
187+
188+
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.

docs/mint.json

Lines changed: 14 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
{
22
"$schema": "https://mintlify.com/schema.json",
33
"name": "Trigger.dev",
4-
"openapi": [
5-
"/openapi.yml",
6-
"/v3-openapi.yaml"
7-
],
4+
"openapi": ["/openapi.yml", "/v3-openapi.yaml"],
85
"api": {
96
"playground": {
107
"mode": "simple"
@@ -107,41 +104,26 @@
107104
"navigation": [
108105
{
109106
"group": "Getting Started",
110-
"pages": [
111-
"introduction",
112-
"quick-start",
113-
"how-it-works",
114-
"upgrading-beta",
115-
"limits"
116-
]
107+
"pages": ["introduction", "quick-start", "how-it-works", "upgrading-beta", "limits"]
117108
},
118109
{
119110
"group": "Fundamentals",
120111
"pages": [
121112
{
122113
"group": "Tasks",
123-
"pages": [
124-
"tasks/overview",
125-
"tasks/scheduled"
126-
]
114+
"pages": ["tasks/overview", "tasks/scheduled"]
127115
},
128116
"triggering",
129117
"apikeys",
130118
{
131119
"group": "Configuration",
132-
"pages": [
133-
"config/config-file",
134-
"config/extensions/overview"
135-
]
120+
"pages": ["config/config-file", "config/extensions/overview"]
136121
}
137122
]
138123
},
139124
{
140125
"group": "Development",
141-
"pages": [
142-
"cli-dev",
143-
"run-tests"
144-
]
126+
"pages": ["cli-dev", "run-tests"]
145127
},
146128
{
147129
"group": "Deployment",
@@ -151,9 +133,7 @@
151133
"github-actions",
152134
{
153135
"group": "Deployment integrations",
154-
"pages": [
155-
"vercel-integration"
156-
]
136+
"pages": ["vercel-integration"]
157137
}
158138
]
159139
},
@@ -165,13 +145,7 @@
165145
"errors-retrying",
166146
{
167147
"group": "Wait",
168-
"pages": [
169-
"wait",
170-
"wait-for",
171-
"wait-until",
172-
"wait-for-event",
173-
"wait-for-request"
174-
]
148+
"pages": ["wait", "wait-for", "wait-until", "wait-for-event", "wait-for-request"]
175149
},
176150
"queue-concurrency",
177151
"versioning",
@@ -189,10 +163,7 @@
189163
"management/overview",
190164
{
191165
"group": "Tasks API",
192-
"pages": [
193-
"management/tasks/trigger",
194-
"management/tasks/batch-trigger"
195-
]
166+
"pages": ["management/tasks/trigger", "management/tasks/batch-trigger"]
196167
},
197168
{
198169
"group": "Runs API",
@@ -230,9 +201,7 @@
230201
},
231202
{
232203
"group": "Projects API",
233-
"pages": [
234-
"management/projects/runs"
235-
]
204+
"pages": ["management/projects/runs"]
236205
}
237206
]
238207
},
@@ -278,11 +247,7 @@
278247
},
279248
{
280249
"group": "Help",
281-
"pages": [
282-
"community",
283-
"help-slack",
284-
"help-email"
285-
]
250+
"pages": ["community", "help-slack", "help-email"]
286251
},
287252
{
288253
"group": "Frameworks",
@@ -306,15 +271,11 @@
306271
},
307272
{
308273
"group": "Dashboard",
309-
"pages": [
310-
"guides/dashboard/creating-a-project"
311-
]
274+
"pages": ["guides/dashboard/creating-a-project"]
312275
},
313276
{
314277
"group": "Migrations",
315-
"pages": [
316-
"guides/use-cases/upgrading-from-v2"
317-
]
278+
"pages": ["guides/use-cases/upgrading-from-v2"]
318279
},
319280
{
320281
"group": "Examples",
@@ -328,6 +289,7 @@
328289
"examples/sharp-image-processing",
329290
"examples/stripe-webhook",
330291
"examples/supabase-storage-upload",
292+
"examples/supabase-database-operations",
331293
"examples/react-pdf",
332294
"examples/resend-email-sequence",
333295
"examples/vercel-ai-sdk"
@@ -339,4 +301,4 @@
339301
"github": "https://github.com/triggerdotdev",
340302
"linkedin": "https://www.linkedin.com/company/triggerdotdev"
341303
}
342-
}
304+
}

0 commit comments

Comments
 (0)