xref: /expo/tools/src/Linear.ts (revision 9d7b0c19)
1import { IssueLabel, LinearClient, User, WorkflowState } from '@linear/sdk';
2import {
3  IssueCreateInput,
4  IssueLabelFilter,
5  UserFilter,
6} from '@linear/sdk/dist/_generated_documents';
7
8const linearClient = new LinearClient({
9  apiKey: process.env.LINEAR_API_KEY ?? '<LINEAR-API-KEY>',
10});
11
12export const ENG_TEAM_ID = 'e678ab8b-874f-4ee2-bf4b-6c0b60ac2743';
13
14/**
15 * Creates a new issue.
16 * Defaults teamId to the Engineering team.
17 */
18export async function createIssueAsync(
19  issueInput: Omit<IssueCreateInput, 'teamId'> & Partial<IssueCreateInput>
20) {
21  await linearClient.createIssue({
22    teamId: ENG_TEAM_ID,
23    ...issueInput,
24  });
25}
26
27/**
28 * Gets a label by name or creates it if it doesn't exist.
29 *
30 */
31export async function getOrCreateLabelAsync(
32  labelName: string,
33  teamId?: string
34): Promise<IssueLabel> {
35  const filter: IssueLabelFilter = { name: { eq: labelName } };
36  if (teamId) {
37    filter.team = { id: { eq: teamId } };
38  }
39
40  const labels = await linearClient.issueLabels({ filter });
41  if (labels.nodes[0]) {
42    return labels.nodes[0];
43  }
44
45  const payload = await linearClient.createIssueLabel({ name: labelName });
46  const label = await payload.issueLabel;
47
48  if (!label) {
49    throw new Error(`Failed to create Linear label: ${labelName}`);
50  }
51
52  return label;
53}
54
55/**
56 * Gets a workflow state by name and team ID.
57 */
58export async function getTeamWorkflowStateAsync(
59  workflowState: string,
60  teamId: string
61): Promise<WorkflowState> {
62  const team = await linearClient.team(teamId);
63  const states = await team.states({ filter: { name: { eq: workflowState } } });
64  const state = states.nodes?.[0];
65
66  if (!state) {
67    throw new Error(`Failed to find Linear state: ${state}`);
68  }
69
70  return state;
71}
72
73/**
74 * Gets a workflow state by name and team ID.
75 */
76export async function getTeamMembersAsync({
77  filter,
78  teamId,
79}: {
80  filter?: UserFilter;
81  teamId: string;
82}): Promise<User[]> {
83  const team = await linearClient.team(teamId);
84  const states = await team.members({ filter });
85
86  return states.nodes;
87}
88