UNPKG

@smushytaco/custompatch

Version:

Tool for patching buggy NPM packages instead of forking them

1 lines 18.9 kB
{"version":3,"file":"patch-utilities.mjs","sources":["../src/patch-utilities.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'pathe';\nimport {\n createTwoFilesPatch,\n parsePatch,\n reversePatch,\n applyPatch\n} from 'diff';\nimport pc from 'picocolors';\nimport { PackageConfig } from './types.js';\nimport {\n ensureDirectoryExists,\n pathNormalize,\n readFileContent\n} from './file-utilities.js';\nimport {\n programOptions,\n currentDirectory,\n temporaryDirectory,\n patchDirectory\n} from './variables.js';\n\nexport function createPatch(\n packageName: string,\n pathname: string,\n patch: fs.WriteStream\n): void {\n const newFile = path.join(\n currentDirectory,\n 'node_modules',\n packageName,\n pathname\n );\n const oldFile = path.join(temporaryDirectory, packageName, pathname);\n const oldString = fs.existsSync(oldFile) ? readFileContent(oldFile) : '';\n const newString = readFileContent(newFile);\n if (pathname === 'package.json' && !programOptions.all) return; // Skip \"package.json\"\n if (oldString !== newString) {\n patch.write(\n createTwoFilesPatch(\n oldFile.replace(temporaryDirectory, ''),\n newFile.replace(\n path.join(currentDirectory, 'node_modules'),\n ''\n ),\n oldString,\n newString\n )\n );\n }\n}\n\nexport function makePatchName(packageName: string, version: string): string {\n return `${packageName.replaceAll('/', '+')}#${version}.patch`;\n}\n\nexport async function comparePackages(\n packageName: string,\n version: string\n): Promise<void> {\n const patchFile = makePatchName(packageName, version);\n\n // Ensure the patches directory exists\n ensureDirectoryExists(patchDirectory);\n\n const stream = fs.createWriteStream(path.join(patchDirectory, patchFile));\n stream.on('error', (error) => {\n console.error(\n `${pc.redBright('ERROR:')} Failed to write to patch file - ${error.message}`\n );\n });\n\n stream.cork();\n scanFiles(packageName, '', stream);\n stream.uncork();\n\n // Handle 'drain' event if necessary\n if (stream.write('')) {\n stream.end();\n } else {\n stream.once('drain', () => {\n stream.end();\n });\n }\n\n console.log(`Successfully created ${pc.greenBright(patchFile)}`);\n}\n\nexport function scanFiles(\n packageName: string,\n source: string,\n patch: fs.WriteStream\n): void {\n const baseDirectory = path.join(\n currentDirectory,\n 'node_modules',\n packageName\n );\n const stack: string[] = [source];\n const visitedPaths = new Set<string>();\n while (stack.length > 0) {\n const currentSource = stack.pop();\n if (currentSource === undefined) continue;\n const directoryPath = path.join(baseDirectory, currentSource);\n let files: string[];\n try {\n files = fs.readdirSync(directoryPath);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Failed to read directory ${directoryPath} - ${error instanceof Error ? error.message : String(error)}`\n );\n continue;\n }\n\n for (const item of files) {\n if (item === 'node_modules') continue;\n\n const pathname = path.join(currentSource, item);\n const itemPath = path.join(baseDirectory, pathname);\n\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(itemPath);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Failed to get stats for ${itemPath} - ${error instanceof Error ? error.message : String(error)}`\n );\n continue;\n }\n\n if (stat.isSymbolicLink()) {\n // Skip symlinks to avoid cycles\n continue;\n }\n\n if (stat.isDirectory()) {\n // Prevent processing the same directory due to hard links or other reasons\n const realPath = fs.realpathSync(itemPath);\n if (visitedPaths.has(realPath)) {\n // Already visited this directory\n continue;\n }\n visitedPaths.add(realPath);\n stack.push(pathname);\n } else {\n createPatch(packageName, pathname, patch);\n }\n }\n }\n}\n\nexport async function readPatch(\n packageName: string,\n version: string,\n reverse: boolean = false\n): Promise<void> {\n const thePackageName = packageName.replaceAll('+', path.sep);\n const config = getConfig(thePackageName);\n if (config) {\n const patchFile = makePatchName(packageName, version);\n const patchFilePath = path.join(patchDirectory, patchFile);\n if (!fs.existsSync(patchFilePath)) {\n console.warn(\n `${pc.yellowBright('WARNING:')} Patch file \"${patchFile}\" does not exist.`\n );\n return;\n }\n const patchContent = readFileContent(patchFilePath);\n\n const patches = parsePatch(patchContent);\n\n for (const patchItem of patches) {\n // Ensure that we have a valid file name\n const filePath = patchItem.newFileName ?? patchItem.oldFileName;\n if (!filePath) {\n console.error(\n `${pc.redBright('ERROR:')} Patch item has no file names for package ${packageName}`\n );\n continue; // Skip this patch item\n }\n\n const normalizedPath = pathNormalize(filePath);\n const fileName = path.join(\n currentDirectory,\n 'node_modules',\n normalizedPath\n );\n\n let fileContent = '';\n if (fs.existsSync(fileName)) {\n fileContent = readFileContent(fileName);\n } else {\n console.warn(\n `${pc.yellowBright('WARNING:')} File \"${fileName}\" does not exist - skipping.`\n );\n continue;\n }\n\n if (reverse) {\n // Reverse the patch\n const reversedPatchText = reversePatch(patchItem);\n const reversePatchedContent = applyPatch(\n fileContent,\n reversedPatchText\n );\n\n if (reversePatchedContent === false) {\n // Failed to reverse the patch\n // Attempt to apply the original patch to check if it's already reversed\n const patchedContent = applyPatch(fileContent, patchItem);\n\n if (patchedContent === false) {\n // Patch failed for other reasons\n console.warn(\n `${pc.yellowBright('WARNING:')} Failed to reverse patch for ${pc.redBright(fileName)}`\n );\n } else {\n // Patch is already reversed\n console.log(\n `Patch already reversed for ${pc.greenBright(fileName)}`\n );\n }\n } else {\n try {\n fs.writeFileSync(\n fileName,\n reversePatchedContent,\n 'utf8'\n );\n console.log(\n `Reversed patch for ${pc.greenBright(fileName)}`\n );\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Could not write the new content for file ${fileName} - ${\n error instanceof Error\n ? error.message\n : String(error)\n }`\n );\n }\n }\n } else {\n // Apply the patch normally\n const patchedContent = applyPatch(fileContent, patchItem);\n\n if (patchedContent === false) {\n // Failed to apply patch normally\n // Try applying the reversed patch to check if already applied\n const reversedPatchText = reversePatch(patchItem);\n const reversePatchedContent = applyPatch(\n fileContent,\n reversedPatchText\n );\n\n if (reversePatchedContent === false) {\n // Patch failed for other reasons\n console.warn(\n `${pc.yellowBright('WARNING:')} Failed to apply patch to ${pc.redBright(fileName)}`\n );\n } else {\n // The patch was already applied\n console.log(\n `Patch already applied to ${pc.greenBright(fileName)}`\n );\n }\n } else {\n try {\n fs.writeFileSync(fileName, patchedContent, 'utf8');\n console.log(`Patched ${pc.greenBright(fileName)}`);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Could not write the new content for file ${fileName} - ${\n error instanceof Error\n ? error.message\n : String(error)\n }`\n );\n }\n }\n }\n }\n } else {\n console.error(\n `${pc.redBright('ERROR:')} Could not get config for package ${packageName}`\n );\n }\n}\n\nexport function getConfig(packageName: string): PackageConfig | false {\n const folder = path.join(currentDirectory, 'node_modules', packageName);\n const configName = path.join(folder, 'package.json');\n if (!fs.existsSync(folder)) {\n console.error(\n `${pc.redBright('ERROR:')} Missing folder \"${pc.whiteBright(folder)}\"`\n );\n return false;\n }\n try {\n fs.accessSync(configName, fs.constants.R_OK);\n } catch {\n console.error(\n `${pc.redBright('ERROR:')} Cannot read \"${pc.whiteBright(configName)}\"`\n );\n return false;\n }\n const packageConfig = readFileContent(configName);\n\n let config: PackageConfig;\n try {\n config = JSON.parse(packageConfig);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Could not parse \"${pc.whiteBright('package.json')}\" - ${pc.redBright(error instanceof Error ? error.message : String(error))}`\n );\n return false;\n }\n return config;\n}\n"],"names":[],"mappings":"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"}