Created
April 18, 2023 17:19
-
-
Save lisadean/72856d118618448d05a60a7ca3b53848 to your computer and use it in GitHub Desktop.
Node script to compare two node_modules directories and return differences
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const path = require('path'); | |
// dir fergy linked | |
const dir1 = '/Users/abb2175/work/react-build-store-alt/node_modules'; | |
// regular dir | |
const dir2 = '/Users/abb2175/work/react-build-store/node_modules'; | |
// compareDirectories(dir1, dir2, 1); | |
const result = findUniqueFiles(dir1, dir2, 1); | |
console.log('Files/folders (', result.uniqueToDir1.size, ') unique to FWP linked dir:', dir1); | |
result.uniqueToDir1.forEach((item) => console.log(item)); | |
console.log(); | |
console.log('Files/folders unique to regular dir:', dir2); | |
// console.log(`Files/folders unique to ${dir2}:`); | |
result.uniqueToDir2.forEach((item) => console.log(item)); | |
function filterByDepth(contents, depth, dir, basePath) { | |
if (depth === 1) { | |
return contents.filter((name) => { | |
const fullPath = path.join(dir, name); | |
const stats = fs.statSync(fullPath, fs.constants.FOLLOW_LINKS); | |
return stats.isDirectory() || stats.isFile(); | |
}); | |
} else if (depth > 1) { | |
return contents.flatMap((name) => { | |
const fullPath = path.join(dir, name); | |
const relPath = path.relative(basePath, fullPath); | |
const stats = fs.statSync(fullPath, fs.constants.FOLLOW_LINKS); | |
if (stats.isDirectory()) { | |
const subContents = fs.readdirSync(fullPath); | |
const subFiltered = filterByDepth(subContents, depth - 1, fullPath, basePath); | |
return subFiltered.map((subName) => path.join(relPath, subName)); | |
} else { | |
return [relPath]; | |
} | |
}); | |
} else { | |
return contents.map((name) => path.relative(basePath, path.join(dir, name))); | |
} | |
} | |
function findUniqueFiles(dir1, dir2, depth) { | |
const excludedFiles = findDevDependencies(dir1); | |
const dir1Contents = fs.readdirSync(dir1); | |
const dir2Contents = fs.readdirSync(dir2); | |
const filteredDir1 = filterByDepth(dir1Contents, depth, dir1, dir1).filter((name) => !excludedFiles.has(name)); | |
const filteredDir2 = filterByDepth(dir2Contents, depth, dir2, dir2); | |
return { | |
uniqueToDir1: getUniqueFiles(filteredDir1, filteredDir2), | |
uniqueToDir2: getUniqueFiles(filteredDir2, filteredDir1) | |
}; | |
} | |
function findDevDependencies(dir) { | |
const excludedFiles = new Set(); | |
const packageJsonPath = path.join(dir, 'package.json'); | |
const packageLockPath = path.join(dir, 'package-lock.json'); | |
try { | |
const packageJsonData = fs.readFileSync(packageJsonPath); | |
const packageJson = JSON.parse(packageJsonData); | |
const devDeps = packageJson.devDependencies || {}; | |
const allDeps = new Set(Object.keys(devDeps)); | |
// Add all dependencies of the dev dependencies to the set of excluded files | |
if (fs.existsSync(packageLockPath)) { | |
const packageLockData = fs.readFileSync(packageLockPath); | |
const packageLock = JSON.parse(packageLockData); | |
Object.keys(devDeps).forEach((dep) => { | |
const depInfo = packageLock.dependencies[dep]; | |
if (depInfo && depInfo.requires) { | |
Object.keys(depInfo.requires).forEach((req) => { | |
allDeps.add(req); | |
}); | |
} | |
}); | |
} | |
// Add the path of each dependency to the set of excluded files | |
allDeps.forEach((dep) => { | |
excludedFiles.add(path.join('node_modules', dep)); | |
}); | |
} catch (err) { | |
// Ignore errors when reading or parsing package.json or package-lock.json files | |
} | |
// Recursively search subdirectories | |
const subdirs = fs | |
.readdirSync(dir, { withFileTypes: true }) | |
.filter((dirent) => dirent.isDirectory()) | |
.map((dirent) => dirent.name); | |
subdirs.forEach((subdir) => { | |
const subExcludedFiles = findDevDependencies(path.join(dir, subdir)); | |
subExcludedFiles.forEach((file) => excludedFiles.add(file)); | |
}); | |
return excludedFiles; | |
} | |
function getUniqueFiles(files1, files2) { | |
const files1Set = new Set(files1); | |
const files2Set = new Set(files2); | |
return [...files1Set].filter((file) => !files2Set.has(file)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment