UNPKG

fixit-cli

Version:
149 lines (148 loc) 5.1 kB
import fs, { readFileSync } from 'node:fs'; import https from 'node:https'; import { dirname, join } from 'node:path'; import process from 'node:process'; import { fileURLToPath } from 'node:url'; import * as p from '@clack/prompts'; import c from 'picocolors'; import shell from 'shelljs'; /** * The root directory of the project, determined by resolving the path of the current module * and navigating two levels up the directory tree. */ const __root = join(dirname(fileURLToPath(import.meta.url)), '../..'); /** * import json file * @param {string} relativePath relative path to json file * @returns {any} json object */ function importJson(relativePath) { const fileContent = readFileSync(join(__root, relativePath), 'utf8'); return JSON.parse(fileContent); } /** * get latest release info from GitHub API * @param {string} repoOwner repo owner * @param {string} repoName repo name * @example getLatestRelease('hugo-fixit', 'FixIt') * @returns {Promise<ReleaseInfo>} release info */ function getLatestRelease(repoOwner, repoName) { return new Promise((resolve, reject) => { const options = { hostname: 'api.github.com', path: `/repos/${repoOwner}/${repoName}/releases/latest`, headers: { 'User-Agent': 'mozilla/5.0', // set Authorization header set to avoid GitHub API rate limit ...(process.env.GITHUB_TOKEN && { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` }), }, }; const req = https.get(options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { if (res.statusCode === 200) { const releaseInfo = JSON.parse(data); const version = releaseInfo.tag_name; const changelog = releaseInfo.body; const homeUrl = releaseInfo.html_url; resolve({ version, changelog, homeUrl }); } else { reject(new Error(`Failed to get latest release (${res.statusCode})`)); } }); }); req.on('error', (err) => { reject(err); }); req.end(); }); } /** * handle target directory * @param {string} targetDir target directory * @returns {Promise<string>} target directory */ async function handleTargetDir(targetDir) { if (fs.existsSync(targetDir)) { const action = await p.select({ message: `Target Directory ${targetDir} is not empty. Please choose how to proceed:`, options: [ { value: 'cancel', label: 'Cancel operation' }, { value: 'rename', label: 'Rename target directory' }, { value: 'remove', label: 'Remove existing files and continue' }, ], }); if (action === 'cancel' || p.isCancel(action)) { p.cancel('Operation cancelled.'); process.exit(0); } if (action === 'rename') { targetDir = `${targetDir}-${Date.now().toString(36)}`; } else if (action === 'remove') { shell.rm('-rf', targetDir); } } return Promise.resolve(targetDir); } /** * Modify a file's content using a provided modification function * @param {string} filePath Path to the file to be modified * @param {(data: string) => string} modifyFn Function to modify the file content * @param {Spinner} spinner Spinner instance to show progress * @param {string} message Message to display during the modification */ async function modifyFile(filePath, modifyFn, spinner, message) { fs.readFile(filePath, 'utf8', (err, data) => { if (err) { spinner.stop(err.message, -1); return; } spinner.message(message); const result = modifyFn(data); fs.writeFile(filePath, result, 'utf8', (err) => { if (err) { spinner.stop(err.message, -1); return; } spinner.message(`${c.green('✔')} ${message}`); }); }); } /** * Remove the remote origin from a git repository * @param {SimpleGit} git SimpleGit instance * @param {Spinner} spinner Spinner instance to show progress */ async function removeRemoteOrigin(git, spinner) { spinner.message('Removing remote origin.'); git.removeRemote('origin', (err) => { if (err) { spinner.stop(err.message, -1); return; } spinner.message(`${c.green('✔')} removed remote origin.`); }); } /** * Timer object to measure elapsed time * @type {Timer} */ const timer = { __start: 0, __end: 0, start: (msg) => { timer.__start = Date.now(); msg && p.intro(msg); }, stop: () => { timer.__end = Date.now(); return timer.__end - timer.__start; }, }; export { getLatestRelease, handleTargetDir, importJson, modifyFile, removeRemoteOrigin, timer, };