@openally/github.sdk 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/.all-contributorsrc +16 -0
- package/.editorconfig +14 -0
- package/.github/dependabot.yml +25 -0
- package/.github/workflows/codeql.yml +78 -0
- package/.github/workflows/node.js.yml +52 -0
- package/.github/workflows/publish.yml +29 -0
- package/.github/workflows/scorecards.yml +76 -0
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/SECURITY.md +5 -0
- package/docs/api/ApiEndpoint.md +37 -0
- package/docs/api/GithubClient.md +50 -0
- package/docs/api/repos.md +97 -0
- package/docs/api/users.md +76 -0
- package/eslint.config.mjs +3 -0
- package/package.json +50 -0
- package/src/api/repos.ts +74 -0
- package/src/api/users.ts +47 -0
- package/src/class/ApiEndpoint.ts +105 -0
- package/src/class/GithubClient.ts +31 -0
- package/src/class/HttpLinkParser.ts +17 -0
- package/src/class/createApiProxy.ts +9 -0
- package/src/index.ts +5 -0
- package/src/types.ts +37 -0
- package/test/ApiEndpoint.spec.ts +301 -0
- package/test/GithubClient.spec.ts +166 -0
- package/test/HttpLinkParser.spec.ts +78 -0
- package/test/createApiProxy.spec.ts +58 -0
- package/test/repos.spec.ts +221 -0
- package/test/users.spec.ts +159 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# users
|
|
2
|
+
|
|
3
|
+
The `users` proxy provides access to GitHub user endpoints.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { users } from "@openally/github.sdk";
|
|
7
|
+
|
|
8
|
+
// Collect all repositories for a user
|
|
9
|
+
const repos = await users.torvalds.repos().all();
|
|
10
|
+
|
|
11
|
+
// Stream followers one by one
|
|
12
|
+
for await (const follower of users.torvalds.followers().iterate()) {
|
|
13
|
+
console.log(follower.login);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Collect all starred repositories
|
|
17
|
+
const starred = await users.torvalds.starred().all();
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Access pattern
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
users[username].<method>()
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
All methods return an [`ApiEndpoint<T>`](./ApiEndpoint.md) instance.
|
|
27
|
+
|
|
28
|
+
## Methods
|
|
29
|
+
|
|
30
|
+
### `.orgs()`
|
|
31
|
+
|
|
32
|
+
Returns `ApiEndpoint<UserOrg>`.
|
|
33
|
+
|
|
34
|
+
Lists all organizations the user belongs to.
|
|
35
|
+
|
|
36
|
+
> GitHub docs: [List organizations for a user](https://docs.github.com/en/rest/orgs/orgs#list-organizations-for-a-user)
|
|
37
|
+
|
|
38
|
+
### `.repos()`
|
|
39
|
+
|
|
40
|
+
Returns `ApiEndpoint<UserRepo>`.
|
|
41
|
+
|
|
42
|
+
Lists all public repositories for the user.
|
|
43
|
+
|
|
44
|
+
> GitHub docs: [List repositories for a user](https://docs.github.com/en/rest/repos/repos#list-repositories-for-a-user)
|
|
45
|
+
|
|
46
|
+
### `.gists()`
|
|
47
|
+
|
|
48
|
+
Returns `ApiEndpoint<UserGist>`.
|
|
49
|
+
|
|
50
|
+
Lists all public gists for the user.
|
|
51
|
+
|
|
52
|
+
> GitHub docs: [List gists for a user](https://docs.github.com/en/rest/gists/gists#list-gists-for-a-user)
|
|
53
|
+
|
|
54
|
+
### `.followers()`
|
|
55
|
+
|
|
56
|
+
Returns `ApiEndpoint<UserFollower>`.
|
|
57
|
+
|
|
58
|
+
Lists all followers of the user.
|
|
59
|
+
|
|
60
|
+
> GitHub docs: [List followers of a user](https://docs.github.com/en/rest/users/followers#list-followers-of-a-user)
|
|
61
|
+
|
|
62
|
+
### `.following()`
|
|
63
|
+
|
|
64
|
+
Returns `ApiEndpoint<UserFollowing>`.
|
|
65
|
+
|
|
66
|
+
Lists all users the user follows.
|
|
67
|
+
|
|
68
|
+
> GitHub docs: [List the people a user follows](https://docs.github.com/en/rest/users/followers#list-the-people-a-user-follows)
|
|
69
|
+
|
|
70
|
+
### `.starred()`
|
|
71
|
+
|
|
72
|
+
Returns `ApiEndpoint<UserStarred>`.
|
|
73
|
+
|
|
74
|
+
Lists all repositories starred by the user.
|
|
75
|
+
|
|
76
|
+
> GitHub docs: [List repositories starred by a user](https://docs.github.com/en/rest/activity/starring#list-repositories-starred-by-a-user)
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openally/github.sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Opiniated Node.js Github SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"prepublishOnly": "npm run build",
|
|
11
|
+
"test": "node --test ./test/**/*.spec.ts",
|
|
12
|
+
"coverage": "c8 --reporter=lcov npm run test",
|
|
13
|
+
"lint": "eslint .",
|
|
14
|
+
"lint:fix": "eslint . --fix"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"registry": "https://registry.npmjs.org",
|
|
18
|
+
"access": "public",
|
|
19
|
+
"provenance": false
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/OpenAlly/github.sdk.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"github",
|
|
27
|
+
"sdk",
|
|
28
|
+
"api",
|
|
29
|
+
"client",
|
|
30
|
+
"nodejs",
|
|
31
|
+
"typescript"
|
|
32
|
+
],
|
|
33
|
+
"author": "GENTILHOMME Thomas <gentilhomme.thomas@gmail.com>",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/OpenAlly/github.sdk/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/OpenAlly/github.sdk#readme",
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@openally/config.eslint": "^2.2.0",
|
|
41
|
+
"@openally/config.typescript": "^1.2.1",
|
|
42
|
+
"@types/node": "25.3.1",
|
|
43
|
+
"c8": "^11.0.0",
|
|
44
|
+
"typescript": "^5.9.3",
|
|
45
|
+
"undici": "7.22.0"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@octokit/types": "16.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/api/repos.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Import Internal Dependencies
|
|
2
|
+
import { ApiEndpoint } from "../class/ApiEndpoint.ts";
|
|
3
|
+
import { createApiProxy } from "../class/createApiProxy.ts";
|
|
4
|
+
import type {
|
|
5
|
+
Tag,
|
|
6
|
+
PullRequest,
|
|
7
|
+
Issue,
|
|
8
|
+
Commit,
|
|
9
|
+
Workflow,
|
|
10
|
+
WorkflowRun,
|
|
11
|
+
Job,
|
|
12
|
+
Artifact,
|
|
13
|
+
WorkflowsResponse,
|
|
14
|
+
WorkflowRunsResponse,
|
|
15
|
+
JobsResponse,
|
|
16
|
+
ArtifactsResponse,
|
|
17
|
+
RequestConfig
|
|
18
|
+
} from "../types.ts";
|
|
19
|
+
|
|
20
|
+
type RepoEndpointMethods = {
|
|
21
|
+
tags: () => ApiEndpoint<Tag>;
|
|
22
|
+
pulls: () => ApiEndpoint<PullRequest>;
|
|
23
|
+
issues: () => ApiEndpoint<Issue>;
|
|
24
|
+
commits: () => ApiEndpoint<Commit>;
|
|
25
|
+
workflows: () => ApiEndpoint<Workflow>;
|
|
26
|
+
workflowRuns: (workflowId: string | number) => ApiEndpoint<WorkflowRun>;
|
|
27
|
+
runJobs: (runId: number) => ApiEndpoint<Job>;
|
|
28
|
+
runArtifacts: (runId: number) => ApiEndpoint<Artifact>;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type ReposProxy = {
|
|
32
|
+
[owner: string]: {
|
|
33
|
+
[repo: string]: RepoEndpointMethods;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function createRepoProxy(
|
|
38
|
+
owner: string,
|
|
39
|
+
repo: string,
|
|
40
|
+
config: RequestConfig = {}
|
|
41
|
+
): RepoEndpointMethods {
|
|
42
|
+
return {
|
|
43
|
+
tags: () => new ApiEndpoint<Tag>(`/repos/${owner}/${repo}/tags`, config),
|
|
44
|
+
pulls: () => new ApiEndpoint<PullRequest>(`/repos/${owner}/${repo}/pulls`, config),
|
|
45
|
+
issues: () => new ApiEndpoint<Issue>(`/repos/${owner}/${repo}/issues`, config),
|
|
46
|
+
commits: () => new ApiEndpoint<Commit>(`/repos/${owner}/${repo}/commits`, config),
|
|
47
|
+
workflows: () => new ApiEndpoint<Workflow>(
|
|
48
|
+
`/repos/${owner}/${repo}/actions/workflows`,
|
|
49
|
+
{ ...config, extractor: (raw: WorkflowsResponse) => raw.workflows }
|
|
50
|
+
),
|
|
51
|
+
workflowRuns: (workflowId: string | number) => new ApiEndpoint<WorkflowRun>(
|
|
52
|
+
`/repos/${owner}/${repo}/actions/workflows/${workflowId}/runs`,
|
|
53
|
+
{ ...config, extractor: (raw: WorkflowRunsResponse) => raw.workflow_runs }
|
|
54
|
+
),
|
|
55
|
+
runJobs: (runId: number) => new ApiEndpoint<Job>(
|
|
56
|
+
`/repos/${owner}/${repo}/actions/runs/${runId}/jobs`,
|
|
57
|
+
{ ...config, extractor: (raw: JobsResponse) => raw.jobs }
|
|
58
|
+
),
|
|
59
|
+
runArtifacts: (runId: number) => new ApiEndpoint<Artifact>(
|
|
60
|
+
`/repos/${owner}/${repo}/actions/runs/${runId}/artifacts`,
|
|
61
|
+
{ ...config, extractor: (raw: ArtifactsResponse) => raw.artifacts }
|
|
62
|
+
)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function createReposProxy(config: RequestConfig = {}): ReposProxy {
|
|
67
|
+
return createApiProxy(
|
|
68
|
+
(owner) => createApiProxy(
|
|
69
|
+
(repo) => createRepoProxy(owner, repo, config)
|
|
70
|
+
)
|
|
71
|
+
) as ReposProxy;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const repos = createReposProxy();
|
package/src/api/users.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Import Internal Dependencies
|
|
2
|
+
import { ApiEndpoint } from "../class/ApiEndpoint.ts";
|
|
3
|
+
import { createApiProxy } from "../class/createApiProxy.ts";
|
|
4
|
+
import type {
|
|
5
|
+
UserOrg,
|
|
6
|
+
UserRepo,
|
|
7
|
+
UserGist,
|
|
8
|
+
UserFollower,
|
|
9
|
+
UserFollowing,
|
|
10
|
+
UserStarred,
|
|
11
|
+
RequestConfig
|
|
12
|
+
} from "../types.ts";
|
|
13
|
+
|
|
14
|
+
// CONSTANTS
|
|
15
|
+
const kUserEndpointResponseMap = {
|
|
16
|
+
orgs: {} as UserOrg,
|
|
17
|
+
repos: {} as UserRepo,
|
|
18
|
+
gists: {} as UserGist,
|
|
19
|
+
followers: {} as UserFollower,
|
|
20
|
+
following: {} as UserFollowing,
|
|
21
|
+
starred: {} as UserStarred
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type UserEndpoint = keyof typeof kUserEndpointResponseMap;
|
|
25
|
+
type UserEndpointMethods = {
|
|
26
|
+
[K in UserEndpoint]: () => ApiEndpoint<typeof kUserEndpointResponseMap[K]>;
|
|
27
|
+
};
|
|
28
|
+
export type UsersProxy = {
|
|
29
|
+
[username: string]: UserEndpointMethods;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function createUserProxy(
|
|
33
|
+
username: string,
|
|
34
|
+
config: RequestConfig = {}
|
|
35
|
+
): UserEndpointMethods {
|
|
36
|
+
return Object.fromEntries(
|
|
37
|
+
(Object.keys(kUserEndpointResponseMap) as UserEndpoint[]).map(
|
|
38
|
+
(endpoint) => [endpoint, () => new ApiEndpoint(`/users/${username}/${endpoint}`, config)]
|
|
39
|
+
)
|
|
40
|
+
) as UserEndpointMethods;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function createUsersProxy(config: RequestConfig = {}): UsersProxy {
|
|
44
|
+
return createApiProxy((username) => createUserProxy(username, config)) as UsersProxy;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const users = createUsersProxy();
|
|
@@ -0,0 +1,105 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Import Third-party Dependencies
|
|
2
|
+
import type { Endpoints } from "@octokit/types";
|
|
3
|
+
|
|
4
|
+
export interface RequestConfig {
|
|
5
|
+
token?: string;
|
|
6
|
+
userAgent?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// --- Repo entity types ---
|
|
10
|
+
export type Tag = Endpoints["GET /repos/{owner}/{repo}/tags"]["response"]["data"][number];
|
|
11
|
+
export type PullRequest = Endpoints["GET /repos/{owner}/{repo}/pulls"]["response"]["data"][number];
|
|
12
|
+
export type Issue = Endpoints["GET /repos/{owner}/{repo}/issues"]["response"]["data"][number];
|
|
13
|
+
export type Commit = Endpoints["GET /repos/{owner}/{repo}/commits"]["response"]["data"][number];
|
|
14
|
+
export type Workflow = Endpoints["GET /repos/{owner}/{repo}/actions/workflows"]["response"]["data"]["workflows"][number];
|
|
15
|
+
export type WorkflowRun = Endpoints[
|
|
16
|
+
"GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs"
|
|
17
|
+
]["response"]["data"]["workflow_runs"][number];
|
|
18
|
+
export type Job = Endpoints["GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs"]["response"]["data"]["jobs"][number];
|
|
19
|
+
export type Artifact = Endpoints[
|
|
20
|
+
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts"
|
|
21
|
+
]["response"]["data"]["artifacts"][number];
|
|
22
|
+
|
|
23
|
+
// Extractor response types (envelope objects returned by the GitHub API)
|
|
24
|
+
export type WorkflowsResponse = Endpoints["GET /repos/{owner}/{repo}/actions/workflows"]["response"]["data"];
|
|
25
|
+
export type WorkflowRunsResponse = Endpoints[
|
|
26
|
+
"GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs"
|
|
27
|
+
]["response"]["data"];
|
|
28
|
+
export type JobsResponse = Endpoints["GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs"]["response"]["data"];
|
|
29
|
+
export type ArtifactsResponse = Endpoints["GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts"]["response"]["data"];
|
|
30
|
+
|
|
31
|
+
// --- User entity types ---
|
|
32
|
+
export type UserOrg = Endpoints["GET /users/{username}/orgs"]["response"]["data"][number];
|
|
33
|
+
export type UserRepo = Endpoints["GET /users/{username}/repos"]["response"]["data"][number];
|
|
34
|
+
export type UserGist = Endpoints["GET /users/{username}/gists"]["response"]["data"][number];
|
|
35
|
+
export type UserFollower = Endpoints["GET /users/{username}/followers"]["response"]["data"][number];
|
|
36
|
+
export type UserFollowing = Endpoints["GET /users/{username}/following"]["response"]["data"][number];
|
|
37
|
+
export type UserStarred = Endpoints["GET /users/{username}/starred"]["response"]["data"][number];
|