diff --git a/src/__tests__/volume/FileHandle.test.ts b/src/__tests__/volume/FileHandle.test.ts new file mode 100644 index 000000000..479028c7c --- /dev/null +++ b/src/__tests__/volume/FileHandle.test.ts @@ -0,0 +1,16 @@ +import { fromStream } from '@jsonjoy.com/util/lib/streams/fromStream'; +import { createFs } from '../util'; + +describe('FileHandle', () => { + describe('.readableWebStream()', () => { + it('can read contest of a file', async () => { + const fs = createFs(); + fs.writeFileSync('/foo', 'bar'); + const handle = await fs.promises.open('/foo', 'r'); + const stream = handle.readableWebStream(); + expect(stream).toBeInstanceOf(ReadableStream); + const data = fromStream(stream); + expect(await data).toEqual(Buffer.from('bar')); + }); + }); +}); diff --git a/src/node/FileHandle.ts b/src/node/FileHandle.ts index b6e40dfbe..4f33ee960 100644 --- a/src/node/FileHandle.ts +++ b/src/node/FileHandle.ts @@ -33,6 +33,16 @@ export class FileHandle implements IFileHandle { return promisify(this.fs, 'fdatasync')(this.fd); } + readableWebStream(options?: opts.IReadableWebStreamOptions): ReadableStream { + return new ReadableStream({ + pull: async (controller) => { + const data = await this.readFile(); + controller.enqueue(data); + controller.close(); + }, + }); + }; + read(buffer: Buffer | Uint8Array, offset: number, length: number, position: number): Promise { return promisify(this.fs, 'read', bytesRead => ({ bytesRead, buffer }))(this.fd, buffer, offset, length, position); } diff --git a/src/node/types/FsPromisesApi.ts b/src/node/types/FsPromisesApi.ts index 61cbc667c..22ea29df3 100644 --- a/src/node/types/FsPromisesApi.ts +++ b/src/node/types/FsPromisesApi.ts @@ -20,7 +20,6 @@ export interface FsPromisesApi { mkdtemp(prefix: string, options?: opts.IOptions): Promise; open(path: misc.PathLike, flags?: misc.TFlags, mode?: misc.TMode): Promise; opendir(path: misc.PathLike, options?: opts.IOpendirOptions): Promise; - readableWebStream: (options?: opts.IReadableWebStreamOptions) => ReadableStream; readdir(path: misc.PathLike, options?: opts.IReaddirOptions | string): Promise; readFile(id: misc.TFileHandle, options?: opts.IReadFileOptions | string): Promise; readlink(path: misc.PathLike, options?: opts.IOptions): Promise; diff --git a/src/node/types/misc.ts b/src/node/types/misc.ts index 8769ee694..7fc77bdef 100644 --- a/src/node/types/misc.ts +++ b/src/node/types/misc.ts @@ -4,8 +4,8 @@ import type { EventEmitter } from 'events'; import type { TSetTimeout } from '../../setTimeoutUnref'; import type { IAppendFileOptions, + IReadableWebStreamOptions, IReadFileOptions, - IReadStreamOptions, IStatOptions, IWriteFileOptions, } from './options'; @@ -129,6 +129,7 @@ export interface IFileHandle { chown(uid: number, gid: number): Promise; close(): Promise; datasync(): Promise; + readableWebStream(options?: IReadableWebStreamOptions): ReadableStream; read(buffer: Buffer | Uint8Array, offset: number, length: number, position: number): Promise; readv(buffers: ArrayBufferView[], position?: number | null): Promise; readFile(options?: IReadFileOptions | string): Promise;