From ac38b5d0e1a6e586a99dcdf00256144c9577e988 Mon Sep 17 00:00:00 2001 From: streamich Date: Thu, 22 Jun 2023 10:17:10 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20missing=20synchron?= =?UTF-8?q?ous=20method=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fsa-to-node/FsaNodeFs.ts | 18 ++++- src/node/lists/fsSynchronousApiList.ts | 5 ++ src/node/types/FsSynchronousApi.ts | 102 +++++++++++++------------ src/node/types/options.ts | 37 +++++++++ src/node/util.ts | 6 +- src/volume.ts | 10 +++ 6 files changed, 125 insertions(+), 53 deletions(-) diff --git a/src/fsa-to-node/FsaNodeFs.ts b/src/fsa-to-node/FsaNodeFs.ts index 6f5e5d9ec..1c1154b51 100644 --- a/src/fsa-to-node/FsaNodeFs.ts +++ b/src/fsa-to-node/FsaNodeFs.ts @@ -25,6 +25,10 @@ const notSupported: (...args: any[]) => any = () => { throw new Error('Method not supported by the File System Access API.'); }; +const notImplemented: (...args: any[]) => any = () => { + throw new Error('Not implemented'); +}; + const noop: (...args: any[]) => any = () => {}; /** @@ -1022,7 +1026,7 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono a: string | Buffer | ArrayBufferView | DataView, b?: number, c?: number | BufferEncoding, - d?: number, + d?: number | null, ): number => { const [, buf, offset, length, position] = util.getWriteSyncArgs(fd, a, b, c, d); const filename = this.getFileName(fd); @@ -1044,6 +1048,14 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono return openFile.fd; }; + public readonly writevSync: FsSynchronousApi['writevSync'] = (fd: number, buffers: ArrayBufferView[], position?: number | null): void => { + if (buffers.length === 0) return; + this.writeSync(fd, buffers[0], 0, buffers[0].byteLength, position); + for (let i = 1; i < buffers.length; i++) { + this.writeSync(fd, buffers[i], 0, buffers[i].byteLength, null); + } + }; + public readonly fdatasyncSync: FsSynchronousApi['fdatasyncSync'] = noop; public readonly fsyncSync: FsSynchronousApi['fsyncSync'] = noop; public readonly chmodSync: FsSynchronousApi['chmodSync'] = noop; @@ -1054,6 +1066,10 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono public readonly lchmodSync: FsSynchronousApi['lchmodSync'] = noop; public readonly lchownSync: FsSynchronousApi['lchownSync'] = noop; public readonly utimesSync: FsSynchronousApi['utimesSync'] = noop; + public readonly lutimesSync: FsSynchronousApi['lutimesSync'] = noop; + + public readonly cpSync: FsSynchronousApi['cpSync'] = notImplemented; + public readonly statfsSync: FsSynchronousApi['statfsSync'] = notImplemented; public readonly symlinkSync: FsSynchronousApi['symlinkSync'] = notSupported; public readonly linkSync: FsSynchronousApi['linkSync'] = notSupported; diff --git a/src/node/lists/fsSynchronousApiList.ts b/src/node/lists/fsSynchronousApiList.ts index ac303852c..b2b4110fe 100644 --- a/src/node/lists/fsSynchronousApiList.ts +++ b/src/node/lists/fsSynchronousApiList.ts @@ -37,4 +37,9 @@ export const fsSynchronousApiList: Array = [ 'utimesSync', 'writeFileSync', 'writeSync', + + // 'cpSync', + // 'lutimesSync', + // 'statfsSync', + // 'writevSync', ]; diff --git a/src/node/types/FsSynchronousApi.ts b/src/node/types/FsSynchronousApi.ts index 3a4fc2d28..d27f49e76 100644 --- a/src/node/types/FsSynchronousApi.ts +++ b/src/node/types/FsSynchronousApi.ts @@ -2,8 +2,41 @@ import type * as misc from './misc'; import type * as opts from './options'; export interface FsSynchronousApi { - openSync(path: misc.PathLike, flags: misc.TFlags, mode?: misc.TMode): number; + accessSync(path: misc.PathLike, mode?: number): void; + appendFileSync(id: misc.TFileId, data: misc.TData, options?: opts.IAppendFileOptions | string): void; + chmodSync(path: misc.PathLike, mode: misc.TMode): void; + chownSync(path: misc.PathLike, uid: number, gid: number): void; closeSync(fd: number): void; + copyFileSync(src: misc.PathLike, dest: misc.PathLike, flags?: misc.TFlagsCopy): void; + cpSync(src: string | URL, dest: string | URL, options?: opts.ICpOptions): void; + existsSync(path: misc.PathLike): boolean; + fchmodSync(fd: number, mode: misc.TMode): void; + fchownSync(fd: number, uid: number, gid: number): void; + fdatasyncSync(fd: number): void; + fstatSync(fd: number, options: { bigint: false }): misc.IStats; + fstatSync(fd: number, options: { bigint: true }): misc.IStats; + fstatSync(fd: number): misc.IStats; + fsyncSync(fd: number): void; + ftruncateSync(fd: number, len?: number): void; + futimesSync(fd: number, atime: misc.TTime, mtime: misc.TTime): void; + lchmodSync(path: misc.PathLike, mode: misc.TMode): void; + lchownSync(path: misc.PathLike, uid: number, gid: number): void; + lutimesSync(path: misc.PathLike, atime: number | string | Date, time: number | string | Date): void; + linkSync(existingPath: misc.PathLike, newPath: misc.PathLike): void; + lstatSync(path: misc.PathLike, options: { bigint: false; throwIfNoEntry: false }): misc.IStats | undefined; + lstatSync(path: misc.PathLike, options: { bigint: false; throwIfNoEntry?: true | undefined }): misc.IStats; + lstatSync(path: misc.PathLike, options: { bigint: true; throwIfNoEntry: false }): misc.IStats | undefined; + lstatSync(path: misc.PathLike, options: { bigint: true; throwIfNoEntry?: true | undefined }): misc.IStats; + lstatSync(path: misc.PathLike, options: { throwIfNoEntry: false }): misc.IStats | undefined; + lstatSync(path: misc.PathLike, options: { throwIfNoEntry?: true | undefined }): misc.IStats; + lstatSync(path: misc.PathLike): misc.IStats; + mkdirSync(path: misc.PathLike, options: opts.IMkdirOptions & { recursive: true }): string | undefined; + mkdirSync(path: misc.PathLike, options?: misc.TMode | (opts.IMkdirOptions & { recursive?: false })): void; + mkdirSync(path: misc.PathLike, options?: misc.TMode | opts.IMkdirOptions): string | undefined; + mkdtempSync(prefix: string, options?: opts.IOptions): misc.TDataOut; + openSync(path: misc.PathLike, flags: misc.TFlags, mode?: misc.TMode): number; + readdirSync(path: misc.PathLike, options?: opts.IReaddirOptions | string): misc.TDataOut[] | misc.IDirent[]; + readlinkSync(path: misc.PathLike, options?: opts.IOptions): misc.TDataOut; readSync( fd: number, buffer: Buffer | ArrayBufferView | DataView, @@ -12,59 +45,30 @@ export interface FsSynchronousApi { position: number, ): number; readFileSync(file: misc.TFileId, options?: opts.IReadFileOptions | string): misc.TDataOut; + realpathSync(path: misc.PathLike, options?: opts.IRealpathOptions | string): misc.TDataOut; + renameSync(oldPath: misc.PathLike, newPath: misc.PathLike): void; + rmdirSync(path: misc.PathLike, options?: opts.IRmdirOptions): void; + rmSync(path: misc.PathLike, options?: opts.IRmOptions): void; + statSync(path: misc.PathLike, options: { bigint: false; throwIfNoEntry: false }): misc.IStats | undefined; + statSync(path: misc.PathLike, options: { bigint: false; throwIfNoEntry?: true }): misc.IStats; + statSync(path: misc.PathLike, options: { bigint: true; throwIfNoEntry: false }): misc.IStats | undefined; + statSync(path: misc.PathLike, options: { bigint: true; throwIfNoEntry?: true }): misc.IStats; + statSync(path: misc.PathLike, options: { throwIfNoEntry: false }): misc.IStats | undefined; + statSync(path: misc.PathLike, options: { throwIfNoEntry?: true }): misc.IStats; + statSync(path: misc.PathLike): misc.IStats; + statfsSync(path: misc.PathLike, options?: opts.IStafsOptions): void; + symlinkSync(target: misc.PathLike, path: misc.PathLike, type?: misc.symlink.Type): void; + truncateSync(id: misc.TFileId, len?: number): void; + unlinkSync(path: misc.PathLike): void; + utimesSync(path: misc.PathLike, atime: misc.TTime, mtime: misc.TTime): void; + writeFileSync(id: misc.TFileId, data: misc.TData, options?: opts.IWriteFileOptions): void; writeSync( fd: number, buffer: Buffer | ArrayBufferView | DataView, offset?: number, length?: number, - position?: number, + position?: number | null, ): number; writeSync(fd: number, str: string, position?: number, encoding?: BufferEncoding): number; - writeFileSync(id: misc.TFileId, data: misc.TData, options?: opts.IWriteFileOptions): void; - copyFileSync(src: misc.PathLike, dest: misc.PathLike, flags?: misc.TFlagsCopy): void; - linkSync(existingPath: misc.PathLike, newPath: misc.PathLike): void; - unlinkSync(path: misc.PathLike): void; - symlinkSync(target: misc.PathLike, path: misc.PathLike, type?: misc.symlink.Type): void; - realpathSync(path: misc.PathLike, options?: opts.IRealpathOptions | string): misc.TDataOut; - lstatSync(path: misc.PathLike): misc.IStats; - lstatSync(path: misc.PathLike, options: { throwIfNoEntry?: true | undefined }): misc.IStats; - lstatSync(path: misc.PathLike, options: { bigint: false; throwIfNoEntry?: true | undefined }): misc.IStats; - lstatSync(path: misc.PathLike, options: { bigint: true; throwIfNoEntry?: true | undefined }): misc.IStats; - lstatSync(path: misc.PathLike, options: { throwIfNoEntry: false }): misc.IStats | undefined; - lstatSync(path: misc.PathLike, options: { bigint: false; throwIfNoEntry: false }): misc.IStats | undefined; - lstatSync(path: misc.PathLike, options: { bigint: true; throwIfNoEntry: false }): misc.IStats | undefined; - statSync(path: misc.PathLike): misc.IStats; - statSync(path: misc.PathLike, options: { throwIfNoEntry?: true }): misc.IStats; - statSync(path: misc.PathLike, options: { throwIfNoEntry: false }): misc.IStats | undefined; - statSync(path: misc.PathLike, options: { bigint: false; throwIfNoEntry?: true }): misc.IStats; - statSync(path: misc.PathLike, options: { bigint: true; throwIfNoEntry?: true }): misc.IStats; - statSync(path: misc.PathLike, options: { bigint: false; throwIfNoEntry: false }): misc.IStats | undefined; - statSync(path: misc.PathLike, options: { bigint: true; throwIfNoEntry: false }): misc.IStats | undefined; - fstatSync(fd: number): misc.IStats; - fstatSync(fd: number, options: { bigint: false }): misc.IStats; - fstatSync(fd: number, options: { bigint: true }): misc.IStats; - renameSync(oldPath: misc.PathLike, newPath: misc.PathLike): void; - existsSync(path: misc.PathLike): boolean; - accessSync(path: misc.PathLike, mode?: number): void; - appendFileSync(id: misc.TFileId, data: misc.TData, options?: opts.IAppendFileOptions | string): void; - readdirSync(path: misc.PathLike, options?: opts.IReaddirOptions | string): misc.TDataOut[] | misc.IDirent[]; - readlinkSync(path: misc.PathLike, options?: opts.IOptions): misc.TDataOut; - fsyncSync(fd: number): void; - fdatasyncSync(fd: number): void; - ftruncateSync(fd: number, len?: number): void; - truncateSync(id: misc.TFileId, len?: number): void; - futimesSync(fd: number, atime: misc.TTime, mtime: misc.TTime): void; - utimesSync(path: misc.PathLike, atime: misc.TTime, mtime: misc.TTime): void; - mkdirSync(path: misc.PathLike, options: opts.IMkdirOptions & { recursive: true }): string | undefined; - mkdirSync(path: misc.PathLike, options?: misc.TMode | (opts.IMkdirOptions & { recursive?: false })): void; - mkdirSync(path: misc.PathLike, options?: misc.TMode | opts.IMkdirOptions): string | undefined; - mkdtempSync(prefix: string, options?: opts.IOptions): misc.TDataOut; - rmdirSync(path: misc.PathLike, options?: opts.IRmdirOptions): void; - rmSync(path: misc.PathLike, options?: opts.IRmOptions): void; - fchmodSync(fd: number, mode: misc.TMode): void; - chmodSync(path: misc.PathLike, mode: misc.TMode): void; - lchmodSync(path: misc.PathLike, mode: misc.TMode): void; - fchownSync(fd: number, uid: number, gid: number): void; - chownSync(path: misc.PathLike, uid: number, gid: number): void; - lchownSync(path: misc.PathLike, uid: number, gid: number): void; + writevSync(fd: number, buffers: ArrayBufferView[], position?: number | null): void; } diff --git a/src/node/types/options.ts b/src/node/types/options.ts index c0499fa18..0d985174f 100644 --- a/src/node/types/options.ts +++ b/src/node/types/options.ts @@ -97,3 +97,40 @@ export interface IWatchOptions extends IOptions { persistent?: boolean; recursive?: boolean; } + +export interface ICpOptions { + /** dereference symlinks. Default: false. */ + dereference?: boolean; + /** + * When force is false, and the destination exists, throw an error. + * Default: false. + */ + errorOnExist?: boolean; + /** + * Function to filter copied files/directories. Return true to copy the item, + * false to ignore it. Default: undefined. + */ + filter?: (src: string, dest: string) => boolean; + /** + * Overwrite existing file or directory. The copy operation will ignore errors + * if you set this to false and the destination exists. Use the errorOnExist + * option to change this behavior. Default: true. + */ + force?: boolean; + /** + * Integer, modifiers for copy operation. Default: 0. See mode flag of + * `fs.copyFileSync()`. + */ + mode: number; + /** When true timestamps from src will be preserved. Default: false. */ + preserveTimestamps: boolean; + /** Copy directories recursively Default: false. */ + recursive: boolean; + /** When true, path resolution for symlinks will be skipped. Default: false. */ + verbatimSymlinks: boolean; +} + +export interface IStafsOptions { + /** Whether the numeric values in the returned `StatFs` object should be bigint. */ + bigint?: boolean; +} diff --git a/src/node/util.ts b/src/node/util.ts index c28684298..0fb341794 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -249,13 +249,13 @@ export const getWriteSyncArgs = ( a: string | Buffer | ArrayBufferView | DataView, b?: number, c?: number | BufferEncoding, - d?: number, -): [fd: number, buf: Buffer, offset: number, length?: number, position?: number] => { + d?: number | null, +): [fd: number, buf: Buffer, offset: number, length?: number, position?: number | null] => { validateFd(fd); let encoding: BufferEncoding | undefined; let offset: number | undefined; let length: number | undefined; - let position: number | undefined; + let position: number | null | undefined; const isBuffer = typeof a !== 'string'; if (isBuffer) { offset = (b || 0) | 0; diff --git a/src/volume.ts b/src/volume.ts index bf20a3972..b62938b05 100644 --- a/src/volume.ts +++ b/src/volume.ts @@ -54,6 +54,7 @@ import { unixify, } from './node/util'; import type { PathLike, symlink } from 'fs'; +import type { FsSynchronousApi } from './node/types'; const resolveCrossPlatform = pathModule.resolve; const { @@ -218,6 +219,10 @@ function flattenJSON(nestedJSON: NestedDirectoryJSON): DirectoryJSON { return flatJSON; } +const notImplemented: (...args: any[]) => any = () => { + throw new Error('Not implemented'); +}; + /** * `Volume` represents a file system. */ @@ -1874,6 +1879,11 @@ export class Volume implements FsCallbackApi { return watcher; } + + public cpSync: FsSynchronousApi['cpSync'] = notImplemented; + public lutimesSync: FsSynchronousApi['lutimesSync'] = notImplemented; + public statfsSync: FsSynchronousApi['statfsSync'] = notImplemented; + public writevSync: FsSynchronousApi['writevSync'] = notImplemented; } function emitStop(self) {