UNPKG

@terascope/fetch-github-release

Version:

Download a specific release from github

116 lines 4.47 kB
import os from 'node:os'; import fs from 'node:fs'; import path from 'node:path'; import extract from 'extract-zip'; import MultiProgress from 'multi-progress'; import { getReleases } from './getReleases.js'; import { getLatest } from './getLatest.js'; import { download } from './download.js'; import { rpad } from './rpad.js'; function pass() { return true; } /** * Download a specific github release * @param user The name of the github user or organization * @param repo The name of the github repository * @param outputDir The directory to write the release to * @param filterRelease Optionally filter the release * @param filterAsset Optionally filter the asset for a given release * @param leaveZipped Optionally leave the file zipped * @param leaveZipped Optionally disable logging for quiet output * @param dryRun Only return information on what would have been downloaded * @param output Returns dry-run information in either plaintext or json format */ export async function downloadRelease(user, repo, outputDir, filterRelease = pass, filterAsset = pass, leaveZipped = false, disableLogging = false, dryRun = false, output = 'text') { if (!user) { throw new Error('Missing user argument'); } if (!repo) { throw new Error('Missing user argument'); } const bars = new MultiProgress(process.stderr); const releases = await getReleases(user, repo); const release = getLatest(releases, filterRelease, filterAsset); if (!release) { throw new Error(`Could not find a release for ${user}/${repo} (${os.platform()} ${os.arch()})`); } if (!disableLogging && !dryRun) { console.error(`Downloading ${user}/${repo}@${release.tag_name}...`); } const promises = release.assets.map(async (asset) => { let progress; if (dryRun) { return asset.name; } if (process.stdout.isTTY && !disableLogging) { const bar = bars.newBar(`${rpad(asset.name, 24)} :bar :etas`, { complete: '▇', incomplete: '-', width: process.stdout.columns - 36, total: 100 }); progress = bar.update.bind(bar); } // eslint-disable-next-line no-param-reassign outputDir = path.isAbsolute(outputDir) ? outputDir : path.resolve(outputDir); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir); } if (!fs.statSync(outputDir).isDirectory()) { throw new Error(`Output path "${outputDir}" must be a directory`); } const destf = path.join(outputDir, asset.name); if (!fs.existsSync(destf)) { const dest = fs.createWriteStream(destf); await download(asset.url, dest, progress); if (!leaveZipped && /\.zip$/.exec(destf)) { await extract(destf, { dir: outputDir }); fs.unlinkSync(destf); } } return destf; }); if (dryRun) { // In case of dryrun, send an organized object const dryRunInfo = { release: `${user}/${repo}@${release.tag_name}`, assetFileNames: await Promise.all(promises) }; /// Give only the release string in the case // that quiet is enabled if (disableLogging && output === 'text') { process.stdout.write(`${dryRunInfo.release}\n`); } else if (disableLogging && output === 'json') { process.stdout.write(`${JSON.stringify(dryRunInfo.release, null, 2)}\n`); } else { printDryRunInfo(dryRunInfo, output); } return Promise.resolve(dryRunInfo); } return Promise.all(promises); } /** * Prints dry-run info in plaintext or JSON format. * * @param {ReleaseInfo} data The release information to display. * @param {string} output The output format, either 'text' or 'json'. */ function printDryRunInfo(data, output) { if (output === 'text') { const prompt = [ `Release: ${data.release}\n`, 'The following files would have been downloaded:\n', ...data.assetFileNames.map((file) => `- ${file}`), ].join('\n'); process.stdout.write(`${prompt}\n`); } else if (output === 'json') { process.stdout.write(`${JSON.stringify(data, null, 2)}\n`); } } //# sourceMappingURL=downloadRelease.js.map