Skip to content

Commit

Permalink
feat: 🎸 implement basic state() method
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Jun 17, 2023
1 parent 4769314 commit 4039d64
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 21 deletions.
10 changes: 5 additions & 5 deletions src/fsa-to-node/FsaNodeDirent.ts
Expand Up @@ -5,23 +5,23 @@ import type { IDirent, TDataOut } from '../node/types/misc';
export class FsaNodeDirent implements IDirent {
public constructor(public readonly name: TDataOut, protected readonly handle: IFileSystemHandle) {}

isDirectory(): boolean {
public isDirectory(): boolean {
return this.handle instanceof NodeFileSystemDirectoryHandle;
}

isFile(): boolean {
public isFile(): boolean {
return this.handle instanceof NodeFileSystemFileHandle;
}

isBlockDevice(): boolean {
public isBlockDevice(): boolean {
return false;
}

isCharacterDevice(): boolean {
public isCharacterDevice(): boolean {
return false;
}

isSymbolicLink(): boolean {
public isSymbolicLink(): boolean {
return false;
}

Expand Down
19 changes: 13 additions & 6 deletions src/fsa-to-node/FsaNodeFs.ts
Expand Up @@ -8,6 +8,7 @@ import {
getRmdirOptions,
optsAndCbGenerator,
getAppendFileOptsAndCb,
getStatOptsAndCb,
} from '../node/options';
import {
createError,
Expand Down Expand Up @@ -38,6 +39,7 @@ import type * as misc from '../node/types/misc';
import type * as opts from '../node/types/options';
import type * as fsa from '../fsa/types';
import type {FsCommonObjects} from '../node/types/FsCommonObjects';
import {FsaNodeStats} from './FsaNodeStats';

const notSupported: (...args: any[]) => any = () => {
throw new Error('Method not supported by the File System Access API.');
Expand Down Expand Up @@ -305,11 +307,16 @@ export class FsaNodeFs implements FsCallbackApi, FsCommonObjects {
throw new Error('Not implemented');
}

stat(path: misc.PathLike, callback: misc.TCallback<misc.IStats>): void;
stat(path: misc.PathLike, options: opts.IStatOptions, callback: misc.TCallback<misc.IStats>): void;
stat(path: misc.PathLike, a: misc.TCallback<misc.IStats> | opts.IStatOptions, b?: misc.TCallback<misc.IStats>): void {
throw new Error('Not implemented');
}
public readonly stat: FsCallbackApi['stat'] = (path: misc.PathLike, a: misc.TCallback<misc.IStats> | opts.IStatOptions, b?: misc.TCallback<misc.IStats>): void => {
const [{ bigint = false, throwIfNoEntry = true }, callback] = getStatOptsAndCb(a, b);
const filename = pathToFilename(path);
const [folder, name] = pathToLocation(filename);
(async () => {
const handle = await this.getFileOrDir(folder, name, 'stat');
const stats = new FsaNodeStats(bigint, handle);
return stats;
})().then(stats => callback(null, stats), error => callback(error));
};

fstat(fd: number, callback: misc.TCallback<misc.IStats>): void;
fstat(fd: number, options: opts.IFStatOptions, callback: misc.TCallback<misc.IStats>): void;
Expand Down Expand Up @@ -682,7 +689,7 @@ export class FsaNodeFs implements FsCallbackApi, FsCommonObjects {
public readonly X_OK = constants.X_OK;
public readonly constants = constants;
public readonly Dirent = FsaNodeDirent;
public readonly Stats = 0 as any;
public readonly Stats = FsaNodeStats;
public readonly StatFs = 0 as any;
public readonly Dir = 0 as any;
public readonly StatsWatcher = 0 as any;
Expand Down
78 changes: 78 additions & 0 deletions src/fsa-to-node/FsaNodeStats.ts
@@ -0,0 +1,78 @@
import { NodeFileSystemDirectoryHandle, NodeFileSystemFileHandle } from '../node-to-fsa';
import type { IFileSystemHandle } from '../fsa/types';
import type * as misc from '../node/types/misc';

const time: number = 0;
const timex: bigint = typeof BigInt === 'function' ? BigInt(time) : time as any as bigint;
const date = new Date(time);

export class FsaNodeStats<T = misc.TStatNumber> implements misc.IStats<T> {
public readonly uid: T;
public readonly gid: T;
public readonly rdev: T;
public readonly blksize: T;
public readonly ino: T;
public readonly size: T;
public readonly blocks: T;
public readonly atime: Date;
public readonly mtime: Date;
public readonly ctime: Date;
public readonly birthtime: Date;
public readonly atimeMs: T;
public readonly mtimeMs: T;
public readonly ctimeMs: T;
public readonly birthtimeMs: T;
public readonly dev: T;
public readonly mode: T;
public readonly nlink: T;

public constructor(isBigInt: boolean, protected readonly handle: IFileSystemHandle) {
const dummy = (isBigInt ? timex : time) as any as T;
this.uid = dummy;
this.gid = dummy;
this.rdev = dummy;
this.blksize = dummy;
this.ino = dummy;
this.size = dummy;
this.blocks = dummy;
this.atime = date;
this.mtime = date;
this.ctime = date;
this.birthtime = date;
this.atimeMs = dummy;
this.mtimeMs = dummy;
this.ctimeMs = dummy;
this.birthtimeMs = dummy;
this.dev = dummy;
this.mode = dummy;
this.nlink = dummy;
}

public isDirectory(): boolean {
return this.handle instanceof NodeFileSystemDirectoryHandle;
}

public isFile(): boolean {
return this.handle instanceof NodeFileSystemFileHandle;
}

public isBlockDevice(): boolean {
return false;
}

public isCharacterDevice(): boolean {
return false;
}

public isSymbolicLink(): boolean {
return false;
}

public isFIFO(): boolean {
return false;
}

public isSocket(): boolean {
return false;
}
}
8 changes: 8 additions & 0 deletions src/fsa-to-node/__tests__/FsaNodeFs.test.ts
Expand Up @@ -463,3 +463,11 @@ describe('.rename()', () => {
});
});
});

describe('.stat()', () => {
test('can stat a file', async () => {
const { fs, mfs } = setup({ folder: { file: 'test' }, 'empty-folder': null, 'f.html': 'test' });
const stats = await fs.promises.stat('/folder/file');
expect(stats.isFile()).toBe(true);
});
});
10 changes: 10 additions & 0 deletions src/node/options.ts
Expand Up @@ -87,3 +87,13 @@ const appendFileDefaults: opts.IAppendFileOptions = {
};
export const getAppendFileOpts = optsGenerator<IAppendFileOptions>(appendFileDefaults);
export const getAppendFileOptsAndCb = optsAndCbGenerator<IAppendFileOptions, void>(getAppendFileOpts);

const statDefaults: opts.IStatOptions = {
bigint: false,
};
export const getStatOptions: (options?: any) => opts.IStatOptions = (options = {}) => Object.assign({}, statDefaults, options);
export const getStatOptsAndCb: (options: any, callback?: misc.TCallback<misc.IStats>) => [opts.IStatOptions, misc.TCallback<misc.IStats>] = (
options,
callback?,
) =>
typeof options === 'function' ? [getStatOptions(), options] : [getStatOptions(options), validateCallback(callback)];
12 changes: 2 additions & 10 deletions src/volume.ts
Expand Up @@ -29,6 +29,8 @@ import {
optsGenerator,
getAppendFileOptsAndCb,
getAppendFileOpts,
getStatOptsAndCb,
getStatOptions,
} from './node/options';
import {
validateCallback,
Expand Down Expand Up @@ -189,16 +191,6 @@ export interface IFStatOptions {
bigint?: boolean;
}

const statDefaults: IStatOptions = {
bigint: false,
};
const getStatOptions: (options?: any) => IStatOptions = (options = {}) => Object.assign({}, statDefaults, options);
const getStatOptsAndCb: (options: any, callback?: TCallback<Stats>) => [IStatOptions, TCallback<Stats>] = (
options,
callback?,
) =>
typeof options === 'function' ? [getStatOptions(), options] : [getStatOptions(options), validateCallback(callback)];

// ---------------------------------------- Utility functions

type TResolve = (filename: string, base?: string) => string;
Expand Down

0 comments on commit 4039d64

Please sign in to comment.