@remcostoeten/fync
Version:
Unified TypeScript library for 9 popular APIs with consistent functional architecture
299 lines • 12.4 kB
JavaScript
import { createApiBuilder, defineResource } from "../core";
const GITLAB_API_BASE = "https://gitlab.com/api/v4";
const userResource = defineResource({
name: "users",
basePath: "/users",
methods: {
getUser: { path: "/{id}" },
getUserProjects: { path: "/{id}/projects" },
getUserSnippets: { path: "/{id}/snippets" },
getUserEvents: { path: "/{id}/events" },
getUserContributedProjects: { path: "/{id}/contributed_projects" },
getUserStarredProjects: { path: "/{id}/starred_projects" },
getUserMemberships: { path: "/{id}/memberships" },
getUserFollowers: { path: "/{id}/followers" },
getUserFollowing: { path: "/{id}/following" },
getCurrentUser: { path: "/current" },
searchUsers: { path: "", method: "GET" },
},
});
const projectResource = defineResource({
name: "projects",
basePath: "/projects",
methods: {
getProject: { path: "/{id}" },
getProjectCommits: { path: "/{id}/repository/commits" },
getProjectCommit: { path: "/{id}/repository/commits/{sha}" },
getProjectBranches: { path: "/{id}/repository/branches" },
getProjectTags: { path: "/{id}/repository/tags" },
getProjectReleases: { path: "/{id}/releases" },
getProjectMembers: { path: "/{id}/members" },
getProjectIssues: { path: "/{id}/issues" },
getProjectIssue: { path: "/{id}/issues/{issue_iid}" },
getProjectMergeRequests: { path: "/{id}/merge_requests" },
getProjectMergeRequest: { path: "/{id}/merge_requests/{merge_request_iid}" },
getProjectContributors: { path: "/{id}/repository/contributors" },
getProjectLanguages: { path: "/{id}/languages" },
getProjectRepository: { path: "/{id}/repository/tree" },
getProjectFile: { path: "/{id}/repository/files/{file_path}" },
getProjectReadme: { path: "/{id}/repository/files/README.md" },
getProjectVariables: { path: "/{id}/variables" },
getProjectPipelines: { path: "/{id}/pipelines" },
getProjectJobs: { path: "/{id}/jobs" },
getProjectEnvironments: { path: "/{id}/environments" },
createProject: { path: "", method: "POST" },
updateProject: { path: "/{id}", method: "PUT" },
deleteProject: { path: "/{id}", method: "DELETE" },
createProjectIssue: { path: "/{id}/issues", method: "POST" },
updateProjectIssue: { path: "/{id}/issues/{issue_iid}", method: "PUT" },
createProjectMergeRequest: { path: "/{id}/merge_requests", method: "POST" },
updateProjectMergeRequest: { path: "/{id}/merge_requests/{merge_request_iid}", method: "PUT" },
starProject: { path: "/{id}/star", method: "POST" },
unstarProject: { path: "/{id}/unstar", method: "POST" },
forkProject: { path: "/{id}/fork", method: "POST" },
},
});
const groupResource = defineResource({
name: "groups",
basePath: "/groups",
methods: {
getGroup: { path: "/{id}" },
getGroupProjects: { path: "/{id}/projects" },
getGroupMembers: { path: "/{id}/members" },
getGroupSubgroups: { path: "/{id}/subgroups" },
getGroupVariables: { path: "/{id}/variables" },
getGroupEpics: { path: "/{id}/epics" },
createGroup: { path: "", method: "POST" },
updateGroup: { path: "/{id}", method: "PUT" },
deleteGroup: { path: "/{id}", method: "DELETE" },
searchGroups: { path: "", method: "GET" },
},
});
const searchResource = defineResource({
name: "search",
basePath: "/search",
methods: {
searchProjects: { path: "", method: "GET" },
searchGroups: { path: "", method: "GET" },
searchUsers: { path: "", method: "GET" },
searchSnippets: { path: "", method: "GET" },
searchIssues: { path: "", method: "GET" },
searchMergeRequests: { path: "", method: "GET" },
searchMilestones: { path: "", method: "GET" },
searchWiki: { path: "", method: "GET" },
searchCommits: { path: "", method: "GET" },
searchBlobs: { path: "", method: "GET" },
},
});
const snippetResource = defineResource({
name: "snippets",
basePath: "/snippets",
methods: {
getPublicSnippets: { path: "/public" },
getSnippet: { path: "/{id}" },
getSnippetContent: { path: "/{id}/raw" },
createSnippet: { path: "", method: "POST" },
updateSnippet: { path: "/{id}", method: "PUT" },
deleteSnippet: { path: "/{id}", method: "DELETE" },
getUserSnippets: { path: "/all" },
},
});
const issueResource = defineResource({
name: "issues",
basePath: "/issues",
methods: {
getIssues: { path: "" },
getIssue: { path: "/{id}" },
createIssue: { path: "", method: "POST" },
updateIssue: { path: "/{id}", method: "PUT" },
deleteIssue: { path: "/{id}", method: "DELETE" },
getIssueNotes: { path: "/{id}/notes" },
createIssueNote: { path: "/{id}/notes", method: "POST" },
},
});
const mergeRequestResource = defineResource({
name: "merge_requests",
basePath: "/merge_requests",
methods: {
getMergeRequests: { path: "" },
getMergeRequest: { path: "/{id}" },
createMergeRequest: { path: "", method: "POST" },
updateMergeRequest: { path: "/{id}", method: "PUT" },
deleteMergeRequest: { path: "/{id}", method: "DELETE" },
acceptMergeRequest: { path: "/{id}/merge", method: "PUT" },
getMergeRequestNotes: { path: "/{id}/notes" },
createMergeRequestNote: { path: "/{id}/notes", method: "POST" },
getMergeRequestCommits: { path: "/{id}/commits" },
getMergeRequestChanges: { path: "/{id}/changes" },
},
});
const pipelineResource = defineResource({
name: "pipelines",
basePath: "/projects/{project_id}/pipelines",
methods: {
getPipelines: { path: "" },
getPipeline: { path: "/{id}" },
createPipeline: { path: "", method: "POST" },
deletePipeline: { path: "/{id}", method: "DELETE" },
retryPipeline: { path: "/{id}/retry", method: "POST" },
cancelPipeline: { path: "/{id}/cancel", method: "POST" },
getPipelineJobs: { path: "/{id}/jobs" },
getPipelineVariables: { path: "/{id}/variables" },
},
});
const activityResource = defineResource({
name: "activity",
basePath: "",
methods: {
getEvents: { path: "/events" },
getUserEvents: { path: "/users/{user_id}/events" },
getProjectEvents: { path: "/projects/{project_id}/events" },
getTodos: { path: "/todos" },
markTodoAsDone: { path: "/todos/{id}/mark_as_done", method: "POST" },
markAllTodosAsDone: { path: "/todos/mark_as_done", method: "POST" },
},
});
const authResource = defineResource({
name: "me",
basePath: "/user",
methods: {
getCurrentUser: { path: "" },
getUserProjects: { path: "/projects" },
getUserStarredProjects: { path: "/starred_projects" },
getUserGPGKeys: { path: "/gpg_keys" },
getUserSSHKeys: { path: "/keys" },
addSSHKey: { path: "/keys", method: "POST" },
deleteSSHKey: { path: "/keys/{key_id}", method: "DELETE" },
getUserEmails: { path: "/emails" },
addEmail: { path: "/emails", method: "POST" },
deleteEmail: { path: "/emails/{email_id}", method: "DELETE" },
getUserMemberships: { path: "/memberships" },
getUserStatus: { path: "/status" },
setUserStatus: { path: "/status", method: "PUT" },
},
});
const resources = {
users: userResource,
projects: projectResource,
groups: groupResource,
search: searchResource,
snippets: snippetResource,
issues: issueResource,
merge_requests: mergeRequestResource,
pipelines: pipelineResource,
activity: activityResource,
me: authResource,
};
const buildGitLab = createApiBuilder({
baseUrl: GITLAB_API_BASE,
auth: { type: "bearer" },
headers: {
"Content-Type": "application/json",
},
});
export function GitLab(config) {
const base = buildGitLab(config, resources);
function parseGitLabUrl(url) {
// GitLab can use project ID or namespace/project format
const match = url.match(/gitlab\.com\/([^/]+\/[^/]+)/);
if (match) {
return { id: encodeURIComponent(match[1]) };
}
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 gitlab = base;
gitlab.getUser = function (id) {
return base.users.getUser({ id: id.toString() });
};
gitlab.getProject = function (id) {
return base.projects.getProject({ id: id.toString() });
};
gitlab.getProjectFromUrl = function (url) {
const parsed = parseGitLabUrl(url);
if (!parsed)
throw new Error("Invalid GitLab URL");
return base.projects.getProject(parsed);
};
gitlab.getUserCommits = async function (userId, options) {
const events = await base.users.getUserEvents({
id: userId.toString(),
per_page: options?.limit || 100,
});
return events.filter((e) => e.action === "pushed");
};
gitlab.getUserLatestCommit = async function (userId) {
const commits = await gitlab.getUserCommits(userId, { limit: 1 });
return commits[0] || null;
};
gitlab.getUserCommitsInTimeframe = async function (userId, timeframe) {
const since = calculateTimeframeDate(timeframe);
const events = await base.users.getUserEvents({ id: userId.toString() });
return events.filter((e) => e.action === "pushed" && new Date(e.created_at) >= new Date(since));
};
gitlab.getProjectStars = async function (projectId) {
const project = await base.projects.getProject({ id: projectId.toString() });
return project.star_count || 0;
};
gitlab.getUserStarredCount = async function (userId) {
const starred = await base.users.getUserStarredProjects({ id: userId.toString() });
return Array.isArray(starred) ? starred.length : 0;
};
gitlab.getUserStats = async function (userId) {
const [user, projects, events] = await Promise.all([
base.users.getUser({ id: userId.toString() }),
base.users.getUserProjects({ id: userId.toString() }),
base.users.getUserEvents({ id: userId.toString(), per_page: 100 }),
]);
const pushEvents = events.filter((e) => e.action === "pushed");
const totalStars = projects.reduce((sum, project) => sum + (project.star_count || 0), 0);
return {
user,
totalProjects: projects.length,
totalStars,
recentCommits: pushEvents.length,
publicProjects: projects.filter((p) => p.visibility === "public").length,
followers: user.followers || 0,
following: user.following || 0,
};
};
gitlab.searchProjects = function (query, options) {
return base.search.searchProjects({ search: query, ...options });
};
gitlab.getUserActivity = function (userId, options) {
return base.users.getUserEvents({ id: userId.toString(), ...options });
};
gitlab.getGroup = function (id) {
return base.groups.getGroup({ id: id.toString() });
};
gitlab.searchGroups = function (query, options) {
return base.search.searchGroups({ search: query, ...options });
};
gitlab.getCurrentUser = function () {
return base.me.getCurrentUser({});
};
return gitlab;
}
//# sourceMappingURL=index.js.map