UNPKG

@xhmikosr/bin-wrapper

Version:

Binary wrapper that makes your programs seamlessly available as local dependencies

184 lines (158 loc) 3.31 kB
import {promises as fs} from 'node:fs'; import path from 'node:path'; import binCheck from '@xhmikosr/bin-check'; import binaryVersionCheck from 'binary-version-check'; import download from '@xhmikosr/downloader'; import osFilterObject from '@xhmikosr/os-filter-obj'; /** * Initialize a new `BinWrapper` * * @param {Object} options * @api public */ export default class BinWrapper { constructor(options = {}) { this.options = options; if (this.options.strip <= 0) { this.options.strip = 0; // eslint-disable-next-line logical-assignment-operators } else if (!this.options.strip) { this.options.strip = 1; } } /** * Get or set files to download * * @param {String} src * @param {String} os * @param {String} arch * @api public */ src(src, os, arch) { if (arguments.length === 0) { return this._src; } this._src ||= []; this._src.push({url: src, os, arch}); return this; } /** * Get or set the destination * * @param {String} dest * @api public */ dest(dest) { if (arguments.length === 0) { return this._dest; } this._dest = dest; return this; } /** * Get or set the binary * * @param {String} bin * @api public */ use(bin) { if (arguments.length === 0) { return this._use; } this._use = bin; return this; } /** * Get or set a semver range to test the binary against * * @param {String} range * @api public */ version(range) { if (arguments.length === 0) { return this._version; } this._version = range; return this; } /** * Get path to the binary * * @api public */ path() { return path.join(this.dest(), this.use()); } /** * Run * * @param {Array} cmd * @api public */ run(cmd = ['--version']) { return this.findExisting().then(() => { if (this.options.skipCheck) { return; } return this.runCheck(cmd); }); } /** * Run binary check * * @param {Array} cmd * @api private */ runCheck(cmd) { return binCheck(this.path(), cmd).then(works => { if (!works) { throw new Error(`The "${this.path()}" binary doesn't seem to work correctly`); } if (this.version()) { return binaryVersionCheck(this.path(), this.version()); } }); } /** * Find existing files * * @api private */ findExisting() { return fs.stat(this.path()).catch(error => { if (error?.code === 'ENOENT') { return this.download(); } throw error; }); } /** * Download files * * @api private */ download() { const files = osFilterObject(this.src() || []); if (files.length === 0) { return Promise.reject(new Error('No binary found matching your system. It\'s probably not supported.')); } const urls = files.map(file => file.url); return Promise.all(urls.map(url => download(url, this.dest(), { extract: true, decompress: { strip: this.options.strip, }, }))).then(result => { const resultFiles = result.flatMap((item, index) => { if (Array.isArray(item)) { return item.map(file => file.path); } const parsedUrl = new URL(files[index].url); const parsedPath = path.parse(parsedUrl.pathname); return parsedPath.base; }); return Promise.all(resultFiles.map(file => fs.chmod(path.join(this.dest(), file), 0o755))); }); } }