-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathLinearClient.ts
225 lines (202 loc) · 5.25 KB
/
LinearClient.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import axios from "axios";
import { AirbyteLogger } from "faros-airbyte-cdk/lib";
import {
Attachment,
AuditEntry,
Comment,
Document,
Issue,
IssueHistory,
IssueLabel,
IssueRelation,
Organization,
Project,
ProjectLink,
ProjectUpdate,
Team,
TeamKey,
TeamMembership,
User,
WorkflowState,
} from "./types";
const LINEAR_API_BASE_URL = "https://api.linear.app/export/";
/**
* Linear client configuration
*/
export type Config = {
// access token provided in linear airbyte integration
apiKey: string;
};
/*
* The supported entity types.
*/
export type EntityType =
| "issue"
| "organization"
| "team"
| "teamkey"
| "teammembership"
| "user"
| "project"
| "projectupdate"
| "projectlink"
| "issuehistory"
| "issuelabel"
| "issuerelation"
| "attachment"
| "auditentry"
| "cycle"
| "workflowstate"
| "document"
| "comment";
/**
* Thin client on top of the rest export api to fetch different resources.
*/
export class LinearClient {
public constructor(
private readonly config: Config,
private readonly logger: AirbyteLogger
) {}
/**
* @returns List of all issues in organization.
*/
public async issues(): Promise<Issue[]> {
return await this.fetchEntities<Issue>("issue");
}
/**
* @returns List of all teams in organization.
*/
public async teams(): Promise<Team[]> {
return await this.fetchEntities<Team>("team");
}
/**
* @returns List of all users in organization.
*/
public async users(): Promise<User[]> {
return await this.fetchEntities<User>("user");
}
/**
* @returns List of all team keys in organization.
*/
public async teamKeys(): Promise<TeamKey[]> {
return await this.fetchEntities<TeamKey>("teamkey");
}
/**
* @returns List of all team memberships in organization.
*/
public async teamMemberships(): Promise<TeamMembership[]> {
return await this.fetchEntities<TeamMembership>("teammembership");
}
/**
* @returns List of all projects in organization.
*/
public async projects(): Promise<Project[]> {
return await this.fetchEntities<Project>("project");
}
/**
* @returns List of all projects in organization.
*/
public async projectUpdates(): Promise<ProjectUpdate[]> {
return await this.fetchEntities<ProjectUpdate>("projectupdate");
}
/**
* @returns List of all project links in organization.
*/
public async projectLinks(): Promise<ProjectLink[]> {
return await this.fetchEntities<ProjectLink>("projectlink");
}
/**
* @returns List of all issue history entries in organization.
*/
public async issueHistory(): Promise<IssueHistory[]> {
return await this.fetchEntities<IssueHistory>("issuehistory");
}
/**
* @returns List of all issue labels in organization.
*/
public async issueLabels(): Promise<IssueLabel[]> {
return await this.fetchEntities<IssueLabel>("issuelabel");
}
/**
* @returns List of all issue relations in organization.
*/
public async issueRelations(): Promise<IssueRelation[]> {
return await this.fetchEntities<IssueRelation>("issuerelation");
}
/**
* @returns List of all attachments in organization.
*/
public async attachments(): Promise<Attachment[]> {
return await this.fetchEntities<Attachment>("attachment");
}
/**
* @returns List of all audit entries in organization.
*/
public async auditEntries(): Promise<AuditEntry[]> {
return await this.fetchEntities<AuditEntry>("auditentry");
}
/**
* @returns List of all comments in organization.
*/
public async comments(): Promise<Comment[]> {
return await this.fetchEntities<Comment>("comment");
}
/**
* @returns List of all cycles in organization.
*/
public async cycles(): Promise<Comment[]> {
return await this.fetchEntities<Comment>("cycle");
}
/**
* @returns List of all workflow states in organization.
*/
public async workflowStates(): Promise<WorkflowState[]> {
return await this.fetchEntities<WorkflowState>("workflowstate");
}
/**
* @returns List of all workflow states in organization.
*/
public async documents(): Promise<Document[]> {
return await this.fetchEntities<Document>("document");
}
/**
*
* @returns Organization associated with api token. The response will always contain a single organization.
*/
public async organizations(): Promise<Organization[]> {
return await this.fetchEntities<Organization>("organization");
}
public async checkConnection(): Promise<void> {
await axios({
method: "GET",
baseURL: LINEAR_API_BASE_URL,
url: "checkConnection",
headers: {
Authorization: this.config.apiKey,
},
});
}
private async fetchEntities<T>(entityType: EntityType): Promise<T[]> {
const response = await axios({
method: "GET",
baseURL: LINEAR_API_BASE_URL,
url: entityType,
transformResponse: (data) => {
try {
return JSON.parse(data);
} catch (error) {
this.logger.error(
`Failed to parse data as JSON.
Data:${data},
Error: ${JSON.stringify(error, null, 2)}`
);
throw error;
}
},
headers: {
Authorization: this.config.apiKey,
},
});
return response.data;
}
}