Skip to content

Commit

Permalink
feat: 🎸 implement .list() method
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Jun 20, 2023
1 parent eb19681 commit 4a064cf
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 30 deletions.
25 changes: 4 additions & 21 deletions src/crud/types.ts
Expand Up @@ -52,19 +52,7 @@ export interface CrudApi {
* @param collection Type of the resource, collection name.
* @returns List of resources of the given type, and sub-types.
*/
list: (collection: CrudCollection) => Promise<CrudTypeEntry[]>;

/**
* Recursively scans all resources of a collection, and sub-collections. Returns
* a cursor to continue scanning.
*
* @param collection Type of the resource, collection name.
* @param cursor Cursor to start scanning from. If empty string, starts from the beginning.
* @returns List of resources of the given type, and sub-collections. Also
* returns a cursor to continue scanning. If the cursor is empty
* string, the scan is complete.
*/
scan: (collection: CrudCollection, cursor?: string | '') => Promise<CrudScanResult>;
list: (collection: CrudCollection) => Promise<CrudCollectionEntry[]>;
}

export type CrudCollection = string[];
Expand All @@ -73,14 +61,14 @@ export interface CrudPutOptions {
throwIf?: 'exists' | 'missing';
}

export interface CrudTypeEntry {
export interface CrudCollectionEntry {
/** Kind of the resource, type or item. */
type: 'resource' | 'collection';
/** Name of the resource. */
id: string;
}

export interface CrudResourceInfo extends CrudTypeEntry {
export interface CrudResourceInfo extends CrudCollectionEntry {
/** Size of the resource in bytes. */
size?: number;
/** Timestamp when the resource last modified. */
Expand All @@ -91,10 +79,5 @@ export interface CrudResourceInfo extends CrudTypeEntry {

export interface CrudScanResult {
cursor: string | '';
list: CrudTypeEntry[];
}

export interface CrudScanEntry extends CrudTypeEntry {
/** Collection, which contains this entry. */
collection: CrudCollection;
list: CrudCollectionEntry[];
}
27 changes: 18 additions & 9 deletions src/fsa-crud/FsaCrud.ts
Expand Up @@ -138,14 +138,23 @@ export class FsaCrud implements crud.CrudApi {
}
};

public readonly list = async (collection: crud.CrudCollection): Promise<crud.CrudTypeEntry[]> => {
throw new Error('Not implemented');
};

public readonly scan = async (
collection: crud.CrudCollection,
cursor?: string | '',
): Promise<crud.CrudScanResult> => {
throw new Error('Not implemented');
public readonly list = async (collection: crud.CrudCollection): Promise<crud.CrudCollectionEntry[]> => {
assertType(collection, 'drop', '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({
type: 'resource',
id,
});
} else if (handle.kind === 'directory') {
entries.push({
type: 'collection',
id,
});
}
}
return entries;
};
}
40 changes: 40 additions & 0 deletions src/fsa-crud/__tests__/FsaCrud.test.ts
Expand Up @@ -275,4 +275,44 @@ onlyOnNode20('FsaCrud', () => {
expect(snapshot()).toEqual({});
});
});

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((<any>err).message).toBe("Failed to execute 'drop' 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 = await crud.list([]);
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 try 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 [, err] = await of(crud.list(['gg']));
expect(err).toBeInstanceOf(DOMException);
expect((<any>err).name).toBe('CollectionNotFound');
});
});
});

0 comments on commit 4a064cf

Please sign in to comment.