diff --git a/.changeset/many-cats-beg.md b/.changeset/many-cats-beg.md new file mode 100644 index 000000000..7c87aeddc --- /dev/null +++ b/.changeset/many-cats-beg.md @@ -0,0 +1,5 @@ +--- +"@trigger.dev/supabase": patch +--- + +Automatically enable database webhooks when using triggers diff --git a/docs/integrations/apis/supabase/management.mdx b/docs/integrations/apis/supabase/management.mdx index 2ce8a4c47..4ddf0c8a4 100644 --- a/docs/integrations/apis/supabase/management.mdx +++ b/docs/integrations/apis/supabase/management.mdx @@ -87,6 +87,11 @@ The `SupabaseManagement` integration also provides the ability to trigger jobs b ### Enable Database Webhooks + + These steps are only needed if you are using `@trigger.dev/supabase` at version `2.0.2` or + earlier. + + Currently the Supabase Management API does not provide a way to enable database webhooks, so you'll need to do this manually. You can do this by visiting your [Database Webhooks settings](https://supabase.com/dashboard/project/_/database/hooks) and clicking the "Enable webhooks" button: diff --git a/examples/job-catalog/package.json b/examples/job-catalog/package.json index f8f395e46..2059420da 100644 --- a/examples/job-catalog/package.json +++ b/examples/job-catalog/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "stripe": "nodemon --watch src/stripe.ts -r tsconfig-paths/register -r dotenv/config src/stripe.ts", + "supabase": "nodemon --watch src/supabase.ts -r tsconfig-paths/register -r dotenv/config src/supabase.ts", "dev:trigger": "trigger-cli dev --port 8080" }, "dependencies": { @@ -16,6 +17,7 @@ "@trigger.dev/slack": "workspace:*", "@trigger.dev/stripe": "workspace:*", "@trigger.dev/typeform": "workspace:*", + "@trigger.dev/supabase": "workspace:*", "@types/node": "20.4.2", "typescript": "5.1.6", "zod": "3.21.4" diff --git a/examples/job-catalog/src/supabase.ts b/examples/job-catalog/src/supabase.ts new file mode 100644 index 000000000..d9237afa1 --- /dev/null +++ b/examples/job-catalog/src/supabase.ts @@ -0,0 +1,41 @@ +import { TriggerClient, eventTrigger } from "@trigger.dev/sdk"; +import { createExpressServer } from "@trigger.dev/express"; +import { z } from "zod"; +import { SupabaseManagement } from "@trigger.dev/supabase"; + +const supabaseManagement = new SupabaseManagement({ + id: "supabase-management", + apiKey: process.env["SUPABASE_API_KEY"]!, +}); + +const db = supabaseManagement.db(process.env["SUPABASE_ID"]!); + +export const client = new TriggerClient({ + id: "job-catalog", + apiKey: process.env["TRIGGER_API_KEY"], + apiUrl: process.env["TRIGGER_API_URL"], + verbose: false, + ioLogLocalEnabled: true, +}); + +createExpressServer(client); + +client.defineJob({ + id: "supabase-management-example-1", + name: "Supabase Management Example 1", + version: "0.1.0", + trigger: db.onInserted({ + table: "users", + }), + run: async (payload, io, ctx) => {}, +}); + +client.defineJob({ + id: "supabase-management-example-2", + name: "Supabase Management Example 2", + version: "0.1.0", + trigger: db.onUpdated({ + table: "users", + }), + run: async (payload, io, ctx) => {}, +}); diff --git a/integrations/supabase/package.json b/integrations/supabase/package.json index a7636de3f..15aac5ecb 100644 --- a/integrations/supabase/package.json +++ b/integrations/supabase/package.json @@ -28,7 +28,7 @@ "@supabase/supabase-js": "^2.26.0", "@trigger.dev/integration-kit": "workspace:^2.0.2", "@trigger.dev/sdk": "workspace:^2.0.2", - "supabase-management-js": "^0.1.3", + "supabase-management-js": "^0.1.4", "zod": "3.21.4" }, "engines": { diff --git a/integrations/supabase/src/management/index.ts b/integrations/supabase/src/management/index.ts index 35efe0f9e..a88a7c6f9 100644 --- a/integrations/supabase/src/management/index.ts +++ b/integrations/supabase/src/management/index.ts @@ -7,6 +7,7 @@ import { IntegrationClient, Logger, TriggerIntegration, + isTriggerError, } from "@trigger.dev/sdk"; import { SupabaseManagementAPI } from "supabase-management-js"; import { z } from "zod"; @@ -293,6 +294,19 @@ export function createWebhookEventSource( const url = new URL(httpSource.url); const id = url.pathname.split("/").pop() ?? randomUUID(); + try { + await io.integration.enableDatabaseWebhooks("enable-webhooks", { ref: params.projectRef }); + } catch (error) { + if (isTriggerError(error)) { + throw error; + } + + await io.logger.info( + "Enabling database webhooks failed, probably because it is already enabled. Continuing...", + { error } + ); + } + // Create the trigger name using the last 12 characters of the id const triggerName = `tr_${id.slice(-12)}`; diff --git a/integrations/supabase/src/management/tasks.ts b/integrations/supabase/src/management/tasks.ts index 9bb627303..f74d1b675 100644 --- a/integrations/supabase/src/management/tasks.ts +++ b/integrations/supabase/src/management/tasks.ts @@ -181,3 +181,27 @@ export const getPGConfig: AuthenticatedTask< }; }, }; + +/** Enable Database Webhooks in project */ +export const enableDatabaseWebhooks: AuthenticatedTask< + SupabaseManagementAPI, + { ref: string }, + void +> = { + run: async (params, client) => { + return client.enableWebhooks(params.ref); + }, + init: (params) => { + return { + name: "Enable Database Webhooks", + params, + icon: "supabase", + properties: [ + { + label: "Project", + text: params.ref, + }, + ], + }; + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 278e75af5..4d9cc08fa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -362,6 +362,7 @@ importers: '@trigger.dev/sdk': workspace:* '@trigger.dev/slack': workspace:* '@trigger.dev/stripe': workspace:* + '@trigger.dev/supabase': workspace:* '@trigger.dev/tsconfig': workspace:* '@trigger.dev/typeform': workspace:* '@types/node': 20.4.2 @@ -381,6 +382,7 @@ importers: '@trigger.dev/sdk': link:../../packages/trigger-sdk '@trigger.dev/slack': link:../../integrations/slack '@trigger.dev/stripe': link:../../integrations/stripe + '@trigger.dev/supabase': link:../../integrations/supabase '@trigger.dev/typeform': link:../../integrations/typeform '@types/node': 20.4.2 typescript: 5.1.6 @@ -705,7 +707,7 @@ importers: '@trigger.dev/sdk': workspace:^2.0.2 '@types/node': 18.x rimraf: ^3.0.2 - supabase-management-js: ^0.1.3 + supabase-management-js: ^0.1.4 tsup: 7.1.x typescript: 4.9.4 zod: 3.21.4 @@ -713,7 +715,7 @@ importers: '@supabase/supabase-js': 2.31.0 '@trigger.dev/integration-kit': link:../../packages/integration-kit '@trigger.dev/sdk': link:../../packages/trigger-sdk - supabase-management-js: 0.1.3 + supabase-management-js: 0.1.4 zod: 3.21.4 devDependencies: '@types/node': 18.15.13 @@ -23046,8 +23048,8 @@ packages: pirates: 4.0.5 ts-interface-checker: 0.1.13 - /supabase-management-js/0.1.3: - resolution: {integrity: sha512-5y1EINERs+AZnzvgZfA4wmj78EKQOmSmgI6IEgg1bMEGpc7q6zXZnVS8zNAyYay/ort9inYefMqExRvbXXJpEA==} + /supabase-management-js/0.1.4: + resolution: {integrity: sha512-yx4LxYrRl4uoXaWLDndJpjiMR+LfYZ7UGWnGP7mXzD31vyTi9XFc0cYBn6luejZuJ/plO5L64pj7rHwM8PlfkA==} engines: {node: '>=18.0.0'} dependencies: openapi-fetch: 0.6.2