UNPKG

gitfm

Version:

A CLI App for searching GitHub/GitLab repos, fetching as filesystem and cloning

266 lines (240 loc) 6.55 kB
import chalk from "chalk"; import { config } from "./config.js"; const { TOKEN_FILE:CONFIG_FILE } = config; const baseURL = "https://gitlab.com/api/v4"; const checkTokenIsValid = async (token) => { const url = `${baseURL}/personal_access_tokens`; try { const response = await fetch(url,{ method: "GET", headers: { "PRIVATE-TOKEN": token, } }); if (response.status === 401) { console.error("invalid access token: Aborted!"); process.exit(1); } else { console.log("Authentication Successful"); return token; } } catch (error) { console.error(error.message); process.exit(1); } } async function revokeToken(token) { const url = `${baseURL}/personal_access_tokens/self`; try { const response = await fetch(url, { method: "DELETE", headers: { "PRIVATE-TOKEN": token, } }); if (response.status === 204) { return "successful"; } else if (response.status === 400) { return "unsuccessful"; } else if (response.status === 401) { return "invalid"; } } catch (error) { console.error("Fetch Error"); console.log(error); } } async function rotateToken(token, expirationDate) { const url = `${baseURL}/personal_access_tokens/self/rotate`; try { const response = await fetch( `${url}?${new URLSearchParams({ expires_at: expirationDate }).toString()}`, { method: "POST", headers: { "PRIVATE-TOKEN": token, } } ); if (response.ok) { const data = await response.json(); console.log("Token Rotated Successfully!"); return data.token; } else { if (response.status === 400) { console.error("Not Rotated Successfully"); process.exit(1); } else if (response.status === 401) { console.error("Either The Token Has Expired Or Has Been Revoked Already"); process.exit(1); } else if (response.status === 403) { console.error("The Token Is Not Allowed To Rotate Itself"); process.exit(1); } else if (response.status === 405) { console.error("The Token Is Not A Personal Access Token"); process.exit(1); } else { console.error(`Unknown Status ${response.status} Error Occurred!`); process.exit(1); } } } catch (error) { console.error("Fetch Error"); console.log(error); } } async function getProjects(token, searchTerm) { const url = `${baseURL}/search?scope=projects&search=${searchTerm}`; try { const response = await fetch(url, { method: "GET", headers: { "PRIVATE-TOKEN": token, } }); if (response.ok) { const data = await response.json(); const projectsList = data.map((project) => ({ name: project.path_with_namespace, description: project.description, url: project.http_url_to_repo, projectID: project.id, })); return projectsList; } else { console.error(response.statusText); console.error(`Request Returned Status ${response.status} Error`); process.exit(1); } } catch (error) { console.error(error); process.exit(1); } } async function getSingleProject(token, id, recursive=false) { const url = `${baseURL}/projects/${id}/repository/tree?recursive=${recursive}`; try { const response = await fetch(url, { method: "GET", headers: { "PRIVATE-TOKEN": token, } }); if (response.ok) { const data = await response.json(); return data; } else { console.error(response.statusText); console.error(`Request Returned Status ${response.status} Error`); process.exit(1); } } catch (error) { console.error("Fetch Error!"); console.log(error); } } async function listRepoBranches(token, id) { const url = `${baseURL}/projects/${id}/repository/branches`; try { const response = await fetch(url, { method: "GET", headers: { "PRIVATE-TOKEN": token, } }); if (response.ok) { const data = await response.json(); return data.map(item => item.name); } else { console.error(response.statusText); console.error(`Request Returned Status ${response.status} Error`); process.exit(1); } } catch (error) { console.error("Fetch Error!"); console.log(error); } } function projectInfo(project) { const { name, description, url} = project; console.log(''); console.log( chalk.bgGreenBright(chalk.black("repo name :")), "\t", chalk.bold(name), "\n", ); console.log( chalk.bgGreenBright(chalk.black("Description :")), "\t", chalk.bold(description), "\n", ); console.log( chalk.bgGreenBright(chalk.black("URL :")), "\t", chalk.bold(chalk.underline(url)), "\n", ); } async function promptProjectSelection(projects) { const choices = projects.map((project) => ({ name: project.name, value: project, description: project.description, })); try { const { default: search } = await import("@inquirer/search"); return await search({ message: `${chalk.greenBright("Select a repository: ")}${chalk.yellow("(Autocomplete Available)")}`, source: async (input, { signal }) => { if (signal.aborted) { console.log(chalk.yellow("Aborted!")); process.exit(1); } if (!input) { return choices; } else { const filteredChoices = choices.filter((choice) => choice.name.includes(input), ); return filteredChoices; } }, }); } catch (_) { console.log(chalk.yellow("Aborted! Exiting Gracefully...")); process.exit(1); } } // Render the repository contents as a folder structure function renderProjectContents(contents, indent = " ") { try { contents.forEach((item) => { if (item.type === "tree") { console.log( `${indent}`, chalk.bgCyanBright(chalk.black(`${item.name}`)), chalk.blueBright("/"), ); } else { console.log(`${indent}${item.name}`); } }); } catch (error) { console.error("Unexpected Error occured while rendering contents"); console.log(error.message); } } export { CONFIG_FILE, checkTokenIsValid, revokeToken, rotateToken, getProjects, getSingleProject, listRepoBranches, projectInfo, promptProjectSelection, renderProjectContents, }