diff --git a/docs/node/reference.md b/docs/node/reference.md index f08d8257e..44cffcbaa 100644 --- a/docs/node/reference.md +++ b/docs/node/reference.md @@ -71,6 +71,7 @@ vol.fromJSON( { './index.js': '...', './package.json': '...', + './index.node': new Buffer(), }, '/app', ); diff --git a/src/__tests__/volume.test.ts b/src/__tests__/volume.test.ts index 279335969..e482f9e9f 100644 --- a/src/__tests__/volume.test.ts +++ b/src/__tests__/volume.test.ts @@ -274,6 +274,16 @@ describe('volume', () => { expect(stat.isDirectory()).toBe(true); expect(vol.readdirSync('/dir')).toEqual([]); }); + + it('supports using buffers for file content', () => { + const vol = new Volume(); + const text = 'bip-boup'; + const buffer = Buffer.from(text, 'utf-8'); + vol.fromJSON({ '/buffer': buffer }); + expect(vol.toJSON()).toStrictEqual({ '/buffer': text }); + expect(vol.readFileSync('/buffer')).toStrictEqual(buffer); + expect(vol.readFileSync('/buffer', 'utf-8')).toStrictEqual(text); + }); }); describe('.fromNestedJSON(nestedJSON[, cwd])', () => { diff --git a/src/volume.ts b/src/volume.ts index 88044c8f2..c9e1cc778 100644 --- a/src/volume.ts +++ b/src/volume.ts @@ -188,13 +188,13 @@ function validateGid(gid: number) { } // ---------------------------------------- Volume -type DirectoryContent = string | null; +type DirectoryContent = string | Buffer | null; -export interface DirectoryJSON { - [key: string]: DirectoryContent; +export interface DirectoryJSON { + [key: string]: T; } -export interface NestedDirectoryJSON { - [key: string]: DirectoryContent | NestedDirectoryJSON; +export interface NestedDirectoryJSON { + [key: string]: T | NestedDirectoryJSON; } function flattenJSON(nestedJSON: NestedDirectoryJSON): DirectoryJSON { @@ -206,7 +206,7 @@ function flattenJSON(nestedJSON: NestedDirectoryJSON): DirectoryJSON { const joinedPath = join(pathPrefix, path); - if (typeof contentOrNode === 'string') { + if (typeof contentOrNode === 'string' || contentOrNode instanceof Buffer) { flatJSON[joinedPath] = contentOrNode; } else if (typeof contentOrNode === 'object' && contentOrNode !== null && Object.keys(contentOrNode).length > 0) { // empty directories need an explicit entry and therefore get handled in `else`, non-empty ones are implicitly considered @@ -526,7 +526,7 @@ export class Volume implements FsCallbackApi, FsSynchronousApi { }); } - private _toJSON(link = this.root, json = {}, path?: string, asBuffer?: boolean): DirectoryJSON { + private _toJSON(link = this.root, json = {}, path?: string, asBuffer?: boolean): DirectoryJSON { let isEmpty = true; let children = link.children; @@ -568,7 +568,7 @@ export class Volume implements FsCallbackApi, FsSynchronousApi { return json; } - toJSON(paths?: PathLike | PathLike[], json = {}, isRelative = false, asBuffer = false): DirectoryJSON { + toJSON(paths?: PathLike | PathLike[], json = {}, isRelative = false, asBuffer = false): DirectoryJSON { const links: Link[] = []; if (paths) { @@ -595,7 +595,7 @@ export class Volume implements FsCallbackApi, FsSynchronousApi { filename = resolve(filename, cwd); - if (typeof data === 'string') { + if (typeof data === 'string' || data instanceof Buffer) { const dir = dirname(filename); this.mkdirpBase(dir, MODE.DIR);