|
const fs = require('fs'); |
|
const path = require('path'); |
|
|
|
console.log('RUNNING PREINSTALL'); |
|
|
|
const isIncluded = (f) => { |
|
//NOTE write any custom inclusion rules for folders here so it doesn't have to scan EVERY folder |
|
return true; |
|
} |
|
|
|
const saveJson = async (filePath, data) => { |
|
await fs.promises.writeFile(filePath, JSON.stringify(data, null, 2)); |
|
console.log('Saved ' + filePath); |
|
} |
|
|
|
const processNodeModules = async (dir, prefix = '') => { |
|
// console.log('processNodeModules', dir); |
|
let files = await fs.promises.readdir(dir, {withFileTypes: true}); |
|
const ans = []; |
|
for (let f of files) { |
|
if (f.isSymbolicLink()) { |
|
let full_path = path.join(dir, f.name); |
|
// console.log(full_path); |
|
try { |
|
const linkString = await fs.promises.readlink(full_path); |
|
if (linkString.indexOf('.pnpm') < 0) { |
|
console.log('global LINKED', dir, linkString, full_path); |
|
ans.push({name: prefix + f.name, path: full_path}); |
|
} |
|
} catch (err) { |
|
console.error(err); |
|
} |
|
} |
|
if (isIncluded(f)) { |
|
let full_path = path.join(dir, f.name); |
|
ans.push(...await processNodeModules(full_path, f.name + '/')); |
|
} |
|
} |
|
return ans; |
|
|
|
}; |
|
|
|
const isWorkspaceRef = (versionString) => { |
|
return versionString.indexOf('*') > -1; |
|
}; |
|
|
|
const stashGlobalDependencies = async (packageInfo) => { |
|
const packageStr = await fs.promises.readFile(packageInfo.packageJson); |
|
const packageData = JSON.parse(packageStr); |
|
|
|
packageInfo.globalDependencies.forEach((dep, i) => { |
|
let versionString = packageData.dependencies[dep.name]; |
|
if (versionString && !isWorkspaceRef(versionString)) { |
|
if (!packageData.stashedGlobalDependencies) packageData.stashedGlobalDependencies = {}; |
|
packageData.stashedGlobalDependencies[dep.name] = versionString; |
|
delete packageData.dependencies[dep.name]; |
|
} |
|
}); |
|
|
|
await saveJson(packageInfo.packageJson, packageData); |
|
}; |
|
|
|
const processDir = async (dir) => { |
|
let files = await fs.promises.readdir(dir, {withFileTypes: true}); |
|
const packageInfo = {globalDependencies: []}; |
|
for (let f of files) { |
|
let full_path = path.join(dir, f.name); |
|
if (f.isDirectory()) { |
|
if (f.name === '.git' || f.name === '.idea' || f.name === '_dev') { |
|
continue; |
|
} |
|
if (f.name === 'node_modules') { |
|
packageInfo.globalDependencies.push(...await processNodeModules(full_path)); |
|
} else { |
|
await processDir(full_path); |
|
} |
|
} else { |
|
if (f.name === 'package.json') { |
|
// console.log('FOUND package.json', path.join(dir, f.name)); |
|
packageInfo.packageJson = path.join(dir, f.name); |
|
} |
|
} |
|
} |
|
if (packageInfo.globalDependencies.length > 0) { |
|
// console.log('PACKAGE INFO: ', dir, JSON.stringify(packageInfo)); |
|
await stashGlobalDependencies(packageInfo); |
|
} |
|
}; |
|
|
|
const findLinks = async () => { |
|
//find all package.json |
|
//look through node_modules |
|
//find all links that don't have a .pnpm or node_modules |
|
//these are the global dependencies that should be deleted from the package.json |
|
//we store these in a 'stashedGlobalDependencies' custom field on package.json |
|
//the post install will run `pnpm install -g` on all these stashedGlobalDependencies |
|
|
|
let baseDir = path.resolve(__dirname, '../'); |
|
console.log('PROCESSING...', baseDir); |
|
await processDir(baseDir); |
|
console.log('DONE PROCESSING ', baseDir); |
|
process.exit(); |
|
}; |
|
findLinks(); |
|
|