reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const { execFileSync } = require('child_process');
|
||||
const os = require('os');
|
||||
|
||||
const TARGETS = {
|
||||
addon: {
|
||||
label: 'native addon.node',
|
||||
version: '25.8.2',
|
||||
nextCheck: 'node scripts/load_native_addon.js --json',
|
||||
},
|
||||
'isolated-vm': {
|
||||
label: 'xbs isolated-vm',
|
||||
version: '26.3.1',
|
||||
nextCheck: 'node scripts/check_xbs_isolated_vm.js --strict --json',
|
||||
},
|
||||
xbs: {
|
||||
label: 'xbs isolated-vm',
|
||||
version: '26.3.1',
|
||||
nextCheck: 'node scripts/check_xbs_isolated_vm.js --strict --json',
|
||||
},
|
||||
};
|
||||
|
||||
function parseArgs(argv) {
|
||||
const args = { target: 'addon', requiredVersion: '', json: false, markdown: false };
|
||||
for (let i = 2; i < argv.length; i++) {
|
||||
const a = argv[i];
|
||||
if (a === '--target') args.target = argv[++i] || '';
|
||||
else if (a === '--required-version') args.requiredVersion = (argv[++i] || '').replace(/^v/i, '');
|
||||
else if (a === '--json') args.json = true;
|
||||
else if (a === '--markdown') args.markdown = true;
|
||||
else if (a === '--help' || a === '-h') args.help = true;
|
||||
else throw new Error('未知参数:' + a);
|
||||
}
|
||||
if (!args.json && !args.markdown) args.markdown = true;
|
||||
return args;
|
||||
}
|
||||
|
||||
function usage() {
|
||||
return [
|
||||
'用法:',
|
||||
' node scripts/check_node_runtime_compat.js --target addon --markdown',
|
||||
' node scripts/check_node_runtime_compat.js --target isolated-vm --json',
|
||||
' node scripts/check_node_runtime_compat.js --required-version 25.8.2 --markdown',
|
||||
'',
|
||||
'说明:只检测当前 Node / ABI / nvm 可用性并输出中文恢复建议,不会安装或切换 Node。',
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
function tryExec(command, args, options = {}) {
|
||||
try {
|
||||
return {
|
||||
ok: true,
|
||||
stdout: execFileSync(command, args, {
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
timeout: options.timeout || 5000,
|
||||
}).trim(),
|
||||
error: '',
|
||||
};
|
||||
} catch (error) {
|
||||
return { ok: false, stdout: '', error: String(error && error.message ? error.message : error) };
|
||||
}
|
||||
}
|
||||
|
||||
function detectNvm() {
|
||||
if (process.platform === 'win32') {
|
||||
const where = tryExec('where.exe', ['nvm']);
|
||||
const version = tryExec('nvm', ['version']);
|
||||
const root = tryExec('nvm', ['root']);
|
||||
return {
|
||||
available: version.ok,
|
||||
kind: 'nvm-windows',
|
||||
path: where.stdout.split(/\r?\n/).filter(Boolean)[0] || '',
|
||||
version: version.stdout,
|
||||
root: root.stdout,
|
||||
error: version.ok ? '' : (where.error || version.error),
|
||||
};
|
||||
}
|
||||
|
||||
const shell = tryExec('bash', ['-lc', 'if command -v nvm >/dev/null 2>&1; then nvm --version; elif [ -s "$NVM_DIR/nvm.sh" ]; then . "$NVM_DIR/nvm.sh" && nvm --version; elif [ -s "$HOME/.nvm/nvm.sh" ]; then . "$HOME/.nvm/nvm.sh" && nvm --version; else exit 127; fi']);
|
||||
return {
|
||||
available: shell.ok,
|
||||
kind: 'nvm-sh',
|
||||
path: shell.ok ? '$NVM_DIR/nvm.sh 或 $HOME/.nvm/nvm.sh' : '',
|
||||
version: shell.stdout,
|
||||
root: '',
|
||||
error: shell.error,
|
||||
};
|
||||
}
|
||||
|
||||
function buildResult(args) {
|
||||
const target = TARGETS[args.target] || null;
|
||||
const requiredVersion = args.requiredVersion || (target && target.version) || args.target.replace(/^v/i, '');
|
||||
const currentVersion = process.version.replace(/^v/i, '');
|
||||
const nvm = detectNvm();
|
||||
const label = target ? target.label : '自定义 Node native 组件';
|
||||
const nextCheck = target ? target.nextCheck : '';
|
||||
return {
|
||||
tool: 'check_node_runtime_compat',
|
||||
target: args.target,
|
||||
label,
|
||||
requiredVersion,
|
||||
currentVersion,
|
||||
currentVersionWithV: process.version,
|
||||
versionMatched: currentVersion === requiredVersion,
|
||||
nodeAbi: process.versions && process.versions.modules ? process.versions.modules : '',
|
||||
platform: process.platform,
|
||||
arch: process.arch,
|
||||
os: os.platform() + '-' + os.arch(),
|
||||
nvm,
|
||||
needsUserConfirmation: currentVersion !== requiredVersion,
|
||||
installCommands: requiredVersion ? [
|
||||
`nvm install ${requiredVersion}`,
|
||||
`nvm use ${requiredVersion}`,
|
||||
'node -v',
|
||||
'node -p "process.versions.modules"',
|
||||
nextCheck,
|
||||
].filter(Boolean) : [],
|
||||
};
|
||||
}
|
||||
|
||||
function renderMarkdown(result) {
|
||||
const lines = [];
|
||||
lines.push('# Node 版本兼容检查');
|
||||
lines.push('');
|
||||
lines.push('- 目标组件:' + result.label);
|
||||
lines.push('- 需要 Node:v' + result.requiredVersion);
|
||||
lines.push('- 当前 Node:' + result.currentVersionWithV);
|
||||
lines.push('- 当前 ABI:' + result.nodeAbi);
|
||||
lines.push('- 平台:' + result.platform + '-' + result.arch);
|
||||
lines.push('- 版本是否匹配:' + (result.versionMatched ? '是' : '否'));
|
||||
lines.push('- nvm 是否可用:' + (result.nvm.available ? '是' : '否'));
|
||||
if (result.nvm.version) lines.push('- nvm 版本:' + result.nvm.version);
|
||||
if (result.nvm.path) lines.push('- nvm 路径:' + result.nvm.path);
|
||||
if (result.nvm.root) lines.push('- nvm root:' + result.nvm.root);
|
||||
if (!result.versionMatched) {
|
||||
lines.push('');
|
||||
lines.push('## 处理建议');
|
||||
lines.push('');
|
||||
lines.push('- 不要直接降级;先让用户确认是否通过 nvm 安装 / 切换兼容 Node。');
|
||||
lines.push('- 用户同意后再执行以下命令:');
|
||||
lines.push('');
|
||||
lines.push('```bash');
|
||||
for (const cmd of result.installCommands) lines.push(cmd);
|
||||
lines.push('```');
|
||||
if (!result.nvm.available) {
|
||||
lines.push('');
|
||||
lines.push('- 当前未检测到 nvm。先让用户选择自动安装 nvm、手动安装 nvm、提供已安装 nvm 路径,或拒绝安装后再进入降级 / 改选流程。');
|
||||
}
|
||||
}
|
||||
return lines.join('\n') + '\n';
|
||||
}
|
||||
|
||||
try {
|
||||
const args = parseArgs(process.argv);
|
||||
if (args.help) {
|
||||
console.log(usage());
|
||||
process.exit(0);
|
||||
}
|
||||
const result = buildResult(args);
|
||||
if (args.json) console.log(JSON.stringify(result, null, 2));
|
||||
if (args.markdown) process.stdout.write(renderMarkdown(result));
|
||||
} catch (error) {
|
||||
console.error(error && error.message ? error.message : String(error));
|
||||
console.error(usage());
|
||||
process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user