From a148fb89d0373442f5773c6656e433abdafdb2a0 Mon Sep 17 00:00:00 2001 From: streamich Date: Sat, 27 Apr 2024 12:22:18 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20implement=20.scan()=20me?= =?UTF-8?q?thod=20for=20FSA=20CRUD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/crud/__tests__/testCrudfs.ts | 53 ++++++++++++++++++++++++++++++-- src/fsa-to-crud/FsaCrud.ts | 18 ++++++----- 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/crud/__tests__/testCrudfs.ts b/src/crud/__tests__/testCrudfs.ts index 433fe2510..6054f71fd 100644 --- a/src/crud/__tests__/testCrudfs.ts +++ b/src/crud/__tests__/testCrudfs.ts @@ -1,5 +1,5 @@ import { of } from '../../thingies'; -import type { CrudApi } from '../types'; +import type { CrudApi, CrudCollectionEntry } from '../types'; export type Setup = () => { crud: CrudApi; @@ -271,12 +271,59 @@ export const testCrudfs = (setup: Setup) => { }); }); + describe('.scan()', () => { + test('throws if the collection is not valid', async () => { + const { crud } = setup(); + try { + const iterable = crud.scan(['./..', 'foo']); + await iterable.next(); + throw 'should not reach here'; + } catch (err) { + expect(err).toBeInstanceOf(TypeError); + expect((err).message).toBe("Failed to execute 'scan' on 'crudfs': Name is not allowed."); + } + }); + + test('can retrieve a list of resources and collections at root', async () => { + const { crud } = setup(); + await crud.put(['foo'], 'bar', b('1')); + await crud.put([], 'baz', b('1')); + await crud.put([], 'qux', b('2')); + const list: CrudCollectionEntry[] = []; + for await (const entry of crud.scan([])) list.push(entry); + expect(list.length).toBe(3); + expect(list.find(x => x.id === 'baz')).toMatchObject({ + type: 'resource', + id: 'baz', + }); + expect(list.find(x => x.id === 'qux')).toMatchObject({ + type: 'resource', + id: 'qux', + }); + expect(list.find(x => x.id === 'foo')).toMatchObject({ + type: 'collection', + id: 'foo', + }); + }); + + test('throws when trying to list a non-existing collection', async () => { + const { crud } = setup(); + await crud.put(['foo'], 'bar', b('1')); + await crud.put([], 'baz', b('1')); + await crud.put([], 'qux', b('2')); + const iterator = crud.scan(['gg']); + const [, err] = await of(iterator.next()); + expect(err).toBeInstanceOf(DOMException); + expect((err).name).toBe('CollectionNotFound'); + }); + }); + describe('.list()', () => { test('throws if the collection is not valid', async () => { const { crud } = setup(); const [, err] = await of(crud.list(['./..', 'foo'])); expect(err).toBeInstanceOf(TypeError); - expect((err).message).toBe("Failed to execute 'drop' on 'crudfs': Name is not allowed."); + expect((err).message).toBe("Failed to execute 'scan' on 'crudfs': Name is not allowed."); }); test('can retrieve a list of resources and collections at root', async () => { @@ -300,7 +347,7 @@ export const testCrudfs = (setup: Setup) => { }); }); - test('throws when try to list a non-existing collection', async () => { + test('throws when trying to list a non-existing collection', async () => { const { crud } = setup(); await crud.put(['foo'], 'bar', b('1')); await crud.put([], 'baz', b('1')); diff --git a/src/fsa-to-crud/FsaCrud.ts b/src/fsa-to-crud/FsaCrud.ts index 9108ac646..59b3472bb 100644 --- a/src/fsa-to-crud/FsaCrud.ts +++ b/src/fsa-to-crud/FsaCrud.ts @@ -137,23 +137,27 @@ export class FsaCrud implements crud.CrudApi { } }; - public readonly list = async (collection: crud.CrudCollection): Promise => { - assertType(collection, 'drop', 'crudfs'); + public readonly scan = async function* (collection: crud.CrudCollection): AsyncIterableIterator { + assertType(collection, 'scan', 'crudfs'); const [dir] = await this.getDir(collection, false); - const entries: crud.CrudCollectionEntry[] = []; for await (const [id, handle] of dir.entries()) { if (handle.kind === 'file') { - entries.push({ + yield { type: 'resource', id, - }); + }; } else if (handle.kind === 'directory') { - entries.push({ + yield { type: 'collection', id, - }); + }; } } + }; + + public readonly list = async (collection: crud.CrudCollection): Promise => { + const entries: crud.CrudCollectionEntry[] = []; + for await (const entry of this.scan(collection)) entries.push(entry); return entries; };