UNPKG

@smushytaco/custompatch

Version:

Tool for patching buggy NPM packages instead of forking them

143 lines (141 loc) 6 kB
#!/usr/bin/env node import fs from 'node:fs'; import path from 'pathe'; import os from 'node:os'; import { program } from 'commander'; import pacote from 'pacote'; import pc from 'picocolors'; import { p as programOptions, o as ownPackage, c as currentDirectory, a as patchDirectory } from './variables.mjs'; import { r as readPatch, g as getConfig, c as comparePackages } from './patch-utilities.mjs'; import { n as npmTarballURL } from './npm-utilities.mjs'; import 'diff'; import './file-utilities.mjs'; import './utilities.mjs'; const patchFiles = []; const missingPackages = []; function addPatchFileIfExists(packageName, version) { const thePackageName = packageName.replaceAll("+", path.sep); const destination = path.join(currentDirectory, "node_modules", thePackageName); if (!fs.existsSync(destination)) { console.warn(`${pc.yellowBright("WARNING:")} Package "${thePackageName}" is not installed, skipping this patch.`); return; } patchFiles.push({ packageName, version }); } try { if (!programOptions.version) { console.log(`${pc.whiteBright("CustomPatch")} version ${pc.greenBright(ownPackage.version)}! `); } if (!fs.existsSync(path.join(currentDirectory, "node_modules"))) { console.error(`${pc.redBright("ERROR:")} Missing "node_modules" folder.`); process.exit(1); } if (programOptions.patch && programOptions.reverse) { console.error(`${pc.redBright("ERROR:")} Cannot use -p/--patch and -r/--reverse together.`); process.exit(1); } if (programOptions.patch || programOptions.reverse) { const action = programOptions.reverse ? "reverse" : "apply"; const packageNames = program.args; if (!fs.existsSync(patchDirectory)) { console.warn(`${pc.yellowBright("WARNING:")} Missing "patches" folder, nothing to do.`); process.exit(2); } const allPatchFiles = fs.readdirSync(patchDirectory).filter((item) => item.endsWith(".patch")); let selectedPatchFiles; if (packageNames.length > 0) { selectedPatchFiles = allPatchFiles.filter((patchFile) => { const package_ = patchFile.replace(".patch", "").split("#"); const packageName = package_[0].replaceAll("+", path.sep); return packageNames.includes(packageName); }); for (const package_ of packageNames) { const found = selectedPatchFiles.some((patchFile) => { const packageInFile = patchFile.replace(".patch", "").split("#")[0]; return packageInFile === package_.replaceAll("/", "+"); }); if (!found) { missingPackages.push(package_); } } if (selectedPatchFiles.length === 0 && missingPackages.length > 0) { for (const package_ of missingPackages) { console.warn(`${pc.yellowBright("WARNING:")} No patches found for package "${package_}".`); } process.exit(0); } } else { selectedPatchFiles = allPatchFiles; } for (const patchFile of selectedPatchFiles) { const package_ = patchFile.replace(".patch", "").split("#"); addPatchFileIfExists(package_[0], package_[1]); } if (missingPackages.length > 0) { for (const package_ of missingPackages) { console.warn(`${pc.yellowBright("WARNING:")} No patches found for package "${package_}".`); } } console.log(`${action === "apply" ? "Applying" : "Reversing"} ${pc.cyanBright(patchFiles.length)} patch${patchFiles.length === 1 ? "." : "es."}`); for (const { packageName, version } of patchFiles) { try { await readPatch(packageName, version, programOptions.reverse); } catch (error) { console.error(`${pc.redBright("ERROR:")} Failed to ${action} patch for ${packageName} - ${error instanceof Error ? error.message : String(error)}`); } } } else if (program.args.length > 0) { for (const packageName of program.args) { await makePatch(packageName); } } else { if (!fs.existsSync(patchDirectory)) { console.warn(`${pc.yellowBright("WARNING:")} Missing "patches" folder, nothing to do.`); process.exit(2); } for (const item of fs.readdirSync(patchDirectory)) { if (!item.endsWith(".patch")) continue; const package_ = item.replace(".patch", "").split("#"); addPatchFileIfExists(package_[0], package_[1]); } console.log(`Found ${pc.cyanBright(patchFiles.length)} ${patchFiles.length === 1 ? "patch." : "patches."}`); for (const { packageName, version } of patchFiles) { try { await readPatch(packageName, version); } catch (error) { console.error(`${pc.redBright("ERROR:")} Failed to apply patch for ${packageName} - ${error instanceof Error ? error.message : String(error)}`); } } } } catch (error) { console.error(`${pc.redBright("ERROR:")} Unhandled error: ${error instanceof Error ? error.message : String(error)}`); process.exit(1); } async function makePatch(packageName) { console.log(`Creating patch for: ${pc.magentaBright(packageName)}.`); const config = getConfig(packageName); if (config) { await fetchPackage(packageName, npmTarballURL(packageName, config.version), config.version); } else { console.error(`${pc.redBright("ERROR:")} Could not find the URL for tarball.`); } } async function fetchPackage(packageName, url, version) { console.log(`Fetching tarball of ${pc.whiteBright(packageName)} from ${pc.green(url)}`); const destination = path.join(os.tmpdir(), packageName); try { await pacote.extract(url, destination); await comparePackages(packageName, version); } catch (error) { console.error(pc.redBright(error instanceof Error ? error.message : String(error))); return; } try { await fs.promises.rm(destination, { recursive: true, force: true }); } catch (error) { console.error(`${pc.redBright("ERROR:")} Could not clean up the TEMP folder - ${error instanceof Error ? error.message : String(error)}`); } } //# sourceMappingURL=cli.mjs.map