/**
 * The main txiki.js APIs are exposed as a single `tjs` global object.
 *
 * ```js
 * // Read a file
 * const data = await tjs.readFile('hello.txt');
 * console.log(new TextDecoder().decode(data));
 *
 * // Start an HTTP server
 * const server = tjs.serve({
 *     fetch: () => new Response('Hello!'),
 *     port: 3000,
 * });
 * ```
 *
 * @module global
 */

declare global {
    /**
    * The main global where txiki.js APIs are exposed.
    */
    namespace tjs {
        /**
        * Array with the arguments passed to the binary.
        *
        * @category System
        */
        const args: readonly string[];

        /**
        * @category Process
        */
        type Signal = 'SIGHUP' | 'SIGINT' | 'SIGQUIT' | 'SIGILL' | 'SIGTRAP'
        | 'SIGABRT' | 'SIGBUS' | 'SIGFPE' | 'SIGKILL' | 'SIGUSR1' | 'SIGSEGV'
        | 'SIGUSR2' | 'SIGPIPE' | 'SIGALRM' | 'SIGTERM' | 'SIGSTKFLT'
        | 'SIGCHLD' | 'SIGCONT' | 'SIGSTOP' | 'SIGTSTP' | 'SIGTTIN' | 'SIGTTOU'
        | 'SIGURG' | 'SIGXCPU' | 'SIGXFSZ' | 'SIGVTALRM' | 'SIGPROF' | 'SIGWINCH'
        | 'SIGPOLL' | 'SIGPWR' | 'SIGSYS';

        /**
        * Signal listener function.
        *
        * @category Process
        */
        type SignalListener = () => void;

        /**
        * Registers a listener for the given signal.
        *
        * ```js
        * tjs.addSignalListener('SIGINT', handleSigint);
        * ```
        *
        * @category Process
        * @param sig Which signal to register a listener for.
        * @param listener Listener function.
        */
        function addSignalListener(sig: Signal, listener: SignalListener): void;

        /**
        * Un-registers a listener for the given signal.
        *
        * ```js
        * tjs.removeSignalListener('SIGINT', handleSigint);
        * ```
        *
        * @category Process
        * @param sig Which signal to un-register a listener for.
        * @param listener Listener function.
        */
        function removeSignalListener(sig: Signal, listener: SignalListener): void;

        /**
        * Send a signal to a process.
        *
        * @category Process
        * @param pid The pid of the process to send a signal to.
        * @param sig The name of the signal to send. Defaults to "SIGTERM".
        */
        function kill(pid: number, sig?: Signal): void;

        /**
        * @category Engine
        */
        type CompiledCode = unknown;

        /**
        * @namespace
        * @category Engine
        */
        const engine : {
            /**
             * Compiles the provided code into bytecode ready to be evaluated or serialized.
             *
             * @param code The code to be compiled.
             * @returns The compiled code.
             */
            compile: (code: Uint8Array) => CompiledCode;

            /**
             * Serializes the compiled code into something that can be easily written to a file.
             *
             * @param compiledCode The compiled code that needs to be serialized.
             * @returns Serialized bytecode.
             */
            serialize: (compiledCode: CompiledCode) => Uint8Array;

            /**
             * Deserializes the given bytecode.
             *
             * @param bytes The serialized bytecode.
             * @returns The de-serialized code.
             */
            deserialize: (bytes: Uint8Array) => CompiledCode;

            /**
             * Executes the given compiled code.
             *
             * @param code Pre-compiled code that needs to be executed.
             * @returns A `Promise` resolving to the value returned by the code, if any.
             */
            evalBytecode: (code: CompiledCode) => Promise<unknown>;

            /**
            * Management for the garbage collection.
            */
            readonly gc: {
                /**
                 * Force garbage collection now.
                 */
                run: () => void;

                /**
                 * Enables / disables automatic garbage collection.
                 */
                enabled: boolean;

                /**
                 * Sets / gets the threshold (in bytes) for automatic garbage collection.
                 */
                threshold: number;
            }

            /**
            * Versions of all included libraries and txiki.js itself.
            */
            readonly versions: {
                readonly quickjs: string;
                readonly tjs: string;
                readonly uv: string;
                readonly lws: string;
                readonly wamr: string;
                readonly sqlite3: string;
                readonly mimalloc?: number;
            };
        }

        /**
        * The txiki.js version.
        *
        * @category System
        */
        const version: string;

        /**
        * Full path to the txiki.js running executable.
        *
        * @category System
        */
        const exePath: string;

        /**
        * Object containing environment variables.
        * Setting and deleting properties on this object causes
        * environment variables to be set / deleted.
        *
        * @category System
        */
        type Environment = { [index: string]: string };

        /**
        * System environment variables.
        *
        * @category System
        */
        const env: Environment;

        /**
        * Current system host name.
        *
        * @category System
        */
        const hostName: string;

        /**
        * Exit the current running program.
        *
        * @category Process
        * @param code Program exit code.
        */
        function exit(code: number): void;

        /**
        * Changes the current working directory.
        *
        * @category System
        */
        function chdir(dir: string): void;

        /**
        * Current working directory.
        *
        * @category System
        */
        const cwd: string;

        /**
        * Result type for {@link lookup}.
        *
        * @category Networking
        */
        interface Addr {
            family: number;
            ip: string;
        }

        /**
        * @category Networking
        */
        interface LookupOptions {
            /**
             * Resolve only the given family results.
             */
            family?: number;

            /**
             * If set to `true` returns all the results, it just returns the first one otherwise (default).
             */
            all?: boolean;
        }

        /**
        * Basic DNS resolution using [getaddrinfo(3)](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html).
        *
        * @category Networking
        * @param host Hostname to be looked up.
        * @param options Criteria for selecting the results.
        */
        function lookup(host: string, options?: LookupOptions): Promise<Addr|Addr[]>;

        /**
        * Error type. It mostly encapsulates the libuv errors.
        *
        * @category Utilities
        */
        class Error {

            constructor(errno: number);

            /**
            * The system error code as a string. For example `EPERM`.
            */
            code: string;

            /**
            * The error string representation in the form `code: description`.
            */
            message: string;
        }

        /**
        * Returns the canonicalized absolute pathname.
        *
        * @category Filesystem
        * @param path Path to convert.
        */
        function realPath(path: string): Promise<string>;

        /**
        * Renames the given path.
        *
        * @category Filesystem
        * @param path Current path.
        * @param newPath New desired path name.
        */
        function rename(path: string, newPath: string): Promise<void>;

        /**
        * Create a unique temporary directory. The given template must end in XXXXXX, and the Xs will
        * be replaced to provide a unique directory name.
        *
        * ```js
        * const tmpDir = await tjs.makeTempDir('tmpDirXXXXXX');
        * ```
        *
        * @category Filesystem
        * @param template Template for the directory.
        */
        function makeTempDir(template: string): Promise<string>;

        /**
        * Create a unique temporary file. The given template must end in XXXXXX, and the Xs will
        * be replaced to provide a unique file name. The returned object is an open file handle.
        *
        * @category Filesystem
        * @param template Template for the file name.
        */
        function makeTempFile(template: string): Promise<FileHandle>;

        /**
        * @category Filesystem
        */
        interface FileHandle extends AsyncDisposable {
            /**
            * Reads data into the given buffer at the given file offset. Returns
            * the amount of read data or null for EOF.
            *
            * @param buffer Buffer to read data into.
            * @param offset Offset in the file to read from.
            */
            read(buffer: Uint8Array, offset?: number): Promise<number|null>;

            /**
            * Writes data from the given buffer at the given file offset. Returns
            * the amount of data written.
            *
            * @param buffer Buffer to write.
            * @param offset Offset in the file to write to.
            */
            write(buffer: Uint8Array, offset?: number): Promise<number>;

            /**
            * Closes the file. Idempotent: closing an already-closed handle
            * resolves successfully.
            *
            * Aliased as `Symbol.asyncDispose`, so
            * `await using f = await tjs.open(...)` closes the handle at scope
            * exit.
            */
            close(): Promise<void>;

            /**
            * Get the file status information.
            * See [stat(2)](https://man7.org/linux/man-pages/man2/lstat.2.html)
            */
            stat(): Promise<StatResult>;

            /**
            * Truncates the file to the given length.
            *
            * @param offset Length to truncate the file to.
            */
            truncate(offset?: number): Promise<void>;

            /**
            * See [fdatasync(2)](https://man7.org/linux/man-pages/man2/fdatasync.2.html)
            */
            datasync(): Promise<void>;

            /**
            * See [fsync(2)](https://man7.org/linux/man-pages/man2/fdatasync.2.html)
            */
            sync(): Promise<void>;

            /**
            * Change permissions of the file.
            * See [fchmod(2)](https://man7.org/linux/man-pages/man2/fchmod.2.html)
            *
            * @param mode The file mode consisting of permission, suid, sgid, and sticky bits.
            */
            chmod(mode: number): Promise<void>;

            /**
             * Change the access and modification time of the file.
             * See [futimes(2)](https://man7.org/linux/man-pages/man2/futimes.2.html)
             *
             * @param atime The new file access time.
             * @param mtime The new file modification time.
             */
            utime(atime: Date, mtime: Date): Promise<void>;

            /**
            * The file path.
            */
            path: string;

            readable: ReadableStream<Uint8Array>;
            writable: WritableStream<Uint8Array>;
        }

        /**
        * @category Filesystem
        */
        interface StatResult {
            dev: number;
            mode: number;
            nlink: number;
            uid: number;
            gid: number;
            rdev: number;
            ino: number;
            size: number;
            blksize: number;
            blocks: number;
            atim: Date;
            mtim: Date;
            ctim: Date;
            birthtim: Date;
            isBlockDevice: boolean;
            isCharacterDevice: boolean;
            isDirectory: boolean;
            isFIFO: boolean;
            isFile: boolean;
            isSocket: boolean;
            isSymbolicLink: boolean;
        }

        /**
        * Gets file status information.
        * See [stat(2)](https://man7.org/linux/man-pages/man2/stat.2.html)
        *
        * @category Filesystem
        * @param path Path to the file.
        */
        function stat(path: string): Promise<StatResult>;

        /**
        * Gets file status information. If the path is a link it returns information
        * about the link itself.
        * See [stat(2)](https://man7.org/linux/man-pages/man2/stat.2.html)
        *
        * @category Filesystem
        * @param path Path to the file.
        */
        function lstat(path: string): Promise<StatResult>;

        /**
        * @category Filesystem
        */
        interface StatFsResult {
            type: number;
            bsize: number;
            blocks: number;
            bfree: number;
            bavail: number;
            files: number;
            ffree: number;
        }

        /**
        * Get file-system statistics.
        * See [statfs(2)](https://man7.org/linux/man-pages/man2/statfs.2.html)
        *
        * @category Filesystem
        * @param path Path to the mount point.
        */
        function statFs(path: string): Promise<StatFsResult>;

        /**
        * Change permissions of a file.
        * See [chmod(2)](https://man7.org/linux/man-pages/man2/chmod.2.html)
        *
        * @category Filesystem
        * @param path Path to the file.
        * @param mode The file mode consisting of permission, suid, sgid, and sticky bits.
        */
        function chmod(path: string, mode: number): Promise<void>;

        /**
        * Change the ownership of a file.
        * See [chown(2)](https://man7.org/linux/man-pages/man2/chown.2.html)
        *
        * @category Filesystem
        * @param path Path to the file.
        * @param owner The uid to change the file's owner to.
        * @param group The gid to change the file's group to.
        */
        function chown(path: string, owner: number, group: number): Promise<void>;

        /**
        * Change the ownership of a file. If the path is a link it changes
        * the ownership of the link itself.
        * See [lchown(2)](https://man7.org/linux/man-pages/man2/lchown.2.html)
        *
        * @category Filesystem
        * @param path Path to the file.
        * @param owner The uid to change the file's owner to.
        * @param group The gid to change the file's group to.
        */
        function lchown(path: string, owner: number, group: number): Promise<void>;

        /**
         * Change the access and modification time of a file.
         * See [futimes(2)](https://man7.org/linux/man-pages/man2/futimes.2.html)
         *
         * @category Filesystem
         * @param path Path to the file.
         * @param atime The new file access time.
         * @param mtime The new file modification time.
         */
        function utime(path: string, atime: Date, mtime: Date): Promise<void>;

        /**
         * Change the access and modification time of a file. If the path is a link it changes
        * the ownership of the link itself.
         * See [futimes(2)](https://man7.org/linux/man-pages/man2/futimes.2.html)
         *
         * @category Filesystem
         * @param path Path to the file.
         * @param atime The new file access time.
         * @param mtime The new file modification time.
         */
        function lutime(path: string, atime: Date, mtime: Date): Promise<void>;

        /**
        * Opens the file at the given path. Opening flags:
        *
        *   - r: open for reading
        *   - w: open for writing, truncating the file if it exists
        *   - x: open with exclusive creation, will fail if the file exists
        *   - a: open for writing, appending at the end if the file exists
        *   - +: open for updating (reading and writing)
        *
        * ```js
        * const f = await tjs.open('file.txt', 'r');
        * ```
        *
        * @category Filesystem
        * @param path The path to the file to be opened.
        * @param flags Flags with which to open the file.
        * @param mode File mode bits applied if the file is created. Defaults to `0o666`.
        */
        function open(path: string, flags: string, mode?: number): Promise<FileHandle>;

        /**
        * @category Filesystem
        */
        interface MakeDirOptions {
            /* The file mode for the new directory. Defaults to `0o777`. */
            mode?: number;
            /* Whether the directories will be created recursively or not. Default to `false`. */
            recursive?: boolean;
        }

        /**
        * Create a directory at the given path.
        *
        * @category Filesystem
        * @param path The path to of the directory to be created.
        * @param options Options for making the directory.
        */
        function makeDir(path: string, options?: MakeDirOptions): Promise<void>;

        /**
        * Copies the source file into the target.
        *
        * @category Filesystem
        * @param path Source path.
        * @param newPath Target path.
        */
        function copyFile(path: string, newPath: string): Promise<void>;

        /**
        * @category Filesystem
        */
        interface DirEnt {
            name: string;
            isBlockDevice: boolean;
            isCharacterDevice: boolean;
            isDirectory: boolean;
            isFIFO: boolean;
            isFile: boolean;
            isSocket: boolean;
            isSymbolicLink: boolean;
        }

        /**
        * Directory entries can be obtained through asynchronous iteration:
        *
        * ```js
        * const dirIter = await tjs.readDir('.');
        * for await (const item of dirIter) {
        *     console.log(item.name);
        * }
        * ```
        *
        * @category Filesystem
        */
        interface DirHandle extends AsyncIterableIterator<DirEnt>, AsyncDisposable {

            /**
            * Closes the directory handle. Idempotent: closing an already-closed
            * handle resolves successfully.
            *
            * Aliased as `Symbol.asyncDispose`, so
            * `await using d = await tjs.readDir(...)` closes the handle at
            * scope exit.
            */
            close(): Promise<void>;

            /**
            * Path of the directory.
            */
            path: string;
        }

        /**
        * Open the directory at the given path in order to navigate its content.
        * See [readdir(3)](https://man7.org/linux/man-pages/man3/readdir.3.html)
        *
        * @category Filesystem
        * @param path Path to the directory.
        */
        function readDir(path: string): Promise<DirHandle>;

        /**
        * Reads the value of a symbolic link.
        * See [readlink(2)](https://man7.org/linux/man-pages/man2/readlink.2.html)
        *
        * @category Filesystem
        * @param path File path.
        */
        function readLink(path: string): Promise<string>;

        /**
        * Reads the entire contents of a file.
        *
        * @category Filesystem
        * @param path File path.
        */
        function readFile(path: string): Promise<Uint8Array>;

        /**
        * @category Filesystem
        */
        interface WriteFileOptions {
            /** File mode (permissions) to set when creating the file. Defaults to `0o644`. */
            mode?: number;
        }

        /**
        * Writes data to a file, replacing the file if it already exists.
        *
        * @category Filesystem
        * @param path File path.
        * @param data Data to write. Strings are encoded as UTF-8.
        * @param options Optional settings.
        */
        function writeFile(path: string, data: string | Uint8Array, options?: WriteFileOptions): Promise<void>;

        /**
        * @category Filesystem
        */
        interface RemoveOptions {
            /* Amount of times to retry the operation in case it fails. Defaults to 0. */
            maxRetries?: number;
            /* Time (in milliseconds) to wait between retries. Defaults to 100. */
            retryDelay?: number;
        }

        /**
         * Recursively delete files and directories at the given path.
         * Equivalent to POSIX "rm -rf".
         *
         * @category Filesystem
         * @param path Path to be removed.
         */
        function remove(path: string, options?: RemoveOptions): Promise<void>;

        /**
         * Create a hard file link.
         * See [link(2)](https://man7.org/linux/man-pages/man2/link.2.html)
         *
         * @category Filesystem
         * @param path Source file path.
         * @param newPath Target file path.
         */
        function link(path: string, newPath: string): Promise<void>;

        /**
        * @category Filesystem
        */
        interface SymlinkOptions {
            /* TYpe of symbolic link to create. Applies to Windows only. */
            type?: 'file' | 'directory' | 'junction';
        }

        /**
         * Create a symbolic link.
         * See [symlink(2)](https://man7.org/linux/man-pages/man2/symlink.2.html)
         *
         * @category Filesystem
         * @param path Source file path.
         * @param newPath Target file path.
         * @param options Options for specifying the type (Windows only).
         */
        function symlink(path: string, newPath: string, options?: SymlinkOptions): Promise<void>;

        /**
        * File watch event handler function.
        *
        * @category Filesystem
        */
        type WatchEventHandler = (filename: string, event: 'change' | 'rename') => void;

        /**
        * @category Filesystem
        */
        interface FileWatcher extends Disposable {
            /**
            * Closes the watcher.
            *
            * Aliased as `Symbol.dispose`, so `using w = tjs.watch(...)` closes
            * the watcher at scope exit.
            */
            close(): void;

            /**
            * Path which is currently being watched.
            */
            path: string;
        }

        /**
        * Watches the given path for changes.
        *
        * @category Filesystem
        * @param path The path to watch.
        * @param handler Function to be called when an event occurs.
        */
        function watch(path: string, handler: WatchEventHandler): FileWatcher;

        /**
        * The current user's home directory.
        *
        * @category System
        */
        const homeDir: string;

        /**
        * The path to the current temporary directory.
        *
        * @category System
        */
        const tmpDir: string;

        /**
        * @category System
        */
        type StdioType = 'tty' | 'pipe' | 'file';

        /**
        * @category System
        */
        interface StdioInputStream extends ReadableStream<Uint8Array> {
            isTerminal: boolean;
            type: StdioType;
            setRawMode(enable: boolean): void;
        }

        /**
        * @category System
        */
        interface StdioOutputStream extends WritableStream<Uint8Array> {
            isTerminal: boolean;
            type: StdioType;
            height: number;
            width: number;
        }

        /**
        * Object providing access to standard input.
        *
        * @category System
        */
        const stdin: StdioInputStream;

        /**
        * Object providing access to standard output.
        *
        * @category System
        */
        const stdout: StdioOutputStream;

        /**
        * Object providing access to standard error.
        *
        * @category System
        */
        const stderr: StdioOutputStream;

        /**
        * @category Process
        */
        interface ProcessStatus {
            exit_status: number;
            term_signal: Signal|null;
        }

        /**
        * @category Process
        */
        interface ProcessReadableStream extends ReadableStream<Uint8Array> {
            arrayBuffer(): Promise<ArrayBuffer>;
            bytes(): Promise<Uint8Array>;
            text(): Promise<string>;
        }

        /**
        * @category Process
        */
        interface Process extends AsyncDisposable {
            kill(signal?: Signal): void;
            /**
            * Resolves once the subprocess has exited.
            *
            * The interface is also async-disposable: at the end of an
            * `await using p = tjs.spawn(...)` scope, `SIGTERM` is sent (best
            * effort) and {@link wait} is awaited.
            */
            wait(): Promise<ProcessStatus>;
            pid: number;
            stdin: WritableStream<Uint8Array> | null;
            stdout: ProcessReadableStream | null;
            stderr: ProcessReadableStream | null;
        }

        /**
        * @category Process
        */
        type ProcessStdio = 'inherit' | 'pipe' | 'ignore';

        /**
        * @category Process
        */
        interface ProcessOptions {
            env?: Environment;
            cwd?: string;
            uid?: number;
            gid?: number;
            stdin?: ProcessStdio;
            stdout?: ProcessStdio;
            stderr?: ProcessStdio;
        }

        /**
        * Spawn a child process.
        *
        * @category Process
        * @param args Command line arguments for the new process.
        * @param options Extra options.
        */
        function spawn(args: string | string[], options?: ProcessOptions): Process;

        /**
        * Replace the current process image with a new process image.
        * This function does not return if successful.
        *
        * See [execvp(3)](https://man7.org/linux/man-pages/man3/execvp.3.html)
        *
        * @category Process
        * @param args Command argument list for the new process image.
        */
        function exec(args: string | string[]): void;

        /**
        * @category Networking
        */
        type Transport = 'tcp' | 'udp' | 'pipe';

        /**
        * @category Networking
        */
        interface ConnectOptions {
            noDelay?: boolean;
            keepAliveDelay?: number;
            dnsQueryType?: 'ipv4' | 'ipv6';
            bindAddr?: { ip: string; port: number };
            ipv6Only?: boolean;
        }

        /**
        * @category Networking
        */
        interface TLSConnectOptions extends ConnectOptions {
            /** Server Name Indication hostname. Defaults to the host argument. */
            sni?: string;
            /** ALPN protocol list to negotiate. */
            alpn?: string[];
            /** PEM-encoded CA certificate(s) to trust. Defaults to the embedded Mozilla CA bundle. */
            ca?: string;
            /** PEM-encoded client certificate for mutual TLS. */
            cert?: string;
            /** PEM-encoded client private key for mutual TLS. */
            key?: string;
            /** Whether to verify the peer's certificate. Defaults to true for clients, false for servers. */
            verifyPeer?: boolean;
        }

        /**
        * Creates a connection to the target host + port over the selected transport.
        * Returns the appropriate Direct Sockets object.
        *
        * @category Networking
        * @param transport Type of transport for the connection.
        * @param host Hostname for the connection. Basic lookup using {@link lookup} will be performed.
        * @param port Destination port (where applicable).
        * @param options Extra connection options.
        */
        function connect(transport: 'tcp', host: string, port: number, options?: ConnectOptions): Promise<TCPSocket>;
        function connect(transport: 'tls', host: string, port: number, options?: TLSConnectOptions): Promise<TLSSocket>;
        function connect(transport: 'pipe', host: string): Promise<PipeSocket>;
        function connect(transport: 'udp', host: string, port: number, options?: ConnectOptions): Promise<UDPSocket>;

        /**
        * @category Networking
        */
        interface ListenOptions {
            backlog?: number;
            ipv6Only?: boolean;
            reuseAddr?: boolean;
        }

        /**
        * @category Networking
        */
        interface TLSListenOptions extends ListenOptions {
            /** PEM-encoded server certificate. Required. */
            cert: string;
            /** PEM-encoded server private key. Required. */
            key: string;
            /** PEM-encoded CA certificate(s) for client certificate verification (mutual TLS). */
            ca?: string;
            /** Whether to verify the peer's certificate. Defaults to true for clients, false for servers. */
            verifyPeer?: boolean;
            /** ALPN protocol list to offer. */
            alpn?: string[];
        }

        /**
        * Listens for incoming connections on the selected transport.
        * Returns the appropriate Direct Sockets object.
        *
        * @category Networking
        * @param transport Transport type.
        * @param host Hostname for listening on.
        * @param port Listening port (where applicable).
        * @param options Extra listen options.
        */
        function listen(transport: 'tcp', host: string, port?: number, options?: ListenOptions): Promise<TCPServerSocket>;
        function listen(transport: 'tls', host: string, port?: number, options?: TLSListenOptions): Promise<TLSServerSocket>;
        function listen(transport: 'pipe', host: string, options?: ListenOptions): Promise<PipeServerSocket>;
        function listen(transport: 'udp', host?: string, port?: number, options?: ListenOptions): Promise<UDPSocket>;

        /**
        * Current process ID.
        *
        * @category Process
        */
        const pid: number;

        /**
        * Parent process ID.
        *
        * @category Process
        */
        const ppid: number;

        namespace system{
            /**
            * @category System
            */
            interface UserInfo {
                userName: string;
                userId: number;
                gorupId: number;
                shell: string | null;
                homeDir: string | null;
            }

            /**
            * @category System
            */
            interface CpuTimes {
                user: number;
                nice: number;
                sys: number;
                idle: number;
                irq: number;
            }

            /**
            * @category System
            */
            interface CpuInfo {
                model: string;
                speed: number;
                times: CpuTimes;
            }

            /**
            * @category System
            */
            interface NetworkInterface {
                name: string;
                address: string;
                mac: string;
                scopeId?: number;
                netmask: string;
                internal: boolean;
            }
        }

        /**
        * @namespace
        * System information.
        *
        * @category System
        */
        const system: {
            /**
            * Information about the CPUs in the system.
            */
            readonly cpus: system.CpuInfo[];

            /**
            * System load average.
            * See [getloadavg(3)](https://man7.org/linux/man-pages/man3/getloadavg.3.html)
            */
            readonly loadAvg: [ number, number, number ];

            /**
            * Information about the network interfaces in the system.
            */
            readonly networkInterfaces: system.NetworkInterface[];

            /**
            * System uptime.
            */
            readonly uptime: number;

            /**
            * Current user information from the password database.
            */
            readonly userInfo: system.UserInfo;
        }

        /**
        * @category Utilities
        */
        interface ConsolePrinterOptions {
            /** output message to stderr instead of stdout */
            isWarn?: boolean;

            /** how much to indent the message (level of groups) */
            indent: number;
        }

        /**
        * Creates a custom `console` object.
        *
        * @category Utilities
        */
        function createConsole(opts: {
            /** function to print messages to somewhere, see https://console.spec.whatwg.org/#printer */
            printer: (logLevel: string, args: unknown[], options: ConsolePrinterOptions) => void,
            /** function to handle normal log messages, see https://console.spec.whatwg.org/#logger */
            logger?: (logLevel: string, args: unknown[], options: ConsolePrinterOptions) => void,
            /** function to clear the console, e.g. send the ASCII ctrl character */
            clearConsole?: () => void,
            /** format given values, either by using a format string as first param or otherwise display values in a well readable format, see https://console.spec.whatwg.org/#formatter */
            formatter?: (args: unknown[]) => string,
            /** format js values to be well readable */
            inspect?: (args: unknown[]) => string,
        }): typeof console;

        // HTTP Server API

        /**
        * Handler function for incoming HTTP requests.
        *
        * @category HTTP Server
        */
        type FetchHandler = (request: Request, context: RequestContext) => Response | Promise<Response> | void;

        /**
        * Context object passed to the fetch handler alongside the request.
        *
        * @category HTTP Server
        */
        interface RequestContext {
            /** The server instance, useful for WebSocket upgrades. */
            server: Server;
            /** The remote client IP address. */
            remoteAddress: string;
        }

        /**
        * TLS options for enabling HTTPS on the server.
        *
        * @category HTTP Server
        */
        interface TlsOptions {
            /** TLS certificate chain in PEM format. */
            cert: string;
            /** TLS private key in PEM format. */
            key: string;
            /** CA certificate(s) in PEM format, for client certificate verification. */
            ca?: string;
            /** Passphrase for an encrypted private key. */
            passphrase?: string;
            /** If `true`, the server requires a valid client certificate. Implies use of {@link ca}. */
            requestCert?: boolean;
        }

        /**
        * Options for configuring the HTTP server.
        *
        * @category HTTP Server
        */
        interface ServeOptions {
            /** Handler function called for each incoming HTTP request. */
            fetch: FetchHandler;
            /** Port to listen on. Defaults to `0` (random available port). */
            port?: number;
            /** IP address to bind to. Defaults to `'0.0.0.0'`. */
            listenIp?: string;
            /** Optional WebSocket event handlers for upgraded connections. */
            websocket?: WebSocketHandlers;
            /** TLS options for enabling HTTPS. When provided, the server listens for HTTPS connections. */
            tls?: TlsOptions;
        }

        /**
        * Event handlers for WebSocket connections upgraded via {@link Server.upgrade}.
        *
        * @category HTTP Server
        */
        interface WebSocketHandlers {
            /** Called when a WebSocket connection is established. */
            open?(ws: ServerWebSocket): void;
            /** Called when a message is received. */
            message?(ws: ServerWebSocket, data: string): void;
            /** Called when the WebSocket connection is closed. */
            close?(ws: ServerWebSocket, code: number, reason: string): void;
            /** Called when an error occurs on the WebSocket connection. */
            error?(ws: ServerWebSocket, error: Error): void;
        }

        /**
        * A WebSocket connection created by upgrading an HTTP request via {@link Server.upgrade}.
        *
        * @category HTTP Server
        */
        interface ServerWebSocket {
            /** Arbitrary data associated with this connection, set via {@link UpgradeOptions.data}. */
            readonly data: unknown;
            /** Send a text message. */
            sendText(data: string): void;
            /** Send a binary message. */
            sendBinary(data: Uint8Array): void;
            /** Close the connection. */
            close(code?: number, reason?: string): void;
        }

        /**
        * Options for upgrading an HTTP request to a WebSocket connection.
        *
        * @category HTTP Server
        */
        interface UpgradeOptions {
            /** Arbitrary data to associate with the WebSocket connection, accessible as `ws.data`. */
            data?: unknown;
        }

        /**
        * An HTTP server instance.
        *
        * @category HTTP Server
        */
        interface Server extends AsyncDisposable {
            /** The port the server is listening on. */
            readonly port: number;
            /**
            * Stop accepting new connections and close the server. The returned
            * promise resolves once the listening socket has been fully torn
            * down. Idempotent; subsequent calls return the same promise.
            *
            * Aliased as `Symbol.asyncDispose`, so
            * `await using server = tjs.serve(...)` closes it automatically at
            * scope exit.
            */
            close(): Promise<void>;
            /**
            * Upgrade an HTTP request to a WebSocket connection. Must be called
            * synchronously inside the fetch handler.
            *
            * @param request The incoming request with an `Upgrade: websocket` header.
            * @param options Options for the WebSocket connection.
            * @returns `true` if the upgrade was successful, `false` otherwise.
            */
            upgrade(request: Request, options?: UpgradeOptions): boolean;
        }

        /**
        * Start an HTTP server.
        *
        * ```js
        * const server = tjs.serve({
        *     fetch(request) {
        *         return new Response('Hello World!');
        *     },
        *     port: 8080,
        * });
        * ```
        *
        * A shorthand is also available when only a fetch handler is needed:
        *
        * ```js
        * const server = tjs.serve((request) => new Response('Hello!'));
        * ```
        *
        * To enable HTTPS, provide TLS certificate and key as PEM strings:
        *
        * ```js
        * const cert = new TextDecoder().decode(await tjs.readFile('cert.pem'));
        * const key = new TextDecoder().decode(await tjs.readFile('key.pem'));
        *
        * const server = tjs.serve({
        *     fetch(request) {
        *         return new Response('Hello HTTPS!');
        *     },
        *     port: 8443,
        *     tls: { cert, key },
        * });
        * ```
        *
        * `close()` returns a promise that resolves once the server has fully
        * shut down; prefer `await server.close()` (or `await using`) when you
        * need to wait for the listening socket to be released:
        *
        * ```js
        * await using server = tjs.serve(request => new Response('ok'));
        * // ...use server...
        * // server.close() runs automatically at scope exit.
        * ```
        *
        * @category HTTP Server
        * @param options Server options or a fetch handler function.
        * @returns The server instance.
        */
        function serve(options: ServeOptions | FetchHandler): Server;

        /**
        * Mapping from a bare specifier (or a `/`-terminated prefix) to a path
        * or URL the specifier should resolve to. Paths starting with `./` or
        * `../` are resolved against the `baseDir` argument passed to
        * `tjs.setImportMap()`. Mapping a key to `null` blocks the import.
        *
        * @category Modules
        */
        interface ImportMap {
            imports?: Record<string, string | null>;
            scopes?: Record<string, Record<string, string | null>>;
        }

        /**
        * Install an [import map](https://github.com/WICG/import-maps) that
        * remaps bare specifiers (e.g. `"lodash"`) and prefixes (e.g.
        * `"lodash/"`) to file paths or URLs. Equivalent to running with
        * `--import-map`, but driven from JavaScript.
        *
        * Must be called before the affected `import` / dynamic `import()` runs
        * — modules already loaded into the runtime are not retroactively
        * remapped. Only one import map is active at a time; calling
        * `setImportMap()` again replaces the previous one.
        *
        * @example
        * ```js
        * tjs.setImportMap({
        *     imports: {
        *         'lodash': './vendor/lodash/index.js',
        *         'lodash/': './vendor/lodash/',
        *         'blocked': null,
        *     },
        *     scopes: {
        *         './legacy/': {
        *             'pkg': './vendor/pkg-v1/index.js',
        *         },
        *     },
        * }, import.meta.dirname);
        *
        * const _ = await import('lodash');
        * ```
        *
        * @category Modules
        * @param map The import map. Relative targets resolve against `baseDir`.
        * @param baseDir Directory used to resolve relative paths in `map`.
        */
        function setImportMap(map: ImportMap, baseDir: string): void;
    }

    // Direct Sockets API
    // See https://wicg.github.io/direct-sockets/

    /**
    * @category Networking
    */
    interface TCPSocketOpenInfo {
        readable: ReadableStream<Uint8Array>;
        writable: WritableStream<Uint8Array>;
        localAddress: string;
        localPort: number;
        remoteAddress: string;
        remotePort: number;
    }

    /**
    * @category Networking
    */
    interface TCPSocketOptions {
        noDelay?: boolean;
        keepAliveDelay?: number;
        dnsQueryType?: 'ipv4' | 'ipv6';
    }

    /**
    * @category Networking
    */
    class TCPSocket {
        constructor(remoteAddress: string, remotePort: number, options?: TCPSocketOptions);
        readonly opened: Promise<TCPSocketOpenInfo>;
        readonly closed: Promise<void>;
        /**
        * Initiates close. Use {@link closed} to await full teardown.
        *
        * The class is also async-disposable: at the end of an
        * `await using s = new TCPSocket(...)` scope the socket is closed and
        * {@link closed} is awaited.
        */
        close(): void;
    }
    interface TCPSocket extends AsyncDisposable {}

    /**
    * @category Networking
    */
    interface TCPServerSocketOpenInfo {
        readable: ReadableStream<TCPSocket>;
        localAddress: string;
        localPort: number;
    }

    /**
    * @category Networking
    */
    interface TCPServerSocketOptions {
        localPort?: number;
        backlog?: number;
        ipv6Only?: boolean;
    }

    /**
    * @category Networking
    */
    class TCPServerSocket {
        constructor(localAddress: string, options?: TCPServerSocketOptions);
        readonly opened: Promise<TCPServerSocketOpenInfo>;
        readonly closed: Promise<void>;
        /**
        * Initiates close. Use {@link closed} to await full teardown.
        *
        * Also async-disposable: at the end of an
        * `await using s = new TCPServerSocket(...)` scope the listener is
        * closed and {@link closed} is awaited.
        */
        close(): void;
    }
    interface TCPServerSocket extends AsyncDisposable {}

    /**
    * Information about an opened TLS socket connection.
    *
    * @category Networking
    */
    interface TLSSocketOpenInfo {
        readable: ReadableStream<Uint8Array>;
        writable: WritableStream<Uint8Array>;
        localAddress: string;
        localPort: number;
        remoteAddress: string;
        remotePort: number;
        /** The ALPN protocol negotiated during the TLS handshake, or null. */
        alpn: string | null;
    }

    /**
    * Options for creating a TLS client socket.
    *
    * @category Networking
    */
    interface TLSSocketOptions {
        /** Server Name Indication hostname. Defaults to remoteAddress. */
        sni?: string;
        /** ALPN protocol list to negotiate. */
        alpn?: string[];
        /** PEM-encoded CA certificate(s) to trust. Defaults to the embedded Mozilla CA bundle. */
        ca?: string;
        /** PEM-encoded client certificate for mutual TLS. */
        cert?: string;
        /** PEM-encoded client private key for mutual TLS. */
        key?: string;
        /** Whether to verify the peer's certificate. Defaults to true for clients, false for servers. */
        verifyPeer?: boolean;
        noDelay?: boolean;
        keepAliveDelay?: number;
        dnsQueryType?: 'ipv4' | 'ipv6';
    }

    /**
    * A TLS client socket. Wraps a TCP connection with TLS encryption.
    * All data read from the readable stream and written to the writable stream is automatically
    * encrypted/decrypted — JS only sees plaintext.
    *
    * @category Networking
    */
    class TLSSocket {
        constructor(remoteAddress: string, remotePort: number, options?: TLSSocketOptions);
        readonly opened: Promise<TLSSocketOpenInfo>;
        readonly closed: Promise<void>;
        /**
        * Initiates close. Use {@link closed} to await full teardown.
        *
        * Also async-disposable: at the end of an
        * `await using s = new TLSSocket(...)` scope the socket is closed and
        * {@link closed} is awaited.
        */
        close(): void;
    }
    interface TLSSocket extends AsyncDisposable {}

    /**
    * Information about an opened TLS server socket.
    *
    * @category Networking
    */
    interface TLSServerSocketOpenInfo {
        readable: ReadableStream<TLSSocket>;
        localAddress: string;
        localPort: number;
    }

    /**
    * Options for creating a TLS server socket.
    *
    * @category Networking
    */
    interface TLSServerSocketOptions {
        localPort?: number;
        /** PEM-encoded server certificate. Required. */
        cert: string;
        /** PEM-encoded server private key. Required. */
        key: string;
        /** PEM-encoded CA certificate(s) for client certificate verification (mutual TLS). */
        ca?: string;
        /** Whether to verify the peer's certificate. Defaults to true for clients, false for servers. */
        verifyPeer?: boolean;
        /** ALPN protocol list to offer. */
        alpn?: string[];
        backlog?: number;
        ipv6Only?: boolean;
    }

    /**
    * A TLS server socket. Listens for incoming TLS connections.
    * Accepted clients are {@link TLSSocket} instances with TLS already negotiated.
    *
    * @category Networking
    */
    class TLSServerSocket {
        constructor(localAddress: string, options: TLSServerSocketOptions);
        readonly opened: Promise<TLSServerSocketOpenInfo>;
        readonly closed: Promise<void>;
        /**
        * Initiates close. Use {@link closed} to await full teardown.
        *
        * Also async-disposable: at the end of an
        * `await using s = new TLSServerSocket(...)` scope the listener is
        * closed and {@link closed} is awaited.
        */
        close(): void;
    }
    interface TLSServerSocket extends AsyncDisposable {}

    /**
    * @category Networking
    */
    interface UDPMessage {
        data: Uint8Array;
        remoteAddress?: string;
        remotePort?: number;
    }

    /**
    * @category Networking
    */
    interface UDPSocketOpenInfo {
        readable: ReadableStream<UDPMessage>;
        writable: WritableStream<UDPMessage>;
        localAddress: string;
        localPort: number;
        remoteAddress?: string;
        remotePort?: number;
        multicastController: MulticastController;
    }

    /**
    * @category Networking
    */
    interface MulticastController {
        /**
         * Joins a multicast group.
         */
        joinGroup(ipAddress: string): Promise<void>;
        /**
         * Leaves a multicast group.
         */
        leaveGroup(ipAddress: string): Promise<void>;
        /**
         * A frozen array of currently joined multicast group addresses.
         */
        readonly joinedGroups: readonly string[];
    }

    /**
    * @category Networking
    */
    interface UDPSocketOptions {
        remoteAddress?: string;
        remotePort?: number;
        localAddress?: string;
        localPort?: number;
        dnsQueryType?: 'ipv4' | 'ipv6';
        reuseAddr?: boolean;
        ipv6Only?: boolean;
        /**
         * TTL for multicast packets. Each router hop decrements this value. Default is 1.
         */
        multicastTimeToLive?: number;
        /**
         * Whether packets sent to the multicast group are looped back to the sender. Default is true.
         */
        multicastLoopback?: boolean;
        /**
         * Permits address reuse, essential for multiple applications listening on the same multicast address/port. Default is false.
         */
        multicastAllowAddressSharing?: boolean;
    }

    /**
    * @category Networking
    */
    class UDPSocket {
        constructor(options: UDPSocketOptions);
        readonly opened: Promise<UDPSocketOpenInfo>;
        readonly closed: Promise<void>;
        /**
        * Initiates close. Use {@link closed} to await full teardown.
        *
        * Also async-disposable: at the end of an
        * `await using s = new UDPSocket(...)` scope the socket is closed and
        * {@link closed} is awaited.
        */
        close(): void;
    }
    interface UDPSocket extends AsyncDisposable {}

    /**
    * @category Networking
    */
    interface PipeSocketOpenInfo {
        readable: ReadableStream<Uint8Array>;
        writable: WritableStream<Uint8Array>;
        localAddress: string;
        remoteAddress: string;
    }

    /**
    * @category Networking
    */
    class PipeSocket {
        constructor(path: string);
        readonly opened: Promise<PipeSocketOpenInfo>;
        readonly closed: Promise<void>;
        /**
        * Initiates close. Use {@link closed} to await full teardown.
        *
        * Also async-disposable: at the end of an
        * `await using s = new PipeSocket(...)` scope the socket is closed and
        * {@link closed} is awaited.
        */
        close(): void;
    }
    interface PipeSocket extends AsyncDisposable {}

    /**
    * @category Networking
    */
    interface PipeServerSocketOpenInfo {
        readable: ReadableStream<PipeSocket>;
        localAddress: string;
    }

    /**
    * @category Networking
    */
    interface PipeServerSocketOptions {
        backlog?: number;
    }

    /**
    * @category Networking
    */
    class PipeServerSocket {
        constructor(path: string, options?: PipeServerSocketOptions);
        readonly opened: Promise<PipeServerSocketOpenInfo>;
        readonly closed: Promise<void>;
        /**
        * Initiates close. Use {@link closed} to await full teardown.
        *
        * Also async-disposable: at the end of an
        * `await using s = new PipeServerSocket(...)` scope the listener is
        * closed and {@link closed} is awaited.
        */
        close(): void;
    }
    interface PipeServerSocket extends AsyncDisposable {}

    /**
    * txiki.js adds `Symbol.dispose` to {@link Worker}, so
    * `using w = new Worker(url)` terminates the worker at scope exit.
    */
    interface Worker extends Disposable {}
}

export {};
