好的,经过大量的头部撞击。我想出了这个:
第 1 步
将此文件添加到您机器的任何位置:
npm.sh
#!/usr/bin/bash
npm() {
NPM_PATH=$(which npm)
CURR_PATH=$(pwd)
NO_NPM_I="$CURR_PATH/.nonpminstall"
if [ "$1" = "i" ] || [ "$1" = "install" ]; then
if [[ -f "$NO_NPM_I" ]]; then
echo ""
echo -e "\033[0;31mPLEASE USE:\033[0m \033[0;33m\"npm run install\"\033[0m"
else
"$NPM_PATH" "$@"
fi
else
"$NPM_PATH" "$@"
fi
}
如果当前目录中有.nonpminstall 文件,这将覆盖npm i 或npm install。
您还需要将源添加到您的~/.bash_profile
~/.bash_profile
source path/to/your/script/npm.sh
然后运行source ~/.bash_profile
第 2 步
将此添加到您的package.json
{
...
"scripts": {
"i": "node relative/path/from/your/projectroot/installDependencies.js",
"install": "node relative/path/from/your/projectroot/installDependencies.js",
}
}
第 3 步
将此添加到您的package.json
{
...
"conflictDependencies": {
"mathjax-full": "^3.2.0",
"@ckeditor/ckeditor5-react": "^3.0.3",
"@sentry/react": "^6.12.0",
"@sentry/tracing": "^6.12.0"
}
}
这些依赖将与npm i <pkg> --force分开安装
第 4 步
installDependencies.js
代码
const { execSync } = require('child_process');
const pkg = require('#root/package.json');
const fs = require('fs');
const {
dependencies,
devDependencies,
conflictDependencies,
} = pkg;
const conflictDepNames = Object.keys(conflictDependencies);
class Memo {
static memo = [];
static memoTemp = [];
static pkg = {};
}
/**
* Saves the package.json in memory
* because npm compains about --legacy-peer-deps
* if there is a package.json file
*/
function pkgJsonMemoStart() {
try {
Memo.pkg = pkg;
fs.unlinkSync('./package.json')
} catch (error) {
console.log(error);
process.exit(1)
}
}
/**
* Temporarily erases the package.json
*/
function pkgJsonMemoSave() {
try {
includeNewDeps();
fs.writeFileSync('./package.json', JSON.stringify(Memo.pkg, null, 2))
} catch (error) {
console.error(error);
console.log('There was a problem writing your package.json, here you go!');
// console.log(Memo.pkg);
process.exit(1);
}
}
/**
* Writes the full npm log to disk
*/
function writeLogs() {
const log = Memo.memo.join('\n')
fs.writeFileSync('depInstallLog.log', log)
process.exit();
}
/**
* Adds new installed dependencies to package.json
*/
function includeNewDeps() {
try {
const newDeps = JSON.parse(fs.readFileSync('./package.json'));
Memo.pkg = {
...Memo.pkg,
devDependencies: {
...Memo.pkg.devDependencies,
...newDeps.devDependencies,
},
dependencies: {
...Memo.pkg.dependencies,
...newDeps.dependencies,
},
}
} catch (error) {
console.error(error);
console.log('There was a problem reading your package.json, here you go!');
// console.log(Memo.pkg);
}
}
/**
* Handles the instalation
* package by package
* @param {*} param0
*/
function npmInstall({deps, prefix = '', suffix = ''}) {
for (dep of deps){
const isWindows = /^win/.test(process.platform)
const npm = isWindows ? 'npm.cmd' : 'npm'
process.stdout.write(`\nInstalling: ${dep}`);
const arg = ['i', prefix, dep, suffix]
.filter(a => a !== '');
const res = execSync([npm, ...arg].join(' ')).toString();
Memo.memo.push(`\x1b[33m#### ${dep.toUpperCase().split('@')[0]} ####\x1b[0m`)
Memo.memo.push(res)
Memo.memoTemp.push(`\x1b[33m#### ${dep.toUpperCase().split('@')[0]} ####\x1b[0m`)
Memo.memoTemp.push(res)
if(res.stderr) {
console.error('\x1b[31mFAIL❌\x1b[0m', `${res.stderr}`)
throw res.stderr.toString();
};
process.stdout.write('\x1b[32m OK ✔\x1b[0m')
process.on('SIGINT', () => {
// eslint-disable-next-line no-console
console.log('\nGracefully shutting down from SIGINT (Crtl-C)');
pkgJsonMemoSave();
});
}
console.log('\n');
const log = Memo.memoTemp.join('\n')
console.log(log);
Memo.memoTemp = [];
process.on('SIGINT', () => {
// eslint-disable-next-line no-console
console.log('\nGracefully shutting down from SIGINT (Crtl-C)');
pkgJsonMemoSave();
writeLogs();
});
}
/**
* Install the non conflicting packages
*/
function installNormal() {
const normalInstallDeps = Object.entries(dependencies)
.filter(([name, version]) => (!conflictDepNames.includes(name)))
.map(([name, version]) => {
if(/^github:/.test(version)) {
return version
}
return [name, version].join('@')
})
console.log('\x1b[34m%s\x1b[0m', `
╭─────────────────────────────────────────╮
│ │
│ INSTALLING NON CONFLICTING DEPENDENCIES │
│ │
╰─────────────────────────────────────────╯
`)
npmInstall({deps: normalInstallDeps});
process.on('SIGINT', () => {
// eslint-disable-next-line no-console
console.log('\nGracefully shutting down from SIGINT (Crtl-C)');
pkgJsonMemoSave();
writeLogs();
});
}
/**
* Installs the devDeps
*/
function installDevDeps() {
const devInstallDeps = Object.entries(devDependencies)
.map(([name, version]) => {
if(/^github:/.test(version)) {
return version
}
return [name, version].join('@')
})
console.log('\x1b[33m%s\x1b[0m', `
╭─────────────────────────────────────────╮
│ │
│ INSTALLING DEV DEPENDENCIES │
│ │
╰─────────────────────────────────────────╯
`)
npmInstall({deps: devInstallDeps, prefix: '-D'});
process.on('SIGINT', () => {
// eslint-disable-next-line no-console
console.log('\nGracefully shutting down from SIGINT (Crtl-C)');
pkgJsonMemoSave();
writeLogs();
});
}
/**
* Installs the conflicting deps with --force
*/
function installConflictDeps() {
const forceInstallDeps = Object.entries(dependencies)
.filter(([name, version]) => (conflictDepNames.includes(name)))
.map(([name, version]) => {
if(/^github:/.test(version)) {
return version
}
return [name, version].join('@')
})
console.log('\x1b[31m%s\x1b[0m', `
╭─────────────────────────────────────────╮
│ │
│ INSTALLING CONFLICTING DEPENDENCIES │
│ │
╰─────────────────────────────────────────╯
`)
npmInstall({deps: forceInstallDeps, suffix: '--force'});
process.on('SIGINT', () => {
// eslint-disable-next-line no-console
console.log('\nGracefully shutting down from SIGINT (Crtl-C)');
pkgJsonMemoSave();
writeLogs();
});
}
/**
* Handles all package instalations with `npm run i`
* or `npm run install`
*/
function install () {
installNormal();
installDevDeps();
installConflictDeps();
}
/**
* Checks the arguments and decides if
* the user wants to install all packages or by name
*/
function main() {
try {
pkgJsonMemoStart();
const args = process.argv
args.splice(0, 2)
const prefixes = args.filter((a) => (/^-+/.test(a)));
const deps = args.filter((a) => (!(/^-+/.test(a))));
if(args.length === 0) install();
else npmInstall({deps, prefix: prefixes.join(' ')});
process.on('SIGINT', () => {
// eslint-disable-next-line no-console
console.log('\nGracefully shutting down from SIGINT (Crtl-C)');
pkgJsonMemoSave();
});
} catch (error) {
console.error(error);
} finally {
pkgJsonMemoSave();
writeLogs();
}
}
main();
process.on('SIGINT', () => {
// eslint-disable-next-line no-console
console.log('\nGracefully shutting down from SIGINT (Crtl-C)');
pkgJsonMemoSave();
writeLogs();
});
哦!顺便说一句,如果你想使用 installDependencies.js const pkg = require('#root/package.json'); 的第 2 行中的语法,你必须将它添加到你的 package.json
{
"imports": {
"#root/*": "./*"
},
}