export class ProjectLimitsPolicy { constructor() { this.softFileLimit = 1000; this.hardFileLimit = 10000; this.softSizeLimitBytes = 1 * 1024 * 1024; this.hardSizeLimitBytes = 10 * 1024 * 1024; } summarizeFileList(fileList) { let totalFiles = 0; let totalBytes = 0; for (const file of fileList) { const relPath = (file.webkitRelativePath || file.name || "").replaceAll("\\", "/"); if (this.#isHiddenPath(relPath)) continue; totalFiles += 1; totalBytes += Number(file.size || 0); } return { totalFiles, totalBytes }; } evaluate(stats) { const softWarnings = []; const hardErrors = []; if (stats.totalFiles > this.hardFileLimit) { hardErrors.push(`Количество файлов ${stats.totalFiles} превышает лимит ${this.hardFileLimit}.`); } else if (stats.totalFiles > this.softFileLimit) { softWarnings.push(`Количество файлов ${stats.totalFiles} больше ${this.softFileLimit}.`); } if (stats.totalBytes > this.hardSizeLimitBytes) { hardErrors.push( `Размер данных ${this.#formatBytes(stats.totalBytes)} превышает лимит ${this.#formatBytes(this.hardSizeLimitBytes)}.` ); } else if (stats.totalBytes > this.softSizeLimitBytes) { softWarnings.push( `Размер данных ${this.#formatBytes(stats.totalBytes)} больше ${this.#formatBytes(this.softSizeLimitBytes)}.` ); } return { softWarnings, hardErrors }; } #isHiddenPath(path) { const parts = String(path || "") .split("/") .filter(Boolean); return parts.some((segment) => segment.startsWith(".")); } #formatBytes(bytes) { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; return `${(bytes / (1024 * 1024)).toFixed(2)} MB`; } }