@openally/github.sdk 1.1.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 (71) hide show
  1. package/dist/api/rawFile.d.ts +20 -0
  2. package/dist/api/rawFile.d.ts.map +1 -0
  3. package/dist/api/rawFile.js +25 -0
  4. package/dist/api/rawFile.js.map +1 -0
  5. package/dist/api/repos.d.ts +21 -0
  6. package/dist/api/repos.d.ts.map +1 -0
  7. package/dist/api/repos.js +32 -0
  8. package/dist/api/repos.js.map +1 -0
  9. package/dist/api/users.d.ts +21 -0
  10. package/dist/api/users.d.ts.map +1 -0
  11. package/dist/api/users.js +20 -0
  12. package/dist/api/users.js.map +1 -0
  13. package/dist/class/ApiEndpoint.d.ts +20 -0
  14. package/dist/class/ApiEndpoint.d.ts.map +1 -0
  15. package/dist/class/ApiEndpoint.js +60 -0
  16. package/dist/class/ApiEndpoint.js.map +1 -0
  17. package/dist/class/GithubClient.d.ts +22 -0
  18. package/dist/class/GithubClient.d.ts.map +1 -0
  19. package/dist/class/GithubClient.js +21 -0
  20. package/dist/class/GithubClient.js.map +1 -0
  21. package/dist/class/HttpLinkParser.d.ts +4 -0
  22. package/dist/class/HttpLinkParser.d.ts.map +1 -0
  23. package/dist/class/HttpLinkParser.js +14 -0
  24. package/dist/class/HttpLinkParser.js.map +1 -0
  25. package/dist/class/createApiProxy.d.ts +2 -0
  26. package/dist/class/createApiProxy.d.ts.map +1 -0
  27. package/dist/class/createApiProxy.js +8 -0
  28. package/dist/class/createApiProxy.js.map +1 -0
  29. package/dist/constants.d.ts +4 -0
  30. package/dist/constants.d.ts.map +1 -0
  31. package/{src/constants.ts → dist/constants.js} +1 -0
  32. package/dist/constants.js.map +1 -0
  33. package/{src/index.ts → dist/index.d.ts} +2 -5
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +5 -0
  36. package/dist/index.js.map +1 -0
  37. package/{src/types.ts → dist/types.d.ts} +14 -27
  38. package/dist/types.d.ts.map +1 -0
  39. package/dist/types.js +2 -0
  40. package/dist/types.js.map +1 -0
  41. package/package.json +5 -2
  42. package/.all-contributorsrc +0 -16
  43. package/.editorconfig +0 -14
  44. package/.github/dependabot.yml +0 -25
  45. package/.github/workflows/codeql.yml +0 -78
  46. package/.github/workflows/node.js.yml +0 -52
  47. package/.github/workflows/publish.yml +0 -29
  48. package/.github/workflows/scorecards.yml +0 -76
  49. package/SECURITY.md +0 -5
  50. package/docs/api/ApiEndpoint.md +0 -66
  51. package/docs/api/GithubClient.md +0 -50
  52. package/docs/api/fetchRawFile.md +0 -106
  53. package/docs/api/repos.md +0 -97
  54. package/docs/api/users.md +0 -76
  55. package/eslint.config.mjs +0 -3
  56. package/src/api/rawFile.ts +0 -73
  57. package/src/api/repos.ts +0 -88
  58. package/src/api/users.ts +0 -51
  59. package/src/class/ApiEndpoint.ts +0 -108
  60. package/src/class/GithubClient.ts +0 -62
  61. package/src/class/HttpLinkParser.ts +0 -17
  62. package/src/class/createApiProxy.ts +0 -9
  63. package/test/ApiEndpoint.spec.ts +0 -362
  64. package/test/GithubClient.spec.ts +0 -185
  65. package/test/HttpLinkParser.spec.ts +0 -78
  66. package/test/createApiProxy.spec.ts +0 -58
  67. package/test/rawFile.spec.ts +0 -382
  68. package/test/repos.spec.ts +0 -221
  69. package/test/tsconfig.json +0 -11
  70. package/test/users.spec.ts +0 -159
  71. package/tsconfig.json +0 -11
@@ -1,362 +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("all() with thenable", () => {
144
- it("should fetch a single page and return all items", 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 result = await new ApiEndpoint("/users/foo/repos");
153
-
154
- assert.deepEqual(result, [{ id: 1 }, { id: 2 }]);
155
- });
156
- });
157
-
158
- describe("iterate()", () => {
159
- it("should yield items one at a time", async() => {
160
- mockAgent
161
- .get(kGithubOrigin)
162
- .intercept({ path: "/users/foo/repos", method: "GET" })
163
- .reply(200, JSON.stringify([{ id: 1 }, { id: 2 }]), {
164
- headers: { "content-type": "application/json" }
165
- });
166
-
167
- const items: unknown[] = [];
168
- for await (const item of new ApiEndpoint("/users/foo/repos").iterate()) {
169
- items.push(item);
170
- }
171
-
172
- assert.deepEqual(items, [{ id: 1 }, { id: 2 }]);
173
- });
174
-
175
- it("should yield items across paginated pages", async() => {
176
- const pool = mockAgent.get(kGithubOrigin);
177
-
178
- pool
179
- .intercept({ path: "/users/foo/repos", method: "GET" })
180
- .reply(200, JSON.stringify([{ id: 1 }]), {
181
- headers: {
182
- "content-type": "application/json",
183
- link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
184
- }
185
- });
186
-
187
- pool
188
- .intercept({ path: "/users/foo/repos?page=2", method: "GET" })
189
- .reply(200, JSON.stringify([{ id: 2 }, { id: 3 }]), {
190
- headers: { "content-type": "application/json" }
191
- });
192
-
193
- const items: unknown[] = [];
194
- for await (const item of new ApiEndpoint("/users/foo/repos").iterate()) {
195
- items.push(item);
196
- }
197
-
198
- assert.deepEqual(items, [{ id: 1 }, { id: 2 }, { id: 3 }]);
199
- });
200
- });
201
-
202
- describe("Symbol.asyncIterator", () => {
203
- it("should yield items one at a time", async() => {
204
- mockAgent
205
- .get(kGithubOrigin)
206
- .intercept({ path: "/users/foo/repos", method: "GET" })
207
- .reply(200, JSON.stringify([{ id: 1 }, { id: 2 }]), {
208
- headers: { "content-type": "application/json" }
209
- });
210
-
211
- const items: unknown[] = [];
212
- for await (const item of new ApiEndpoint("/users/foo/repos")) {
213
- items.push(item);
214
- }
215
-
216
- assert.deepEqual(items, [{ id: 1 }, { id: 2 }]);
217
- });
218
-
219
- it("should yield items across paginated pages", async() => {
220
- const pool = mockAgent.get(kGithubOrigin);
221
-
222
- pool
223
- .intercept({ path: "/users/foo/repos", method: "GET" })
224
- .reply(200, JSON.stringify([{ id: 1 }]), {
225
- headers: {
226
- "content-type": "application/json",
227
- link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
228
- }
229
- });
230
-
231
- pool
232
- .intercept({ path: "/users/foo/repos?page=2", method: "GET" })
233
- .reply(200, JSON.stringify([{ id: 2 }, { id: 3 }]), {
234
- headers: { "content-type": "application/json" }
235
- });
236
-
237
- const items: unknown[] = [];
238
- for await (const item of new ApiEndpoint("/users/foo/repos")) {
239
- items.push(item);
240
- }
241
-
242
- assert.deepEqual(items, [{ id: 1 }, { id: 2 }, { id: 3 }]);
243
- });
244
- });
245
-
246
- describe("headers", () => {
247
- it("should send the default User-Agent header", async() => {
248
- mockAgent
249
- .get(kGithubOrigin)
250
- .intercept({
251
- path: "/users/foo/repos",
252
- method: "GET",
253
- headers: { "user-agent": "@openally/github.sdk/1.0.0" }
254
- })
255
- .reply(200, JSON.stringify([]), {
256
- headers: { "content-type": "application/json" }
257
- });
258
-
259
- // If header doesn't match, undici will throw — this is the assertion
260
- await assert.doesNotReject(
261
- new ApiEndpoint("/users/foo/repos").all()
262
- );
263
- });
264
-
265
- it("should send a custom User-Agent when set via setAgent()", async() => {
266
- mockAgent
267
- .get(kGithubOrigin)
268
- .intercept({
269
- path: "/users/foo/repos",
270
- method: "GET",
271
- headers: { "user-agent": "custom-agent/2.0" }
272
- })
273
- .reply(200, JSON.stringify([]), {
274
- headers: { "content-type": "application/json" }
275
- });
276
-
277
- await assert.doesNotReject(
278
- new ApiEndpoint("/users/foo/repos").setAgent("custom-agent/2.0").all()
279
- );
280
- });
281
-
282
- it("should send the Authorization header when a token is provided", async() => {
283
- mockAgent
284
- .get(kGithubOrigin)
285
- .intercept({
286
- path: "/users/foo/repos",
287
- method: "GET",
288
- headers: { authorization: "token secret123" }
289
- })
290
- .reply(200, JSON.stringify([]), {
291
- headers: { "content-type": "application/json" }
292
- });
293
-
294
- await assert.doesNotReject(
295
- new ApiEndpoint("/users/foo/repos", { token: "secret123" }).all()
296
- );
297
- });
298
-
299
- it("should send the Authorization header when set via setBearerToken()", async() => {
300
- mockAgent
301
- .get(kGithubOrigin)
302
- .intercept({
303
- path: "/users/foo/repos",
304
- method: "GET",
305
- headers: { authorization: "token runtime-token" }
306
- })
307
- .reply(200, JSON.stringify([]), {
308
- headers: { "content-type": "application/json" }
309
- });
310
-
311
- await assert.doesNotReject(
312
- new ApiEndpoint("/users/foo/repos").setBearerToken("runtime-token").all()
313
- );
314
- });
315
- });
316
-
317
- describe("extractor", () => {
318
- it("should apply the extractor to transform the raw response", async() => {
319
- const workflows = [{ id: 10 }, { id: 20 }];
320
-
321
- mockAgent
322
- .get(kGithubOrigin)
323
- .intercept({ path: "/repos/foo/bar/actions/workflows", method: "GET" })
324
- .reply(200, JSON.stringify({ total_count: 2, workflows }), {
325
- headers: { "content-type": "application/json" }
326
- });
327
-
328
- const result = await new ApiEndpoint(
329
- "/repos/foo/bar/actions/workflows",
330
- { extractor: (raw) => raw.workflows }
331
- ).all();
332
-
333
- assert.deepEqual(result, workflows);
334
- });
335
-
336
- it("should apply the extractor on every page when paginating", async() => {
337
- const pool = mockAgent.get(kGithubOrigin);
338
-
339
- pool
340
- .intercept({ path: "/repos/foo/bar/actions/workflows", method: "GET" })
341
- .reply(200, JSON.stringify({ total_count: 3, workflows: [{ id: 10 }] }), {
342
- headers: {
343
- "content-type": "application/json",
344
- link: '<https://api.github.com/repos/foo/bar/actions/workflows?page=2>; rel="next"'
345
- }
346
- });
347
-
348
- pool
349
- .intercept({ path: "/repos/foo/bar/actions/workflows?page=2", method: "GET" })
350
- .reply(200, JSON.stringify({ total_count: 3, workflows: [{ id: 20 }, { id: 30 }] }), {
351
- headers: { "content-type": "application/json" }
352
- });
353
-
354
- const result = await new ApiEndpoint(
355
- "/repos/foo/bar/actions/workflows",
356
- { extractor: (raw) => raw.workflows }
357
- ).all();
358
-
359
- assert.deepEqual(result, [{ id: 10 }, { id: 20 }, { id: 30 }]);
360
- });
361
- });
362
- });
@@ -1,185 +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(
111
- client.repos.owner.myrepo.tags() instanceof ApiEndpoint
112
- );
113
- assert.ok(
114
- client.repos.owner.myrepo.pulls() instanceof ApiEndpoint
115
- );
116
- assert.ok(
117
- client.repos.owner.myrepo.workflows() instanceof ApiEndpoint
118
- );
119
- });
120
-
121
- it("should use the configured token when fetching repo data", async() => {
122
- const client = new GithubClient({ token: "repotoken" });
123
-
124
- mockAgent
125
- .get(kGithubOrigin)
126
- .intercept({
127
- path: "/repos/octocat/hello-world/tags",
128
- method: "GET",
129
- headers: { authorization: "token repotoken" }
130
- })
131
- .reply(200, JSON.stringify([{ name: "v1.0.0" }]), {
132
- headers: { "content-type": "application/json" }
133
- });
134
-
135
- const result = await client.repos.octocat["hello-world"]
136
- .tags()
137
- .all();
138
-
139
- assert.deepEqual(result, [{ name: "v1.0.0" }]);
140
- });
141
-
142
- it("should use the configured userAgent when fetching", async() => {
143
- const client = new GithubClient({ userAgent: "my-app/1.0" });
144
-
145
- mockAgent
146
- .get(kGithubOrigin)
147
- .intercept({
148
- path: "/repos/octocat/hello-world/tags",
149
- method: "GET",
150
- headers: { "user-agent": "my-app/1.0" }
151
- })
152
- .reply(200, JSON.stringify([]), {
153
- headers: { "content-type": "application/json" }
154
- });
155
-
156
- await assert.doesNotReject(
157
- client.repos.octocat["hello-world"].tags().all()
158
- );
159
- });
160
-
161
- it("should fetch workflows with the envelope extractor", async() => {
162
- const client = new GithubClient();
163
- const workflows = [{ id: 7, name: "CI" }];
164
-
165
- mockAgent
166
- .get(kGithubOrigin)
167
- .intercept({
168
- path: "/repos/octocat/hello-world/actions/workflows",
169
- method: "GET"
170
- })
171
- .reply(200, JSON.stringify({ total_count: 1, workflows }), {
172
- headers: { "content-type": "application/json" }
173
- });
174
-
175
- const result = await client.repos.octocat["hello-world"]
176
- .workflows()
177
- .all();
178
-
179
- assert.deepEqual(
180
- result,
181
- workflows
182
- );
183
- });
184
- });
185
- });
@@ -1,78 +0,0 @@
1
- // Import Node.js Dependencies
2
- import { describe, it } from "node:test";
3
- import assert from "node:assert/strict";
4
-
5
- // Import Internal Dependencies
6
- import { HttpLinkParser } from "../src/class/HttpLinkParser.ts";
7
-
8
- describe("HttpLinkParser", () => {
9
- describe("parse()", () => {
10
- it("should return a Map instance", () => {
11
- const result = HttpLinkParser.parse("");
12
-
13
- assert.ok(result instanceof Map);
14
- });
15
-
16
- it("should return an empty map for an empty string", () => {
17
- const result = HttpLinkParser.parse("");
18
-
19
- assert.equal(result.size, 0);
20
- });
21
-
22
- it("should return an empty map for a malformed header", () => {
23
- const result = HttpLinkParser.parse("not a link header");
24
-
25
- assert.equal(result.size, 0);
26
- });
27
-
28
- it("should parse a single link relation", () => {
29
- const header = '<https://api.github.com/repos/foo/bar/tags?page=2>; rel="next"';
30
- const result = HttpLinkParser.parse(header);
31
-
32
- assert.equal(result.size, 1);
33
- assert.equal(result.get("next"), "https://api.github.com/repos/foo/bar/tags?page=2");
34
- });
35
-
36
- it("should parse multiple link relations", () => {
37
- const header = [
38
- '<https://api.github.com/repos/foo/bar/tags?page=2>; rel="next"',
39
- '<https://api.github.com/repos/foo/bar/tags?page=5>; rel="last"'
40
- ].join(", ");
41
- const result = HttpLinkParser.parse(header);
42
-
43
- assert.equal(result.size, 2);
44
- assert.equal(result.get("next"), "https://api.github.com/repos/foo/bar/tags?page=2");
45
- assert.equal(result.get("last"), "https://api.github.com/repos/foo/bar/tags?page=5");
46
- });
47
-
48
- it("should parse all four standard link relations", () => {
49
- const header = [
50
- '<https://api.github.com/repos/foo/bar/tags?page=2>; rel="next"',
51
- '<https://api.github.com/repos/foo/bar/tags?page=5>; rel="last"',
52
- '<https://api.github.com/repos/foo/bar/tags?page=1>; rel="first"',
53
- '<https://api.github.com/repos/foo/bar/tags?page=1>; rel="prev"'
54
- ].join(", ");
55
- const result = HttpLinkParser.parse(header);
56
-
57
- assert.equal(result.size, 4);
58
- assert.ok(result.has("next"));
59
- assert.ok(result.has("last"));
60
- assert.ok(result.has("first"));
61
- assert.ok(result.has("prev"));
62
- });
63
-
64
- it("should ignore parts that have no URL match", () => {
65
- const header = 'no-url; rel="next"';
66
- const result = HttpLinkParser.parse(header);
67
-
68
- assert.equal(result.size, 0);
69
- });
70
-
71
- it("should ignore parts that have no rel match", () => {
72
- const header = "<https://api.github.com/repos/foo/bar/tags?page=2>";
73
- const result = HttpLinkParser.parse(header);
74
-
75
- assert.equal(result.size, 0);
76
- });
77
- });
78
- });
@@ -1,58 +0,0 @@
1
- /* eslint-disable no-unused-expressions */
2
- // Import Node.js Dependencies
3
- import { describe, it } from "node:test";
4
- import assert from "node:assert/strict";
5
-
6
- // Import Internal Dependencies
7
- import { createApiProxy } from "../src/class/createApiProxy.ts";
8
-
9
- describe("createApiProxy", () => {
10
- it("should call the factory with the accessed property key", () => {
11
- const proxy = createApiProxy((key) => key.toUpperCase());
12
-
13
- assert.equal(proxy.hello, "HELLO");
14
- assert.equal(proxy.world, "WORLD");
15
- });
16
-
17
- it("should call the factory on each property access", () => {
18
- let callCount = 0;
19
- const proxy = createApiProxy((key) => {
20
- callCount++;
21
-
22
- return key;
23
- });
24
-
25
- proxy.a;
26
- proxy.b;
27
- proxy.a;
28
-
29
- assert.equal(callCount, 3);
30
- });
31
-
32
- it("should return different values for different keys", () => {
33
- const proxy = createApiProxy((key) => {
34
- return { name: key };
35
- });
36
-
37
- assert.notDeepEqual(proxy.foo, proxy.bar);
38
- assert.equal(proxy.foo.name, "foo");
39
- assert.equal(proxy.bar.name, "bar");
40
- });
41
-
42
- it("should support nested proxies", () => {
43
- const proxy = createApiProxy(
44
- (owner: string) => createApiProxy(
45
- (repo: string) => `${owner}/${repo}`
46
- )
47
- );
48
-
49
- assert.equal(proxy.myorg.myrepo, "myorg/myrepo");
50
- assert.equal(proxy.another.sdk, "another/sdk");
51
- });
52
-
53
- it("should return a plain object (no prototype)", () => {
54
- const proxy = createApiProxy((key) => key);
55
-
56
- assert.equal(Object.getPrototypeOf(proxy), null);
57
- });
58
- });