Skip to content

Commit 87031aa

Browse files
committed
Pagination helper and docs
1 parent b72a8da commit 87031aa

File tree

3 files changed

+151
-5
lines changed

3 files changed

+151
-5
lines changed

docs/integrations/apis/linear.mdx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,72 @@ client.defineJob({
122122
});
123123
```
124124

125+
### Pagination
126+
127+
You can paginate responses three different ways:
128+
129+
1. Via the raw Linear SDK exposed in `io.runTask()`
130+
2. Iterating the same integration task with different params
131+
3. Using the `getAll` helper exposed on the integration (**recommended!**)
132+
133+
_When ordering results, make sure to use the `PaginationOrderBy` enum._
134+
135+
```ts
136+
import { Linear, PaginationOrderBy, serializeLinearOutput } from "@trigger.dev/linear";
137+
...
138+
client.defineJob({
139+
id: "linear-pagination",
140+
name: "Linear Pagination",
141+
version: "0.1.0",
142+
integrations: {
143+
linear,
144+
},
145+
trigger: eventTrigger({
146+
name: "linear.paginate",
147+
}),
148+
run: async (payload, io, ctx) => {
149+
//the same params will be used for all tasks
150+
const params = { first: 5, orderBy: PaginationOrderBy.UpdatedAt };
151+
152+
//1. Linear SDK
153+
const sdkIssues = await io.linear.runTask("all-issues-via-sdk", async (client) => {
154+
const edges = await client.issues(params);
155+
156+
//this will keep appending nodes until there are no more
157+
while (edges.pageInfo.hasNextPage) {
158+
await edges.fetchNext();
159+
}
160+
161+
//use serialization helper to remove functions etc
162+
return serializeLinearOutput(edges.nodes);
163+
});
164+
165+
//2. Linear integration - no pagination helper
166+
let edges = await io.linear.issues("get-issues", params);
167+
let noHelper = edges.nodes;
168+
169+
for (let i = 0; edges.pageInfo.hasNextPage; i++) {
170+
edges = await io.linear.issues(`get-more-issues-${i}`, {
171+
...params,
172+
after: edges.pageInfo.endCursor,
173+
});
174+
noHelper = noHelper.concat(edges.nodes);
175+
}
176+
177+
//3. Linear integration - with the pagination helper
178+
const withHelper = await io.linear.getAll(io.linear.issues, "get-all", params);
179+
180+
return {
181+
issueCounts: {
182+
withSdk: sdkIssues.length,
183+
noHelper: noHelper.length,
184+
withHelper: withHelper.length,
185+
},
186+
};
187+
},
188+
});
189+
```
190+
125191
## Triggers
126192

127193
### Attachments

integrations/linear/src/index.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
Comment,
1818
CommentConnection,
1919
CommentPayload,
20+
Connection,
2021
CreateOrJoinOrganizationResponse,
2122
CycleArchivePayload,
2223
CyclePayload,
@@ -42,6 +43,7 @@ import {
4243
IssueRelationPayload,
4344
IssueSearchPayload,
4445
LinearClient,
46+
LinearDocument,
4547
LinearError,
4648
Notification,
4749
NotificationArchivePayload,
@@ -80,8 +82,6 @@ import {
8082
WorkflowStateConnection,
8183
WorkflowStatePayload,
8284
} from "@linear/sdk";
83-
import * as events from "./events";
84-
import { TriggerParams, Webhooks, createTrigger, createWebhookEventSource } from "./webhooks";
8585
import {
8686
ArchiveIssueMutationVariables,
8787
ArchiveProjectMutationVariables,
@@ -139,8 +139,11 @@ import {
139139
WorkflowStateCreateInput,
140140
WorkflowStatesQueryVariables,
141141
} from "@linear/sdk/dist/_generated_documents";
142+
143+
import * as events from "./events";
142144
import { AwaitNested, LinearReturnType, SerializedLinearOutput } from "./types";
143-
import { queryProperties } from "./utils";
145+
import { Nullable, QueryVariables, queryProperties } from "./utils";
146+
import { TriggerParams, Webhooks, createTrigger, createWebhookEventSource } from "./webhooks";
144147

145148
export type LinearIntegrationOptions = {
146149
id: string;
@@ -228,6 +231,29 @@ export class Linear implements TriggerIntegration {
228231
);
229232
}
230233

234+
async getAll<
235+
TTask extends (
236+
key: IntegrationTaskKey,
237+
params: Partial<Nullable<QueryVariables>>
238+
) => LinearReturnType<Connection<unknown>>,
239+
>(
240+
task: TTask,
241+
key: IntegrationTaskKey,
242+
params: Nullable<QueryVariables> = {}
243+
): Promise<Awaited<ReturnType<TTask>>["nodes"]> {
244+
const boundTask = task.bind(this);
245+
246+
let edges = await boundTask(`${key}-0`, params);
247+
let nodes = edges.nodes;
248+
249+
for (let i = 1; edges.pageInfo.hasNextPage; i++) {
250+
edges = await boundTask(`${key}-${i}`, { ...params, after: edges.pageInfo.endCursor });
251+
nodes = nodes.concat(edges.nodes);
252+
}
253+
254+
return nodes;
255+
}
256+
231257
attachment(key: IntegrationTaskKey, params: { id: string }): LinearReturnType<Attachment> {
232258
return this.runTask(
233259
key,
@@ -2056,3 +2082,5 @@ export const serializeLinearOutput = <T>(obj: T): Prettify<SerializedLinearOutpu
20562082
};
20572083

20582084
export { events };
2085+
2086+
export const PaginationOrderBy = LinearDocument.PaginationOrderBy

references/job-catalog/src/linear.ts

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createExpressServer } from "@trigger.dev/express";
22
import { TriggerClient, eventTrigger } from "@trigger.dev/sdk";
3-
import { Linear, serializeLinearOutput } from "@trigger.dev/linear";
3+
import { Linear, PaginationOrderBy, serializeLinearOutput } from "@trigger.dev/linear";
44
import { z } from "zod";
55

66
export const client = new TriggerClient({
@@ -87,7 +87,7 @@ client.defineJob({
8787
await io.linear.viewer("get-viewer");
8888
await io.linear.organization("get-org");
8989

90-
const fourDigits = Math.floor(Math.random() * 1000)
90+
const fourDigits = Math.floor(Math.random() * 1000);
9191

9292
//create an organization
9393
await io.linear.createOrganizationFromOnboarding("create-org", {
@@ -118,4 +118,56 @@ client.defineJob({
118118
},
119119
});
120120

121+
client.defineJob({
122+
id: "linear-pagination",
123+
name: "Linear Pagination",
124+
version: "0.1.0",
125+
integrations: {
126+
linear,
127+
},
128+
trigger: eventTrigger({
129+
name: "linear.paginate",
130+
}),
131+
run: async (payload, io, ctx) => {
132+
//the same params will be used for all tasks
133+
const params = { first: 5, orderBy: PaginationOrderBy.UpdatedAt };
134+
135+
//1. Linear SDK
136+
const sdkIssues = await io.linear.runTask("all-issues-via-sdk", async (client) => {
137+
const edges = await client.issues(params);
138+
139+
//this will keep appending nodes until there are no more
140+
while (edges.pageInfo.hasNextPage) {
141+
await edges.fetchNext();
142+
}
143+
144+
//use serialization helper to remove functions etc
145+
return serializeLinearOutput(edges.nodes);
146+
});
147+
148+
//2. Linear integration - no pagination helper
149+
let edges = await io.linear.issues("get-issues", params);
150+
let noHelper = edges.nodes;
151+
152+
for (let i = 0; edges.pageInfo.hasNextPage; i++) {
153+
edges = await io.linear.issues(`get-more-issues-${i}`, {
154+
...params,
155+
after: edges.pageInfo.endCursor,
156+
});
157+
noHelper = noHelper.concat(edges.nodes);
158+
}
159+
160+
//3. Linear integration - with the pagination helper
161+
const withHelper = await io.linear.getAll(io.linear.issues, "get-all", params);
162+
163+
return {
164+
issueCounts: {
165+
withSdk: sdkIssues.length,
166+
noHelper: noHelper.length,
167+
withHelper: withHelper.length,
168+
},
169+
};
170+
},
171+
});
172+
121173
createExpressServer(client);

0 commit comments

Comments
 (0)