feat: BYO Auth (#491)
* feat: BYO Auth Define client-side auth resolvers to be able to supply custom authentication credentials for integrations before a run is performed - Added new defineAuthResolver - Update all integrations to support the new auth resolvers - Strip internal symbols from .d.ts in integrations and trigger-sdk - Added BYO Auth docs - Update Dynamic Schedule to support associated account IDs - Create external accounts just-in-time - Added Account ID field to test job when there are external auth integrations - Show Account ID on run dashboard - Added new Run error state called “Unresolved auth” * Added changeset * Remove @internal from TriggerIntegration public methods * Add void to the result union * DynamicTriggers now work with the new BYO auth system, and added a bunch of docs and docs changes * Add additional key material for registering dynamic trigger task * Add new define* instance methods to the overview
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
<CodeGroup>
|
||||
|
||||
```bash npm
|
||||
npm install @trigger.dev/slack@latest
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm install @trigger.dev/slack@latest
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add @trigger.dev/slack@latest
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
@@ -0,0 +1,49 @@
|
||||
<ParamField body="options" type="object" required>
|
||||
<Expandable title="properties" defaultOpen>
|
||||
<ParamField body="id" type="string" required>
|
||||
The `id` property is used to uniquely identify the Job. Only change this if you want to create a new Job.
|
||||
</ParamField>
|
||||
<ParamField body="name" type="string" required>
|
||||
The `name` of the Job that you want to appear in the dashboard and logs. You can change this without creating a new Job.
|
||||
</ParamField>
|
||||
<ParamField body="version" type="string" required>
|
||||
The `version` property is used to version your Job. A new version will be created if you change this property. We recommend using [semantic versioning](https://www.baeldung.com/cs/semantic-versioning), e.g. `1.0.3`.
|
||||
</ParamField>
|
||||
<ParamField body="trigger" type="object" required>
|
||||
The `trigger` property is used to define when the Job should run. There are currently the following Trigger types:
|
||||
- [cronTrigger](/sdk/crontrigger)
|
||||
- [intervalTrigger](/sdk/intervaltrigger)
|
||||
- [eventTrigger](/sdk/eventtrigger)
|
||||
- [DynamicTrigger](/sdk/dynamictrigger)
|
||||
- [DynamicSchedule](/sdk/dynamicschedule)
|
||||
- integration Triggers, like webhooks. See the [integrations](/integrations) page for more information.
|
||||
</ParamField>
|
||||
<ParamField body="run" type="function" required>
|
||||
This function gets called automatically when a Run is Triggered. It has three parameters:
|
||||
1. `payload` – The payload that was sent to the Trigger API.
|
||||
2. [io](/sdk/io) – An object that contains the integrations that you specified in the `integrations` property and other useful functions like delays and running Tasks.
|
||||
3. [context](/sdk/context) – An object that contains information about the Organization, Job, Run and more.
|
||||
|
||||
This is where you put the code you want to run for a Job. You can use normal code in here and you can also use Tasks.
|
||||
|
||||
You can return a value from this function and it will be sent back to the Trigger API.
|
||||
</ParamField>
|
||||
<ParamField body="integrations" type="object">
|
||||
Imports the specified integrations into the Job. The integrations will be available on the `io` object in the `run()` function with the same name as the key. For example:
|
||||
<Snippet file="how-to-pass-integrations.mdx" />
|
||||
</ParamField>
|
||||
<ParamField body="enabled" type="boolean">
|
||||
The `enabled` property is an optional property that specifies whether the Job is enabled or not. The Job will be enabled by default if you omit this property. When a job is disabled, no new runs will be triggered or resumed. In progress runs will continue to run until they are finished or delayed by using `io.wait`.
|
||||
</ParamField>
|
||||
<ParamField body="logLevel" type="log | error | warn | info | debug">
|
||||
The `logLevel` property is an optional property that specifies the level of
|
||||
logging for the Job. The level is inherited from the client if you omit this property.
|
||||
- `log` - logs only essential messages
|
||||
- `error` - logs error messages
|
||||
- `warn` - logs errors and warning messages
|
||||
- `info` - logs errors, warnings and info messages
|
||||
- `debug` - logs everything with full verbosity
|
||||
</ParamField>
|
||||
|
||||
</Expandable>
|
||||
</ParamField>
|
||||
@@ -12,7 +12,7 @@ Sometimes you don't know when you write the code what the trigger or schedule wi
|
||||
|
||||
```typescript
|
||||
//1. create a DynamicSchedule
|
||||
const dynamicSchedule = new DynamicSchedule(client, {
|
||||
const dynamicSchedule = client.defineDynamicSchedule({
|
||||
id: "dynamicinterval",
|
||||
});
|
||||
|
||||
@@ -53,15 +53,18 @@ client.defineJob({
|
||||
}),
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
//6. Register the DynamicSchedule
|
||||
await io.registerInterval("📆", dynamicSchedule, payload.userId, {
|
||||
seconds: payload.seconds,
|
||||
//6. Register the DynamicSchedule (this will automatically create a task)
|
||||
await dynamicSchedule.register(userId, {
|
||||
type: "cron",
|
||||
options: {
|
||||
cron: userSchedule,
|
||||
},
|
||||
});
|
||||
|
||||
await io.wait("wait", 60);
|
||||
|
||||
//7. Unregister the DynamicSchedule if you want
|
||||
await io.unregisterInterval("❌📆", dynamicSchedule, payload.id);
|
||||
//7. Unregister the DynamicSchedule if you want (this will automatically create a task)
|
||||
await dynamicSchedule.unregister(userId);
|
||||
},
|
||||
});
|
||||
```
|
||||
@@ -70,7 +73,7 @@ client.defineJob({
|
||||
|
||||
```typescript
|
||||
//1. create a DynamicTrigger
|
||||
const dynamicOnIssueOpenedTrigger = new DynamicTrigger(client, {
|
||||
const dynamicOnIssueOpenedTrigger = client.defineDynamicTrigger({
|
||||
id: "github-issue-opened",
|
||||
event: events.onIssueOpened,
|
||||
source: github.sources.repo,
|
||||
@@ -96,7 +99,7 @@ client.defineJob({
|
||||
//3. Register the DynamicTrigger anywhere in your app
|
||||
async function registerRepo(owner: string, repo: string) {
|
||||
//the first param (key) should be unique
|
||||
await dynamicOnIssueOpenedTrigger.register(`${owner}/${repo}`, {
|
||||
await dynamicOnIssueOpenedTrigger.register(`${owner}-${repo}`, {
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
@@ -114,15 +117,10 @@ client.defineJob({
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
//6. Register the dynamic trigger so you get notified when an issue is opened
|
||||
return await io.registerTrigger(
|
||||
"register-repo",
|
||||
dynamicOnIssueOpenedTrigger,
|
||||
payload.repository.name,
|
||||
{
|
||||
owner: payload.repository.owner.login,
|
||||
repo: payload.repository.name,
|
||||
}
|
||||
);
|
||||
await dynamicOnIssueOpenedTrigger.register(`${owner}-${repo}`, {
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: "API Keys and Personal Access Tokens"
|
||||
description: "Lots of APIs use API Keys or Personal Access Tokens to authenticate. This guide will show you how to use them."
|
||||
sidebarTitle: "API Keys and PATs"
|
||||
---
|
||||
|
||||
## 1. Create an Integration client
|
||||
|
||||
@@ -0,0 +1,515 @@
|
||||
---
|
||||
title: "Bring Your Own Auth"
|
||||
description: "Use Auth Resolvers to provide custom authentication credentials"
|
||||
---
|
||||
|
||||
In the previous guides we've covered how you can use our integrations with [API Keys](/documentation/guides/using-integrations-apikeys) or [OAuth](/documentation/guides/using-integrations-oauth), but in both cases those authentication credentials belong **to you** the developer.
|
||||
|
||||
If you want to use our integrations using auth credentials of **your users** you can use an Auth Resolver which allows you to implement your own custom auth resolving using a third-party service like [Clerk](https://clerk.com/) or [Nango](https://www.nango.dev/)
|
||||
|
||||
In this guide we'll demonstrate how to use Clerk.com's [Social Connections](https://clerk.com/docs/authentication/social-connections/oauth) to allow you to make requests with your user's Slack credentials and the official Trigger.dev [Slack integration](/integrations/apis/slack)
|
||||
|
||||
<Note>
|
||||
We won't be covering how to setup Clerk.com and their Social Connections to get the auth. This
|
||||
guide assumes you already have all that setup.
|
||||
</Note>
|
||||
|
||||
## 1. Install the Slack integration package
|
||||
|
||||
<Snippet file="installs/slack.mdx" />
|
||||
|
||||
## 2. Create a Slack integration
|
||||
|
||||
```ts slack.ts
|
||||
import { Slack } from "@trigger.dev/slack";
|
||||
|
||||
const byoSlack = new Slack({
|
||||
id: "byo-slack",
|
||||
});
|
||||
```
|
||||
|
||||
## 3. Define an Auth Resolver
|
||||
|
||||
Using your `TriggerClient` instance, define a new Auth Resolver for the `slack` integration:
|
||||
|
||||
```ts slack.ts
|
||||
import { Slack } from "@trigger.dev/slack";
|
||||
// Import your TriggerClient instance. This is merely an example of how you could do it
|
||||
import { client } from "./trigger";
|
||||
|
||||
const byoSlack = new Slack({
|
||||
id: "byo-slack",
|
||||
});
|
||||
|
||||
client.defineAuthResolver(byoSlack, async (ctx) => {
|
||||
// this is where we'll use the clerk backend SDK
|
||||
});
|
||||
```
|
||||
|
||||
## 4. Define a job
|
||||
|
||||
Before we finish the Slack Auth Resolver, let's create an example job that uses the Slack integration:
|
||||
|
||||
```ts slack.ts
|
||||
import { z } from "zod";
|
||||
|
||||
client.defineJob({
|
||||
id: "post-a-message",
|
||||
name: "Post a Slack Message",
|
||||
version: "1.0.0",
|
||||
trigger: eventTrigger({
|
||||
name: "post.message",
|
||||
schema: z.object({
|
||||
text: z.string(),
|
||||
channel: z.string(),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
slack: byoSlack,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.slack.postMessage("💬", {
|
||||
channel: payload.channel,
|
||||
text: payload.text,
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
As you can see above, we're passing the `byoSlack` integration into the Job and using it by calling `io.slack.postMessage`.
|
||||
|
||||
## 5. Install the Clerk backend SDK
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash npm
|
||||
npm install @clerk/backend@latest
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm install @clerk/backend@latest
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add @clerk/backend@latest
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## 6. Import and initialize the Clerk SDK
|
||||
|
||||
```ts slack.ts
|
||||
import { Clerk } from "@clerk/backend";
|
||||
|
||||
// Clerk is not a class so the omission of `new Clerk` here is on purpose
|
||||
const clerk = Clerk({ apiKey: process.env.CLERK_API_KEY });
|
||||
```
|
||||
|
||||
## 7. Implement the Auth Resolver
|
||||
|
||||
Now we'll implement the Auth Resolver to provide authentication credentials saved in Clerk.com for Job runs, depending on the account ID of the run.
|
||||
|
||||
```ts slack.ts
|
||||
client.defineAuthResolver(slack, async (ctx) => {
|
||||
if (!ctx.account?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tokens = await clerk.users.getUserOauthAccessToken(ctx.account.id, "oauth_slack");
|
||||
|
||||
if (tokens.length === 0) {
|
||||
throw new Error(`Could not find Slack auth for account ${ctx.account.id}`);
|
||||
}
|
||||
|
||||
return {
|
||||
type: "oauth",
|
||||
token: tokens[0].token,
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
The first parameter to the Auth Resolver callback is the run context ([reference docs](/sdk/context)), which optionally contains an associated account (more on this below).
|
||||
|
||||
<Warning>
|
||||
If the Auth Resolver returns undefined or throws an Error, any Job Run that uses the `byoSlack`
|
||||
integration will fail with an "Unresolved auth" error.
|
||||
</Warning>
|
||||
|
||||
## Bonus: Multiple Slack integration clients
|
||||
|
||||
If you want to also use Slack with your own authentication credentials, you can always create _another_ slack integration with a different `id`.
|
||||
|
||||
```ts slack.ts
|
||||
const ourSlack = new Slack({ id: "our-slack" });
|
||||
|
||||
client.defineJob({
|
||||
id: "post-a-message",
|
||||
name: "Post a Slack Message",
|
||||
version: "1.0.0",
|
||||
trigger: eventTrigger({
|
||||
name: "post.message",
|
||||
schema: z.object({
|
||||
text: z.string(),
|
||||
channel: z.string(),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
byoSlack: byoSlack,
|
||||
ourSlack: ourSlack,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.byoSlack.postMessage("💬", {
|
||||
channel: payload.channel,
|
||||
text: payload.text,
|
||||
});
|
||||
|
||||
await io.ourSlack.postMessage("📢", {
|
||||
channel: "C01234567",
|
||||
text: `We just sent the following message to ${ctx.account?.id}: ${payload.text}`,
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
# How to Trigger Job runs with an Account ID
|
||||
|
||||
Now that we have a working Clerk.com Auth Resolver for Slack we're ready to start triggering jobs with an associated account ID. The way you do this is different depending on the Trigger type.
|
||||
|
||||
## Event Triggers
|
||||
|
||||
Jobs that have [Event Triggers](/documentation/concepts/triggers/events) can be run with an associated account by providing an `accountId` when calling `sendEvent`:
|
||||
|
||||
```ts backend.ts
|
||||
// This is an instance of `TriggerClient`
|
||||
await client.sendEvent(
|
||||
{
|
||||
name: "post.created",
|
||||
payload: { id: "post_123" },
|
||||
},
|
||||
{
|
||||
accountId: "user_123",
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
The `accountId` value is completely arbitrary and doesn't map to anything inside Trigger.dev, but generally it should be a unique ID that can be used to lookup Auth credentials in your Auth Resolvers.
|
||||
|
||||
You can also send events with an associated account ID from the run of another job:
|
||||
|
||||
```ts anotherJob.ts
|
||||
client.defineJob({
|
||||
id: "event-1",
|
||||
name: "Run when the foo.bar event happens",
|
||||
version: "0.0.1",
|
||||
trigger: eventTrigger({
|
||||
name: "foo.bar",
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
//send an event using `io`
|
||||
await io.sendEvent(
|
||||
"🎫",
|
||||
{
|
||||
name: "post.created",
|
||||
payload: { id: "post_123" },
|
||||
},
|
||||
{
|
||||
accountId: "user_123",
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
When a run is triggered with an associated account ID, you'll see the account ID in the run dashboard:
|
||||
|
||||

|
||||
|
||||
## Scheduled Triggers
|
||||
|
||||
Running a job with an associated account ID that is triggered by a [Scheduled Trigger](/documentation/concepts/triggers/scheduled) works a bit differently than Event Triggers as you'll need to convert your normal `intervalTrigger` or `cronTrigger` into using a [Dynamic Schedule](/documentation/concepts/triggers/dynamic#dynamicschedule) and then registering schedules with an associated account ID.
|
||||
|
||||
### 1. Convert a job to using a Dynamic Schedule
|
||||
|
||||
First let's convert the following job from an `intervalTrigger` to a Dynamic Schedule:
|
||||
|
||||
```ts dynamicSchedule.ts
|
||||
// Before
|
||||
client.defineJob({
|
||||
id: "scheduled-job",
|
||||
name: "Scheduled Job",
|
||||
version: "1.0.0",
|
||||
trigger: intervalTrigger({
|
||||
seconds: 60,
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.logger.info("This runs every 60 seconds");
|
||||
},
|
||||
});
|
||||
|
||||
// After
|
||||
export const dynamicInterval = client.defineDynamicSchedule({ id: "my-schedule" });
|
||||
|
||||
client.defineJob({
|
||||
id: "scheduled-job",
|
||||
name: "Scheduled Job",
|
||||
version: "1.0.0",
|
||||
trigger: dynamicInterval,
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.logger.info("This runs dynamic schedules");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
As you can see above, we've dropped the specific interval when defining the trigger as that will now be specific when registering schedules.
|
||||
|
||||
### 2. Register a schedule
|
||||
|
||||
You can now use the `dynamicInterval` instance to register a schedule, which will trigger the `scheduled-job`:
|
||||
|
||||
```ts backend.ts
|
||||
import { dynamicInterval } from "./dynamicSchedule";
|
||||
|
||||
// Somewhere in your backend
|
||||
await dynamicInterval.register("schedule_123", {
|
||||
type: "interval",
|
||||
options: { seconds: 60 },
|
||||
accountId: "user_123", // associate runs triggered by this schedule with user_123
|
||||
});
|
||||
```
|
||||
|
||||
As you can see above, we've associated this registered schedule with an `accountId`, so any runs triggered by this schedule will be associated with `"user_123"`
|
||||
|
||||
The first parameter above `"schedule_123"` is the Schedule ID and can be used to unregister the schedule at a later point:
|
||||
|
||||
```ts backend.ts
|
||||
import { dynamicInterval } from "./dynamicSchedule";
|
||||
|
||||
// Somewhere in your backend
|
||||
await dynamicInterval.unregister("schedule_123");
|
||||
```
|
||||
|
||||
You can also use register/unregister inside another job run and it will automatically create a [Task](/documentation/concepts/tasks):
|
||||
|
||||
```ts otherJob.ts
|
||||
import { dynamicInterval } from "./dynamicSchedule";
|
||||
|
||||
client.defineJob({
|
||||
id: "event-1",
|
||||
name: "Run when the foo.bar event happens",
|
||||
version: "0.0.1",
|
||||
trigger: eventTrigger({
|
||||
name: "foo.bar",
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
await dynamicInterval.register("schedule_123", {
|
||||
type: "interval",
|
||||
options: { seconds: 60 },
|
||||
accountId: "user_123", // associate runs triggered by this schedule with user_123
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Will produce the following run dashboard:
|
||||
|
||||

|
||||
|
||||
<Tip>
|
||||
If you will only ever add a single schedule for a user on a given Dynamic Schedule, you can just
|
||||
use the accountId as the Schedule ID
|
||||
|
||||
```ts
|
||||
const accountId = "user_123";
|
||||
await dynamicInterval.register(accountId, {
|
||||
type: "interval",
|
||||
options: { seconds: 60 },
|
||||
accountId,
|
||||
});
|
||||
```
|
||||
|
||||
</Tip>
|
||||
|
||||
## Webhook Triggers
|
||||
|
||||
Running a job with an associated account ID that is triggered by a [Webhook Trigger](/documentation/concepts/triggers/webhook) requires converting to the use of a [Dynamic Trigger](/documentation/concepts/triggers/dynamic#dynamictrigger)
|
||||
|
||||
Dynamic Trigger's work very similarly to Dynamic Schedules, but instead of registering schedules, you register triggers:
|
||||
|
||||
<Steps>
|
||||
<Step title="Create Dynamic Trigger">
|
||||
|
||||
Using the GitHub integration we'll create a Dynamic Trigger that is triggered by the `onIssueOpened` event:
|
||||
|
||||
```ts github.ts
|
||||
import { Github, events } from "@trigger.dev/github";
|
||||
|
||||
const github = new Github({
|
||||
id: "github",
|
||||
});
|
||||
|
||||
const dynamicOnIssueOpenedTrigger = client.defineDynamicTrigger({
|
||||
id: "github-issue-opened",
|
||||
event: events.onIssueOpened,
|
||||
source: github.sources.repo,
|
||||
});
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Use the Dynamic Trigger">
|
||||
|
||||
Now we'll use the Dynamic Trigger to define a Job that is triggered by it:
|
||||
|
||||
```ts github.ts
|
||||
client.defineJob({
|
||||
id: "listen-for-dynamic-trigger",
|
||||
name: "Listen for dynamic trigger",
|
||||
version: "0.1.1",
|
||||
trigger: dynamicOnIssueOpenedTrigger,
|
||||
integrations: {
|
||||
github,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.github.issues.createComment("create-issue-comment", {
|
||||
owner: payload.repository.owner.login,
|
||||
repo: payload.repository.name,
|
||||
issueNumber: payload.issue.number,
|
||||
body: "First! 🥇",
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Define Auth Resolver">
|
||||
|
||||
Define an Auth Resolver to fetch the GitHub OAuth token from Clerk.com:
|
||||
|
||||
```ts github.ts
|
||||
client.defineAuthResolver(github, async (ctx) => {
|
||||
if (!ctx.account?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tokens = await clerk.users.getUserOauthAccessToken(ctx.account.id, "oauth_github");
|
||||
|
||||
if (tokens.length === 0) {
|
||||
throw new Error(`Could not find GitHub auth for account ${ctx.account.id}`);
|
||||
}
|
||||
|
||||
return {
|
||||
type: "oauth",
|
||||
token: tokens[0].token,
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
<Note>
|
||||
If you are using clerk, you'll probably want to [Add additional
|
||||
scopes](https://clerk.com/docs/authentication/social-connections/oauth#request-additional-o-auth-scopes-after-sign-up)
|
||||
to be able to do useful things with the GitHub integration. For example, if you plan on
|
||||
registering GitHub triggers you'll need `write:repo_hook` and `read:repo_hook` or just
|
||||
`admin:repo_hook`. If you want to create issues you'll need `repo` or `public_repo`.
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Register a new trigger">
|
||||
|
||||
Finally, we can register a new Trigger at "runtime", either inside another Job run or in your backend:
|
||||
|
||||
```ts github.ts
|
||||
// Register inside another job run:
|
||||
client.defineJob({
|
||||
id: "register-issue-opened",
|
||||
name: "Register Issue Opened for Account",
|
||||
version: "0.0.1",
|
||||
trigger: eventTrigger({
|
||||
name: "register.issue.opened",
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
// This will automatically create a task in this run with the `payload.id` as the Task Key.
|
||||
await dynamicOnIssueOpenedTrigger.register(
|
||||
payload.id,
|
||||
{
|
||||
owner: payload.owner,
|
||||
repo: payload.repo,
|
||||
},
|
||||
{
|
||||
accountId: payload.accountId,
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// Register in your backend:
|
||||
// This skips creating a Task since it's outside a job and will just call our backend API directly
|
||||
async function registerIssueOpenedTrigger(
|
||||
id: string,
|
||||
owner: string,
|
||||
repo: string,
|
||||
accountId?: string
|
||||
) {
|
||||
return await dynamicOnIssueOpenedTrigger.register(
|
||||
id,
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
},
|
||||
{
|
||||
accountId,
|
||||
}
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
# Testing jobs with Account ID
|
||||
|
||||
If a job uses any integrations with an Auth Resolver that requires an account ID, you'll need to provide an account ID when testing the job:
|
||||
|
||||

|
||||
|
||||
# Auth Resolver reference
|
||||
|
||||
The Auth Resolver callback has the following signature:
|
||||
|
||||
```ts
|
||||
type TriggerAuthResolver = (
|
||||
ctx: TriggerContext,
|
||||
integration: TriggerIntegration
|
||||
) => Promise<AuthResolverResult | undefined>;
|
||||
|
||||
type AuthResolverResult = {
|
||||
type: "apiKey" | "oauth";
|
||||
token: string;
|
||||
additionalFields?: Record<string, string>;
|
||||
};
|
||||
```
|
||||
|
||||
The `ctx` parameter is the [TriggerContext](/sdk/context) for the run and the `integration` parameter is the [TriggerIntegration](/sdk/integrations) instance that the Auth Resolver is being called for. You can use the `integration` parameter to check the `id` of the integration to determine which integration the Auth Resolver is being called for:
|
||||
|
||||
```ts
|
||||
client.defineAuthResolver(slack, async (ctx, integration) => {
|
||||
if (integration.id === "byo-slack") {
|
||||
// do something
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
You can also return `additionalFields` in the Auth Resolver result which will be passed to the integration when making requests. This is useful if you need to provide additional fields to the integration that are not part of the standard integration options.
|
||||
|
||||
```ts
|
||||
client.defineAuthResolver(shopify, async (ctx, integration) => {
|
||||
return {
|
||||
type: "apiKey",
|
||||
token: "my-api-key",
|
||||
additionalFields: {
|
||||
shop: "my-shop-name",
|
||||
},
|
||||
};
|
||||
});
|
||||
```
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
title: "Using Integrations"
|
||||
description: "How to use Integrations"
|
||||
title: "Integrations Overview"
|
||||
description: "How to use Trigger.dev Integrations"
|
||||
sidebarTitle: "Overview"
|
||||
---
|
||||
|
||||
<Note>
|
||||
You can use any API in your Jobs by using existing Node.js SDKs or HTTP
|
||||
requests. Integrations just make it much easier especially when you want to
|
||||
use OAuth. And you get great logging.
|
||||
You can use any API in your Jobs by using existing Node.js SDKs or HTTP requests. Integrations
|
||||
just make it much easier especially when you want to use OAuth. And you get great logging.
|
||||
</Note>
|
||||
|
||||
[Integrations](/documentation/concepts/integrations) allow you to quickly use APIs, including webhooks and Tasks.
|
||||
@@ -37,6 +37,14 @@ There are two ways to authenticate Integrations, OAuth and API Keys/Access Token
|
||||
>
|
||||
Use OAuth to connect an Integration for your team or your users
|
||||
</Card>
|
||||
<Card
|
||||
title="Bring-your-own Auth"
|
||||
icon="user"
|
||||
href="/documentation/guides/using-integrations-byo-auth"
|
||||
>
|
||||
Use our integrations with your user’s auth credentials, using Clerk.com, Nango.dev, or rolling
|
||||
your own with our custom auth resolvers
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Using for Jobs & Tasks
|
||||
@@ -121,7 +129,7 @@ import { Stripe } from "@trigger.dev/stripe";
|
||||
|
||||
const stripe = new Stripe({
|
||||
id: "stripe",
|
||||
apiKey: process.env.STRIPE_SECRET_KEY!
|
||||
apiKey: process.env.STRIPE_SECRET_KEY!,
|
||||
});
|
||||
|
||||
async function createCustomer() {
|
||||
@@ -161,7 +169,6 @@ client.defineJob({
|
||||
Behind the scenes, our `@trigger.dev/github` integration will create a webhook on your repository that will call our API when a new push event is received. We will then start your Job with the payload from the push event.
|
||||
|
||||
<Note>
|
||||
If you are just using an integration to trigger a job but not using
|
||||
authenticated tasks inside the job run, there is no need to pass the
|
||||
integration in the job `integrations` option.
|
||||
If you are just using an integration to trigger a job but not using authenticated tasks inside the
|
||||
job run, there is no need to pass the integration in the job `integrations` option.
|
||||
</Note>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 291 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 153 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
+19
-7
@@ -151,7 +151,6 @@
|
||||
"documentation/guides/manual/fastify"
|
||||
]
|
||||
},
|
||||
|
||||
"documentation/guides/running-jobs",
|
||||
"documentation/guides/jobs/managing",
|
||||
{
|
||||
@@ -168,7 +167,8 @@
|
||||
"pages": [
|
||||
"documentation/guides/using-integrations",
|
||||
"documentation/guides/using-integrations-apikeys",
|
||||
"documentation/guides/using-integrations-oauth"
|
||||
"documentation/guides/using-integrations-oauth",
|
||||
"documentation/guides/using-integrations-byo-auth"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -277,7 +277,11 @@
|
||||
"sdk/triggerclient/instancemethods/sendevent",
|
||||
"sdk/triggerclient/instancemethods/getevent",
|
||||
"sdk/triggerclient/instancemethods/getruns",
|
||||
"sdk/triggerclient/instancemethods/getrun"
|
||||
"sdk/triggerclient/instancemethods/getrun",
|
||||
"sdk/triggerclient/instancemethods/define-job",
|
||||
"sdk/triggerclient/instancemethods/define-dynamic-trigger",
|
||||
"sdk/triggerclient/instancemethods/define-dynamic-schedule",
|
||||
"sdk/triggerclient/instancemethods/define-auth-resolver"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -311,7 +315,10 @@
|
||||
"sdk/dynamictrigger/constructor",
|
||||
{
|
||||
"group": "Instance methods",
|
||||
"pages": ["sdk/dynamictrigger/register", "sdk/dynamictrigger/unregister"]
|
||||
"pages": [
|
||||
"sdk/dynamictrigger/register",
|
||||
"sdk/dynamictrigger/unregister"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -322,7 +329,10 @@
|
||||
"sdk/dynamicschedule/constructor",
|
||||
{
|
||||
"group": "Instance methods",
|
||||
"pages": ["sdk/dynamicschedule/register", "sdk/dynamicschedule/unregister"]
|
||||
"pages": [
|
||||
"sdk/dynamicschedule/register",
|
||||
"sdk/dynamicschedule/unregister"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -343,7 +353,9 @@
|
||||
},
|
||||
{
|
||||
"group": "Overview",
|
||||
"pages": ["examples/introduction"]
|
||||
"pages": [
|
||||
"examples/introduction"
|
||||
]
|
||||
}
|
||||
],
|
||||
"footerSocials": {
|
||||
@@ -356,4 +368,4 @@
|
||||
"apiKey": "phc_hwYmedO564b3Ik8nhA4Csrb5SueY0EwFJWCbseGwWW"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ Use this method to unregister a schedule from the DynamicSchedule, using the id
|
||||
|
||||
```typescript
|
||||
//1. create a DynamicSchedule
|
||||
const dynamicSchedule = new DynamicSchedule(client, {
|
||||
const dynamicSchedule = client.defineDynamicSchedule({
|
||||
id: "dynamicinterval",
|
||||
});
|
||||
|
||||
@@ -76,14 +76,17 @@ client.defineJob({
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
//6. Register the DynamicSchedule
|
||||
await io.registerInterval("📆", dynamicSchedule, payload.userId, {
|
||||
seconds: payload.seconds,
|
||||
await dynamicSchedule.register(payload.userId, {
|
||||
type: "interval",
|
||||
options: {
|
||||
seconds: payload.seconds,
|
||||
},
|
||||
});
|
||||
|
||||
await io.wait("wait", 60);
|
||||
|
||||
//7. Unregister the DynamicSchedule if you want
|
||||
await io.unregisterInterval("❌📆", dynamicSchedule, payload.id);
|
||||
//7. Unregister the DynamicSchedule at some later date
|
||||
await dynamicSchedule.unregister(payload.userId);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
@@ -7,8 +7,8 @@ description: "Use this method to register a new schedule with the DynamicSchedul
|
||||
## Parameters
|
||||
|
||||
<ResponseField name="id" type="string" required>
|
||||
The id of the schedule to register. The identifier you use will be available
|
||||
in the `context.source.id` when the Job runs.
|
||||
The id of the schedule to register. The identifier you use will be available in the
|
||||
`context.source.id` when the Job runs.
|
||||
</ResponseField>
|
||||
<ResponseField name="schedule" type="Schedule" required>
|
||||
The schedule to register. It is either a `cron` or `interval` schedule.
|
||||
@@ -24,8 +24,13 @@ description: "Use this method to register a new schedule with the DynamicSchedul
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
<ResponseField name="metadata" type="any">
|
||||
Any additional data you wish to store with the schedule. This will be
|
||||
available in the `context.source.metadata` when the Job runs.
|
||||
Any additional data you wish to store with the schedule. This will be available in the
|
||||
`context.source.metadata` when the Job runs.
|
||||
</ResponseField>
|
||||
<ResponseField name="accountId" type="string">
|
||||
An optional account ID to use when running the job. This will be available in the Job
|
||||
[context](/sdk/context) and can be used in [auth
|
||||
resolvers](/sdk/triggerclient/instancemethods/define-auth-resolver)
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
<Expandable title="interval">
|
||||
@@ -40,8 +45,13 @@ description: "Use this method to register a new schedule with the DynamicSchedul
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
<ResponseField name="metadata" type="any">
|
||||
Any additional data you wish to store with the schedule. This will be
|
||||
available in the `context.source.metadata` when the Job runs.
|
||||
Any additional data you wish to store with the schedule. This will be available in the
|
||||
`context.source.metadata` when the Job runs.
|
||||
</ResponseField>
|
||||
<ResponseField name="accountId" type="string">
|
||||
An optional account ID to use when running the job. This will be available in the Job
|
||||
[context](/sdk/context) and can be used in [auth
|
||||
resolvers](/sdk/triggerclient/instancemethods/define-auth-resolver)
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
@@ -16,9 +16,8 @@ description: "The `DynamicTrigger()` constructor creates a new [DynamicTrigger](
|
||||
Used to uniquely identify a DynamicTrigger
|
||||
</ResponseField>
|
||||
<ResponseField name="event" type="event" required>
|
||||
An event from an [Integration](/integrations) package that you want to
|
||||
attach to the DynamicTrigger. The event types will come through to the
|
||||
payload in your Job's run.
|
||||
An event from an [Integration](/integrations) package that you want to attach to the
|
||||
DynamicTrigger. The event types will come through to the payload in your Job's run.
|
||||
</ResponseField>
|
||||
<ResponseField name="source" type="source" required>
|
||||
An external source fron an [Integration](/integrations) package
|
||||
|
||||
@@ -9,7 +9,7 @@ Sometimes you want to subscribe to a webhook but you don't know the exact config
|
||||
|
||||
### [DynamicTrigger()](/sdk/dynamictrigger/constructor)
|
||||
|
||||
Creates a new `DynamicTrigger` instance.
|
||||
Creates a new `DynamicTrigger` instance. You should use the [`TriggerClient.defineDynamicTrigger`]() method instead of calling this directly.
|
||||
|
||||
## Instance methods
|
||||
|
||||
@@ -33,7 +33,7 @@ Use this method to unregister a schedule from the DynamicTrigger, using the id y
|
||||
|
||||
```typescript DynamicTrigger
|
||||
//1. create a DynamicTrigger
|
||||
const dynamicOnIssueOpenedTrigger = new DynamicTrigger(client, {
|
||||
const dynamicOnIssueOpenedTrigger = client.defineDynamicTrigger({
|
||||
id: "github-issue-opened",
|
||||
event: events.onIssueOpened,
|
||||
source: github.sources.repo,
|
||||
@@ -59,7 +59,7 @@ client.defineJob({
|
||||
//3. Register the DynamicTrigger anywhere in your app
|
||||
async function registerRepo(owner: string, repo: string) {
|
||||
//the first param (key) should be unique
|
||||
await dynamicOnIssueOpenedTrigger.register(`${owner}/${repo}`, {
|
||||
await dynamicOnIssueOpenedTrigger.register(`${owner}-${repo}`, {
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
@@ -76,16 +76,13 @@ client.defineJob({
|
||||
org: "triggerdotdev",
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
//6. Register the dynamic trigger so you get notified when an issue is opened
|
||||
return await io.registerTrigger(
|
||||
"register-repo",
|
||||
dynamicOnIssueOpenedTrigger,
|
||||
payload.repository.name,
|
||||
{
|
||||
owner: payload.repository.owner.login,
|
||||
repo: payload.repository.name,
|
||||
}
|
||||
);
|
||||
const owner = payload.repository.owner.login;
|
||||
const repo = payload.repository.name;
|
||||
//6. Register the dynamic trigger so you get notified when an issue is opened. A task will automatically be created
|
||||
await dynamicOnIssueOpenedTrigger.register(`${owner}-${repo}`, {
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
@@ -7,12 +7,25 @@ description: "Use this method to register a new configuration with the DynamicTr
|
||||
## Parameters
|
||||
|
||||
<ResponseField name="id" type="string" required>
|
||||
The id of the registration. The identifier you use will be available in the
|
||||
`context.source.id` when the Job runs. It will also be used to unregister.
|
||||
The id of the registration. The identifier you use will be available in the `context.source.id`
|
||||
when the Job runs. It will also be used to unregister.
|
||||
</ResponseField>
|
||||
<ResponseField name="params" type="Object" required>
|
||||
The shape of this object will depend on the type of event you set when
|
||||
constructing the `DynamicTrigger`.
|
||||
The shape of this object will depend on the type of event you set when constructing the
|
||||
`DynamicTrigger`.
|
||||
</ResponseField>
|
||||
<ResponseField name="options" type="object">
|
||||
<Expandable title="fields" defaultOpen>
|
||||
<ResponseField name="accountId" type="string">
|
||||
An optional account ID to use when running the job. This will be available in the Job
|
||||
[context](/sdk/context) and can be used in [auth
|
||||
resolvers](/sdk/triggerclient/instancemethods/define-auth-resolver)
|
||||
</ResponseField>
|
||||
<ResponseField name="filter" type="EventFilter">
|
||||
An optional filter to apply to the event. See our [EventFilter
|
||||
guide](/documentation/guides/event-filter) for more
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
## Returns
|
||||
|
||||
@@ -4,6 +4,10 @@ sidebarTitle: "registerCron()"
|
||||
description: "`io.registerCron()` allows you to register a [DynamicSchedule](/sdk/dynamicschedule) that will trigger any jobs it's attached to on a regular CRON schedule."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
This has been deprecated in favor of [DynamicSchedule.register](/sdk/dynamicschedule/register)
|
||||
</Warning>
|
||||
|
||||
## Parameters
|
||||
|
||||
<Snippet file="stable-key-param.mdx" />
|
||||
|
||||
@@ -4,6 +4,10 @@ sidebarTitle: "registerInterval()"
|
||||
description: "`io.registerInterval()` allows you to register a [DynamicSchedule](/sdk/dynamicschedule) that will trigger any jobs it's attached to on a regular interval."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
This has been deprecated in favor of [DynamicSchedule.register](/sdk/dynamicschedule/register)
|
||||
</Warning>
|
||||
|
||||
## Parameters
|
||||
|
||||
<Snippet file="stable-key-param.mdx" />
|
||||
|
||||
@@ -4,6 +4,10 @@ sidebarTitle: "registerTrigger()"
|
||||
description: "`io.registerTrigger()` allows you to register a [DynamicTrigger](/sdk/dynamictrigger) with the specified trigger data."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
This has been deprecated in favor of [DynamicTrigger.register](/sdk/dynamictrigger/register)
|
||||
</Warning>
|
||||
|
||||
## Parameters
|
||||
|
||||
<Snippet file="stable-key-param.mdx" />
|
||||
@@ -30,9 +34,9 @@ A Promise that resolves to an object with the following fields:
|
||||
|
||||
## Example
|
||||
|
||||
```typescript
|
||||
```ts
|
||||
//1. create a DynamicTrigger
|
||||
const dynamicOnIssueOpenedTrigger = new DynamicTrigger(client, {
|
||||
const dynamicOnIssueOpenedTrigger = client.defineDynamicTrigger({
|
||||
id: "github-issue-opened",
|
||||
event: events.onIssueOpened,
|
||||
source: github.sources.repo,
|
||||
|
||||
@@ -4,6 +4,10 @@ sidebarTitle: "unregisterCron()"
|
||||
description: "`io.unregisterCron()` allows you to unregister a [DynamicSchedule](/sdk/dynamicschedule) that was previously registered with `io.registerCron()`."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
This has been deprecated in favor of [DynamicSchedule.unregister](/sdk/dynamicschedule/unregister)
|
||||
</Warning>
|
||||
|
||||
## Parameters
|
||||
|
||||
<Snippet file="stable-key-param.mdx" />
|
||||
|
||||
@@ -4,6 +4,10 @@ sidebarTitle: "unregisterInterval()"
|
||||
description: "`io.unregisterInterval()` allows you to unregister a [DynamicSchedule](/sdk/dynamicschedule) that was previously registered with `io.registerInterval()`."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
This has been deprecated in favor of [DynamicSchedule.unregister](/sdk/dynamicschedule/unregister)
|
||||
</Warning>
|
||||
|
||||
## Parameters
|
||||
|
||||
<Snippet file="stable-key-param.mdx" />
|
||||
|
||||
@@ -4,6 +4,10 @@ sidebarTitle: "unregisterTrigger()"
|
||||
description: "`io.unregisterTrigger()` allows you to unregister a [DynamicTrigger](/sdk/dynamictrigger) that was previously registered with `io.registerTrigger()`."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
This has been deprecated in favor of [DynamicTrigger.unregister](/sdk/dynamictrigger/unregister)
|
||||
</Warning>
|
||||
|
||||
## Parameters
|
||||
|
||||
<Snippet file="stable-key-param.mdx" />
|
||||
|
||||
+1
-49
@@ -59,55 +59,7 @@ client.defineJob({
|
||||
An instance of [TriggerClient](/sdk/triggerclient) that is used to send events to the Trigger API.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="options" type="object" required>
|
||||
<Expandable title="properties" defaultOpen>
|
||||
<ParamField body="id" type="string" required>
|
||||
The `id` property is used to uniquely identify the Job. Only change this if you want to create a new Job.
|
||||
</ParamField>
|
||||
<ParamField body="name" type="string" required>
|
||||
The `name` of the Job that you want to appear in the dashboard and logs. You can change this without creating a new Job.
|
||||
</ParamField>
|
||||
<ParamField body="version" type="string" required>
|
||||
The `version` property is used to version your Job. A new version will be created if you change this property. We recommend using [semantic versioning](https://www.baeldung.com/cs/semantic-versioning), e.g. `1.0.3`.
|
||||
</ParamField>
|
||||
<ParamField body="trigger" type="object" required>
|
||||
The `trigger` property is used to define when the Job should run. There are currently the following Trigger types:
|
||||
- [cronTrigger](/sdk/crontrigger)
|
||||
- [intervalTrigger](/sdk/intervaltrigger)
|
||||
- [eventTrigger](/sdk/eventtrigger)
|
||||
- [DynamicTrigger](/sdk/dynamictrigger)
|
||||
- [DynamicSchedule](/sdk/dynamicschedule)
|
||||
- integration Triggers, like webhooks. See the [integrations](/integrations) page for more information.
|
||||
</ParamField>
|
||||
<ParamField body="run" type="function" required>
|
||||
This function gets called automatically when a Run is Triggered. It has three parameters:
|
||||
1. `payload` – The payload that was sent to the Trigger API.
|
||||
2. [io](/sdk/io) – An object that contains the integrations that you specified in the `integrations` property and other useful functions like delays and running Tasks.
|
||||
3. [context](/sdk/context) – An object that contains information about the Organization, Job, Run and more.
|
||||
|
||||
This is where you put the code you want to run for a Job. You can use normal code in here and you can also use Tasks.
|
||||
|
||||
You can return a value from this function and it will be sent back to the Trigger API.
|
||||
</ParamField>
|
||||
<ParamField body="integrations" type="object">
|
||||
Imports the specified integrations into the Job. The integrations will be available on the `io` object in the `run()` function with the same name as the key. For example:
|
||||
<Snippet file="how-to-pass-integrations.mdx" />
|
||||
</ParamField>
|
||||
<ParamField body="enabled" type="boolean">
|
||||
The `enabled` property is an optional property that specifies whether the Job is enabled or not. The Job will be enabled by default if you omit this property. When a job is disabled, no new runs will be triggered or resumed. In progress runs will continue to run until they are finished or delayed by using `io.wait`.
|
||||
</ParamField>
|
||||
<ParamField body="logLevel" type="log | error | warn | info | debug">
|
||||
The `logLevel` property is an optional property that specifies the level of
|
||||
logging for the Job. The level is inherited from the client if you omit this property.
|
||||
- `log` - logs only essential messages
|
||||
- `error` - logs error messages
|
||||
- `warn` - logs errors and warning messages
|
||||
- `info` - logs errors, warnings and info messages
|
||||
- `debug` - logs everything with full verbosity
|
||||
</ParamField>
|
||||
|
||||
</Expandable>
|
||||
</ParamField>
|
||||
<Snippet file="jobs/options.mdx" />
|
||||
|
||||
## Returns
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: "defineAuthResolver()"
|
||||
description: "Define a custom auth resolver for a specific integration"
|
||||
---
|
||||
|
||||
Auth Resolvers allow you to inject the authentication credentials of **your users**, using a third-party service like [Clerk](https://clerk.com/) or [Nango](https://www.nango.dev/) or your own custom solution.
|
||||
|
||||
See our [Bring-your-own Auth Guide](/documentation/guides/using-integrations-byo-auth) for more about how this works.
|
||||
|
||||
<RequestExample>
|
||||
|
||||
```ts example
|
||||
client.defineAuthResolver(slack, async (ctx) => {
|
||||
if (!ctx.account?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tokens = await clerk.users.getUserOauthAccessToken(ctx.account.id, "oauth_slack");
|
||||
|
||||
if (tokens.length === 0) {
|
||||
throw new Error(`Could not find Slack auth for account ${ctx.account.id}`);
|
||||
}
|
||||
|
||||
return {
|
||||
type: "oauth",
|
||||
token: tokens[0].token,
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
</RequestExample>
|
||||
|
||||
## Parameters
|
||||
|
||||
<ParamField body="integration" type="TriggerIntegration" required>
|
||||
The Integration client (e.g. `slack`) to define the auth resolver for.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="resolver" type="AuthResolver" required>
|
||||
The resolver function to use for this integration. Should return a [AuthResolverResult](#authresolverresult) object.
|
||||
|
||||
{" "}
|
||||
|
||||
<Expandable title="arguments" defaultOpen>
|
||||
<ParamField body="ctx" type="TriggerContext" required>
|
||||
The [TriggerContext](/sdk/context) object for the run that is requesting authentication.
|
||||
</ParamField>
|
||||
<ParamField body="integration" type="TriggerIntegration">
|
||||
The Integration client that is requesting authentication.
|
||||
</ParamField>
|
||||
</Expandable>
|
||||
|
||||
</ParamField>
|
||||
|
||||
## AuthResolverResult
|
||||
|
||||
<ParamField body="type" type="string" required>
|
||||
Should be either "apiKey" or "oauth"
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="token" type="string" required>
|
||||
The authentication token to use for this integration.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="additionalFields" type="Record<string, string>">
|
||||
Additional fields to pass to the integration.
|
||||
</ParamField>
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
title: "defineDynamicSchedule()"
|
||||
description: "Define a Dynamic Schedule"
|
||||
---
|
||||
|
||||
## Parameters
|
||||
|
||||
<ResponseField name="options" type="DynamicScheduleOptions" required>
|
||||
The options for the dynamic schedule.
|
||||
<Expandable title="options" defaultOpen>
|
||||
<ResponseField name="id" type="string" required>
|
||||
Used to uniquely identify a DynamicSchedule
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
## Returns
|
||||
|
||||
<ResponseField name="DynamicSchedule instance" type="DynamicSchedule" />
|
||||
|
||||
<RequestExample>
|
||||
|
||||
```ts example
|
||||
const dynamicSchedule = client.defineDynamicSchedule({
|
||||
id: "dynamicinterval",
|
||||
});
|
||||
```
|
||||
|
||||
</RequestExample>
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "defineDynamicTrigger()"
|
||||
description: "Define a Dynamic Trigger"
|
||||
---
|
||||
|
||||
## Parameters
|
||||
|
||||
<ResponseField name="options" type="DynamicTriggerOptions" required>
|
||||
The options for the dynamic trigger.
|
||||
<Expandable title="options" defaultOpen>
|
||||
<ResponseField name="id" type="string" required>
|
||||
Used to uniquely identify a DynamicTrigger
|
||||
</ResponseField>
|
||||
<ResponseField name="event" type="event" required>
|
||||
An event from an [Integration](/integrations) package that you want to attach to the
|
||||
DynamicTrigger. The event types will come through to the payload in your Job's run.
|
||||
</ResponseField>
|
||||
<ResponseField name="source" type="source" required>
|
||||
An external source fron an [Integration](/integrations) package
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
## Returns
|
||||
|
||||
<ResponseField name="DynamicTrigger instance" type="DynamicTrigger" />
|
||||
|
||||
<RequestExample>
|
||||
|
||||
```ts example
|
||||
const dynamicOnIssueOpenedTrigger = client.defineDynamicTrigger({
|
||||
id: "github-issue-opened",
|
||||
event: events.onIssueOpened,
|
||||
source: github.sources.repo,
|
||||
});
|
||||
```
|
||||
|
||||
</RequestExample>
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
title: "defineJob()"
|
||||
description: "Defines a job"
|
||||
---
|
||||
|
||||
A [Job](/documentation/concepts/jobs) is used to define the [Trigger](/documentation/concepts/triggers), metadata, and what happens when it runs.
|
||||
|
||||
<RequestExample>
|
||||
|
||||
```ts example
|
||||
client.defineJob({
|
||||
id: "github-integration-on-issue",
|
||||
name: "GitHub Integration - On Issue",
|
||||
version: "0.1.0",
|
||||
trigger: github.triggers.repo({
|
||||
event: events.onIssue,
|
||||
owner: "triggerdotdev",
|
||||
repo: "empty",
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.logger.info("This is a simple log info message");
|
||||
return { payload, ctx };
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
</RequestExample>
|
||||
|
||||
## Parameters
|
||||
|
||||
<Snippet file="jobs/options.mdx" />
|
||||
|
||||
## Returns
|
||||
|
||||
<ResponseField name="Job instance" type="Job" />
|
||||
@@ -4,7 +4,7 @@ sidebarTitle: "sendEvent()"
|
||||
description: "The `sendEvent()` instance method send an event that triggers any Jobs that are listening for that event (based on the name)."
|
||||
---
|
||||
|
||||
You can call this function from anywhere in your code to send an event. The other way to send an event is by using [io.sendEvent()](/sdk/io/sendevent) from inside a `run()` function.
|
||||
You can call this function from anywhere in your backend to send an event. The other way to send an event is by using [io.sendEvent()](/sdk/io/sendevent) from inside a `run()` function.
|
||||
|
||||
Use [eventTrigger()](/sdk/eventtrigger) on a Job to listen for events.
|
||||
|
||||
|
||||
@@ -43,3 +43,19 @@ The `getRuns()` method gets runs for a Job.
|
||||
#### [getRun()](/sdk/triggerclient/instancemethods/getrun)
|
||||
|
||||
The `getRun()` method gets the details for a given Run.
|
||||
|
||||
#### [defineJob()](/sdk/triggerclient/instancemethods/define-job)
|
||||
|
||||
The `defineJob()` method defines a new Job.
|
||||
|
||||
#### [defineDynamicTrigger()](/sdk/triggerclient/instancemethods/define-dynamic-trigger)
|
||||
|
||||
The `defineDynamicTrigger()` method defines a new Dynamic Trigger.
|
||||
|
||||
#### [defineDynamicSchedule()](/sdk/triggerclient/instancemethods/define-dynamic-schedule)
|
||||
|
||||
The `defineDynamicSchedule()` method defines a new Dynamic Schedule.
|
||||
|
||||
#### [defineAuthResolver()](/sdk/triggerclient/instancemethods/define-auth-resolver)
|
||||
|
||||
The `defineAuthResolver()` method defines a new Auth Resolver.
|
||||
|
||||
Reference in New Issue
Block a user