Files
triggerdotdev--trigger.dev/docs/integrations/create-client.mdx
T

129 lines
4.3 KiB
Plaintext

---
title: Creating the client
description: "Each integration has a client that performs the actual HTTP requests. Usually this is a wrapper around an official SDK provided by the service."
---
### `src/index.ts`
This is where the client should live.
<Tip>
We're adopting the naming convention of naming the class after the service, without a suffix or
prefix. We prefer the exported name be `Slack` instead of something like `SlackIntegration` or
`SlackConnector`
</Tip>
## Example: GitHub
Comments are for instructional purposes only and should be removed in your implementation.
```ts
import { ConnectionAuth, IO, TriggerIntegration } from "@trigger.dev/sdk";
//the official GitHub SDK
import { Octokit } from "octokit";
//define the options that will be passed to the constructor
export type GithubIntegrationOptions = {
//this is required
id: string;
//GitHub can use OAuth or Personal Access Tokens, so this is optional
token?: string;
};
export class Github implements TriggerIntegration {
private _options: GithubIntegrationOptions;
private _client?: Octokit;
private _io?: IO;
private _connectionKey?: string;
constructor(private options: GithubIntegrationOptions) {
//if the token key is present but undefined, throw an error
//this is NOT the same as just: if (!options.token)
//it's a common user bug where an env var is used for the token but hasn't been set
if (Object.keys(options).includes("token") && !options.token) {
throw `Can't create GitHub integration (${options.id}) as token was undefined`;
}
this._options = options;
}
//this is used internally to identify the integration
get id() {
return this.options.id;
}
//this is used internally to identify the integration, and display nicely in the dashboard
get metadata() {
return { name: "GitHub", id: "github" };
}
//the two possible options are "LOCAL" or "HOSTED"
//LOCAL means that the client is using local auth (like a token)
//HOSTED means that the client is using hosted auth (like OAuth)
//GitHub supports both, and we use the presence of the token to determine which one to use
get authSource() {
return this._options.token ? ("LOCAL" as const) : ("HOSTED" as const);
}
//before the `run()` method is called on a Job, this function gets invoked
//this is important because the authentication data is dynamic, and can change (like OAuth credentials refreshing)
cloneForRun(io: IO, connectionKey: string, auth?: ConnectionAuth) {
const github = new Github(this._options);
github._io = io;
github._connectionKey = connectionKey;
if (this._options.token) {
github._client = new Octokit({
auth: this._options.token,
retry: {
enabled: false,
},
});
} else {
if (!auth) {
throw new Error("No auth");
}
github._client = new Octokit({
auth: auth.accessToken,
retry: {
enabled: false,
},
});
}
return github;
}
}
```
The `TriggerIntegration` interface requires three properties and one method to be implemented:
<ParamField body="id" type="string" required>
The `id` that uniquely identifies the Integration. This should always be passed through the
constructor options.
</ParamField>
<ParamField body="metadata" type="object" required>
<Expandable title="properties">
<ParamField body="id" type="string" required>
A unique identifier for the Integration. For example, the OpenAI Integration has an id of
`"openai"`.
</ParamField>
<ParamField body="name" type="string" required>
The name of the Integration. For example, the OpenAI Integration has a name of `"OpenAI"`.
</ParamField>
</Expandable>
</ParamField>
<ParamField body="authSource" type="LOCAL | HOSTED" required>
"LOCAL" should be returned for API keys. "HOSTED" should be returned for OAuth.
</ParamField>
<ParamField body="cloneForRun" type="function" required>
This method is called before the `run()` method is called on a Job. This is important because the
authentication data is dynamic, and can change (like OAuth credentials refreshing). This method
should return a new instance of the Integration, with the new authentication data, io, and
connectionKey set so they can be used by runTask and any Triggers.
</ParamField>