streaming zip archiver/extractor
jsr.io/@mary/zip
typescript
jsr
1/**
2 * @module
3 * This module contains Node.js-specific functions
4 */
5
6import type { FileHandle } from 'node:fs/promises';
7
8import type { Reader } from './types.ts';
9
10/**
11 * creates a reader from a Node.js' FileHandle
12 * @param handle the file handle to read from
13 * @returns a reader for the file
14 */
15export const fromFileHandle = async (handle: FileHandle): Promise<Reader> => {
16 const totalLength = (await handle.stat()).size;
17
18 return {
19 length: totalLength,
20 // deno-lint-ignore require-await
21 async read(offset: number, length?: number): Promise<ReadableStream<Uint8Array<ArrayBuffer>>> {
22 let remaining = length !== undefined ? length : totalLength - offset;
23
24 return new ReadableStream<Uint8Array<ArrayBuffer>>({
25 type: 'bytes',
26 async pull(controller) {
27 const size = Math.min(controller.desiredSize!, remaining);
28
29 const buffer = new Uint8Array(size);
30 const { bytesRead } = await handle.read(buffer, 0, size, offset);
31
32 if (bytesRead === 0) {
33 // end of file
34 controller.close();
35 return;
36 }
37
38 if (bytesRead < size) {
39 // partial read, slice the buffer
40 controller.enqueue(buffer.subarray(0, bytesRead));
41 } else {
42 controller.enqueue(buffer);
43 }
44
45 remaining -= bytesRead;
46 offset += bytesRead;
47
48 if (remaining <= 0) {
49 controller.close();
50 return;
51 }
52 },
53 }, { highWaterMark: 64 * 1024 });
54 },
55 };
56};