monitor/core/lib/fxserver/scanMonitorFiles.ts
2025-04-16 22:30:27 +07:00

108 lines
3.2 KiB
TypeScript

//FIXME: after refactor, move to the correct path
import fs from 'node:fs/promises';
import path from 'node:path';
import { createHash } from 'node:crypto';
import { txEnv } from '../../globalData';
//Hash test
const hashFile = async (filePath: string) => {
const rawFile = await fs.readFile(filePath, 'utf8')
const normalized = rawFile.normalize('NFKC')
.replace(/\r\n/g, '\n')
.replace(/^\uFEFF/, '');
return createHash('sha1').update(normalized).digest('hex');
}
// Limits
const MAX_FILES = 300;
const MAX_TOTAL_SIZE = 52_428_800; // 50MB
const MAX_FILE_SIZE = 20_971_520; // 20MB
const MAX_DEPTH = 10;
const MAX_EXECUTION_TIME = 30 * 1000;
const IGNORED_FOLDERS = [
'db',
'cache',
'dist',
'.reports',
'license_report',
'tmp_core_tsc',
'node_modules',
'txData',
];
type ContentFileType = {
path: string;
size: number;
hash: string;
}
export default async function scanMonitorFiles() {
const rootPath = txEnv.txaPath;
const allFiles: ContentFileType[] = [];
let totalFiles = 0;
let totalSize = 0;
try {
const tsStart = Date.now();
const scanDir = async (dir: string, depth: number = 0) => {
if (depth > MAX_DEPTH) {
throw new Error('MAX_DEPTH');
}
let filesFound = 0;
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
if (totalFiles >= MAX_FILES) {
throw new Error('MAX_FILES');
} else if (totalSize >= MAX_TOTAL_SIZE) {
throw new Error('MAX_TOTAL_SIZE');
} else if (Date.now() - tsStart > MAX_EXECUTION_TIME) {
throw new Error('MAX_EXECUTION_TIME');
}
const entryPath = path.join(dir, entry.name);
let relativeEntryPath = path.relative(rootPath, entryPath);
relativeEntryPath = './' + relativeEntryPath.split(path.sep).join(path.posix.sep);
if (entry.isDirectory()) {
if (IGNORED_FOLDERS.includes(entry.name)) {
continue;
}
await scanDir(entryPath, depth + 1);
} else if (entry.isFile()) {
const stats = await fs.stat(entryPath);
if (stats.size > MAX_FILE_SIZE) {
throw new Error('MAX_SIZE');
}
allFiles.push({
path: relativeEntryPath,
size: stats.size,
hash: await hashFile(entryPath),
});
filesFound++;
totalFiles++;
totalSize += stats.size;
}
}
return filesFound;
};
await scanDir(rootPath);
allFiles.sort((a, b) => a.path.localeCompare(b.path));
return {
totalFiles,
totalSize,
allFiles,
};
} catch (error) {
//At least saving the progress
return {
error: (error as any).message,
totalFiles,
totalSize,
allFiles,
};
}
}