/**
 * The following code is modified based on
 * https://github.com/webpack/webpack/blob/4b4ca3b/lib/util/fs.js
 *
 * MIT Licensed
 * Author Tobias Koppers @sokra
 * Copyright (c) JS Foundation and other contributors
 * https://github.com/webpack/webpack/blob/main/LICENSE
 */
import type { Abortable } from 'node:events';
import type { WatchOptions } from '../config/index.js';
export interface Watcher {
    close(): void;
    pause(): void;
    getAggregatedChanges?(): Set<string>;
    getAggregatedRemovals?(): Set<string>;
    getFileTimeInfoEntries?(): Map<string, FileSystemInfoEntry | 'ignore'>;
    getContextTimeInfoEntries?(): Map<string, FileSystemInfoEntry | 'ignore'>;
    getInfo(): WatcherInfo;
}
export interface WatcherInfo {
    changes: Set<string>;
    removals: Set<string>;
    fileTimeInfoEntries: Map<string, FileSystemInfoEntry | 'ignore'>;
    contextTimeInfoEntries: Map<string, FileSystemInfoEntry | 'ignore'>;
}
export type IStatsBase<T> = {
    isFile: () => boolean;
    isDirectory: () => boolean;
    isBlockDevice: () => boolean;
    isCharacterDevice: () => boolean;
    isSymbolicLink: () => boolean;
    isFIFO: () => boolean;
    isSocket: () => boolean;
    dev: T;
    ino: T;
    mode: T;
    nlink: T;
    uid: T;
    gid: T;
    rdev: T;
    size: T;
    blksize: T;
    blocks: T;
    atimeMs: T;
    mtimeMs: T;
    ctimeMs: T;
    birthtimeMs: T;
    atime: Date;
    mtime: Date;
    ctime: Date;
    birthtime: Date;
};
export type IStats = IStatsBase<number>;
export type IBigIntStats = IStatsBase<bigint> & {
    atimeNs: bigint;
    mtimeNs: bigint;
    ctimeNs: bigint;
    birthtimeNs: bigint;
};
interface IDirent {
    isFile: () => boolean;
    isDirectory: () => boolean;
    isBlockDevice: () => boolean;
    isCharacterDevice: () => boolean;
    isSymbolicLink: () => boolean;
    isFIFO: () => boolean;
    isSocket: () => boolean;
    name: string | Buffer;
}
export interface StreamOptions {
    flags?: string;
    encoding?: NodeJS.BufferEncoding;
    fd?: any;
    mode?: number;
    autoClose?: boolean;
    emitClose?: boolean;
    start?: number;
    signal?: null | AbortSignal;
}
export interface FSImplementation {
    open?: (...args: any[]) => any;
    close?: (...args: any[]) => any;
}
export type CreateReadStreamFSImplementation = FSImplementation & {
    read: (...args: any[]) => any;
};
export type ReadStreamOptions = StreamOptions & {
    fs?: null | CreateReadStreamFSImplementation;
    end?: number;
};
export type CreateReadStream = (path: PathLike, options?: NodeJS.BufferEncoding | ReadStreamOptions) => NodeJS.ReadableStream;
export interface OutputFileSystem {
    writeFile: (arg0: string | number, arg1: string | Buffer, arg2: (arg0?: null | NodeJS.ErrnoException) => void) => void;
    mkdir: (arg0: string, arg1: (arg0?: null | NodeJS.ErrnoException) => void) => void;
    readdir: (arg0: string, arg1: (arg0?: null | NodeJS.ErrnoException, arg1?: (string | Buffer)[] | IDirent[]) => void) => void;
    rmdir: (arg0: string, arg1: (arg0?: null | NodeJS.ErrnoException) => void) => void;
    unlink: (arg0: string, arg1: (arg0?: null | NodeJS.ErrnoException) => void) => void;
    stat: (arg0: string, arg1: (arg0?: null | NodeJS.ErrnoException, arg1?: IStats) => void) => void;
    lstat?: (arg0: string, arg1: (arg0?: null | NodeJS.ErrnoException, arg1?: IStats) => void) => void;
    readFile: (arg0: string, arg1: (arg0?: null | NodeJS.ErrnoException, arg1?: string | Buffer) => void) => void;
    chmod: (arg0: string, arg1: number, arg2: (arg0?: NodeJS.ErrnoException | null) => void) => void;
    join?: (arg0: string, arg1: string) => string;
    relative?: (arg0: string, arg1: string) => string;
    dirname?: (arg0: string) => string;
    createReadStream?: CreateReadStream;
}
export type JsonPrimitive = string | number | boolean | null;
export type JsonArray = JsonValue[];
export type JsonValue = JsonPrimitive | JsonObject | JsonArray;
export type JsonObject = {
    [Key in string]: JsonValue;
} & {
    [Key in string]?: JsonValue | undefined;
};
export type StringCallback = (err: NodeJS.ErrnoException | null, data?: string) => void;
export type BufferCallback = (err: NodeJS.ErrnoException | null, data?: Buffer) => void;
export type StringOrBufferCallback = (err: NodeJS.ErrnoException | null, data?: string | Buffer) => void;
export type ReaddirStringCallback = (err: NodeJS.ErrnoException | null, files?: string[]) => void;
export type ReaddirBufferCallback = (err: NodeJS.ErrnoException | null, files?: Buffer[]) => void;
export type ReaddirStringOrBufferCallback = (err: NodeJS.ErrnoException | null, files?: string[] | Buffer[]) => void;
export type ReaddirDirentCallback = (err: NodeJS.ErrnoException | null, files?: IDirent[]) => void;
export type StatsCallback = (err: NodeJS.ErrnoException | null, stats?: IStats) => void;
export type BigIntStatsCallback = (err: NodeJS.ErrnoException | null, stats?: IBigIntStats) => void;
export type StatsOrBigIntStatsCallback = (err: NodeJS.ErrnoException | null, stats?: IStats | IBigIntStats) => void;
export type ReadJsonCallback = (err: NodeJS.ErrnoException | Error | null, data?: JsonObject) => void;
export type PathLike = string | Buffer | URL;
export type PathOrFileDescriptor = PathLike | number;
export type ObjectEncodingOptions = {
    encoding?: BufferEncoding | null;
};
export type ReadFile = {
    (path: PathOrFileDescriptor, options: ({
        encoding: null | undefined;
        flag?: string;
    } & Abortable) | null | undefined, callback: BufferCallback): void;
    (path: PathOrFileDescriptor, options: ({
        encoding: BufferEncoding;
        flag?: string;
    } & Abortable) | BufferEncoding, callback: StringCallback): void;
    (path: PathOrFileDescriptor, options: (ObjectEncodingOptions & {
        flag?: string;
    } & Abortable) | BufferEncoding | null | undefined, callback: StringOrBufferCallback): void;
    (path: PathOrFileDescriptor, callback: BufferCallback): void;
};
export type ReadFileSync = {
    (path: PathOrFileDescriptor, options: {
        encoding: null | undefined;
        flag?: string;
    } | null): Buffer;
    (path: PathOrFileDescriptor, options: {
        encoding: BufferEncoding;
        flag?: string;
    } | BufferEncoding): string;
    (path: PathOrFileDescriptor, options: (ObjectEncodingOptions & {
        flag?: string;
    }) | BufferEncoding | null): string | Buffer;
};
export type EncodingOption = ObjectEncodingOptions | BufferEncoding | undefined | null;
export type BufferEncodingOption = 'buffer' | {
    encoding: 'buffer';
};
export type StatOptions = {
    bigint?: boolean;
};
export type StatSyncOptions = {
    bigint?: boolean;
    throwIfNoEntry?: boolean;
};
export type Readlink = {
    (path: PathLike, options: EncodingOption, callback: StringCallback): void;
    (path: PathLike, options: BufferEncodingOption, callback: BufferCallback): void;
    (path: PathLike, options: EncodingOption, callback: StringOrBufferCallback): void;
    (path: PathLike, callback: StringCallback): void;
};
export type ReadlinkSync = {
    (path: PathLike, options: EncodingOption): string;
    (path: PathLike, options: BufferEncodingOption): Buffer;
    (path: PathLike, options: EncodingOption): string | Buffer;
};
export type Readdir = {
    (path: PathLike, options: {
        encoding: BufferEncoding | null;
        withFileTypes?: false;
        recursive?: boolean;
    } | BufferEncoding | null | undefined, callback: ReaddirStringCallback): void;
    (path: PathLike, options: {
        encoding: 'buffer';
        withFileTypes?: false;
        recursive?: boolean;
    } | 'buffer', callback: ReaddirBufferCallback): void;
    (path: PathLike, callback: ReaddirStringCallback): void;
    (path: PathLike, options: (ObjectEncodingOptions & {
        withFileTypes: true;
        recursive?: boolean;
    }) | BufferEncoding | null | undefined, callback: ReaddirStringOrBufferCallback): void;
    (path: PathLike, options: ObjectEncodingOptions & {
        withFileTypes: true;
        recursive?: boolean;
    }, callback: ReaddirDirentCallback): void;
};
export type ReaddirSync = {
    (path: PathLike, options: {
        encoding: BufferEncoding | null;
        withFileTypes?: false;
        recursive?: boolean;
    } | BufferEncoding | null): string[];
    (path: PathLike, options: {
        encoding: 'buffer';
        withFileTypes?: false;
        recursive?: boolean;
    } | 'buffer'): Buffer[];
    (path: PathLike, options: (ObjectEncodingOptions & {
        withFileTypes?: false;
        recursive?: boolean;
    }) | BufferEncoding | null): string[] | Buffer[];
    (path: PathLike, options: ObjectEncodingOptions & {
        withFileTypes: true;
        recursive?: boolean;
    }): IDirent[];
};
export type Stat = {
    (path: PathLike, callback: StatsCallback): void;
    (path: PathLike, options: (StatOptions & {
        bigint?: false;
    }) | undefined, callback: StatsCallback): void;
    (path: PathLike, options: StatOptions & {
        bigint: true;
    }, callback: BigIntStatsCallback): void;
    (path: PathLike, options: StatOptions | undefined, callback: StatsOrBigIntStatsCallback): void;
};
export type StatSync = {
    (path: PathLike, options?: undefined): IStats;
    (path: PathLike, options?: StatSyncOptions & {
        bigint?: false;
        throwIfNoEntry: false;
    }): IStats | undefined;
    (path: PathLike, options: StatSyncOptions & {
        bigint: true;
        throwIfNoEntry: false;
    }): IBigIntStats | undefined;
    (path: PathLike, options?: StatSyncOptions & {
        bigint?: false;
    }): IStats;
    (path: PathLike, options: StatSyncOptions & {
        bigint: true;
    }): IBigIntStats;
    (path: PathLike, options: StatSyncOptions & {
        bigint: boolean;
        throwIfNoEntry?: false;
    }): IStats | IBigIntStats;
    (path: PathLike, options?: StatSyncOptions): IStats | IBigIntStats | undefined;
};
export type LStat = {
    (path: PathLike, callback: StatsCallback): void;
    (path: PathLike, options: (StatOptions & {
        bigint?: false;
    }) | undefined, callback: StatsCallback): void;
    (path: PathLike, options: StatOptions & {
        bigint: true;
    }, callback: BigIntStatsCallback): void;
    (path: PathLike, options: StatOptions | undefined, callback: StatsOrBigIntStatsCallback): void;
};
export type LStatSync = {
    (path: PathLike, options?: undefined): IStats;
    (path: PathLike, options?: StatSyncOptions & {
        bigint?: false;
        throwIfNoEntry: false;
    }): IStats | undefined;
    (path: PathLike, options: StatSyncOptions & {
        bigint: true;
        throwIfNoEntry: false;
    }): IBigIntStats | undefined;
    (path: PathLike, options?: StatSyncOptions & {
        bigint?: false;
    }): IStats;
    (path: PathLike, options: StatSyncOptions & {
        bigint: true;
    }): IBigIntStats;
    (path: PathLike, options: StatSyncOptions & {
        bigint: boolean;
        throwIfNoEntry?: false;
    }): IStats | IBigIntStats;
    (path: PathLike, options?: StatSyncOptions): IStats | IBigIntStats | undefined;
};
export type RealPath = {
    (path: PathLike, options: EncodingOption, callback: StringCallback): void;
    (path: PathLike, options: BufferEncodingOption, callback: BufferCallback): void;
    (path: PathLike, options: EncodingOption, callback: StringOrBufferCallback): void;
    (path: PathLike, callback: StringCallback): void;
};
export type RealPathSync = {
    (path: PathLike, options?: EncodingOption): string;
    (path: PathLike, options: BufferEncodingOption): Buffer;
    (path: PathLike, options?: EncodingOption): string | Buffer;
};
export type ReadJson = (path: PathOrFileDescriptor, callback: ReadJsonCallback) => void;
export type ReadJsonSync = (path: PathOrFileDescriptor) => JsonObject;
export type Purge = (files?: string | string[] | Set<string>) => void;
export type InputFileSystem = {
    readFile: ReadFile;
    readFileSync?: ReadFileSync;
    readlink: Readlink;
    readlinkSync?: ReadlinkSync;
    readdir: Readdir;
    readdirSync?: ReaddirSync;
    stat: Stat;
    statSync?: StatSync;
    lstat?: LStat;
    lstatSync?: LStatSync;
    realpath?: RealPath;
    realpathSync?: RealPathSync;
    readJson?: ReadJson;
    readJsonSync?: ReadJsonSync;
    purge?: Purge;
    join?: (path1: string, path2: string) => string;
    relative?: (from: string, to: string) => string;
    dirname?: (path: string) => string;
};
export type IntermediateFileSystem = InputFileSystem & OutputFileSystem & IntermediateFileSystemExtras;
export type MakeDirectoryOptions = {
    recursive?: boolean;
    mode?: string | number;
};
export type MkdirSync = (path: PathLike, options: MakeDirectoryOptions) => undefined | string;
export type ReadAsyncOptions<TBuffer extends ArrayBufferView = Buffer> = {
    offset?: number;
    length?: number;
    position?: null | number | bigint;
    buffer?: TBuffer;
};
export type Read<TBuffer extends ArrayBufferView = Buffer> = (fd: number, options: ReadAsyncOptions<TBuffer>, callback: (err: null | NodeJS.ErrnoException, bytesRead: number, buffer: TBuffer) => void) => void;
export type WriteAsyncOptions<TBuffer extends ArrayBufferView = Buffer> = {
    offset?: number;
    length?: number;
    position?: null | number | bigint;
    buffer?: TBuffer;
};
export type Write<TBuffer extends ArrayBufferView = Buffer> = (fd: number, content: Buffer, options: WriteAsyncOptions<TBuffer>, callback: (err: null | NodeJS.ErrnoException, bytesWrite: number, buffer: TBuffer) => void) => void;
export type Open = (file: PathLike, flags: undefined | string | number, callback: (arg0: null | NodeJS.ErrnoException, arg1?: number) => void) => void;
export type IntermediateFileSystemExtras = {
    rename: (arg0: PathLike, arg1: PathLike, arg2: (arg0: null | NodeJS.ErrnoException) => void) => void;
    mkdirSync: MkdirSync;
    write: Write;
    open: Open;
    read: Read;
    close: (arg0: number, arg1: (arg0: null | NodeJS.ErrnoException) => void) => void;
};
export declare function rmrf(fs: OutputFileSystem, p: string, callback: (err?: Error | null) => void): void;
export declare const mkdirp: (fs: OutputFileSystem, p: string, callback: (error?: Error) => void) => void;
export interface FileSystemInfoEntry {
    safeTime: number;
    timestamp?: number;
}
export interface WatchFileSystem {
    watch(files: Iterable<string> & {
        added?: Iterable<String>;
        removed?: Iterable<String>;
    }, directories: Iterable<string> & {
        added?: Iterable<String>;
        removed?: Iterable<String>;
    }, missing: Iterable<string> & {
        added?: Iterable<String>;
        removed?: Iterable<String>;
    }, startTime: number, options: WatchOptions, callback: (error: Error | null, fileTimeInfoEntries: Map<string, FileSystemInfoEntry | 'ignore'>, contextTimeInfoEntries: Map<string, FileSystemInfoEntry | 'ignore'>, changedFiles: Set<string>, removedFiles: Set<string>) => void, callbackUndelayed: (fileName: string, changeTime: number) => void): Watcher;
    on?(event: 'change', listener: (filename: string, mtime: number) => void): this;
    on?(event: 'remove', listener: (filename: string) => void): this;
    on?(event: 'aggregated', listener: (changes: Set<string>, removals: Set<string>) => void): this;
    once?(event: 'change', listener: (filename: string, mtime: number) => void): this;
    once?(event: 'remove', listener: (filename: string) => void): this;
    once?(event: 'aggregated', listener: (changes: Set<string>, removals: Set<string>) => void): this;
    emit?(event: 'change', filename: string, mtime: number): boolean;
    emit?(event: 'remove', filename: string): boolean;
    emit?(event: 'aggregated', changes: Set<string>, removals: Set<string>): boolean;
}
export {};
