From f13de3b65631a2c8ab8776a19b894c120b2b373a Mon Sep 17 00:00:00 2001 From: streamich Date: Wed, 14 Jun 2023 18:26:33 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20implement=20.values()=20?= =?UTF-8?q?and=20.entries()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NodeFileSystemDirectoryHandle.ts | 35 ++++---- src/node-to-fsa/NodeFileSystemFileHandle.ts | 2 +- .../NodeFileSystemDirectoryHandle.test.ts | 84 +++++++++++++++++++ 3 files changed, 105 insertions(+), 16 deletions(-) diff --git a/src/node-to-fsa/NodeFileSystemDirectoryHandle.ts b/src/node-to-fsa/NodeFileSystemDirectoryHandle.ts index a772d2428..9c2ef1987 100644 --- a/src/node-to-fsa/NodeFileSystemDirectoryHandle.ts +++ b/src/node-to-fsa/NodeFileSystemDirectoryHandle.ts @@ -1,5 +1,6 @@ import {NodeFileSystemHandle} from "./NodeFileSystemHandle"; import {basename, ctx as createCtx} from "./util"; +import {NodeFileSystemFileHandle} from "./NodeFileSystemFileHandle"; import type {NodeFsaContext, NodeFsaFs} from "./types"; /** @@ -14,25 +15,29 @@ export class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle { super('directory', basename(path, ctx.separator!)); } - /** - * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/entries - */ - public entries(): AsyncIterableIterator<[string, NodeFileSystemHandle]> { - throw new Error('Not implemented'); - } - /** * Returns a new array iterator containing the keys for each item in * {@link NodeFileSystemDirectoryHandle} object. * * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/keys */ - public keys(): AsyncIterableIterator { - const {path, fs} = this; - return (async function*() { - const list = await fs.promises.readdir(path); - for (const name of list) yield name; - })(); + public async * keys(): AsyncIterableIterator { + const list = await this.fs.promises.readdir(this.path); + for (const name of list) yield name; + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/entries + */ + public async * entries(): AsyncIterableIterator<[string, NodeFileSystemHandle]> { + const {path, fs, ctx} = this; + const list = await fs.promises.readdir(path, {withFileTypes: true}); + for (const dirent of list) { + const name = dirent.name; + const newPath = path + ctx.separator! + name; + if (dirent.isDirectory()) yield [name, new NodeFileSystemDirectoryHandle(fs, newPath, ctx)]; + else if (dirent.isFile()) yield [name, new NodeFileSystemFileHandle(fs, name, ctx)]; + } } /** @@ -41,8 +46,8 @@ export class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle { * * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/values */ - public values(): AsyncIterableIterator { - throw new Error('Not implemented'); + public async * values(): AsyncIterableIterator { + for await (const [, value] of this.entries()) yield value; } /** diff --git a/src/node-to-fsa/NodeFileSystemFileHandle.ts b/src/node-to-fsa/NodeFileSystemFileHandle.ts index 714fa1ab3..7df0e7d94 100644 --- a/src/node-to-fsa/NodeFileSystemFileHandle.ts +++ b/src/node-to-fsa/NodeFileSystemFileHandle.ts @@ -9,7 +9,7 @@ export class NodeFileSystemFileHandle extends NodeFileSystemHandle { protected readonly path: string, protected readonly ctx: Partial = createCtx(ctx), ) { - super('directory', basename(path, ctx.separator!)); + super('file', basename(path, ctx.separator!)); } /** diff --git a/src/node-to-fsa/__tests__/NodeFileSystemDirectoryHandle.test.ts b/src/node-to-fsa/__tests__/NodeFileSystemDirectoryHandle.test.ts index 816e4fca6..85e3b19ef 100644 --- a/src/node-to-fsa/__tests__/NodeFileSystemDirectoryHandle.test.ts +++ b/src/node-to-fsa/__tests__/NodeFileSystemDirectoryHandle.test.ts @@ -1,5 +1,7 @@ import {DirectoryJSON, memfs} from '../..'; import {NodeFileSystemDirectoryHandle} from '../NodeFileSystemDirectoryHandle'; +import {NodeFileSystemFileHandle} from '../NodeFileSystemFileHandle'; +import {NodeFileSystemHandle} from '../NodeFileSystemHandle'; const setup = (json: DirectoryJSON = {}) => { const fs = memfs(json, '/'); @@ -45,3 +47,85 @@ describe('.keys()', () => { expect(list).toEqual(['file.txt']); }); }); + +describe('.entries()', () => { + test('returns an empty iterator for an empty directory', async () => { + const {dir} = setup(); + const keys = dir.entries(); + expect(await keys.next()).toEqual({done: true, value: undefined}); + }); + + test('returns a folder', async () => { + const {dir} = setup({'My Documents': null}); + for await (const [name, subdir] of dir.entries()) { + expect(name).toBe('My Documents'); + expect(subdir).toBeInstanceOf(NodeFileSystemDirectoryHandle); + expect(subdir.kind).toBe('directory'); + expect(subdir.name).toBe('My Documents'); + } + }); + + test('returns a file', async () => { + const {dir} = setup({ + 'file.txt': 'Hello, world!', + }); + for await (const [name, file] of dir.entries()) { + expect(name).toBe('file.txt'); + expect(file).toBeInstanceOf(NodeFileSystemFileHandle); + expect(file.kind).toBe('file'); + expect(file.name).toBe('file.txt'); + } + }); + + test('returns two entries', async () => { + const {dir} = setup({ + 'index.html': 'Hello, world!', + 'another/folder': null, + }); + const handles: NodeFileSystemHandle[] = []; + for await (const entry of dir.entries()) handles.push(entry[1]); + expect(handles.length).toBe(2); + expect(handles.find(handle => handle.name === 'index.html')).toBeInstanceOf(NodeFileSystemFileHandle); + expect(handles.find(handle => handle.name === 'another')).toBeInstanceOf(NodeFileSystemDirectoryHandle); + }); +}); + +describe('.values()', () => { + test('returns an empty iterator for an empty directory', async () => { + const {dir} = setup(); + const values = dir.values(); + expect(await values.next()).toEqual({done: true, value: undefined}); + }); + + test('returns a folder', async () => { + const {dir} = setup({'My Documents': null}); + for await (const subdir of dir.values()) { + expect(subdir).toBeInstanceOf(NodeFileSystemDirectoryHandle); + expect(subdir.kind).toBe('directory'); + expect(subdir.name).toBe('My Documents'); + } + }); + + test('returns a file', async () => { + const {dir} = setup({ + 'file.txt': 'Hello, world!', + }); + for await (const file of dir.values()) { + expect(file).toBeInstanceOf(NodeFileSystemFileHandle); + expect(file.kind).toBe('file'); + expect(file.name).toBe('file.txt'); + } + }); + + test('returns two entries', async () => { + const {dir} = setup({ + 'index.html': 'Hello, world!', + 'another/folder': null, + }); + const handles: NodeFileSystemHandle[] = []; + for await (const entry of dir.values()) handles.push(entry); + expect(handles.length).toBe(2); + expect(handles.find(handle => handle.name === 'index.html')).toBeInstanceOf(NodeFileSystemFileHandle); + expect(handles.find(handle => handle.name === 'another')).toBeInstanceOf(NodeFileSystemDirectoryHandle); + }); +});