66 lines
2.5 KiB
JavaScript
66 lines
2.5 KiB
JavaScript
|
|
// auto-patch-egg.js (v3)
|
||
|
|
const fs = require('fs');
|
||
|
|
const path = require('path');
|
||
|
|
const BASE = path.resolve(__dirname, 'node_modules');
|
||
|
|
const TARGET_DIRS = ['egg', 'egg-cluster', 'cluster-client', 'egg-sequelize', 'egg-logger', 'egg-cors', 'egg-security', 'egg-onerror', 'egg-session', 'egg-view', 'egg-validate', 'egg-jsonp'];
|
||
|
|
|
||
|
|
const BUILTINS = new Set([
|
||
|
|
'fs', 'path', 'os', 'util', 'events', 'stream', 'crypto', 'url', 'http', 'https',
|
||
|
|
'net', 'tls', 'buffer', 'assert', 'process', 'v8', 'vm', 'zlib', 'querystring',
|
||
|
|
'child_process', 'cluster', 'dns', 'dgram', 'readline', 'repl', 'string_decoder',
|
||
|
|
'timers', 'tty', 'domain', 'module', 'console', 'perf_hooks', 'async_hooks',
|
||
|
|
'worker_threads', 'inspector', 'trace_events', 'wasi',
|
||
|
|
]);
|
||
|
|
|
||
|
|
function findRequires(filePath) {
|
||
|
|
try {
|
||
|
|
const content = fs.readFileSync(filePath, 'utf8');
|
||
|
|
const re = /require\(['"]([^./][^'"]*)['"]\)/g;
|
||
|
|
const modules = new Set(); let match;
|
||
|
|
while ((match = re.exec(content)) !== null) {
|
||
|
|
const name = match[1].split('/')[0];
|
||
|
|
if (!BUILTINS.has(name)) modules.add(name);
|
||
|
|
}
|
||
|
|
return modules;
|
||
|
|
} catch { return new Set(); }
|
||
|
|
}
|
||
|
|
|
||
|
|
function moduleExists(name) {
|
||
|
|
try { require.resolve(name, { paths: [BASE] }); return true; } catch { return false; }
|
||
|
|
}
|
||
|
|
|
||
|
|
function walkDir(dir) {
|
||
|
|
const results = [];
|
||
|
|
try {
|
||
|
|
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
||
|
|
const full = path.join(dir, e.name);
|
||
|
|
if (e.isDirectory() && e.name !== 'node_modules') results.push(...walkDir(full));
|
||
|
|
else if (e.isFile() && /\.(js|cjs)$/.test(e.name) && !e.name.includes('.test.')) results.push(full);
|
||
|
|
}
|
||
|
|
} catch {}
|
||
|
|
return results;
|
||
|
|
}
|
||
|
|
|
||
|
|
function createShim(name) {
|
||
|
|
const dir = path.join(BASE, name);
|
||
|
|
if (fs.existsSync(dir)) return false;
|
||
|
|
fs.mkdirSync(dir, { recursive: true });
|
||
|
|
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name, version: '0.0.1-shim', main: 'index.js' }, null, 2));
|
||
|
|
fs.writeFileSync(path.join(dir, 'index.js'), `'use strict';module.exports={};`);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('=== 扫描依赖树 ===');
|
||
|
|
const allRequires = new Set();
|
||
|
|
for (const target of TARGET_DIRS) {
|
||
|
|
const targetDir = path.join(BASE, target);
|
||
|
|
if (!fs.existsSync(targetDir)) continue;
|
||
|
|
const files = walkDir(targetDir);
|
||
|
|
for (const f of files) { const reqs = findRequires(f); reqs.forEach(r => allRequires.add(r)); }
|
||
|
|
}
|
||
|
|
let count = 0;
|
||
|
|
for (const mod of allRequires) {
|
||
|
|
if (!moduleExists(mod)) { if (createShim(mod)) count++; }
|
||
|
|
}
|
||
|
|
console.log(`=== 创建 ${count} 个 shim ===`);
|