@openally/github.sdk 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +5 -4
  3. package/dist/api/rawFile.d.ts +20 -0
  4. package/dist/api/rawFile.d.ts.map +1 -0
  5. package/dist/api/rawFile.js +25 -0
  6. package/dist/api/rawFile.js.map +1 -0
  7. package/dist/api/repos.d.ts +21 -0
  8. package/dist/api/repos.d.ts.map +1 -0
  9. package/dist/api/repos.js +32 -0
  10. package/dist/api/repos.js.map +1 -0
  11. package/dist/api/users.d.ts +21 -0
  12. package/dist/api/users.d.ts.map +1 -0
  13. package/dist/api/users.js +20 -0
  14. package/dist/api/users.js.map +1 -0
  15. package/dist/class/ApiEndpoint.d.ts +20 -0
  16. package/dist/class/ApiEndpoint.d.ts.map +1 -0
  17. package/dist/class/ApiEndpoint.js +60 -0
  18. package/dist/class/ApiEndpoint.js.map +1 -0
  19. package/dist/class/GithubClient.d.ts +22 -0
  20. package/dist/class/GithubClient.d.ts.map +1 -0
  21. package/dist/class/GithubClient.js +21 -0
  22. package/dist/class/GithubClient.js.map +1 -0
  23. package/dist/class/HttpLinkParser.d.ts +4 -0
  24. package/dist/class/HttpLinkParser.d.ts.map +1 -0
  25. package/dist/class/HttpLinkParser.js +14 -0
  26. package/dist/class/HttpLinkParser.js.map +1 -0
  27. package/dist/class/createApiProxy.d.ts +2 -0
  28. package/dist/class/createApiProxy.d.ts.map +1 -0
  29. package/dist/class/createApiProxy.js +8 -0
  30. package/dist/class/createApiProxy.js.map +1 -0
  31. package/dist/constants.d.ts +4 -0
  32. package/dist/constants.d.ts.map +1 -0
  33. package/dist/constants.js +4 -0
  34. package/dist/constants.js.map +1 -0
  35. package/{src/index.ts → dist/index.d.ts} +2 -1
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +5 -0
  38. package/dist/index.js.map +1 -0
  39. package/{src/types.ts → dist/types.d.ts} +14 -19
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +2 -0
  42. package/dist/types.js.map +1 -0
  43. package/package.json +6 -3
  44. package/.all-contributorsrc +0 -16
  45. package/.editorconfig +0 -14
  46. package/.github/dependabot.yml +0 -25
  47. package/.github/workflows/codeql.yml +0 -78
  48. package/.github/workflows/node.js.yml +0 -52
  49. package/.github/workflows/publish.yml +0 -29
  50. package/.github/workflows/scorecards.yml +0 -76
  51. package/SECURITY.md +0 -5
  52. package/docs/api/ApiEndpoint.md +0 -37
  53. package/docs/api/GithubClient.md +0 -50
  54. package/docs/api/repos.md +0 -97
  55. package/docs/api/users.md +0 -76
  56. package/eslint.config.mjs +0 -3
  57. package/src/api/repos.ts +0 -74
  58. package/src/api/users.ts +0 -47
  59. package/src/class/ApiEndpoint.ts +0 -105
  60. package/src/class/GithubClient.ts +0 -31
  61. package/src/class/HttpLinkParser.ts +0 -17
  62. package/src/class/createApiProxy.ts +0 -9
  63. package/test/ApiEndpoint.spec.ts +0 -301
  64. package/test/GithubClient.spec.ts +0 -166
  65. package/test/HttpLinkParser.spec.ts +0 -78
  66. package/test/createApiProxy.spec.ts +0 -58
  67. package/test/repos.spec.ts +0 -221
  68. package/test/users.spec.ts +0 -159
  69. package/tsconfig.json +0 -11
@@ -1,105 +0,0 @@
1
- // Import Internal Dependencies
2
- import { HttpLinkParser } from "./HttpLinkParser.ts";
3
-
4
- // CONSTANTS
5
- const kGithubURL = new URL("https://api.github.com/");
6
-
7
- export class ApiEndpointOptions<T> {
8
- /**
9
- * By default, the raw response from the GitHub API is returned as-is.
10
- * You can provide a custom extractor function to transform the raw response
11
- * into an array of type T.
12
- */
13
- extractor?: (raw: any) => T[];
14
- /**
15
- * A personal access token is required to access private resources,
16
- * and to increase the rate limit for unauthenticated requests.
17
- */
18
- token?: string;
19
- /**
20
- * @default "@openally/github.sdk/1.0.0"
21
- * @see https://docs.github.com/en/rest/using-the-rest-api/getting-started-with-the-rest-api?apiVersion=2022-11-28#user-agent
22
- */
23
- userAgent?: string;
24
- }
25
-
26
- export class ApiEndpoint<T> {
27
- #userAgent: string;
28
- #bearerToken?: string;
29
-
30
- #nextURL: string | null = null;
31
- #apiEndpoint: string | URL;
32
- #extractor: (raw: any) => T[];
33
-
34
- constructor(
35
- apiEndpoint: string | URL,
36
- options: ApiEndpointOptions<T> = {}
37
- ) {
38
- const {
39
- userAgent = "@openally/github.sdk/1.0.0",
40
- token,
41
- extractor = ((raw) => raw as T[])
42
- } = options;
43
-
44
- this.#userAgent = userAgent;
45
- this.#bearerToken = token;
46
- this.#apiEndpoint = apiEndpoint;
47
- this.#extractor = extractor;
48
- }
49
-
50
- setBearerToken(
51
- token: string
52
- ): this {
53
- this.#bearerToken = token;
54
-
55
- return this;
56
- }
57
-
58
- setAgent(
59
- userAgent: string
60
- ): this {
61
- this.#userAgent = userAgent;
62
-
63
- return this;
64
- }
65
-
66
- async #next(): Promise<T[]> {
67
- const headers = {
68
- "User-Agent": this.#userAgent,
69
- Accept: "application/vnd.github.v3.raw",
70
- ...(
71
- typeof this.#bearerToken === "string" ?
72
- { Authorization: `token ${this.#bearerToken}` } :
73
- {}
74
- )
75
- };
76
-
77
- const url = this.#nextURL === null ?
78
- new URL(this.#apiEndpoint, kGithubURL) :
79
- new URL(this.#nextURL, kGithubURL);
80
- const response = await fetch(
81
- url,
82
- { headers }
83
- );
84
- const rawData = await response.json();
85
-
86
- const linkHeader = response.headers.get("link");
87
- this.#nextURL = linkHeader
88
- ? HttpLinkParser.parse(linkHeader).get("next") ?? null
89
- : null;
90
-
91
- return this.#extractor(rawData);
92
- }
93
-
94
- async* iterate(): AsyncIterableIterator<T> {
95
- do {
96
- const pageResults = await this.#next();
97
-
98
- yield* pageResults;
99
- } while (this.#nextURL !== null);
100
- }
101
-
102
- all(): Promise<T[]> {
103
- return Array.fromAsync(this.iterate());
104
- }
105
- }
@@ -1,31 +0,0 @@
1
- // Import Internal Dependencies
2
- import {
3
- createUsersProxy,
4
- type UsersProxy
5
- } from "../api/users.ts";
6
- import {
7
- createReposProxy,
8
- type ReposProxy
9
- } from "../api/repos.ts";
10
-
11
- export interface GithubClientOptions {
12
- token?: string;
13
- userAgent?: string;
14
- }
15
-
16
- export class GithubClient {
17
- readonly users: UsersProxy;
18
- readonly repos: ReposProxy;
19
-
20
- constructor(
21
- options: GithubClientOptions = {}
22
- ) {
23
- const config = {
24
- token: options.token,
25
- userAgent: options.userAgent
26
- };
27
-
28
- this.users = createUsersProxy(config);
29
- this.repos = createReposProxy(config);
30
- }
31
- }
@@ -1,17 +0,0 @@
1
- export class HttpLinkParser {
2
- static parse(
3
- headerValue: string
4
- ): Map<string, string> {
5
- const result = new Map<string, string>();
6
-
7
- for (const part of headerValue.split(", ")) {
8
- const urlMatch = part.match(/^<([^>]+)>/);
9
- const relMatch = part.match(/rel="([^"]+)"/);
10
- if (urlMatch && relMatch) {
11
- result.set(relMatch[1], urlMatch[1]);
12
- }
13
- }
14
-
15
- return result;
16
- }
17
- }
@@ -1,9 +0,0 @@
1
- export function createApiProxy<T>(
2
- factory: (key: string) => T
3
- ): Record<string, T> {
4
- return new Proxy(Object.create(null), {
5
- get(_, key: string) {
6
- return factory(key);
7
- }
8
- }) as Record<string, T>;
9
- }
@@ -1,301 +0,0 @@
1
- // Import Node.js Dependencies
2
- import { describe, it, beforeEach, afterEach } from "node:test";
3
- import assert from "node:assert/strict";
4
-
5
- // Import Third-party Dependencies
6
- import { MockAgent, setGlobalDispatcher, getGlobalDispatcher, type Dispatcher } from "undici";
7
-
8
- // Import Internal Dependencies
9
- import { ApiEndpoint } from "../src/class/ApiEndpoint.ts";
10
-
11
- // CONSTANTS
12
- const kGithubOrigin = "https://api.github.com";
13
-
14
- describe("ApiEndpoint", () => {
15
- let mockAgent: MockAgent;
16
- let originalDispatcher: Dispatcher;
17
-
18
- beforeEach(() => {
19
- originalDispatcher = getGlobalDispatcher();
20
- mockAgent = new MockAgent();
21
- mockAgent.disableNetConnect();
22
- setGlobalDispatcher(mockAgent);
23
- });
24
-
25
- afterEach(async() => {
26
- await mockAgent.close();
27
- setGlobalDispatcher(originalDispatcher);
28
- });
29
-
30
- describe("constructor", () => {
31
- it("should accept a string endpoint", () => {
32
- const endpoint = new ApiEndpoint("/users/foo/repos");
33
-
34
- assert.ok(endpoint instanceof ApiEndpoint);
35
- });
36
-
37
- it("should accept a URL endpoint", () => {
38
- const endpoint = new ApiEndpoint(new URL("https://api.github.com/users/foo/repos"));
39
-
40
- assert.ok(endpoint instanceof ApiEndpoint);
41
- });
42
- });
43
-
44
- describe("setBearerToken()", () => {
45
- it("should return this for chaining", () => {
46
- const endpoint = new ApiEndpoint("/users/foo/repos");
47
-
48
- assert.strictEqual(endpoint.setBearerToken("mytoken"), endpoint);
49
- });
50
- });
51
-
52
- describe("setAgent()", () => {
53
- it("should return this for chaining", () => {
54
- const endpoint = new ApiEndpoint("/users/foo/repos");
55
-
56
- assert.strictEqual(endpoint.setAgent("my-agent/1.0"), endpoint);
57
- });
58
- });
59
-
60
- describe("all()", () => {
61
- it("should fetch a single page and return all items", async() => {
62
- mockAgent
63
- .get(kGithubOrigin)
64
- .intercept({ path: "/users/foo/repos", method: "GET" })
65
- .reply(200, JSON.stringify([{ id: 1 }, { id: 2 }]), {
66
- headers: { "content-type": "application/json" }
67
- });
68
-
69
- const result = await new ApiEndpoint("/users/foo/repos").all();
70
-
71
- assert.deepEqual(result, [{ id: 1 }, { id: 2 }]);
72
- });
73
-
74
- it("should return an empty array when the response is empty", async() => {
75
- mockAgent
76
- .get(kGithubOrigin)
77
- .intercept({ path: "/users/foo/repos", method: "GET" })
78
- .reply(200, JSON.stringify([]), {
79
- headers: { "content-type": "application/json" }
80
- });
81
-
82
- const result = await new ApiEndpoint("/users/foo/repos").all();
83
-
84
- assert.deepEqual(result, []);
85
- });
86
-
87
- it("should follow pagination using the link header", async() => {
88
- const pool = mockAgent.get(kGithubOrigin);
89
-
90
- pool
91
- .intercept({ path: "/users/foo/repos", method: "GET" })
92
- .reply(200, JSON.stringify([{ id: 1 }]), {
93
- headers: {
94
- "content-type": "application/json",
95
- link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
96
- }
97
- });
98
-
99
- pool
100
- .intercept({ path: "/users/foo/repos?page=2", method: "GET" })
101
- .reply(200, JSON.stringify([{ id: 2 }]), {
102
- headers: { "content-type": "application/json" }
103
- });
104
-
105
- const result = await new ApiEndpoint("/users/foo/repos").all();
106
-
107
- assert.deepEqual(result, [{ id: 1 }, { id: 2 }]);
108
- });
109
-
110
- it("should follow multiple pages until no next link", async() => {
111
- const pool = mockAgent.get(kGithubOrigin);
112
-
113
- pool
114
- .intercept({ path: "/users/foo/repos", method: "GET" })
115
- .reply(200, JSON.stringify([{ id: 1 }]), {
116
- headers: {
117
- "content-type": "application/json",
118
- link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
119
- }
120
- });
121
-
122
- pool
123
- .intercept({ path: "/users/foo/repos?page=2", method: "GET" })
124
- .reply(200, JSON.stringify([{ id: 2 }]), {
125
- headers: {
126
- "content-type": "application/json",
127
- link: '<https://api.github.com/users/foo/repos?page=3>; rel="next"'
128
- }
129
- });
130
-
131
- pool
132
- .intercept({ path: "/users/foo/repos?page=3", method: "GET" })
133
- .reply(200, JSON.stringify([{ id: 3 }]), {
134
- headers: { "content-type": "application/json" }
135
- });
136
-
137
- const result = await new ApiEndpoint("/users/foo/repos").all();
138
-
139
- assert.deepEqual(result, [{ id: 1 }, { id: 2 }, { id: 3 }]);
140
- });
141
- });
142
-
143
- describe("iterate()", () => {
144
- it("should yield items one at a time", async() => {
145
- mockAgent
146
- .get(kGithubOrigin)
147
- .intercept({ path: "/users/foo/repos", method: "GET" })
148
- .reply(200, JSON.stringify([{ id: 1 }, { id: 2 }]), {
149
- headers: { "content-type": "application/json" }
150
- });
151
-
152
- const items: unknown[] = [];
153
- for await (const item of new ApiEndpoint("/users/foo/repos").iterate()) {
154
- items.push(item);
155
- }
156
-
157
- assert.deepEqual(items, [{ id: 1 }, { id: 2 }]);
158
- });
159
-
160
- it("should yield items across paginated pages", async() => {
161
- const pool = mockAgent.get(kGithubOrigin);
162
-
163
- pool
164
- .intercept({ path: "/users/foo/repos", method: "GET" })
165
- .reply(200, JSON.stringify([{ id: 1 }]), {
166
- headers: {
167
- "content-type": "application/json",
168
- link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
169
- }
170
- });
171
-
172
- pool
173
- .intercept({ path: "/users/foo/repos?page=2", method: "GET" })
174
- .reply(200, JSON.stringify([{ id: 2 }, { id: 3 }]), {
175
- headers: { "content-type": "application/json" }
176
- });
177
-
178
- const items: unknown[] = [];
179
- for await (const item of new ApiEndpoint("/users/foo/repos").iterate()) {
180
- items.push(item);
181
- }
182
-
183
- assert.deepEqual(items, [{ id: 1 }, { id: 2 }, { id: 3 }]);
184
- });
185
- });
186
-
187
- describe("headers", () => {
188
- it("should send the default User-Agent header", async() => {
189
- mockAgent
190
- .get(kGithubOrigin)
191
- .intercept({
192
- path: "/users/foo/repos",
193
- method: "GET",
194
- headers: { "user-agent": "@openally/github.sdk/1.0.0" }
195
- })
196
- .reply(200, JSON.stringify([]), {
197
- headers: { "content-type": "application/json" }
198
- });
199
-
200
- // If header doesn't match, undici will throw — this is the assertion
201
- await assert.doesNotReject(
202
- new ApiEndpoint("/users/foo/repos").all()
203
- );
204
- });
205
-
206
- it("should send a custom User-Agent when set via setAgent()", async() => {
207
- mockAgent
208
- .get(kGithubOrigin)
209
- .intercept({
210
- path: "/users/foo/repos",
211
- method: "GET",
212
- headers: { "user-agent": "custom-agent/2.0" }
213
- })
214
- .reply(200, JSON.stringify([]), {
215
- headers: { "content-type": "application/json" }
216
- });
217
-
218
- await assert.doesNotReject(
219
- new ApiEndpoint("/users/foo/repos").setAgent("custom-agent/2.0").all()
220
- );
221
- });
222
-
223
- it("should send the Authorization header when a token is provided", async() => {
224
- mockAgent
225
- .get(kGithubOrigin)
226
- .intercept({
227
- path: "/users/foo/repos",
228
- method: "GET",
229
- headers: { authorization: "token secret123" }
230
- })
231
- .reply(200, JSON.stringify([]), {
232
- headers: { "content-type": "application/json" }
233
- });
234
-
235
- await assert.doesNotReject(
236
- new ApiEndpoint("/users/foo/repos", { token: "secret123" }).all()
237
- );
238
- });
239
-
240
- it("should send the Authorization header when set via setBearerToken()", async() => {
241
- mockAgent
242
- .get(kGithubOrigin)
243
- .intercept({
244
- path: "/users/foo/repos",
245
- method: "GET",
246
- headers: { authorization: "token runtime-token" }
247
- })
248
- .reply(200, JSON.stringify([]), {
249
- headers: { "content-type": "application/json" }
250
- });
251
-
252
- await assert.doesNotReject(
253
- new ApiEndpoint("/users/foo/repos").setBearerToken("runtime-token").all()
254
- );
255
- });
256
- });
257
-
258
- describe("extractor", () => {
259
- it("should apply the extractor to transform the raw response", async() => {
260
- mockAgent
261
- .get(kGithubOrigin)
262
- .intercept({ path: "/repos/foo/bar/actions/workflows", method: "GET" })
263
- .reply(200, JSON.stringify({ total_count: 2, workflows: [{ id: 10 }, { id: 20 }] }), {
264
- headers: { "content-type": "application/json" }
265
- });
266
-
267
- const result = await new ApiEndpoint(
268
- "/repos/foo/bar/actions/workflows",
269
- { extractor: (raw) => raw.workflows }
270
- ).all();
271
-
272
- assert.deepEqual(result, [{ id: 10 }, { id: 20 }]);
273
- });
274
-
275
- it("should apply the extractor on every page when paginating", async() => {
276
- const pool = mockAgent.get(kGithubOrigin);
277
-
278
- pool
279
- .intercept({ path: "/repos/foo/bar/actions/workflows", method: "GET" })
280
- .reply(200, JSON.stringify({ total_count: 3, workflows: [{ id: 10 }] }), {
281
- headers: {
282
- "content-type": "application/json",
283
- link: '<https://api.github.com/repos/foo/bar/actions/workflows?page=2>; rel="next"'
284
- }
285
- });
286
-
287
- pool
288
- .intercept({ path: "/repos/foo/bar/actions/workflows?page=2", method: "GET" })
289
- .reply(200, JSON.stringify({ total_count: 3, workflows: [{ id: 20 }, { id: 30 }] }), {
290
- headers: { "content-type": "application/json" }
291
- });
292
-
293
- const result = await new ApiEndpoint(
294
- "/repos/foo/bar/actions/workflows",
295
- { extractor: (raw) => raw.workflows }
296
- ).all();
297
-
298
- assert.deepEqual(result, [{ id: 10 }, { id: 20 }, { id: 30 }]);
299
- });
300
- });
301
- });
@@ -1,166 +0,0 @@
1
- // Import Node.js Dependencies
2
- import { describe, it, beforeEach, afterEach } from "node:test";
3
- import assert from "node:assert/strict";
4
-
5
- // Import Third-party Dependencies
6
- import { MockAgent, setGlobalDispatcher, getGlobalDispatcher, type Dispatcher } from "undici";
7
-
8
- // Import Internal Dependencies
9
- import { GithubClient } from "../src/class/GithubClient.ts";
10
- import { ApiEndpoint } from "../src/class/ApiEndpoint.ts";
11
-
12
- // CONSTANTS
13
- const kGithubOrigin = "https://api.github.com";
14
-
15
- describe("GithubClient", () => {
16
- let mockAgent: MockAgent;
17
- let originalDispatcher: Dispatcher;
18
-
19
- beforeEach(() => {
20
- originalDispatcher = getGlobalDispatcher();
21
- mockAgent = new MockAgent();
22
- mockAgent.disableNetConnect();
23
- setGlobalDispatcher(mockAgent);
24
- });
25
-
26
- afterEach(async() => {
27
- await mockAgent.close();
28
- setGlobalDispatcher(originalDispatcher);
29
- });
30
-
31
- describe("constructor", () => {
32
- it("should instantiate with no options", () => {
33
- const client = new GithubClient();
34
-
35
- assert.ok(client instanceof GithubClient);
36
- });
37
-
38
- it("should instantiate with a token", () => {
39
- const client = new GithubClient({ token: "mytoken" });
40
-
41
- assert.ok(client instanceof GithubClient);
42
- });
43
-
44
- it("should instantiate with a custom userAgent", () => {
45
- const client = new GithubClient({ userAgent: "my-app/1.0" });
46
-
47
- assert.ok(client instanceof GithubClient);
48
- });
49
-
50
- it("should expose a users proxy", () => {
51
- const client = new GithubClient();
52
-
53
- assert.ok(client.users !== undefined);
54
- });
55
-
56
- it("should expose a repos proxy", () => {
57
- const client = new GithubClient();
58
-
59
- assert.ok(client.repos !== undefined);
60
- });
61
- });
62
-
63
- describe("client.users", () => {
64
- it("should return ApiEndpoints for user sub-resources", () => {
65
- const client = new GithubClient();
66
-
67
- assert.ok(client.users.foo.repos() instanceof ApiEndpoint);
68
- assert.ok(client.users.foo.orgs() instanceof ApiEndpoint);
69
- });
70
-
71
- it("should use the configured token when fetching user data", async() => {
72
- const client = new GithubClient({ token: "clienttoken" });
73
-
74
- mockAgent
75
- .get(kGithubOrigin)
76
- .intercept({
77
- path: "/users/octocat/repos",
78
- method: "GET",
79
- headers: { authorization: "token clienttoken" }
80
- })
81
- .reply(200, JSON.stringify([{ id: 1 }]), {
82
- headers: { "content-type": "application/json" }
83
- });
84
-
85
- const result = await client.users.octocat.repos().all();
86
-
87
- assert.deepEqual(result, [{ id: 1 }]);
88
- });
89
-
90
- it("should fetch user data without a token", async() => {
91
- const client = new GithubClient();
92
-
93
- mockAgent
94
- .get(kGithubOrigin)
95
- .intercept({ path: "/users/octocat/followers", method: "GET" })
96
- .reply(200, JSON.stringify([{ login: "user1" }]), {
97
- headers: { "content-type": "application/json" }
98
- });
99
-
100
- const result = await client.users.octocat.followers().all();
101
-
102
- assert.deepEqual(result, [{ login: "user1" }]);
103
- });
104
- });
105
-
106
- describe("client.repos", () => {
107
- it("should return ApiEndpoints for repo sub-resources", () => {
108
- const client = new GithubClient();
109
-
110
- assert.ok(client.repos.owner.myrepo.tags() instanceof ApiEndpoint);
111
- assert.ok(client.repos.owner.myrepo.pulls() instanceof ApiEndpoint);
112
- assert.ok(client.repos.owner.myrepo.workflows() instanceof ApiEndpoint);
113
- });
114
-
115
- it("should use the configured token when fetching repo data", async() => {
116
- const client = new GithubClient({ token: "repotoken" });
117
-
118
- mockAgent
119
- .get(kGithubOrigin)
120
- .intercept({
121
- path: "/repos/octocat/hello-world/tags",
122
- method: "GET",
123
- headers: { authorization: "token repotoken" }
124
- })
125
- .reply(200, JSON.stringify([{ name: "v1.0.0" }]), {
126
- headers: { "content-type": "application/json" }
127
- });
128
-
129
- const result = await client.repos.octocat["hello-world"].tags().all();
130
-
131
- assert.deepEqual(result, [{ name: "v1.0.0" }]);
132
- });
133
-
134
- it("should use the configured userAgent when fetching", async() => {
135
- const client = new GithubClient({ userAgent: "my-app/1.0" });
136
-
137
- mockAgent
138
- .get(kGithubOrigin)
139
- .intercept({
140
- path: "/repos/octocat/hello-world/tags",
141
- method: "GET",
142
- headers: { "user-agent": "my-app/1.0" }
143
- })
144
- .reply(200, JSON.stringify([]), {
145
- headers: { "content-type": "application/json" }
146
- });
147
-
148
- await assert.doesNotReject(client.repos.octocat["hello-world"].tags().all());
149
- });
150
-
151
- it("should fetch workflows with the envelope extractor", async() => {
152
- const client = new GithubClient();
153
-
154
- mockAgent
155
- .get(kGithubOrigin)
156
- .intercept({ path: "/repos/octocat/hello-world/actions/workflows", method: "GET" })
157
- .reply(200, JSON.stringify({ total_count: 1, workflows: [{ id: 7, name: "CI" }] }), {
158
- headers: { "content-type": "application/json" }
159
- });
160
-
161
- const result = await client.repos.octocat["hello-world"].workflows().all();
162
-
163
- assert.deepEqual(result, [{ id: 7, name: "CI" }]);
164
- });
165
- });
166
- });