(
url: string,
offset: number,
byteCount: number,
)
| 779 | } |
| 780 | |
| 781 | async function readPdfRange( |
| 782 | url: string, |
| 783 | offset: number, |
| 784 | byteCount: number, |
| 785 | ): Promise<{ data: Uint8Array; totalBytes: number }> { |
| 786 | const normalized = isArxivUrl(url) ? normalizeArxivUrl(url) : url; |
| 787 | const clampedByteCount = Math.min(byteCount, MAX_CHUNK_BYTES); |
| 788 | |
| 789 | if (isFileUrl(normalized) || isLocalPath(normalized)) { |
| 790 | const filePath = isFileUrl(normalized) |
| 791 | ? fileUrlToPath(normalized) |
| 792 | : decodeURIComponent(normalized); |
| 793 | const stats = await fs.promises.stat(filePath); |
| 794 | const totalBytes = stats.size; |
| 795 | |
| 796 | // Clamp to file bounds |
| 797 | const start = Math.min(offset, totalBytes); |
| 798 | const end = Math.min(start + clampedByteCount, totalBytes); |
| 799 | |
| 800 | if (start >= totalBytes) { |
| 801 | return { data: new Uint8Array(0), totalBytes }; |
| 802 | } |
| 803 | |
| 804 | // Read range from local file |
| 805 | const buffer = Buffer.alloc(end - start); |
| 806 | const fd = await fs.promises.open(filePath, "r"); |
| 807 | try { |
| 808 | await fd.read(buffer, 0, end - start, start); |
| 809 | } finally { |
| 810 | await fd.close(); |
| 811 | } |
| 812 | |
| 813 | return { data: new Uint8Array(buffer), totalBytes }; |
| 814 | } |
| 815 | |
| 816 | // Serve from cache if we previously downloaded the full body |
| 817 | const cached = getCacheEntry(normalized); |
| 818 | if (cached) { |
| 819 | return sliceToChunk(cached, offset, clampedByteCount); |
| 820 | } |
| 821 | |
| 822 | // Remote URL - try Range request, fall back to full GET if not supported |
| 823 | let response = await fetch(normalized, { |
| 824 | headers: { |
| 825 | Range: `bytes=${offset}-${offset + clampedByteCount - 1}`, |
| 826 | }, |
| 827 | }); |
| 828 | |
| 829 | // If server doesn't support Range (501, 416, etc.), fall back to plain GET |
| 830 | if (!response.ok && response.status !== 206) { |
| 831 | response = await fetch(normalized); |
| 832 | if (!response.ok) { |
| 833 | throw new Error( |
| 834 | `Failed to fetch PDF: ${response.status} ${response.statusText}`, |
| 835 | ); |
| 836 | } |
| 837 | } |
| 838 |
no test coverage detected
searching dependent graphs…