Last active
January 22, 2026 14:59
-
-
Save kiritocode1/b012dd11611e20a19317f41550ecb785 to your computer and use it in GitHub Desktop.
am I ahead of Jarred Sumner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Effect, Schema, Console } from "effect"; | |
| import { | |
| FetchHttpClient, | |
| HttpClient, | |
| HttpClientRequest, | |
| HttpClientResponse, | |
| } from "@effect/platform"; | |
| // ============================================================================ | |
| // Custom Errors (Effect best practice - use tagged errors) | |
| // ============================================================================ | |
| class UserNotFoundError extends Schema.TaggedError<UserNotFoundError>()( | |
| "UserNotFoundError", | |
| { | |
| username: Schema.String, | |
| }, | |
| ) {} | |
| class MissingTokenError extends Schema.TaggedError<MissingTokenError>()( | |
| "MissingTokenError", | |
| {}, | |
| ) {} | |
| // ============================================================================ | |
| // GitHub GraphQL Response Schemas | |
| // ============================================================================ | |
| // Schema for a user's contribution data in a specific year | |
| const ContributionsCollectionSchema = Schema.Struct({ | |
| totalCommitContributions: Schema.Number, | |
| totalIssueContributions: Schema.Number, | |
| totalPullRequestContributions: Schema.Number, | |
| totalRepositoryContributions: Schema.Number, | |
| contributionCalendar: Schema.Struct({ | |
| totalContributions: Schema.Number, | |
| }), | |
| startedAt: Schema.String, | |
| endedAt: Schema.String, | |
| }); | |
| // Full GraphQL response schema | |
| const GithubContributionsResponseSchema = Schema.Struct({ | |
| data: Schema.Struct({ | |
| user: Schema.NullOr( | |
| Schema.Struct({ | |
| login: Schema.String, | |
| contributionsCollection: ContributionsCollectionSchema, | |
| }), | |
| ), | |
| }), | |
| }); | |
| // ============================================================================ | |
| // GraphQL Query, fetch a person's contribution data for a person | |
| // ============================================================================ | |
| const CONTRIBUTIONS_QUERY = ` | |
| query GetUserContributions($username: String!, $from: DateTime!, $to: DateTime!) { | |
| user(login: $username) { | |
| login | |
| contributionsCollection(from: $from, to: $to) { | |
| totalCommitContributions | |
| totalIssueContributions | |
| totalPullRequestContributions | |
| totalRepositoryContributions | |
| contributionCalendar { | |
| totalContributions | |
| } | |
| startedAt | |
| endedAt | |
| } | |
| } | |
| } | |
| `; | |
| // ============================================================================ | |
| // API Function | |
| // ============================================================================ | |
| interface GetYearlyCommitsParams { | |
| username: string; | |
| year?: number; | |
| token: string; // GitHub personal access token required for GraphQL API | |
| } | |
| export const getYearlyCommits = ({ | |
| username, | |
| year, | |
| token, | |
| }: GetYearlyCommitsParams) => | |
| Effect.gen(function* () { | |
| const client = yield* HttpClient.HttpClient; | |
| // Calculate year date range (UTC) | |
| if (!year) { | |
| const now = new Date(); | |
| year = now.getUTCFullYear(); | |
| } | |
| const from = `${year}-01-01T00:00:00Z`; | |
| const to = `${year}-12-31T23:59:59Z`; | |
| const request = yield* HttpClientRequest.post( | |
| "https://api.github.com/graphql", | |
| ).pipe( | |
| HttpClientRequest.setHeaders({ | |
| Authorization: `Bearer ${token}`, | |
| "Content-Type": "application/json", | |
| "User-Agent": "blank-effect-github-application", | |
| }), | |
| HttpClientRequest.bodyJson({ | |
| query: CONTRIBUTIONS_QUERY, | |
| variables: { username, from, to }, | |
| }), | |
| ); | |
| const response = yield* client.execute(request); | |
| const json = yield* HttpClientResponse.schemaBodyJson( | |
| GithubContributionsResponseSchema, | |
| )(response); | |
| if (json.data.user === null) { | |
| return yield* new UserNotFoundError({ username }); | |
| } | |
| return { | |
| username: json.data.user.login, | |
| year, | |
| totalCommits: | |
| json.data.user.contributionsCollection.totalCommitContributions, | |
| totalIssues: | |
| json.data.user.contributionsCollection.totalIssueContributions, | |
| totalPullRequests: | |
| json.data.user.contributionsCollection.totalPullRequestContributions, | |
| totalRepositories: | |
| json.data.user.contributionsCollection.totalRepositoryContributions, | |
| totalContributions: | |
| json.data.user.contributionsCollection.contributionCalendar | |
| .totalContributions, | |
| }; | |
| }); | |
| // ============================================================================ | |
| // Example Usage | |
| // ============================================================================ | |
| export const getDifferenceInStats = ({ | |
| JaredStats, | |
| Mystats, | |
| }: { | |
| JaredStats: { | |
| totalCommits: number; | |
| totalIssues: number; | |
| totalPullRequests: number; | |
| totalRepositories: number; | |
| totalContributions: number; | |
| }; | |
| Mystats: { | |
| totalCommits: number; | |
| totalIssues: number; | |
| totalPullRequests: number; | |
| totalRepositories: number; | |
| totalContributions: number; | |
| }; | |
| }): { | |
| totalCommits: number; | |
| totalIssues: number; | |
| totalPullRequests: number; | |
| totalRepositories: number; | |
| totalContributions: number; | |
| } => { | |
| const difference = { | |
| totalCommits: Mystats.totalCommits - JaredStats.totalCommits, | |
| totalIssues: Mystats.totalIssues - JaredStats.totalIssues, | |
| totalPullRequests: Mystats.totalPullRequests - JaredStats.totalPullRequests, | |
| totalRepositories: Mystats.totalRepositories - JaredStats.totalRepositories, | |
| totalContributions: | |
| Mystats.totalContributions - JaredStats.totalContributions, | |
| }; | |
| return difference; | |
| }; | |
| const program = Effect.gen(function* () { | |
| // Bun.env auto-loads .env files! | |
| const token = Bun.env["GITHUB_TOKEN"]; | |
| if (!token) { | |
| return yield* new MissingTokenError(); | |
| } | |
| // Example: Get Jared Sumner's (Bun creator) commits for 2025 | |
| const JaredSumnerStats = yield* getYearlyCommits({ | |
| username: "Jarred-Sumner", | |
| year: 2026, | |
| token, | |
| }); | |
| // need to fetch mine | |
| // | |
| const MyStats = yield* getYearlyCommits({ | |
| username: "kiritocode1", | |
| year: 2026, | |
| token, | |
| }); | |
| // make an object with the stats | |
| const CalculateDifference = getDifferenceInStats({ | |
| JaredStats: JaredSumnerStats, | |
| Mystats: MyStats, | |
| }); | |
| const amIAhead = Object.fromEntries( | |
| Object.entries(CalculateDifference).map(([key, value]) => [key, value > 0]) | |
| ); | |
| return amIAhead; | |
| }); | |
| // Run with FetchHttpClient | |
| const runnable = program.pipe(Effect.provide(FetchHttpClient.layer)).pipe( | |
| Effect.catchTag("UserNotFoundError", ({ username }) => | |
| Console.error(`User ${username} not found.`), | |
| ), | |
| Effect.catchTag("MissingTokenError", () => | |
| Console.error( | |
| "Missing GITHUB_TOKEN environment variable. please set it in your .env file.", | |
| ), | |
| ), | |
| Effect.catchAll((error) => Console.error(`Unknown error: ${error}`)), | |
| ); | |
| Effect.runPromise(runnable).then((amIAhead) =>{ | |
| if (!amIAhead) { | |
| throw new Error("You are not ahead of Jarred Sumner in any category. why? coz your program is not working"); | |
| }; | |
| Object.entries(amIAhead).forEach(([key, value]) => { | |
| const message = value ? `You are ahead of Jarred Sumner in ${key}` : `You are behind Jared Sumner in ${key}`; | |
| console.log(message) | |
| }); | |
| }).catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment