From 4db13219aec4d6896d55012b83d7ea3f874f2dc1 Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Fri, 16 Jun 2023 02:03:26 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20create=20Node=20fs=20api?= =?UTF-8?q?=20tyeps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/node/types/callback.ts | 102 ++++++++++++++++++++++++++++ src/node/types/index.ts | 7 ++ src/node/types/misc.ts | 136 +++++++++++++++++++++++++++++++++++++ src/node/types/options.ts | 85 +++++++++++++++++++++++ src/node/types/promises.ts | 30 ++++++++ src/node/types/sync.ts | 71 +++++++++++++++++++ 6 files changed, 431 insertions(+) create mode 100644 src/node/types/callback.ts create mode 100644 src/node/types/index.ts create mode 100644 src/node/types/misc.ts create mode 100644 src/node/types/options.ts create mode 100644 src/node/types/promises.ts create mode 100644 src/node/types/sync.ts diff --git a/src/node/types/callback.ts b/src/node/types/callback.ts new file mode 100644 index 000000000..a5dbd9360 --- /dev/null +++ b/src/node/types/callback.ts @@ -0,0 +1,102 @@ +import type { PathLike, symlink } from 'fs'; +import type * as misc from './misc'; +import type * as opts from './options'; + +export interface FsCallbackApi { + open(path: PathLike, flags: misc.TFlags, /* ... */ callback: misc.TCallback); + open(path: PathLike, flags: misc.TFlags, mode: misc.TMode, callback: misc.TCallback); + close(fd: number, callback: misc.TCallback): void; + read( + fd: number, + buffer: Buffer | ArrayBufferView | DataView, + offset: number, + length: number, + position: number, + callback: (err?: Error | null, bytesRead?: number, buffer?: Buffer | ArrayBufferView | DataView) => void, + ): void; + readFile(id: misc.TFileId, callback: misc.TCallback); + readFile(id: misc.TFileId, options: opts.IReadFileOptions | string, callback: misc.TCallback); + write(fd: number, buffer: Buffer | ArrayBufferView | DataView, callback: (...args) => void); + write(fd: number, buffer: Buffer | ArrayBufferView | DataView, offset: number, callback: (...args) => void); + write( + fd: number, + buffer: Buffer | ArrayBufferView | DataView, + offset: number, + length: number, + callback: (...args) => void, + ); + write( + fd: number, + buffer: Buffer | ArrayBufferView | DataView, + offset: number, + length: number, + position: number, + callback: (...args) => void, + ); + write(fd: number, str: string, callback: (...args) => void); + write(fd: number, str: string, position: number, callback: (...args) => void); + write(fd: number, str: string, position: number, encoding: BufferEncoding, callback: (...args) => void); + writeFile(id: misc.TFileId, data: misc.TData, callback: misc.TCallback); + writeFile(id: misc.TFileId, data: misc.TData, options: opts.IWriteFileOptions | string, callback: misc.TCallback); + copyFile(src: PathLike, dest: PathLike, callback: misc.TCallback); + copyFile(src: PathLike, dest: PathLike, flags: misc.TFlagsCopy, callback: misc.TCallback); + link(existingPath: PathLike, newPath: PathLike, callback: misc.TCallback): void; + unlink(path: PathLike, callback: misc.TCallback): void; + symlink(target: PathLike, path: PathLike, callback: misc.TCallback); + symlink(target: PathLike, path: PathLike, type: symlink.Type, callback: misc.TCallback); + realpath(path: PathLike, callback: misc.TCallback); + realpath(path: PathLike, options: opts.IRealpathOptions | string, callback: misc.TCallback); + lstat(path: PathLike, callback: misc.TCallback): void; + lstat(path: PathLike, options: opts.IStatOptions, callback: misc.TCallback): void; + stat(path: PathLike, callback: misc.TCallback): void; + stat(path: PathLike, options: opts.IStatOptions, callback: misc.TCallback): void; + fstat(fd: number, callback: misc.TCallback): void; + fstat(fd: number, options: opts.IFStatOptions, callback: misc.TCallback): void; + rename(oldPath: PathLike, newPath: PathLike, callback: misc.TCallback): void; + exists(path: PathLike, callback: (exists: boolean) => void): void; + access(path: PathLike, callback: misc.TCallback); + access(path: PathLike, mode: number, callback: misc.TCallback); + appendFile(id: misc.TFileId, data: misc.TData, callback: misc.TCallback); + appendFile(id: misc.TFileId, data: misc.TData, options: opts.IAppendFileOptions | string, callback: misc.TCallback); + readdir(path: PathLike, callback: misc.TCallback); + readdir(path: PathLike, options: opts.IReaddirOptions | string, callback: misc.TCallback); + readlink(path: PathLike, callback: misc.TCallback); + readlink(path: PathLike, options: opts.IOptions, callback: misc.TCallback); + fsyncSync(fd: number): void; + fsync(fd: number, callback: misc.TCallback): void; + fdatasync(fd: number, callback: misc.TCallback): void; + ftruncate(fd: number, callback: misc.TCallback); + ftruncate(fd: number, len: number, callback: misc.TCallback); + truncate(id: misc.TFileId, callback: misc.TCallback); + truncate(id: misc.TFileId, len: number, callback: misc.TCallback); + futimes(fd: number, atime: misc.TTime, mtime: misc.TTime, callback: misc.TCallback): void; + utimes(path: PathLike, atime: misc.TTime, mtime: misc.TTime, callback: misc.TCallback): void; + mkdir(path: PathLike, callback: misc.TCallback); + mkdir(path: PathLike, mode: misc.TMode | (opts.IMkdirOptions & { recursive?: false }), callback: misc.TCallback); + mkdir(path: PathLike, mode: opts.IMkdirOptions & { recursive: true }, callback: misc.TCallback); + mkdir(path: PathLike, mode: misc.TMode | opts.IMkdirOptions, callback: misc.TCallback); + mkdirp(path: PathLike, callback: misc.TCallback); + mkdirp(path: PathLike, mode: misc.TMode, callback: misc.TCallback); + mkdtemp(prefix: string, callback: misc.TCallback): void; + mkdtemp(prefix: string, options: opts.IOptions, callback: misc.TCallback); + rmdir(path: PathLike, callback: misc.TCallback); + rmdir(path: PathLike, options: opts.IRmdirOptions, callback: misc.TCallback); + rm(path: PathLike, callback: misc.TCallback): void; + rm(path: PathLike, options: opts.IRmOptions, callback: misc.TCallback): void; + fchmod(fd: number, mode: misc.TMode, callback: misc.TCallback): void; + chmod(path: PathLike, mode: misc.TMode, callback: misc.TCallback): void; + lchmod(path: PathLike, mode: misc.TMode, callback: misc.TCallback): void; + fchown(fd: number, uid: number, gid: number, callback: misc.TCallback): void; + chown(path: PathLike, uid: number, gid: number, callback: misc.TCallback): void; + lchown(path: PathLike, uid: number, gid: number, callback: misc.TCallback): void; + watchFile(path: PathLike, listener: (curr: misc.IStats, prev: misc.IStats) => void): misc.IStatWatcher; + watchFile(path: PathLike, options: opts.IWatchFileOptions, listener: (curr: misc.IStats, prev: misc.IStats) => void): misc.IStatWatcher; + unwatchFile(path: PathLike, listener?: (curr: misc.IStats, prev: misc.IStats) => void): void; + createReadStream(path: PathLike, options?: opts.IReadStreamOptions | string): misc.IReadStream; + createWriteStream(path: PathLike, options?: opts.IWriteStreamOptions | string): misc.IWriteStream; + watch( + path: PathLike, + options?: opts.IWatchOptions | string, + listener?: (eventType: string, filename: string) => void, + ): misc.IFSWatcher; +} diff --git a/src/node/types/index.ts b/src/node/types/index.ts new file mode 100644 index 000000000..5842917e1 --- /dev/null +++ b/src/node/types/index.ts @@ -0,0 +1,7 @@ +import type {FsCallbackApi} from "./callback"; +import type {FsPromisesApi} from "./promises"; +import type {FsSynchronousApi} from "./sync"; + +export interface FsApi extends FsCallbackApi, FsSynchronousApi { + promises: FsPromisesApi; +} diff --git a/src/node/types/misc.ts b/src/node/types/misc.ts new file mode 100644 index 000000000..25dc3553f --- /dev/null +++ b/src/node/types/misc.ts @@ -0,0 +1,136 @@ +import type {PathLike, symlink} from 'fs'; +import type {constants} from '../../constants'; +import type {EventEmitter} from 'events'; +import type {TSetTimeout} from '../../setTimeoutUnref'; +import type {IAppendFileOptions, IReadFileOptions, IReadStreamOptions, IStatOptions, IWriteFileOptions, IWriteStreamOptions} from './options'; +import type {Readable, Writable} from 'stream'; + +export {PathLike, symlink}; + +export type TDataOut = string | Buffer; // Data formats we give back to users. +export type TEncodingExtended = BufferEncoding | 'buffer'; +export type TFileId = PathLike | number; // Number is used as a file descriptor. +export type TData = TDataOut | ArrayBufferView | DataView; // Data formats users can give us. +export type TFlags = string | number; +export type TMode = string | number; // Mode can be a String, although docs say it should be a Number. +export type TTime = number | string | Date; +export type TCallback = (error?: IError | null, data?: TData) => void; + +export interface IError extends Error { + code?: string; +} + +export type TFlagsCopy = + | typeof constants.COPYFILE_EXCL + | typeof constants.COPYFILE_FICLONE + | typeof constants.COPYFILE_FICLONE_FORCE; + +export type TStatNumber = number | bigint; + +export interface IStats { + uid: T; + gid: T; + rdev: T; + blksize: T; + ino: T; + size: T; + blocks: T; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + atimeMs: T; + mtimeMs: T; + ctimeMs: T; + birthtimeMs: T; + dev: T; + mode: T; + nlink: T; + isDirectory(): boolean; + isFile(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; +} + +export interface IDirent { + name: TDataOut; + isDirectory(): boolean; + isFile(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; +} + +export interface IStatWatcher extends EventEmitter { + filename: string; + interval: number; + timeoutRef?; + setTimeout: TSetTimeout; + prev: IStats; + start(path: string, persistent?: boolean, interval?: number): void; + stop(): void; +} + +export interface IReadStream extends Readable { + new (path: PathLike, options: IReadStreamOptions); + open(); + close(callback: TCallback); + bytesRead: number; + path: string; +} + +export interface IWriteStream extends Writable { + bytesWritten: number; + path: string; + new (path: PathLike, options: IWriteStreamOptions); + open(); + close(); +} + +export interface IFSWatcher extends EventEmitter { + start( + path: PathLike, + persistent?: boolean, + recursive?: boolean, + encoding?: BufferEncoding, + ): void; + close(): void; +} + +export interface IFileHandle { + fd: number; + appendFile(data: TData, options?: IAppendFileOptions | string): Promise; + chmod(mode: TMode): Promise; + chown(uid: number, gid: number): Promise; + close(): Promise; + datasync(): Promise; + read(buffer: Buffer | Uint8Array, offset: number, length: number, position: number): Promise; + readFile(options?: IReadFileOptions | string): Promise; + stat(options?: IStatOptions): Promise; + truncate(len?: number): Promise; + utimes(atime: TTime, mtime: TTime): Promise; + write( + buffer: Buffer | ArrayBufferView | DataView, + offset?: number, + length?: number, + position?: number, + ): Promise; + writeFile(data: TData, options?: IWriteFileOptions): Promise; +} + +export type TFileHandle = PathLike | IFileHandle; + +export interface TFileHandleReadResult { + bytesRead: number; + buffer: Buffer | Uint8Array; +} + +export interface TFileHandleWriteResult { + bytesWritten: number; + buffer: Buffer | Uint8Array; +} diff --git a/src/node/types/options.ts b/src/node/types/options.ts new file mode 100644 index 000000000..354e2a340 --- /dev/null +++ b/src/node/types/options.ts @@ -0,0 +1,85 @@ +import type {TEncodingExtended, TFlags, TMode} from "./misc"; + +export interface IOptions { + encoding?: BufferEncoding | TEncodingExtended; +} + +export interface IFileOptions extends IOptions { + mode?: TMode; + flag?: TFlags; +} + +export interface IWriteFileOptions extends IFileOptions {} + +export interface IReadFileOptions extends IOptions { + flag?: string; +} + +export interface IRealpathOptions { + encoding?: TEncodingExtended; +} + +export interface IAppendFileOptions extends IFileOptions {} + +export interface IStatOptions { + bigint?: boolean; + throwIfNoEntry?: boolean; +} + +export interface IFStatOptions { + bigint?: boolean; +} + +export interface IAppendFileOptions extends IFileOptions {} + +export interface IReaddirOptions extends IOptions { + withFileTypes?: boolean; +} + +export interface IMkdirOptions { + mode?: TMode; + recursive?: boolean; +} + +export interface IRmdirOptions { + /** @deprecated */ + recursive?: boolean; + maxRetries?: number; + retryDelay?: number; +} + +export interface IRmOptions { + force?: boolean; + maxRetries?: number; + recursive?: boolean; + retryDelay?: number; +} + +export interface IWatchFileOptions { + persistent?: boolean; + interval?: number; +} + +export interface IReadStreamOptions { + flags?: TFlags; + encoding?: BufferEncoding; + fd?: number; + mode?: TMode; + autoClose?: boolean; + start?: number; + end?: number; +} + +export interface IWriteStreamOptions { + flags?: TFlags; + defaultEncoding?: BufferEncoding; + fd?: number; + mode?: TMode; + autoClose?: boolean; + start?: number; +} + +export interface IWatchOptions extends IOptions { + persistent?: boolean; + recursive?: boolean; +} diff --git a/src/node/types/promises.ts b/src/node/types/promises.ts new file mode 100644 index 000000000..e71ac1885 --- /dev/null +++ b/src/node/types/promises.ts @@ -0,0 +1,30 @@ +import * as misc from "./misc"; +import * as opts from "./options"; + +export interface FsPromisesApi { + access(path: misc.PathLike, mode?: number): Promise; + appendFile(path: misc.TFileHandle, data: misc.TData, options?: opts.IAppendFileOptions | string): Promise; + chmod(path: misc.PathLike, mode: misc.TMode): Promise; + chown(path: misc.PathLike, uid: number, gid: number): Promise; + copyFile(src: misc.PathLike, dest: misc.PathLike, flags?: misc.TFlagsCopy): Promise; + lchmod(path: misc.PathLike, mode: misc.TMode): Promise; + lchown(path: misc.PathLike, uid: number, gid: number): Promise; + link(existingPath: misc.PathLike, newPath: misc.PathLike): Promise; + lstat(path: misc.PathLike, options?: opts.IStatOptions): Promise; + mkdir(path: misc.PathLike, options?: misc.TMode | opts.IMkdirOptions): Promise; + mkdtemp(prefix: string, options?: opts.IOptions): Promise; + open(path: misc.PathLike, flags: misc.TFlags, mode?: misc.TMode): Promise; + readdir(path: misc.PathLike, options?: opts.IReaddirOptions | string): Promise; + readFile(id: misc.TFileHandle, options?: opts.IReadFileOptions | string): Promise; + readlink(path: misc.PathLike, options?: opts.IOptions): Promise; + realpath(path: misc.PathLike, options?: opts.IRealpathOptions | string): Promise; + rename(oldPath: misc.PathLike, newPath: misc.PathLike): Promise; + rmdir(path: misc.PathLike, options?: opts.IRmdirOptions): Promise; + rm(path: misc.PathLike, options?: opts.IRmOptions): Promise; + stat(path: misc.PathLike, options?: opts.IStatOptions): Promise; + symlink(target: misc.PathLike, path: misc.PathLike, type?: misc.symlink.Type): Promise; + truncate(path: misc.PathLike, len?: number): Promise; + unlink(path: misc.PathLike): Promise; + utimes(path: misc.PathLike, atime: misc.TTime, mtime: misc.TTime): Promise; + writeFile(id: misc.TFileHandle, data: misc.TData, options?: opts.IWriteFileOptions): Promise; +} diff --git a/src/node/types/sync.ts b/src/node/types/sync.ts new file mode 100644 index 000000000..0e7a1eb3d --- /dev/null +++ b/src/node/types/sync.ts @@ -0,0 +1,71 @@ +import type { PathLike, symlink } from 'fs'; +import type * as misc from './misc'; +import type * as opts from './options'; + +export interface FsSynchronousApi { + openSync(path: PathLike, flags: misc.TFlags, mode?: misc.TMode): number; + closeSync(fd: number): void; + readSync( + fd: number, + buffer: Buffer | ArrayBufferView | DataView, + offset: number, + length: number, + position: number, + ): number; + readFileSync(file: misc.TFileId, options?: opts.IReadFileOptions | string): misc.TDataOut; + writeSync( + fd: number, + buffer: Buffer | ArrayBufferView | DataView, + offset?: number, + length?: number, + position?: number, + ): number; + writeSync(fd: number, str: string, position?: number, encoding?: BufferEncoding): number; + writeFileSync(id: misc.TFileId, data: misc.TData, options?: opts.IWriteFileOptions): void; + copyFileSync(src: PathLike, dest: PathLike, flags?: misc.TFlagsCopy): void; + linkSync(existingPath: PathLike, newPath: PathLike): void; + unlinkSync(path: PathLike): void; + symlinkSync(target: PathLike, path: PathLike, type?: symlink.Type): void; + realpathSync(path: PathLike, options?: opts.IRealpathOptions | string): misc.TDataOut; + lstatSync(path: PathLike): misc.IStats; + lstatSync(path: PathLike, options: { throwIfNoEntry?: true | undefined }): misc.IStats; + lstatSync(path: PathLike, options: { bigint: false; throwIfNoEntry?: true | undefined }): misc.IStats; + lstatSync(path: PathLike, options: { bigint: true; throwIfNoEntry?: true | undefined }): misc.IStats; + lstatSync(path: PathLike, options: { throwIfNoEntry: false }): misc.IStats | undefined; + lstatSync(path: PathLike, options: { bigint: false; throwIfNoEntry: false }): misc.IStats | undefined; + lstatSync(path: PathLike, options: { bigint: true; throwIfNoEntry: false }): misc.IStats | undefined; + statSync(path: PathLike): misc.IStats; + statSync(path: PathLike, options: { throwIfNoEntry?: true }): misc.IStats; + statSync(path: PathLike, options: { throwIfNoEntry: false }): misc.IStats | undefined; + statSync(path: PathLike, options: { bigint: false; throwIfNoEntry?: true }): misc.IStats; + statSync(path: PathLike, options: { bigint: true; throwIfNoEntry?: true }): misc.IStats; + statSync(path: PathLike, options: { bigint: false; throwIfNoEntry: false }): misc.IStats | undefined; + statSync(path: 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: PathLike, newPath: PathLike): void; + existsSync(path: PathLike): boolean; + accessSync(path: PathLike, mode?: number): void; + appendFileSync(id: misc.TFileId, data: misc.TData, options?: opts.IAppendFileOptions | string): void; + readdirSync(path: PathLike, options?: opts.IReaddirOptions | string): misc.TDataOut[] | misc.IDirent[]; + readlinkSync(path: PathLike, options?: opts.IOptions): misc.TDataOut; + 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: PathLike, atime: misc.TTime, mtime: misc.TTime): void; + mkdirSync(path: PathLike, options: opts.IMkdirOptions & { recursive: true }): string | undefined; + mkdirSync(path: PathLike, options?: misc.TMode | (opts.IMkdirOptions & { recursive?: false })): void; + mkdirSync(path: PathLike, options?: misc.TMode | opts.IMkdirOptions): string | undefined; + mkdirpSync(path: PathLike, mode?: misc.TMode): void; + mkdtempSync(prefix: string, options?: opts.IOptions): misc.TDataOut; + rmdirSync(path: PathLike, options?: opts.IRmdirOptions): void; + rmSync(path: PathLike, options?: opts.IRmOptions): void; + fchmodSync(fd: number, mode: misc.TMode): void; + chmodSync(path: PathLike, mode: misc.TMode): void; + lchmodSync(path: PathLike, mode: misc.TMode): void; + fchownSync(fd: number, uid: number, gid: number): void; + chownSync(path: PathLike, uid: number, gid: number): void; + lchownSync(path: PathLike, uid: number, gid: number): void; +}