修复本地Node.js低版本报错,修复不能在web中设置证书验证为0 (#106)

* 修复兼容层不支持动态导入

* 修复不能在web中设置证书验证为0

* 使用更严谨的正则和注入

* 使用更安全的注入
This commit is contained in:
Elegy233 authored and GitHub committed 2025-12-08 23:51:23 +08:00
1 parent 995d5f10e0
commit c7afee82e1
2 files changed
+72 -31

No files matched your search

+1 -1
View File
@@ -243,7 +243,7 @@ export class Envs {
'DEPLOY_PLATFROM_ACCOUNT': { category: 'system', type: 'text', description: '部署平台账号ID' },
'DEPLOY_PLATFROM_PROJECT': { category: 'system', type: 'text', description: '部署平台项目名称' },
'DEPLOY_PLATFROM_TOKEN': { category: 'system', type: 'text', description: '部署平台访问令牌' },
'NODE_TLS_REJECT_UNAUTHORIZED': { category: 'system', type: 'number', description: '在建立 HTTPS 连接时是否验证服务器的 SSL/TLS 证书,0表示忽略' },
'NODE_TLS_REJECT_UNAUTHORIZED': { category: 'system', type: 'number', description: '在建立 HTTPS 连接时是否验证服务器的 SSL/TLS 证书,0表示忽略,默认为1', min: 0, max: 1 },
};
return {
+71 -30
View File
@@ -97,32 +97,7 @@ try {
throw err;
}
// ------------------- _compile hook -------------------
const origCompile = Module.prototype._compile;
Module.prototype._compile = function (content, filename) {
try {
if (
typeof filename === 'string' &&
filename.startsWith(projectRoot) &&
!filename.includes('node_modules') &&
/\b(?:import|export)\b/.test(content)
) {
console.log(`[esm-shim] Transforming ESM syntax in: ${path.relative(projectRoot, filename)}`);
const out = esbuild.transformSync(content, {
loader: 'js',
format: 'cjs',
target: 'es2018',
sourcemap: 'inline',
});
return origCompile.call(this, out.code, filename);
}
} catch (e) {
console.error('[esm-shim] esbuild transform failed:', filename, e.message || e);
}
return origCompile.call(this, content, filename);
};
// ------------------- _load hook for node-fetch v3 -------------------
// =============== node-fetch v3 兼容层 ===============
let fetchCache = null;
let fetchPromise = null;
@@ -199,7 +174,42 @@ function createFetchCompat() {
return syncFetch;
}
// 拦截 node-fetch 的 require 调用
// =============== 处理动态导入 ===============
// 将动态 import() 转换为 require(),并修复 import.meta.url
function preprocessESMFeatures(content, filename) {
let modified = content;
// 修复 1: 动态 import() - 统一处理所有模式
// 匹配: import(...) 不管有没有 await,不管是字符串还是表达式
modified = modified.replace(
/(await\s+)?import\s*\(((?:[^()]|\([^)]*\))*)\)/g,
(match, awaitKeyword, importArg) => {
console.log(`[esm-shim] Converting dynamic import in ${path.basename(filename)}`);
// 如果有 await,保持 await;如果没有,也不加
return `${awaitKeyword || ''}Promise.resolve(require(${importArg}))`;
}
);
// 修复 2: import.meta.url
if (content.includes('import.meta.url')) {
// 检查是否已经处理过
if (content.includes('__importMetaUrl')) {
console.log(`[esm-shim] __importMetaUrl already exists in ${path.basename(filename)}, skipping injection`);
// 只做替换,不注入
modified = modified.replace(/import\.meta\.url/g, '__importMetaUrl');
} else {
console.log(`[esm-shim] Fixing import.meta.url in ${path.basename(filename)}`);
// 注入 + 替换
const metaUrlFix = `const __importMetaUrl = require('url').pathToFileURL(__filename).href;\n`;
modified = metaUrlFix + modified;
modified = modified.replace(/import\.meta\.url/g, '__importMetaUrl');
}
}
return modified;
}
// =============== Module Hooks ===============
const origLoad = Module._load;
Module._load = function (request, parent, isMain) {
if (request === 'node-fetch') {
@@ -212,7 +222,38 @@ Module._load = function (request, parent, isMain) {
return origLoad.call(this, request, parent, isMain);
};
// 导出加载函数
global.loadNodeFetch = loadNodeFetchV3;
const origCompile = Module.prototype._compile;
Module.prototype._compile = function (content, filename) {
try {
if (
typeof filename === 'string' &&
filename.startsWith(projectRoot) &&
!filename.includes('node_modules') &&
/\b(?:import|export)\b/.test(content)
) {
console.log(`[esm-shim] Transforming ESM syntax in: ${path.relative(projectRoot, filename)}`);
// 预处理 ESM 特性
const preprocessed = preprocessESMFeatures(content, filename);
// esbuild 转换
const out = esbuild.transformSync(preprocessed, {
loader: 'js',
format: 'cjs',
target: 'es2018',
sourcemap: 'inline',
});
// 确保 exports 同步(简化版)
const fixedCode = out.code + `\n;(function(){if(exports!==module.exports&&typeof exports==='object'){Object.keys(exports).forEach(k=>{if(k!=='__esModule'&&!(k in module.exports))module.exports[k]=exports[k]})};if(typeof module.exports==='object'&&Object.keys(module.exports).length===0){Object.keys(exports).forEach(k=>{if(k!=='__esModule')module.exports[k]=exports[k]})}})();`;
return origCompile.call(this, fixedCode, filename);
}
} catch (e) {
console.error('[esm-shim] esbuild transform failed:', filename, e.message || e);
}
return origCompile.call(this, content, filename);
};
console.log('[esm-shim] ESM compatibility shim active with hooks installed');
global.loadNodeFetch = loadNodeFetchV3;
console.log('[esm-shim] ESM compatibility shim active with hooks installed');