Skip to content

Commit db8fd8c

Browse files
committed
refactor: Move GitHub service into submodule
1 parent 3006714 commit db8fd8c

File tree

6 files changed

+301
-209
lines changed

6 files changed

+301
-209
lines changed

src/services.ts

-209
This file was deleted.

src/services/github/errors.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export enum GithubRepositoriesServiceError {
2+
RequestFailed = "GitHub GraphQL request is failed",
3+
DeserializationFailed = "Deserialization of GraphQL response is failed",
4+
}

src/services/github/index.ts

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { Octokit } from "@octokit/core";
2+
import { retry } from "@octokit/plugin-retry";
3+
import { type Result, ResultAsync, ok } from "neverthrow";
4+
import { GithubRepositoriesServiceError } from "./errors";
5+
import starredRepositoriesQuery from "./queries/starredRepositories.gql";
6+
import totalStarredRepositoriesCountQuery from "./queries/totalStarredRepositoriesCount.gql";
7+
import type { GitHubGraphQl } from "./types";
8+
9+
export interface StarredRepositoriesQueryResult {
10+
repositories: GitHubGraphQl.StarredRepositoryEdge[];
11+
totalCount: number;
12+
hasNextPage: boolean;
13+
endCursor?: string;
14+
}
15+
16+
export interface IGithubRepositoriesService {
17+
accessToken: string;
18+
client: Octokit;
19+
20+
getUserStarredRepositories(
21+
pageSize: number,
22+
): AsyncGenerator<
23+
Result<
24+
GitHubGraphQl.StarredRepositoryEdge[],
25+
GithubRepositoriesServiceError
26+
>,
27+
void,
28+
unknown
29+
>;
30+
31+
getTotalStarredRepositoriesCount(): Promise<
32+
ResultAsync<number, GithubRepositoriesServiceError>
33+
>;
34+
}
35+
36+
export class GithubRepositoriesService implements IGithubRepositoriesService {
37+
accessToken: string;
38+
client: Octokit;
39+
40+
constructor(accessToken: string) {
41+
this.accessToken = accessToken;
42+
const OctokitWithRetries = Octokit.plugin(retry);
43+
this.client = new OctokitWithRetries({
44+
auth: this.accessToken,
45+
request: { retries: 1, retryAfter: 1 },
46+
});
47+
}
48+
49+
private async getOnePageOfStarredRepos(
50+
after: string,
51+
pageSize: number,
52+
): Promise<
53+
ResultAsync<
54+
StarredRepositoriesQueryResult,
55+
GithubRepositoriesServiceError
56+
>
57+
> {
58+
const makeRequest = ResultAsync.fromPromise(
59+
this.client.graphql<GitHubGraphQl.StarredRepositoriesResponse>(
60+
starredRepositoriesQuery,
61+
{
62+
after,
63+
pageSize,
64+
},
65+
),
66+
() => GithubRepositoriesServiceError.RequestFailed,
67+
);
68+
69+
return makeRequest.andThen((response) => {
70+
return ok({
71+
repositories: response.viewer.starredRepositories.edges,
72+
totalCount: response.viewer.starredRepositories.totalCount,
73+
hasNextPage:
74+
response.viewer.starredRepositories.pageInfo.hasNextPage,
75+
endCursor:
76+
response.viewer.starredRepositories.pageInfo.endCursor,
77+
});
78+
});
79+
}
80+
81+
public async *getUserStarredRepositories(
82+
pageSize: number,
83+
): AsyncGenerator<
84+
Result<
85+
GitHubGraphQl.StarredRepositoryEdge[],
86+
GithubRepositoriesServiceError
87+
>,
88+
void,
89+
unknown
90+
> {
91+
let after = "";
92+
let hasNextPage = false;
93+
let totalFetched = 0;
94+
do {
95+
const requestResult = await this.getOnePageOfStarredRepos(
96+
after,
97+
pageSize,
98+
);
99+
const result = requestResult.andThen((data) => {
100+
hasNextPage = data.hasNextPage;
101+
after = data.endCursor ? data.endCursor : "";
102+
totalFetched += data.repositories.length;
103+
return ok(data.repositories);
104+
});
105+
yield result;
106+
} while (hasNextPage);
107+
}
108+
109+
public async getTotalStarredRepositoriesCount(): Promise<
110+
ResultAsync<number, GithubRepositoriesServiceError>
111+
> {
112+
return ResultAsync.fromPromise(
113+
this.client.graphql<GitHubGraphQl.StarredRepositoriesResponse>(
114+
totalStarredRepositoriesCountQuery,
115+
),
116+
() => GithubRepositoriesServiceError.RequestFailed,
117+
).map((response) => response.viewer.starredRepositories.totalCount);
118+
}
119+
}

0 commit comments

Comments
 (0)