diff --git a/package.json b/package.json index 02169ea0f..428ac92c6 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ }, "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.1.2", + "@jsonjoy.com/util": "^1.3.0", "tree-dump": "^1.0.1", "tslib": "^2.0.0" }, 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/fsa-to-node/json.ts b/src/fsa-to-node/json.ts index 0f9a5e492..c06de8cf3 100644 --- a/src/fsa-to-node/json.ts +++ b/src/fsa-to-node/json.ts @@ -1,5 +1,2 @@ -import { CborEncoder } from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; -import { CborDecoder } from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; - -export const encoder = new CborEncoder(); -export const decoder = new CborDecoder(); +import { encoder, decoder } from '@jsonjoy.com/json-pack/lib/cbor/shared'; +export { encoder, decoder }; diff --git a/src/node/FileHandle.ts b/src/node/FileHandle.ts index b6e40dfbe..22054626a 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/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; diff --git a/src/node/types/options.ts b/src/node/types/options.ts index 7faae9f7e..f1d99f9ed 100644 --- a/src/node/types/options.ts +++ b/src/node/types/options.ts @@ -32,6 +32,10 @@ export interface IFStatOptions { export interface IAppendFileOptions extends IFileOptions {} +export interface IReadableWebStreamOptions { + type?: 'bytes' | undefined; +} + export interface IReaddirOptions extends IOptions { recursive?: boolean; withFileTypes?: boolean; diff --git a/yarn.lock b/yarn.lock index 8267115b2..ee9018298 100644 --- a/yarn.lock +++ b/yarn.lock @@ -616,6 +616,11 @@ resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-1.2.0.tgz#0fe9a92de72308c566ebcebe8b5a3f01d3149df2" integrity sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg== +"@jsonjoy.com/util@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-1.3.0.tgz#e5623885bb5e0c48c1151e4dae422fb03a5887a1" + integrity sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw== + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.5" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" @@ -6837,16 +6842,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6906,14 +6902,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -7740,16 +7729,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==