An Effect layer to interact with Github Octokit api.
You first need to create a github token with a scope related to your needs.
GITHUB_TOKEN="my-github-token"The layer exposes functions with the following type:
import type { ConfigError, Effect } from 'effect';
type LayerErrors = GithubApiError | ApiRateLimitError | ConfigError.ConfigError;
type LayerFunction<TArgs, TResult> = (
args: TArgs
) => Effect<TResult, LayerErrors, never>;For example, getting user profile can be done with this function:
type GetUserProfile = (
username: string
) => Effect<UserProfileResult, LayerErrors, never>;import { Effect, pipe } from 'effect';
import { OctokitLayer, OctokitLayerLive } from 'effect-octokit-layer';
const octokitUser = OctokitLayer.user('jpb06');
const [
profile,
repos,
orgs,
events,
commits,
issues,
pullRequests,
userPullRequestsCount,
userCommitsCount,
userIssuesCount,
] = await Effect.runPromise(
pipe(
Effect.all(
[
// Get user profile
octokitUser.profile(),
// Get user repos
octokitUser.repos('all'),
// Get user organizations
octokitUser.orgs(),
// Get user events
octokitUser.events(),
// Search in user commits (1000 results max)
octokitUser.searchCommits(''),
// Search in user issues (all, issue or pr) (1000 results max)
octokitUser.searchIssues('pr', ''),
// Search in user merged pull requests (1000 results max)
octokitUser.searchPullRequests('merged', ''),
// Get entities count
octokitUser.getPullRequestsCount('draft'),
octokitUser.getCommitsCount(),
octokitUser.getIssuesCount('pr'),
],
// Fetch all these in parallel
{ concurrency: 'unbounded' }
),
Effect.provide(OctokitLayerLive)
)
);import { Effect, pipe } from 'effect';
import { OctokitLayer, OctokitLayerLive } from 'effect-octokit-layer';
const orgs = await Effect.runPromise(
pipe(
// Get organization repos
OctokitLayer.org('my-org').repos(),
Effect.provide(OctokitLayerLive)
)
);import { Effect, pipe } from 'effect';
import { OctokitLayer, OctokitLayerLive } from 'effect-octokit-layer';
const octokitRepo = OctokitLayer.repo({
owner: 'facebook',
repo: 'react',
});
const [
languagesBytes,
releases,
tags,
issues,
issue34,
issue34Comments,
pulls,
pullsComments,
] = await Effect.runPromise(
pipe(
Effect.all(
[
// Get bytes written per language
octokitRepo.languages(),
// Get releases
octokitRepo.releases(),
// Get tags
octokitRepo.tags(),
// Get all issues which are not pull requests and were created by user 'mcmullinboy15'
octokitRepo.issues({
state: 'all',
excludePulls: true,
creator: 'mcmullinboy15',
}),
// Get issue #34
octokitRepo.issue(34).details(),
// Get issue #34 comments
octokitRepo.issue(34).comments(),
// Get all pull requests matching head filter 'user:branch-name'
octokitRepo.pulls.getAll({
state: 'all',
sort: 'created',
direction: 'desc',
head: 'jpb06:renovate/readme-package-icons-1.x',
}),
// Get all pull requests comments in repo
octokitRepo.pulls.comments(),
],
// Fetch all these in parallel
{ concurrency: 'unbounded' }
),
Effect.provide(OctokitLayerLive)
)
);import { Effect, pipe } from 'effect';
import { OctokitLayer, OctokitLayerLive } from 'effect-octokit-layer';
const pull = OctokitLayer.repo({
owner: 'facebook',
repo: 'react',
}).pull(39);
const [details, comments, reviews, createdReview, deletedReview] =
await Effect.runPromise(
pipe(
Effect.all(
[
// Pull request details
pull.details(),
// All the comments made on the pull request #39
pull.comments(),
// Pull request #39 reviews
pull.reviews.get(),
// Create a review
pull.reviews.create({
event: 'REQUEST_CHANGES',
body: 'I think some points need to be adressed',
comments: [
{
path: './src/cool.ts',
body: "Shouldn't this file be renamed",
},
],
}),
// Delete review #2
pull.reviews.delete(2),
],
{ concurrency: 'unbounded' }
),
Effect.provide(OctokitLayerLive)
)
);import { Effect, pipe } from 'effect';
import { RepoArgs, OctokitLayer, OctokitLayerLive } from 'effect-octokit-layer';
const reactRepo: RepoArgs = {
owner: 'facebook',
repo: 'react',
};
const pull = OctokitLayer.repo(reactRepo).pull(39);
const review = pull.review(2593339077);
const [createdComment, comments, deletedComment] = await Effect.runPromise(
pipe(
Effect.all([
// Create a comment in review #2593339077 on pull request #39
review.comments.create({
path: './src',
body: 'cool',
commitId: 'ff',
}),
// Get review #2593339077 comments
review.comments.get(),
// Delete comment #1 in review #2593339077
review.comments.delete(1),
]),
Effect.provide(OctokitLayerLive)
)
);Default:
10
You can specify the concurrency parameter on calls doing several requests in parallel (paginated data). For example:
// Will fetch the first page and then 100 pages concurrently
OctokitLayer.repo({
owner: 'facebook',
name: 'react',
}).pulls(100);Note that github api enforces api rate limits. Fetching too many results concurrently will cause an api rate limit. In that case, a warning will be displayed and the call will be attempted again after the time window provided by github api.
