diff --git a/docs/guides/examples/intro.mdx b/docs/guides/examples/intro.mdx index 8b9dfc2bf1..fe41b1f3bb 100644 --- a/docs/guides/examples/intro.mdx +++ b/docs/guides/examples/intro.mdx @@ -4,16 +4,17 @@ sidebarTitle: "Introduction" description: "Learn how to use Trigger.dev with these practical task examples." --- -| Example task | Description | -| :------------------------------------------------------------ | :-------------------------------------------------------------------------- | -| [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. | -| [FFmpeg video processing](/guides/examples/ffmpeg-video-processing) | Use FFmpeg to process a video in various ways and save it to Cloudflare R2. | -| [OpenAI with retrying](/guides/examples/open-ai-with-retrying) | Create a reusable OpenAI task with custom retry options. | -| [PDF to image](/guides/examples/pdf-to-image) | Use `MuPDF` to turn a PDF into images and save them to Cloudflare R2. | -| [React to PDF](/guides/examples/react-pdf) | Use `react-pdf` to generate a PDF and save it to Cloudflare R2. | -| [Puppeteer](/guides/examples/puppeteer) | Use Puppeteer to generate a PDF or scrape a webpage. | -| [Resend email sequence](/guides/examples/resend-email-sequence) | Send a sequence of emails over several days using Resend with Trigger.dev. | -| [Sharp image processing](/guides/examples/sharp-image-processing) | Use Sharp to process an image and save it to Cloudflare R2. | -| [Stripe webhook](/guides/examples/stripe-webhook) | Trigger a task from Stripe webhook events. | -| [Supabase Storage upload](/guides/examples/supabase-storage-upload) | Download a video from a URL and upload it to Supabase Storage using S3. | -| [Vercel AI SDK](/guides/examples/vercel-ai-sdk) | Use Vercel AI SDK to generate text using OpenAI. | +| Example task | Description | +| :---------------------------------------------------------------------------- | :----------------------------------------------------------------------------- | +| [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. | +| [FFmpeg video processing](/guides/examples/ffmpeg-video-processing) | Use FFmpeg to process a video in various ways and save it to Cloudflare R2. | +| [OpenAI with retrying](/guides/examples/open-ai-with-retrying) | Create a reusable OpenAI task with custom retry options. | +| [PDF to image](/guides/examples/pdf-to-image) | Use `MuPDF` to turn a PDF into images and save them to Cloudflare R2. | +| [React to PDF](/guides/examples/react-pdf) | Use `react-pdf` to generate a PDF and save it to Cloudflare R2. | +| [Puppeteer](/guides/examples/puppeteer) | Use Puppeteer to generate a PDF or scrape a webpage. | +| [Resend email sequence](/guides/examples/resend-email-sequence) | Send a sequence of emails over several days using Resend with Trigger.dev. | +| [Sharp image processing](/guides/examples/sharp-image-processing) | Use Sharp to process an image and save it to Cloudflare R2. | +| [Stripe webhook](/guides/examples/stripe-webhook) | Trigger a task from Stripe webhook events. | +| [Supabase database operations](/guides/examples/supabase-database-operations) | Run basic CRUD operations on a table in a Supabase database using Trigger.dev. | +| [Supabase Storage upload](/guides/examples/supabase-storage-upload) | Download a video from a URL and upload it to Supabase Storage using S3. | +| [Vercel AI SDK](/guides/examples/vercel-ai-sdk) | Use Vercel AI SDK to generate text using OpenAI. | diff --git a/docs/guides/examples/supabase-database-operations.mdx b/docs/guides/examples/supabase-database-operations.mdx new file mode 100644 index 0000000000..d5454475ac --- /dev/null +++ b/docs/guides/examples/supabase-database-operations.mdx @@ -0,0 +1,197 @@ +--- +title: "Supabase database operations using Trigger.dev" +sidebarTitle: "Supabase database operations" +description: "These examples demonstrate how to run basic CRUD operations on a table in a Supabase database using Trigger.dev." +--- + +import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; + +## Add a new user to a table in a Supabase database + +This is a basic task which inserts a new row into a table from a Trigger.dev task. + +### Key features + +- Shows how to set up a Supabase client using the `@supabase/supabase-js` library +- Shows how to add a new row to a table using `insert` + +### Prerequisites + +- A [Supabase account](https://supabase.com/dashboard/) and a project set up +- In your Supabase project, create a table called `user_subscriptions`. +- In your `user_subscriptions` table, create a new column: + - `user_id`, with the data type: `text` + +### Task code + +```ts trigger/supabase-database-insert.ts +import { createClient } from "@supabase/supabase-js"; +import { task } from "@trigger.dev/sdk/v3"; +// Generate the Typescript types using the Supabase CLI: https://supabase.com/docs/guides/api/rest/generating-types +import { Database } from "database.types"; + +// Create a single Supabase client for interacting with your database +// 'Database' supplies the type definitions to supabase-js +const supabase = createClient( + // These details can be found in your Supabase project settings under `API` + process.env.SUPABASE_PROJECT_URL as string, // e.g. https://abc123.supabase.co - replace 'abc123' with your project ID + process.env.SUPABASE_SERVICE_ROLE_KEY as string // Your service role secret key +); + +export const supabaseDatabaseInsert = task({ + id: "add-new-user", + run: async (payload: { userId: string }) => { + const { userId } = payload; + + // Insert a new row into the user_subscriptions table with the provided userId + const { error } = await supabase.from("user_subscriptions").insert({ + user_id: userId, + }); + + // If there was an error inserting the new user, throw an error + if (error) { + throw new Error(`Failed to insert new user: ${error.message}`); + } + + return { + message: `New user added successfully: ${userId}`, + }; + }, +}); +``` + + + This task uses your service role secret key to bypass Row Level Security. There are different ways + of configuring your [RLS + policies](https://supabase.com/docs/guides/database/postgres/row-level-security), so always make + sure you have the correct permissions set up for your project. + + +### Testing your task + +To test this task in the [Trigger.dev dashboard](https://cloud.trigger.dev), you can use the following payload: + +```json +{ + "userId": "user_12345" +} +``` + +If the task completes successfully, you will see a new row in your `user_subscriptions` table with the `user_id` set to `user_12345`. + +## Update a user's subscription on a table in a Supabase database + +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. + +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. + +### Key features + +- Shows how to set up a Supabase client using the `@supabase/supabase-js` library +- Adds a new row to the table if the user doesn't exist using `insert` +- Checks if the user already has a plan, and if they do updates the existing row using `update` +- 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 + +### Prerequisites + +- A [Supabase account](https://supabase.com/dashboard/) and a project set up +- In your Supabase project, create a table called `user_subscriptions` (if you haven't already) +- In your `user_subscriptions` table, create these columns (if they don't already exist): + + - `user_id`, with the data type: `text` + - `plan`, with the data type: `text` + - `updated_at`, with the data type: `timestamptz` + +### Task code + +```ts trigger/supabase-update-user-subscription.ts +import { createClient } from "@supabase/supabase-js"; +import { AbortTaskRunError, task } from "@trigger.dev/sdk/v3"; +// Generate the Typescript types using the Supabase CLI: https://supabase.com/docs/guides/api/rest/generating-types +import { Database } from "database.types"; + +// Define the allowed plan types +type PlanType = "hobby" | "pro" | "enterprise"; + +// Create a single Supabase client for interacting with your database +// 'Database' supplies the type definitions to supabase-js +const supabase = createClient( + // These details can be found in your Supabase project settings under `API` + process.env.SUPABASE_PROJECT_URL as string, // e.g. https://abc123.supabase.co - replace 'abc123' with your project ID + process.env.SUPABASE_SERVICE_ROLE_KEY as string // Your service role secret key +); + +export const supabaseUpdateUserSubscription = task({ + id: "update-user-subscription", + run: async (payload: { userId: string; newPlan: PlanType }) => { + const { userId, newPlan } = payload; + + // Abort the task run without retrying if the new plan type is invalid + if (!["hobby", "pro", "enterprise"].includes(newPlan)) { + throw new AbortTaskRunError( + `Invalid plan type: ${newPlan}. Allowed types are 'hobby', 'pro', or 'enterprise'.` + ); + } + + // Query the user_subscriptions table to check if the user already has a subscription + const { data: existingSubscriptions } = await supabase + .from("user_subscriptions") + .select("user_id") + .eq("user_id", userId); + + if (!existingSubscriptions || existingSubscriptions.length === 0) { + // If there are no existing users with the provided userId and plan, insert a new row + const { error: insertError } = await supabase.from("user_subscriptions").insert({ + user_id: userId, + plan: newPlan, + updated_at: new Date().toISOString(), + }); + + // If there was an error inserting the new subscription, throw an error + if (insertError) { + throw new Error(`Failed to insert user subscription: ${insertError.message}`); + } + } else { + // If the user already has a subscription, update their existing row + const { error: updateError } = await supabase + .from("user_subscriptions") + // Set the plan to the new plan and update the timestamp + .update({ plan: newPlan, updated_at: new Date().toISOString() }) + .eq("user_id", userId); + + // If there was an error updating the subscription, throw an error + if (updateError) { + throw new Error(`Failed to update user subscription: ${updateError.message}`); + } + } + + // Return an object with the userId and newPlan + return { + userId, + newPlan, + }; + }, +}); +``` + + + This task uses your service role secret key to bypass Row Level Security. There are different ways + of configuring your [RLS + policies](https://supabase.com/docs/guides/database/postgres/row-level-security), so always make + sure you have the correct permissions set up for your project. + + +## Testing your task + +To test this task in the [Trigger.dev dashboard](https://cloud.trigger.dev), you can use the following payload: + +```json +{ + "userId": "user_12345", + "newPlan": "pro" +} +``` + +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. + + diff --git a/docs/guides/examples/supabase-storage-upload.mdx b/docs/guides/examples/supabase-storage-upload.mdx index c570c96a4d..583ced16dc 100644 --- a/docs/guides/examples/supabase-storage-upload.mdx +++ b/docs/guides/examples/supabase-storage-upload.mdx @@ -4,6 +4,8 @@ sidebarTitle: "Supabase Storage upload" description: "This example demonstrates how to download a video from a URL and upload it to Supabase Storage using Trigger.dev." --- +import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; + ## Overview 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: "videoUrl": "" // Replace with the URL of the video you want to upload } ``` + + diff --git a/docs/guides/frameworks/supabase-edge-functions-basic.mdx b/docs/guides/frameworks/supabase-edge-functions-basic.mdx index 86e6489be8..9cf2749485 100644 --- a/docs/guides/frameworks/supabase-edge-functions-basic.mdx +++ b/docs/guides/frameworks/supabase-edge-functions-basic.mdx @@ -15,6 +15,7 @@ import TriggerTaskNextjs from "/snippets/trigger-tasks-nextjs.mdx"; import NextjsTroubleshootingMissingApiKey from "/snippets/nextjs-missing-api-key.mdx"; import NextjsTroubleshootingButtonSyntax from "/snippets/nextjs-button-syntax.mdx"; import WorkerFailedToStartWhenRunningDevCommand from "/snippets/worker-failed-to-start.mdx"; +import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; ## Overview @@ -177,4 +178,4 @@ Check your [cloud.trigger.dev](http://cloud.trigger.dev) dashboard and you shoul - + diff --git a/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx b/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx index 4cbeb8961e..a9986a576c 100644 --- a/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx +++ b/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx @@ -1,7 +1,7 @@ --- title: "Triggering tasks from Supabase database webhooks" sidebarTitle: "Database webhooks" -description: "This guide will show you how to trigger a task when a row is added to a table using Supabase database webhooks." +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." --- import Prerequisites from "/snippets/framework-prerequisites.mdx"; @@ -15,6 +15,7 @@ import TriggerTaskNextjs from "/snippets/trigger-tasks-nextjs.mdx"; import NextjsTroubleshootingMissingApiKey from "/snippets/nextjs-missing-api-key.mdx"; import NextjsTroubleshootingButtonSyntax from "/snippets/nextjs-button-syntax.mdx"; import WorkerFailedToStartWhenRunningDevCommand from "/snippets/worker-failed-to-start.mdx"; +import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; ## Overview @@ -233,4 +234,4 @@ Inside that run you will see the payload that was sent from the database webhook - + diff --git a/docs/guides/frameworks/supabase-guides-overview.mdx b/docs/guides/frameworks/supabase-guides-overview.mdx index 74405a4f3d..93df10a77a 100644 --- a/docs/guides/frameworks/supabase-guides-overview.mdx +++ b/docs/guides/frameworks/supabase-guides-overview.mdx @@ -1,22 +1,9 @@ --- -title: "Supabase guides" +title: "Supabase overview" sidebarTitle: "Overview" -description: "Guides for using Supabase with Trigger.dev." +description: "Guides and examples for using Supabase with Trigger.dev." --- - - - Learn how to trigger a task from a Supabase edge function when a URL is visited. - - - Learn how to trigger a task from a Supabase edge function when an event occurs in your database. - - +import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; + + diff --git a/docs/mint.json b/docs/mint.json index 99ff892f87..77053589c0 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -1,10 +1,7 @@ { "$schema": "https://mintlify.com/schema.json", "name": "Trigger.dev", - "openapi": [ - "/openapi.yml", - "/v3-openapi.yaml" - ], + "openapi": ["/openapi.yml", "/v3-openapi.yaml"], "api": { "playground": { "mode": "simple" @@ -106,41 +103,26 @@ "navigation": [ { "group": "Getting Started", - "pages": [ - "introduction", - "quick-start", - "how-it-works", - "upgrading-beta", - "limits" - ] + "pages": ["introduction", "quick-start", "how-it-works", "upgrading-beta", "limits"] }, { "group": "Fundamentals", "pages": [ { "group": "Tasks", - "pages": [ - "tasks/overview", - "tasks/scheduled" - ] + "pages": ["tasks/overview", "tasks/scheduled"] }, "triggering", "apikeys", { "group": "Configuration", - "pages": [ - "config/config-file", - "config/extensions/overview" - ] + "pages": ["config/config-file", "config/extensions/overview"] } ] }, { "group": "Development", - "pages": [ - "cli-dev", - "run-tests" - ] + "pages": ["cli-dev", "run-tests"] }, { "group": "Deployment", @@ -150,9 +132,7 @@ "github-actions", { "group": "Deployment integrations", - "pages": [ - "vercel-integration" - ] + "pages": ["vercel-integration"] } ] }, @@ -164,13 +144,7 @@ "errors-retrying", { "group": "Wait", - "pages": [ - "wait", - "wait-for", - "wait-until", - "wait-for-event", - "wait-for-request" - ] + "pages": ["wait", "wait-for", "wait-until", "wait-for-event", "wait-for-request"] }, "queue-concurrency", "versioning", @@ -188,10 +162,7 @@ "management/overview", { "group": "Tasks API", - "pages": [ - "management/tasks/trigger", - "management/tasks/batch-trigger" - ] + "pages": ["management/tasks/trigger", "management/tasks/batch-trigger"] }, { "group": "Runs API", @@ -230,9 +201,7 @@ }, { "group": "Projects API", - "pages": [ - "management/projects/runs" - ] + "pages": ["management/projects/runs"] } ] }, @@ -278,11 +247,7 @@ }, { "group": "Help", - "pages": [ - "community", - "help-slack", - "help-email" - ] + "pages": ["community", "help-slack", "help-email"] }, { "group": "Frameworks", @@ -315,6 +280,7 @@ "guides/examples/puppeteer", "guides/examples/sharp-image-processing", "guides/examples/stripe-webhook", + "guides/examples/supabase-database-operations", "guides/examples/supabase-storage-upload", "guides/examples/react-pdf", "guides/examples/resend-email-sequence", @@ -323,15 +289,11 @@ }, { "group": "Dashboard", - "pages": [ - "guides/dashboard/creating-a-project" - ] + "pages": ["guides/dashboard/creating-a-project"] }, { "group": "Migrations", - "pages": [ - "guides/use-cases/upgrading-from-v2" - ] + "pages": ["guides/use-cases/upgrading-from-v2"] } ], "footerSocials": { @@ -339,4 +301,4 @@ "github": "https://github.com/triggerdotdev", "linkedin": "https://www.linkedin.com/company/triggerdotdev" } -} \ No newline at end of file +} diff --git a/docs/snippets/supabase-docs-cards.mdx b/docs/snippets/supabase-docs-cards.mdx new file mode 100644 index 0000000000..857b39f0c1 --- /dev/null +++ b/docs/snippets/supabase-docs-cards.mdx @@ -0,0 +1,35 @@ +## Learn more about Supabase and Trigger.dev + +### Full walkthrough guides from development to deployment + + + + Learn how to trigger a task from a Supabase edge function when a URL is visited. + + + Learn how to trigger a task from a Supabase edge function when an event occurs in your database. + + + +### Task examples with code you can copy and paste + + + + Run basic CRUD operations on a table in a Supabase database using Trigger.dev. + + + Download a video from a URL and upload it to Supabase Storage using S3. + +