perf(web): optimize document upload validation with static sets, MIME checks, and 50MB size guard - #1560
Conversation
| return { | ||
| name, | ||
| size, | ||
| type, | ||
| lastModified: Date.now(), | ||
| slice: () => new Blob(), | ||
| stream: () => new ReadableStream(), | ||
| text: () => Promise.resolve(""), | ||
| arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)), | ||
| } as unknown as File |
There was a problem hiding this comment.
The object literal returned from createMockFile uses a type assertion (as unknown as File) instead of a type annotation. According to the 'Type assertions and casting' rule, you should use type annotations instead of assertions for object literals. Consider defining a typed variable with an explicit annotation, e.g., const mock: File = { name, size, type, ... }, or extracting a typed interface for the mock, rather than casting with as unknown as File.
| return { | |
| name, | |
| size, | |
| type, | |
| lastModified: Date.now(), | |
| slice: () => new Blob(), | |
| stream: () => new ReadableStream(), | |
| text: () => Promise.resolve(""), | |
| arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)), | |
| } as unknown as File | |
| const mock: File = Object.assign(new File([], name), { | |
| name, | |
| size, | |
| type, | |
| lastModified: Date.now(), | |
| slice: () => new Blob(), | |
| stream: () => new ReadableStream(), | |
| text: () => Promise.resolve(""), | |
| arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)), | |
| }) | |
| return mock | |
Spotted by Graphite (based on custom rule: TypeScript style guide (Google))
Is this helpful? React 👍 or 👎 to let us know.
| for (const file of incoming) { | ||
| if (file.size > MAX_DOCUMENT_FILE_BYTES) { | ||
| oversizedCount++ | ||
| } else if (!isAcceptedFile(file)) { | ||
| unsupportedCount++ | ||
| } else { | ||
| accepted.push(file) | ||
| } | ||
| } |
There was a problem hiding this comment.
Empty files (size = 0) are incorrectly categorized as "unsupported" rather than being handled separately. An empty PDF file will show "One file type is not supported" even though the file type is valid.
Impact: Misleading user feedback - users will think they uploaded the wrong file type when they actually uploaded an empty file.
Fix: Add a separate check for empty files:
for (const file of incoming) {
if (file.size <= 0) {
emptyCount++
} else if (file.size > MAX_DOCUMENT_FILE_BYTES) {
oversizedCount++
} else if (!isAcceptedFile(file)) {
unsupportedCount++
} else {
accepted.push(file)
}
}Then add appropriate toast message for empty files.
| for (const file of incoming) { | |
| if (file.size > MAX_DOCUMENT_FILE_BYTES) { | |
| oversizedCount++ | |
| } else if (!isAcceptedFile(file)) { | |
| unsupportedCount++ | |
| } else { | |
| accepted.push(file) | |
| } | |
| } | |
| for (const file of incoming) { | |
| if (file.size <= 0) { | |
| emptyCount++ | |
| } else if (file.size > MAX_DOCUMENT_FILE_BYTES) { | |
| oversizedCount++ | |
| } else if (!isAcceptedFile(file)) { | |
| unsupportedCount++ | |
| } else { | |
| accepted.push(file) | |
| } | |
| } | |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.
… checks, and 50MB size guard - Hoist extension and MIME type Set allocations to module scope in document-file-validation - Add fail-fast 50MB size check to reject oversized uploads prior to network requests - Support direct MIME lookup for PDFs, images, and standard office documents alongside extension fallback - Add unit test suite covering extension, MIME, size, and corrupt/empty file validation Fixes supermemoryai#1559
89f3e36 to
0bf6801
Compare
Description
Fixes #1559
Optimizes client-side document file validation in
apps/web/components/add-document/file.tsxduring batch uploads and drag-and-drop operations.Changes
apps/web/lib/document-file-validation.tswithALLOWED_EXTENSIONSandALLOWED_MIME_TYPESSets allocated once at module scope rather than allocating dynamicSets on every single file check."One file exceeds the 50MB limit"), preventing wasted upload bandwidth.application/pdf,image/*, and standard document types alongside clean fallback extension parsing.apps/web/lib/document-file-validation.test.tstesting standard extensions, uppercase multi-dot filenames, extensionless MIME blobs, >50MB bounds, and zero-byte/unsupported files.Verification
bun test apps/web/lib/document-file-validation.test.ts(6/6 tests passing).bunx biome check apps/web/components/add-document/file.tsx apps/web/lib/document-file-validation.ts apps/web/lib/document-file-validation.test.ts(clean).