修复脚本导包

This commit is contained in:
mtvpls
2026-03-22 00:52:28 +08:00
parent 691247cb8e
commit 4bb6cd679d
+9 -32
View File
@@ -8,6 +8,10 @@ import { db } from '@/lib/db';
const SOURCE_SCRIPT_REGISTRY_KEY = 'source-script:registry'; const SOURCE_SCRIPT_REGISTRY_KEY = 'source-script:registry';
const DEFAULT_TIMEOUT_MS = 20000; const DEFAULT_TIMEOUT_MS = 20000;
// 绕过 webpack 静态分析,获取真正的 Node.js require
// eslint-disable-next-line no-eval
const _nodeRequire = eval('require') as NodeRequire;
// ---- 内存缓存 ---- // ---- 内存缓存 ----
let _registryCache: { data: SourceScriptRegistry; ts: number } | null = null; let _registryCache: { data: SourceScriptRegistry; ts: number } | null = null;
const REGISTRY_CACHE_TTL_MS = 5_000; const REGISTRY_CACHE_TTL_MS = 5_000;
@@ -188,24 +192,6 @@ function assertScriptKey(key: string) {
} }
} }
function assertSafeCode(code: string) {
const blockedPatterns = [
/\brequire\s*\(/,
/\bprocess\./,
/\bchild_process\b/,
/\bfs\b/,
/\bimport\s*\(/,
/\beval\s*\(/,
/\bnew\s+Function\b/,
];
for (const pattern of blockedPatterns) {
if (pattern.test(code)) {
throw new Error(`脚本包含不允许的用法: ${pattern}`);
}
}
}
function createLogCollector() { function createLogCollector() {
const logs: string[] = []; const logs: string[] = [];
@@ -313,17 +299,10 @@ function createUtils() {
} }
function createScriptFactory(code: string) { function createScriptFactory(code: string) {
assertSafeCode(code);
return new Function( return new Function(
`"use strict"; 'require',
const process = undefined; `"use strict";\n${code}`
const require = undefined; ) as (req: NodeRequire) => any;
const module = undefined;
const exports = undefined;
const fetch = undefined;
${code}`
) as () => any;
} }
async function createScriptContext(script: SourceScriptRecord, configValues?: Record<string, string>) { async function createScriptContext(script: SourceScriptRecord, configValues?: Record<string, string>) {
@@ -462,7 +441,7 @@ function getOrCompileScript(script: SourceScriptRecord) {
if (cached) return cached; if (cached) return cached;
const factory = createScriptFactory(script.code); const factory = createScriptFactory(script.code);
const compiled = normalizeScript(factory()); const compiled = normalizeScript(factory(_nodeRequire));
if (_compiledCache.size >= MAX_COMPILED_CACHE_SIZE) { if (_compiledCache.size >= MAX_COMPILED_CACHE_SIZE) {
const firstKey = _compiledCache.keys().next().value; const firstKey = _compiledCache.keys().next().value;
@@ -550,7 +529,6 @@ export async function saveSourceScript(input: {
enabled?: boolean; enabled?: boolean;
}) { }) {
assertScriptKey(input.key); assertScriptKey(input.key);
assertSafeCode(input.code);
const registry = await loadRegistry(); const registry = await loadRegistry();
const now = Date.now(); const now = Date.now();
@@ -602,7 +580,6 @@ export async function importSourceScripts(items: SourceScriptImportItem[]) {
} }
assertScriptKey(item.key); assertScriptKey(item.key);
assertSafeCode(item.code);
const existing = registry.items.find((record) => record.key === item.key); const existing = registry.items.find((record) => record.key === item.key);
@@ -682,7 +659,7 @@ export async function testSourceScript(input: {
}; };
const factory = createScriptFactory(input.code); const factory = createScriptFactory(input.code);
const compiled = normalizeScript(factory()); const compiled = normalizeScript(factory(_nodeRequire));
const hook = compiled[input.hook]; const hook = compiled[input.hook];
if (typeof hook !== 'function') { if (typeof hook !== 'function') {
throw new Error(`脚本未实现 ${input.hook} hook`); throw new Error(`脚本未实现 ${input.hook} hook`);