Skip to content

Commit

Permalink
feat: 🎸 implement .resolve() method
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Jun 14, 2023
1 parent dca57a2 commit 9d5669c
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 11 deletions.
28 changes: 19 additions & 9 deletions src/node-to-fsa/NodeFileSystemDirectoryHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import type Dirent from "../Dirent";
export class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle {
constructor (
protected readonly fs: NodeFsaFs,
protected readonly path: string,
public readonly __path: string,
protected readonly ctx: Partial<NodeFsaContext> = createCtx(ctx),
) {
super('directory', basename(path, ctx.separator!));
super('directory', basename(__path, ctx.separator!));
}

/**
Expand All @@ -23,15 +23,15 @@ export class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle {
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/keys
*/
public async * keys(): AsyncIterableIterator<string> {
const list = await this.fs.promises.readdir(this.path);
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 {__path: path, fs, ctx} = this;
const list = await fs.promises.readdir(path, {withFileTypes: true});
for (const d of list) {
const dirent = d as Dirent;
Expand Down Expand Up @@ -64,7 +64,7 @@ export class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle {
*/
public async getDirectoryHandle(name: string, options?: GetDirectoryHandleOptions): Promise<NodeFileSystemDirectoryHandle> {
assertName(name, 'getDirectoryHandle', 'FileSystemDirectoryHandle');
const filename = this.path + this.ctx.separator! + name;
const filename = this.__path + this.ctx.separator! + name;
try {
const stats = await this.fs.promises.stat(filename);
if (!stats.isDirectory()) throw newTypeMismatchError();
Expand Down Expand Up @@ -100,7 +100,7 @@ export class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle {
*/
public async getFileHandle(name: string, options?: GetFileHandleOptions): Promise<NodeFileSystemFileHandle> {
assertName(name, 'getFileHandle', 'FileSystemDirectoryHandle');
const filename = this.path + this.ctx.separator! + name;
const filename = this.__path + this.ctx.separator! + name;
try {
const stats = await this.fs.promises.stat(filename);
if (!stats.isFile()) throw newTypeMismatchError();
Expand Down Expand Up @@ -136,7 +136,7 @@ export class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle {
*/
public async removeEntry(name: string, {recursive = false}: RemoveEntryOptions = {}): Promise<void> {
assertName(name, 'removeEntry', 'FileSystemDirectoryHandle');
const filename = this.path + this.ctx.separator! + name;
const filename = this.__path + this.ctx.separator! + name;
const promises = this.fs.promises;
try {
const stats = await promises.stat(filename);
Expand Down Expand Up @@ -172,8 +172,18 @@ export class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle {
* @param possibleDescendant The {@link NodeFileSystemFileHandle} from which
* to return the relative path.
*/
public resolve(possibleDescendant: NodeFileSystemHandle): Promise<string[] | null> {
throw new Error('Not implemented');
public async resolve(possibleDescendant: NodeFileSystemHandle): Promise<string[] | null> {
if (possibleDescendant instanceof NodeFileSystemDirectoryHandle || possibleDescendant instanceof NodeFileSystemFileHandle) {
const path = this.__path;
const childPath = possibleDescendant.__path;
if (!childPath.startsWith(path)) return null;
let relative = childPath.slice(path.length);
if (relative === '') return [];
const separator = this.ctx.separator!;
if (relative[0] === separator) relative = relative.slice(1);
return relative.split(separator);
}
return null;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/node-to-fsa/NodeFileSystemFileHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import type {NodeFsaContext, NodeFsaFs} from "./types";
export class NodeFileSystemFileHandle extends NodeFileSystemHandle {
constructor (
protected readonly fs: NodeFsaFs,
protected readonly path: string,
public readonly __path: string,
protected readonly ctx: Partial<NodeFsaContext> = createCtx(ctx),
) {
super('file', basename(path, ctx.separator!));
super('file', basename(__path, ctx.separator!));
}

/**
Expand Down
38 changes: 38 additions & 0 deletions src/node-to-fsa/__tests__/NodeFileSystemDirectoryHandle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,41 @@ describe('.removeEntry()', () => {
expect(res).toBe(undefined);
});
});

describe('.resolve()', () => {
test('return empty array for itself', async () => {
const {dir} = setup({});
const res = await dir.resolve(dir);
expect(res).toEqual([]);
});

test('can resolve one level deep child', async () => {
const {dir} = setup({
file: 'contents',
});
const child = await dir.getFileHandle('file');
const res = await dir.resolve(child);
expect(res).toEqual(['file']);
});

test('can resolve two level deep child', async () => {
const {dir} = setup({
'dir/file': 'contents',
});
const child1 = await dir.getDirectoryHandle('dir');
const child2 = await child1.getFileHandle('file');
const res = await dir.resolve(child2);
expect(res).toEqual(['dir', 'file']);
const res2 = await child1.resolve(child2);
expect(res2).toEqual(['file']);
});

test('returns "null" if not a descendant', async () => {
const {dir} = setup({
'dir/file': 'contents',
});
const child1 = await dir.getDirectoryHandle('dir');
const res = await child1.resolve(dir);
expect(res).toBe(null);
});
});

0 comments on commit 9d5669c

Please sign in to comment.