gh-api-client 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +371 -0
- package/dist/index.d.mts +1726 -0
- package/dist/index.d.ts +1726 -0
- package/dist/index.js +971 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +948 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 el_jijuna
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
# gh-api-client
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
|
|
5
|
+
TypeScript client for the [GitHub REST API](https://docs.github.com/en/rest).
|
|
6
|
+
Works in **Node.js** and the **browser** (isomorphic). Fully typed, zero runtime dependencies.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install gh-api-client
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { GitHubClient } from 'gh-api-client';
|
|
22
|
+
|
|
23
|
+
const gh = new GitHubClient({
|
|
24
|
+
token: 'ghp_yourPersonalAccessToken',
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
For **GitHub Enterprise Server**, pass a custom `apiUrl`:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
const gh = new GitHubClient({
|
|
32
|
+
token: 'ghp_yourPersonalAccessToken',
|
|
33
|
+
apiUrl: 'https://github.mycompany.com/api/v3',
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## API reference
|
|
40
|
+
|
|
41
|
+
### Current user
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
const me = await gh.currentUser();
|
|
45
|
+
// { login: 'octocat', name: 'The Octocat', ... }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Users
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// Get a user's profile
|
|
52
|
+
const user = await gh.user('octocat');
|
|
53
|
+
|
|
54
|
+
// List a user's public repositories
|
|
55
|
+
const repos = await gh.user('octocat').repos();
|
|
56
|
+
const repos = await gh.user('octocat').repos({ sort: 'updated', per_page: 50 });
|
|
57
|
+
|
|
58
|
+
// Navigate into a user repository
|
|
59
|
+
const repo = await gh.user('octocat').repo('Hello-World');
|
|
60
|
+
const content = await gh.user('octocat').repo('Hello-World').raw('README.md');
|
|
61
|
+
|
|
62
|
+
// Followers and following
|
|
63
|
+
const followers = await gh.user('octocat').followers();
|
|
64
|
+
const following = await gh.user('octocat').following();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Organizations
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Get an organization
|
|
71
|
+
const org = await gh.org('github');
|
|
72
|
+
|
|
73
|
+
// List an organization's repositories
|
|
74
|
+
const repos = await gh.org('github').repos();
|
|
75
|
+
const repos = await gh.org('github').repos({ type: 'public', per_page: 100 });
|
|
76
|
+
|
|
77
|
+
// List members
|
|
78
|
+
const members = await gh.org('github').members();
|
|
79
|
+
const members = await gh.org('github').members({ role: 'admin' });
|
|
80
|
+
|
|
81
|
+
// Navigate into an org repository
|
|
82
|
+
const repo = await gh.org('github').repo('linguist');
|
|
83
|
+
const prs = await gh.org('github').repo('linguist').pullRequests({ state: 'open' });
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Repositories
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// Shortcut: access any repo by owner + name
|
|
90
|
+
const repo = await gh.repo('octocat', 'Hello-World');
|
|
91
|
+
|
|
92
|
+
// Repository info
|
|
93
|
+
const repo = await gh.repo('octocat', 'Hello-World');
|
|
94
|
+
// { id, name, full_name, owner, private, default_branch, ... }
|
|
95
|
+
|
|
96
|
+
// Forks
|
|
97
|
+
const forks = await gh.repo('octocat', 'Hello-World').forks();
|
|
98
|
+
const forks = await gh.repo('octocat', 'Hello-World').forks({ sort: 'newest' });
|
|
99
|
+
|
|
100
|
+
// Webhooks
|
|
101
|
+
const hooks = await gh.repo('octocat', 'Hello-World').webhooks();
|
|
102
|
+
|
|
103
|
+
// Topics
|
|
104
|
+
const topics = await gh.repo('octocat', 'Hello-World').topics();
|
|
105
|
+
// ['typescript', 'api-client']
|
|
106
|
+
|
|
107
|
+
// Contributors
|
|
108
|
+
const contributors = await gh.repo('octocat', 'Hello-World').contributors();
|
|
109
|
+
|
|
110
|
+
// Raw file content (returns string)
|
|
111
|
+
const content = await gh.repo('octocat', 'Hello-World').raw('README.md');
|
|
112
|
+
const content = await gh.repo('octocat', 'Hello-World').raw('src/index.ts', { ref: 'main' });
|
|
113
|
+
|
|
114
|
+
// File/directory contents (returns GitHubContent or GitHubContent[])
|
|
115
|
+
const file = await gh.repo('octocat', 'Hello-World').contents('README.md');
|
|
116
|
+
const dir = await gh.repo('octocat', 'Hello-World').contents('src');
|
|
117
|
+
const root = await gh.repo('octocat', 'Hello-World').contents();
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Branches
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// List branches
|
|
124
|
+
const branches = await gh.repo('octocat', 'Hello-World').branches();
|
|
125
|
+
const branches = await gh.repo('octocat', 'Hello-World').branches({ protected: true });
|
|
126
|
+
|
|
127
|
+
// Get a single branch
|
|
128
|
+
const branch = await gh.repo('octocat', 'Hello-World').branch('main');
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Tags
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
const tags = await gh.repo('octocat', 'Hello-World').tags();
|
|
135
|
+
const tags = await gh.repo('octocat', 'Hello-World').tags({ per_page: 50 });
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Releases
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// List releases
|
|
142
|
+
const releases = await gh.repo('octocat', 'Hello-World').releases();
|
|
143
|
+
|
|
144
|
+
// Get the latest published release
|
|
145
|
+
const latest = await gh.repo('octocat', 'Hello-World').latestRelease();
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Commits
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// List commits
|
|
152
|
+
const commits = await gh.repo('octocat', 'Hello-World').commits();
|
|
153
|
+
const commits = await gh.repo('octocat', 'Hello-World').commits({
|
|
154
|
+
sha: 'main',
|
|
155
|
+
path: 'src/index.ts',
|
|
156
|
+
author: 'octocat',
|
|
157
|
+
since: '2024-01-01T00:00:00Z',
|
|
158
|
+
until: '2024-12-31T23:59:59Z',
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Get a single commit (includes stats and files)
|
|
162
|
+
const commit = await gh.repo('octocat', 'Hello-World').commit('abc123def456');
|
|
163
|
+
|
|
164
|
+
// Commit statuses (from external CI/CD via Statuses API)
|
|
165
|
+
const statuses = await gh.repo('octocat', 'Hello-World').commit('abc123').statuses();
|
|
166
|
+
|
|
167
|
+
// Combined status (aggregate of all statuses)
|
|
168
|
+
const combined = await gh.repo('octocat', 'Hello-World').commit('abc123').combinedStatus();
|
|
169
|
+
// { state: 'success', total_count: 3, statuses: [...] }
|
|
170
|
+
|
|
171
|
+
// GitHub Actions check runs
|
|
172
|
+
const checks = await gh.repo('octocat', 'Hello-World').commit('abc123').checkRuns();
|
|
173
|
+
const checks = await gh.repo('octocat', 'Hello-World').commit('abc123').checkRuns({ status: 'completed' });
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Pull requests
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// List pull requests
|
|
180
|
+
const prs = await gh.repo('octocat', 'Hello-World').pullRequests();
|
|
181
|
+
const prs = await gh.repo('octocat', 'Hello-World').pullRequests({
|
|
182
|
+
state: 'open',
|
|
183
|
+
base: 'main',
|
|
184
|
+
sort: 'updated',
|
|
185
|
+
direction: 'desc',
|
|
186
|
+
per_page: 50,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Get a single pull request
|
|
190
|
+
const pr = await gh.repo('octocat', 'Hello-World').pullRequest(42);
|
|
191
|
+
|
|
192
|
+
// Commits in the PR
|
|
193
|
+
const commits = await gh.repo('octocat', 'Hello-World').pullRequest(42).commits();
|
|
194
|
+
|
|
195
|
+
// Changed files
|
|
196
|
+
const files = await gh.repo('octocat', 'Hello-World').pullRequest(42).files();
|
|
197
|
+
|
|
198
|
+
// Reviews
|
|
199
|
+
const reviews = await gh.repo('octocat', 'Hello-World').pullRequest(42).reviews();
|
|
200
|
+
|
|
201
|
+
// Inline review comments (diff comments)
|
|
202
|
+
const comments = await gh.repo('octocat', 'Hello-World').pullRequest(42).reviewComments();
|
|
203
|
+
|
|
204
|
+
// Check if merged
|
|
205
|
+
const merged = await gh.repo('octocat', 'Hello-World').pullRequest(42).isMerged();
|
|
206
|
+
// true | false
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Repository search
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// Search repositories using GitHub's search syntax
|
|
213
|
+
const results = await gh.searchRepos({ q: 'language:typescript stars:>1000' });
|
|
214
|
+
const results = await gh.searchRepos({ q: 'user:octocat', sort: 'stars', order: 'desc' });
|
|
215
|
+
|
|
216
|
+
console.log(`Found ${results.totalCount} repositories`);
|
|
217
|
+
results.values; // GitHubRepository[]
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Pagination
|
|
223
|
+
|
|
224
|
+
Every list method returns a `GitHubPagedResponse<T>`:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
const page = await gh.repo('octocat', 'Hello-World').commits({ per_page: 30 });
|
|
228
|
+
|
|
229
|
+
page.values // GitHubCommit[] — the items on this page
|
|
230
|
+
page.hasNextPage // boolean
|
|
231
|
+
page.nextPage // number | undefined — pass as `page` to get the next page
|
|
232
|
+
page.totalCount // number | undefined — only available on search endpoints
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Iterate all pages:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
let page = 1;
|
|
239
|
+
let hasMore = true;
|
|
240
|
+
|
|
241
|
+
while (hasMore) {
|
|
242
|
+
const res = await gh.repo('octocat', 'Hello-World').commits({ per_page: 100, page });
|
|
243
|
+
process(res.values);
|
|
244
|
+
hasMore = res.hasNextPage;
|
|
245
|
+
page = res.nextPage ?? page + 1;
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Request events
|
|
252
|
+
|
|
253
|
+
Subscribe to every HTTP request made by the client for logging, monitoring, or debugging:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
gh.on('request', (event) => {
|
|
257
|
+
console.log(`[${event.method}] ${event.url} → ${event.statusCode} (${event.durationMs}ms)`);
|
|
258
|
+
if (event.error) {
|
|
259
|
+
console.error('Request failed:', event.error.message);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The `event` object contains:
|
|
265
|
+
|
|
266
|
+
| Field | Type | Description |
|
|
267
|
+
|---|---|---|
|
|
268
|
+
| `url` | `string` | Full URL that was requested |
|
|
269
|
+
| `method` | `'GET'` | HTTP method used |
|
|
270
|
+
| `startedAt` | `Date` | When the request started |
|
|
271
|
+
| `finishedAt` | `Date` | When the request finished |
|
|
272
|
+
| `durationMs` | `number` | Duration in milliseconds |
|
|
273
|
+
| `statusCode` | `number \| undefined` | HTTP status code, if a response was received |
|
|
274
|
+
| `error` | `Error \| undefined` | Present only if the request failed |
|
|
275
|
+
|
|
276
|
+
Multiple listeners can be registered. `on()` returns `this` for chaining.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Error handling
|
|
281
|
+
|
|
282
|
+
Non-2xx responses throw a `GitHubApiError` with the HTTP status code and status text:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { GitHubApiError } from 'gh-api-client';
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
await gh.repo('octocat', 'nonexistent-repo');
|
|
289
|
+
} catch (err) {
|
|
290
|
+
if (err instanceof GitHubApiError) {
|
|
291
|
+
console.log(err.status); // 404
|
|
292
|
+
console.log(err.statusText); // 'Not Found'
|
|
293
|
+
console.log(err.message); // 'GitHub API error: 404 Not Found'
|
|
294
|
+
console.log(err.stack); // full stack trace
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Chainable resource pattern
|
|
302
|
+
|
|
303
|
+
Every resource that maps to a single entity implements `PromiseLike`, so you can **await it directly** or **chain methods** to access sub-resources:
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
// Await directly → fetches the resource
|
|
307
|
+
const user = await gh.user('octocat');
|
|
308
|
+
const repo = await gh.repo('octocat', 'Hello-World');
|
|
309
|
+
const pr = await gh.repo('octocat', 'Hello-World').pullRequest(42);
|
|
310
|
+
|
|
311
|
+
// Chain → access sub-resources without awaiting intermediate objects
|
|
312
|
+
const repos = await gh.user('octocat').repos({ sort: 'updated' });
|
|
313
|
+
const commits = await gh.repo('octocat', 'Hello-World').pullRequest(42).commits();
|
|
314
|
+
const statuses = await gh.org('github').repo('linguist').commit('abc123').statuses();
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Authentication
|
|
320
|
+
|
|
321
|
+
The client uses **Bearer token authentication**. Supported token types:
|
|
322
|
+
|
|
323
|
+
- **Personal Access Token (PAT)** — generate at GitHub → Settings → Developer settings → Personal access tokens
|
|
324
|
+
- **Fine-grained PAT** — recommended for scoped access
|
|
325
|
+
- **OAuth token** — from an OAuth App
|
|
326
|
+
- **GitHub App installation token** — for GitHub App integrations
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
const gh = new GitHubClient({ token: 'ghp_yourToken' });
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## TypeScript types
|
|
335
|
+
|
|
336
|
+
All domain types are exported:
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
import type {
|
|
340
|
+
// Pagination
|
|
341
|
+
GitHubPagedResponse, PaginationParams,
|
|
342
|
+
// Client
|
|
343
|
+
GitHubClientOptions, RequestEvent, GitHubClientEvents,
|
|
344
|
+
// Users & Orgs
|
|
345
|
+
GitHubUser, UsersParams, SearchUsersParams,
|
|
346
|
+
GitHubOrganization, OrgMembersParams,
|
|
347
|
+
// Repositories
|
|
348
|
+
GitHubRepository, ReposParams, ForksParams, SearchReposParams,
|
|
349
|
+
// Pull Requests
|
|
350
|
+
GitHubPullRequest, GitHubRef, GitHubLabel, GitHubMilestone, PullRequestsParams,
|
|
351
|
+
GitHubReview, GitHubReviewComment, ReviewsParams, ReviewCommentsParams,
|
|
352
|
+
GitHubPullRequestFile, PullRequestFilesParams,
|
|
353
|
+
// Commits
|
|
354
|
+
GitHubCommit, GitHubCommitFile, CommitsParams,
|
|
355
|
+
GitHubCommitStatus, GitHubCombinedStatus, GitHubCheckRun,
|
|
356
|
+
CommitStatusesParams, CheckRunsParams,
|
|
357
|
+
// Branches, Tags, Releases
|
|
358
|
+
GitHubBranch, BranchesParams,
|
|
359
|
+
GitHubTag, TagsParams,
|
|
360
|
+
GitHubRelease, GitHubReleaseAsset, ReleasesParams,
|
|
361
|
+
// Webhooks & Content
|
|
362
|
+
GitHubWebhook, WebhooksParams,
|
|
363
|
+
GitHubContent, ContentParams,
|
|
364
|
+
} from 'gh-api-client';
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## License
|
|
370
|
+
|
|
371
|
+
[MIT](LICENSE)
|