UNPKG

@remcostoeten/fync

Version:

Unified TypeScript library for 9 popular APIs with consistent functional architecture

544 lines (543 loc) 12.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _exportNames = { GitHub: true, GitHubOAuth: true, createGitHubOAuth: true, gitHubOAuth: true }; exports.GitHub = GitHub; Object.defineProperty(exports, "GitHubOAuth", { enumerable: true, get: function () { return _oauth.GitHubOAuth; } }); Object.defineProperty(exports, "createGitHubOAuth", { enumerable: true, get: function () { return _oauth.createGitHubOAuth; } }); Object.defineProperty(exports, "gitHubOAuth", { enumerable: true, get: function () { return _oauth.gitHubOAuth; } }); var _core = require("../core"); var _oauth = require("./oauth"); var _types = require("./types"); Object.keys(_types).forEach(function (key) { if (key === "default" || key === "__esModule") return; if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; if (key in exports && exports[key] === _types[key]) return; Object.defineProperty(exports, key, { enumerable: true, get: function () { return _types[key]; } }); }); const GITHUB_API_BASE = "https://api.github.com"; const userResource = (0, _core.defineResource)({ name: "users", basePath: "/users", methods: { getUser: { path: "/{username}" }, getUserRepos: { path: "/{username}/repos" }, getUserGists: { path: "/{username}/gists" }, getUserFollowers: { path: "/{username}/followers" }, getUserFollowing: { path: "/{username}/following" }, getUserStarred: { path: "/{username}/starred" }, getUserOrgs: { path: "/{username}/orgs" }, getUserEvents: { path: "/{username}/events" }, getUserReceivedEvents: { path: "/{username}/received_events" }, checkUserFollowing: { path: "/{username}/following/{target}" } } }); const repoResource = (0, _core.defineResource)({ name: "repos", basePath: "/repos", methods: { getRepo: { path: "/{owner}/{repo}" }, getRepoCommits: { path: "/{owner}/{repo}/commits" }, getRepoCommit: { path: "/{owner}/{repo}/commits/{sha}" }, getRepoBranches: { path: "/{owner}/{repo}/branches" }, getRepoTags: { path: "/{owner}/{repo}/tags" }, getRepoReleases: { path: "/{owner}/{repo}/releases" }, getRepoLatestRelease: { path: "/{owner}/{repo}/releases/latest" }, getRepoContributors: { path: "/{owner}/{repo}/contributors" }, getRepoLanguages: { path: "/{owner}/{repo}/languages" }, getRepoTopics: { path: "/{owner}/{repo}/topics" }, getRepoStargazers: { path: "/{owner}/{repo}/stargazers" }, getRepoForks: { path: "/{owner}/{repo}/forks" }, getRepoIssues: { path: "/{owner}/{repo}/issues" }, getRepoIssue: { path: "/{owner}/{repo}/issues/{issue_number}" }, getRepoPulls: { path: "/{owner}/{repo}/pulls" }, getRepoPull: { path: "/{owner}/{repo}/pulls/{pull_number}" }, getRepoContents: { path: "/{owner}/{repo}/contents/{path}" }, getRepoReadme: { path: "/{owner}/{repo}/readme" }, createRepoIssue: { path: "/{owner}/{repo}/issues", method: "POST" }, updateRepoIssue: { path: "/{owner}/{repo}/issues/{issue_number}", method: "PATCH" }, createRepoPull: { path: "/{owner}/{repo}/pulls", method: "POST" } } }); const searchResource = (0, _core.defineResource)({ name: "search", basePath: "/search", methods: { searchRepos: { path: "/repositories" }, searchCode: { path: "/code" }, searchIssues: { path: "/issues" }, searchUsers: { path: "/users" }, searchTopics: { path: "/topics" }, searchLabels: { path: "/labels" }, searchCommits: { path: "/commits" } } }); const gistResource = (0, _core.defineResource)({ name: "gists", basePath: "/gists", methods: { getPublicGists: { path: "" }, getUserGists: { path: "/users/{username}/gists" }, getGist: { path: "/{gist_id}" }, createGist: { path: "", method: "POST" }, updateGist: { path: "/{gist_id}", method: "PATCH" }, deleteGist: { path: "/{gist_id}", method: "DELETE" }, getGistComments: { path: "/{gist_id}/comments" }, createGistComment: { path: "/{gist_id}/comments", method: "POST" } } }); const orgResource = (0, _core.defineResource)({ name: "orgs", basePath: "/orgs", methods: { getOrg: { path: "/{org}" }, getOrgRepos: { path: "/{org}/repos" }, getOrgMembers: { path: "/{org}/members" }, getOrgTeams: { path: "/{org}/teams" }, getOrgProjects: { path: "/{org}/projects" }, getOrgEvents: { path: "/{org}/events" }, checkOrgMembership: { path: "/{org}/members/{username}" } } }); const activityResource = (0, _core.defineResource)({ name: "activity", basePath: "", methods: { getPublicEvents: { path: "/events" }, getNotifications: { path: "/notifications" }, markNotificationAsRead: { path: "/notifications/{notification_id}", method: "PATCH" }, getStarred: { path: "/user/starred" }, starRepo: { path: "/user/starred/{owner}/{repo}", method: "PUT" }, unstarRepo: { path: "/user/starred/{owner}/{repo}", method: "DELETE" }, getWatching: { path: "/user/subscriptions" }, watchRepo: { path: "/user/subscriptions/{owner}/{repo}", method: "PUT" }, unwatchRepo: { path: "/user/subscriptions/{owner}/{repo}", method: "DELETE" } } }); const authUserResource = (0, _core.defineResource)({ name: "me", basePath: "/user", methods: { getAuthenticatedUser: { path: "" }, updateAuthenticatedUser: { path: "", method: "PATCH" }, getMyRepos: { path: "/repos" }, getMyOrgs: { path: "/orgs" }, getMyGists: { path: "/gists" }, getMyFollowers: { path: "/followers" }, getMyFollowing: { path: "/following" }, followUser: { path: "/following/{username}", method: "PUT" }, unfollowUser: { path: "/following/{username}", method: "DELETE" }, getMyEmails: { path: "/emails" }, getMySSHKeys: { path: "/keys" }, addSSHKey: { path: "/keys", method: "POST" }, deleteSSHKey: { path: "/keys/{key_id}", method: "DELETE" } } }); const statsResource = (0, _core.defineResource)({ name: "stats", basePath: "/repos/{owner}/{repo}/stats", methods: { getContributorStats: { path: "/contributors" }, getCommitActivity: { path: "/commit_activity" }, getCodeFrequency: { path: "/code_frequency" }, getParticipation: { path: "/participation" }, getPunchCard: { path: "/punch_card" } } }); const gitDataResource = (0, _core.defineResource)({ name: "git", basePath: "/repos/{owner}/{repo}/git", methods: { getRef: { path: "/ref/{ref}" }, getRefs: { path: "/refs" }, createRef: { path: "/refs", method: "POST" }, updateRef: { path: "/refs/{ref}", method: "PATCH" }, deleteRef: { path: "/refs/{ref}", method: "DELETE" }, getCommit: { path: "/commits/{commit_sha}" }, createCommit: { path: "/commits", method: "POST" }, getTree: { path: "/trees/{tree_sha}" }, createTree: { path: "/trees", method: "POST" }, getBlob: { path: "/blobs/{file_sha}" }, createBlob: { path: "/blobs", method: "POST" }, getTag: { path: "/tags/{tag_sha}" }, createTag: { path: "/tags", method: "POST" } } }); const resources = { users: userResource, repos: repoResource, search: searchResource, gists: gistResource, orgs: orgResource, activity: activityResource, me: authUserResource, stats: statsResource, git: gitDataResource }; const buildGitHub = (0, _core.createApiBuilder)({ baseUrl: GITHUB_API_BASE, auth: { type: "bearer" }, headers: { Accept: "application/vnd.github.v3+json", "X-GitHub-Api-Version": "2022-11-28" } }); function GitHub(config) { const base = buildGitHub(config, resources); function parseGitHubUrl(url) { const match = url.match(/github\.com\/([^/]+)\/([^/]+)/); if (match) { return { owner: match[1], repo: match[2].replace(/\.git$/, "") }; } return null; } function calculateTimeframeDate(timeframe) { const now = new Date(); const match = timeframe.match(/(\d+)([DWMY])/i); if (!match) return now.toISOString(); const [, amount, unit] = match; const num = parseInt(amount, 10); switch (unit.toUpperCase()) { case "D": now.setDate(now.getDate() - num); break; case "W": now.setDate(now.getDate() - num * 7); break; case "M": now.setMonth(now.getMonth() - num); break; case "Y": now.setFullYear(now.getFullYear() - num); break; } return now.toISOString(); } const github = base; github.getUser = function (username) { return base.users.getUser({ username }); }; github.getRepository = function (owner, repo) { return base.repos.getRepo({ owner, repo }); }; github.getRepositoryFromUrl = function (url) { const parsed = parseGitHubUrl(url); if (!parsed) throw new Error("Invalid GitHub URL"); return base.repos.getRepo(parsed); }; github.getUserCommits = async function (username, options) { const events = await base.users.getUserEvents({ username, per_page: options?.limit || 100 }); return events.filter(e => e.type === "PushEvent"); }; github.getUserLatestCommit = async function (username) { const commits = await github.getUserCommits(username, { limit: 1 }); return commits[0] || null; }; github.getUserCommitsInTimeframe = async function (username, timeframe) { const since = calculateTimeframeDate(timeframe); const events = await base.users.getUserEvents({ username }); return events.filter(e => e.type === "PushEvent" && new Date(e.created_at) >= new Date(since)); }; github.getRepositoryStars = async function (owner, repo) { const repository = await base.repos.getRepo({ owner, repo }); return repository.stargazers_count || 0; }; github.getUserStarredCount = async function (username) { const starred = await base.users.getUserStarred({ username }); return Array.isArray(starred) ? starred.length : 0; }; github.getUserStats = async function (username) { const [user, repos, events] = await Promise.all([base.users.getUser({ username }), base.users.getUserRepos({ username }), base.users.getUserEvents({ username, per_page: 100 })]); const pushEvents = events.filter(e => e.type === "PushEvent"); const totalStars = repos.reduce((sum, repo) => sum + (repo.stargazers_count || 0), 0); return { user, totalRepos: repos.length, totalStars, recentCommits: pushEvents.length, publicRepos: user.public_repos, publicGists: user.public_gists, followers: user.followers, following: user.following }; }; github.searchRepositories = function (query, options) { return base.search.searchRepos({ q: query, ...options }); }; github.getUserActivity = function (username, options) { return base.users.getUserEvents({ username, ...options }); }; return github; } // Export OAuth functionality