@remcostoeten/fync
Version:
Unified TypeScript library for 9 popular APIs with consistent functional architecture
544 lines (543 loc) • 12.1 kB
JavaScript
;
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