/**
 * Bun.js runtime APIs
 *
 * @example
 *
 * ```js
 * import {file} from 'bun';
 *
 * // Log the file to the console
 * const input = await file('/path/to/file.txt').text();
 * console.log(input);
 * ```
 *
 * This module aliases `globalThis.Bun`.
 */
declare module "bun" {
	import type { Encoding as CryptoEncoding } from "crypto";
	import type {
		CipherNameAndProtocol,
		EphemeralKeyInfo,
		PeerCertificate,
	} from "tls";
	interface Env {
		NODE_ENV?: string;
		/**
		 * Can be used to change the default timezone at runtime
		 */
		TZ?: string;
	}

	/**
	 * The environment variables of the process
	 *
	 * Defaults to `process.env` as it was when the current Bun process launched.
	 *
	 * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly.
	 */
	const env: NodeJS.ProcessEnv;
	/**
	 * The raw arguments passed to the process, including flags passed to Bun. If you want to easily read flags passed to your script, consider using `process.argv` instead.
	 */
	const argv: string[];
	const origin: string;

	/**
	 * Find the path to an executable, similar to typing which in your terminal. Reads the `PATH` environment variable unless overridden with `options.PATH`.
	 *
	 * @param {string} command The name of the executable or script
	 * @param {string} options.PATH Overrides the PATH environment variable
	 * @param {string} options.cwd When given a relative path, use this path to join it.
	 */
	function which(
		command: string,
		options?: { PATH?: string; cwd?: string },
	): string | null;

	/**
	 * Get the column count of a string as it would be displayed in a terminal.
	 * Supports ANSI escape codes, emoji, and wide characters.
	 *
	 * This is useful for:
	 * - Aligning text in a terminal
	 * - Quickly checking if a string contains ANSI escape codes
	 * - Measuring the width of a string in a terminal
	 *
	 * This API is designed to match the popular "string-width" package, so that
	 * existing code can be easily ported to Bun and vice versa.
	 *
	 * @returns The width of the string in columns
	 *
	 * ## Examples
	 * @example
	 * ```ts
	 * import { stringWidth } from "bun";
	 *
	 * console.log(stringWidth("abc")); // 3
	 * console.log(stringWidth("👩‍👩‍👧‍👦")); // 1
	 * console.log(stringWidth("\u001b[31mhello\u001b[39m")); // 5
	 * console.log(stringWidth("\u001b[31mhello\u001b[39m", { countAnsiEscapeCodes: false })); // 5
	 * console.log(stringWidth("\u001b[31mhello\u001b[39m", { countAnsiEscapeCodes: true })); // 13
	 * ```
	 *
	 */
	function stringWidth(
		/**
		 * The string to measure
		 */
		input: string,
		options?: {
			/**
			 * If `true`, count ANSI escape codes as part of the string width. If `false`, ANSI escape codes are ignored when calculating the string width.
			 *
			 * @default false
			 */
			countAnsiEscapeCodes?: boolean;
			/**
			 * When it's ambiugous and `true`, count emoji as 1 characters wide. If `false`, emoji are counted as 2 character wide.
			 *
			 * @default true
			 */
			ambiguousIsNarrow?: boolean;
		},
	): number;

	export type ShellFunction = (input: Uint8Array) => Uint8Array;

	export type ShellExpression =
		| { toString(): string }
		| Array<ShellExpression>
		| string
		| { raw: string }
		| Subprocess
		| SpawnOptions.Readable
		| SpawnOptions.Writable
		| ReadableStream;

	class ShellError extends Error implements ShellOutput {
		readonly stdout: Buffer;
		readonly stderr: Buffer;
		readonly exitCode: number;

		/**
		 * Read from stdout as a string
		 *
		 * @param encoding - The encoding to use when decoding the output
		 * @returns Stdout as a string with the given encoding
		 * @example
		 *
		 * ## Read as UTF-8 string
		 *
		 * ```ts
		 * const output = await $`echo hello`;
		 * console.log(output.text()); // "hello\n"
		 * ```
		 *
		 * ## Read as base64 string
		 *
		 * ```ts
		 * const output = await $`echo ${atob("hello")}`;
		 * console.log(output.text("base64")); // "hello\n"
		 * ```
		 *
		 */
		text(encoding?: BufferEncoding): string;

		/**
		 * Read from stdout as a JSON object
		 *
		 * @returns Stdout as a JSON object
		 * @example
		 *
		 * ```ts
		 * const output = await $`echo '{"hello": 123}'`;
		 * console.log(output.json()); // { hello: 123 }
		 * ```
		 *
		 */
		json(): any;

		/**
		 * Read from stdout as an ArrayBuffer
		 *
		 * @returns Stdout as an ArrayBuffer
		 * @example
		 *
		 * ```ts
		 * const output = await $`echo hello`;
		 * console.log(output.arrayBuffer()); // ArrayBuffer { byteLength: 6 }
		 * ```
		 */
		arrayBuffer(): ArrayBuffer;

		/**
		 * Read from stdout as a Blob
		 *
		 * @returns Stdout as a blob
		 * @example
		 * ```ts
		 * const output = await $`echo hello`;
		 * console.log(output.blob()); // Blob { size: 6, type: "" }
		 * ```
		 */
		blob(): Blob;
	}

	class ShellPromise extends Promise<ShellOutput> {
		get stdin(): WritableStream;
		/**
		 * Change the current working directory of the shell.
		 * @param newCwd - The new working directory
		 */
		cwd(newCwd: string): this;
		/**
		 * Set environment variables for the shell.
		 * @param newEnv - The new environment variables
		 *
		 * @example
		 * ```ts
		 * await $`echo $FOO`.env({ ...process.env, FOO: "LOL!" })
		 * expect(stdout.toString()).toBe("LOL!");
		 * ```
		 */
		env(newEnv: Record<string, string> | undefined): this;
		/**
		 * By default, the shell will write to the current process's stdout and stderr, as well as buffering that output.
		 *
		 * This configures the shell to only buffer the output.
		 */
		quiet(): this;

		/**
		 * Read from stdout as a string, line by line
		 *
		 * Automatically calls {@link quiet} to disable echoing to stdout.
		 */
		lines(): AsyncIterable<string>;

		/**
		 * Read from stdout as a string
		 *
		 * Automatically calls {@link quiet} to disable echoing to stdout.
		 * @param encoding - The encoding to use when decoding the output
		 * @returns A promise that resolves with stdout as a string
		 * @example
		 *
		 * ## Read as UTF-8 string
		 *
		 * ```ts
		 * const output = await $`echo hello`.text();
		 * console.log(output); // "hello\n"
		 * ```
		 *
		 * ## Read as base64 string
		 *
		 * ```ts
		 * const output = await $`echo ${atob("hello")}`.text("base64");
		 * console.log(output); // "hello\n"
		 * ```
		 *
		 */
		text(encoding?: BufferEncoding): Promise<string>;

		/**
		 * Read from stdout as a JSON object
		 *
		 * Automatically calls {@link quiet}
		 *
		 * @returns A promise that resolves with stdout as a JSON object
		 * @example
		 *
		 * ```ts
		 * const output = await $`echo '{"hello": 123}'`.json();
		 * console.log(output); // { hello: 123 }
		 * ```
		 *
		 */
		json(): Promise<any>;

		/**
		 * Read from stdout as an ArrayBuffer
		 *
		 * Automatically calls {@link quiet}
		 * @returns A promise that resolves with stdout as an ArrayBuffer
		 * @example
		 *
		 * ```ts
		 * const output = await $`echo hello`.arrayBuffer();
		 * console.log(output); // ArrayBuffer { byteLength: 6 }
		 * ```
		 */
		arrayBuffer(): Promise<ArrayBuffer>;

		/**
		 * Read from stdout as a Blob
		 *
		 * Automatically calls {@link quiet}
		 * @returns A promise that resolves with stdout as a Blob
		 * @example
		 * ```ts
		 * const output = await $`echo hello`.blob();
		 * console.log(output); // Blob { size: 6, type: "" }
		 * ```
		 */
		blob(): Promise<Blob>;

		/**
		 * Configure the shell to not throw an exception on non-zero exit codes. Throwing can be re-enabled with `.throws(true)`.
		 *
		 * By default, the shell with throw an exception on commands which return non-zero exit codes.
		 */
		nothrow(): this;

		/**
		 * Configure whether or not the shell should throw an exception on non-zero exit codes.
		 *
		 * By default, this is configured to `true`.
		 */
		throws(shouldThrow: boolean): this;
	}

	interface ShellConstructor {
		new (): Shell;
	}

	export interface Shell {
		(
			strings: TemplateStringsArray,
			...expressions: ShellExpression[]
		): ShellPromise;

		/**
		 * Perform bash-like brace expansion on the given pattern.
		 * @param pattern - Brace pattern to expand
		 *
		 * @example
		 * ```js
		 * const result = braces('index.{js,jsx,ts,tsx}');
		 * console.log(result) // ['index.js', 'index.jsx', 'index.ts', 'index.tsx']
		 * ```
		 */
		braces(pattern: string): string[];

		/**
		 * Escape strings for input into shell commands.
		 * @param input
		 */
		escape(input: string): string;

		/**
		 *
		 * Change the default environment variables for shells created by this instance.
		 *
		 * @param newEnv Default environment variables to use for shells created by this instance.
		 * @default process.env
		 *
		 * ## Example
		 *
		 * ```js
		 * import {$} from 'bun';
		 * $.env({ BUN: "bun" });
		 * await $`echo $BUN`;
		 * // "bun"
		 * ```
		 */
		env(newEnv?: Record<string, string | undefined>): this;

		/**
		 *
		 * @param newCwd Default working directory to use for shells created by this instance.
		 */
		cwd(newCwd?: string): this;

		/**
		 * Configure the shell to not throw an exception on non-zero exit codes.
		 */
		nothrow(): this;

		/**
		 * Configure whether or not the shell should throw an exception on non-zero exit codes.
		 */
		throws(shouldThrow: boolean): this;

		readonly ShellPromise: typeof ShellPromise;
		readonly Shell: ShellConstructor;
	}

	export interface ShellOutput {
		readonly stdout: Buffer;
		readonly stderr: Buffer;
		readonly exitCode: number;

		/**
		 * Read from stdout as a string
		 *
		 * @param encoding - The encoding to use when decoding the output
		 * @returns Stdout as a string with the given encoding
		 * @example
		 *
		 * ## Read as UTF-8 string
		 *
		 * ```ts
		 * const output = await $`echo hello`;
		 * console.log(output.text()); // "hello\n"
		 * ```
		 *
		 * ## Read as base64 string
		 *
		 * ```ts
		 * const output = await $`echo ${atob("hello")}`;
		 * console.log(output.text("base64")); // "hello\n"
		 * ```
		 *
		 */
		text(encoding?: BufferEncoding): string;

		/**
		 * Read from stdout as a JSON object
		 *
		 * @returns Stdout as a JSON object
		 * @example
		 *
		 * ```ts
		 * const output = await $`echo '{"hello": 123}'`;
		 * console.log(output.json()); // { hello: 123 }
		 * ```
		 *
		 */
		json(): any;

		/**
		 * Read from stdout as an ArrayBuffer
		 *
		 * @returns Stdout as an ArrayBuffer
		 * @example
		 *
		 * ```ts
		 * const output = await $`echo hello`;
		 * console.log(output.arrayBuffer()); // ArrayBuffer { byteLength: 6 }
		 * ```
		 */
		arrayBuffer(): ArrayBuffer;

		/**
		 * Read from stdout as an Uint8Array
		 *
		 * @returns Stdout as an Uint8Array
		 * @example
		 *
		 * ```ts
		 * const output = await $`echo hello`;
		 * console.log(output.bytes()); // Uint8Array { byteLength: 6 }
		 * ```
		 */
		bytes(): Uint8Array;

		/**
		 * Read from stdout as a Blob
		 *
		 * @returns Stdout as a blob
		 * @example
		 * ```ts
		 * const output = await $`echo hello`;
		 * console.log(output.blob()); // Blob { size: 6, type: "" }
		 * ```
		 */
		blob(): Blob;
	}

	export const $: Shell;

	interface TOML {
		/**
		 * Parse a TOML string into a JavaScript object.
		 *
		 * @param {string} command The name of the executable or script
		 * @param {string} options.PATH Overrides the PATH environment variable
		 * @param {string} options.cwd Limits the search to a particular directory in which to searc
		 */
		parse(input: string): object;
	}
	const TOML: TOML;

	type Serve<WebSocketDataType = undefined> =
		| ServeOptions
		| TLSServeOptions
		| UnixServeOptions
		| UnixTLSServeOptions
		| WebSocketServeOptions<WebSocketDataType>
		| TLSWebSocketServeOptions<WebSocketDataType>
		| UnixWebSocketServeOptions<WebSocketDataType>
		| UnixTLSWebSocketServeOptions<WebSocketDataType>;

	/**
	 * Start a fast HTTP server.
	 *
	 * @param options Server options (port defaults to $PORT || 3000)
	 *
	 * -----
	 *
	 * @example
	 *
	 * ```ts
	 * Bun.serve({
	 *   fetch(req: Request): Response | Promise<Response> {
	 *     return new Response("Hello World!");
	 *   },
	 *
	 *   // Optional port number - the default value is 3000
	 *   port: process.env.PORT || 3000,
	 * });
	 * ```
	 * -----
	 *
	 * @example
	 *
	 * Send a file
	 *
	 * ```ts
	 * Bun.serve({
	 *   fetch(req: Request): Response | Promise<Response> {
	 *     return new Response(Bun.file("./package.json"));
	 *   },
	 *
	 *   // Optional port number - the default value is 3000
	 *   port: process.env.PORT || 3000,
	 * });
	 * ```
	 */
	// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
	function serve<T>(options: Serve<T>): Server;

	/**
	 * Synchronously resolve a `moduleId` as though it were imported from `parent`
	 *
	 * On failure, throws a `ResolveMessage`
	 */
	// tslint:disable-next-line:unified-signatures
	function resolveSync(moduleId: string, parent: string): string;

	/**
	 * Resolve a `moduleId` as though it were imported from `parent`
	 *
	 * On failure, throws a `ResolveMessage`
	 *
	 * For now, use the sync version. There is zero performance benefit to using this async version. It exists for future-proofing.
	 */
	// tslint:disable-next-line:unified-signatures
	function resolve(moduleId: string, parent: string): Promise<string>;

	/**
	 * Use the fastest syscalls available to copy from `input` into `destination`.
	 *
	 * If `destination` exists, it must be a regular file or symlink to a file. If `destination`'s directory does not exist, it will be created by default.
	 *
	 * @param destination The file or file path to write to
	 * @param input The data to copy into `destination`.
	 * @returns A promise that resolves with the number of bytes written.
	 */
	// tslint:disable-next-line:unified-signatures
	function write(
		destination: BunFile | Bun.PathLike,
		input: Blob | NodeJS.TypedArray | ArrayBufferLike | string | Bun.BlobPart[],
		options?: {
			/** If writing to a PathLike, set the permissions of the file. */
			mode?: number;
			/**
			 * If `true`, create the parent directory if it doesn't exist. By default, this is `true`.
			 *
			 * If `false`, this will throw an error if the directory doesn't exist.
			 *
			 * @default true
			 */
			createPath?: boolean;
		},
	): Promise<number>;

	/**
	 * Persist a {@link Response} body to disk.
	 *
	 * @param destination The file to write to. If the file doesn't exist,
	 * it will be created and if the file does exist, it will be
	 * overwritten. If `input`'s size is less than `destination`'s size,
	 * `destination` will be truncated.
	 * @param input - `Response` object
	 * @returns A promise that resolves with the number of bytes written.
	 */
	function write(
		destination: BunFile,
		input: Response,
		options?: {
			/**
			 * If `true`, create the parent directory if it doesn't exist. By default, this is `true`.
			 *
			 * If `false`, this will throw an error if the directory doesn't exist.
			 *
			 * @default true
			 */
			createPath?: boolean;
		},
	): Promise<number>;

	/**
	 * Persist a {@link Response} body to disk.
	 *
	 * @param destinationPath The file path to write to. If the file doesn't
	 * exist, it will be created and if the file does exist, it will be
	 * overwritten. If `input`'s size is less than `destination`'s size,
	 * `destination` will be truncated.
	 * @param input - `Response` object
	 * @returns A promise that resolves with the number of bytes written.
	 */
	// tslint:disable-next-line:unified-signatures
	function write(
		destinationPath: Bun.PathLike,
		input: Response,
		options?: {
			/**
			 * If `true`, create the parent directory if it doesn't exist. By default, this is `true`.
			 *
			 * If `false`, this will throw an error if the directory doesn't exist.
			 *
			 * @default true
			 */
			createPath?: boolean;
		},
	): Promise<number>;

	/**
	 * Use the fastest syscalls available to copy from `input` into `destination`.
	 *
	 * If `destination` exists, it must be a regular file or symlink to a file.
	 *
	 * On Linux, this uses `copy_file_range`.
	 *
	 * On macOS, when the destination doesn't already exist, this uses
	 * [`clonefile()`](https://www.manpagez.com/man/2/clonefile/) and falls
	 * back to [`fcopyfile()`](https://www.manpagez.com/man/2/fcopyfile/)
	 *
	 * @param destination The file to write to. If the file doesn't exist,
	 * it will be created and if the file does exist, it will be
	 * overwritten. If `input`'s size is less than `destination`'s size,
	 * `destination` will be truncated.
	 * @param input The file to copy from.
	 * @returns A promise that resolves with the number of bytes written.
	 */
	// tslint:disable-next-line:unified-signatures
	function write(
		destination: BunFile,
		input: BunFile,
		options?: {
			/**
			 * If `true`, create the parent directory if it doesn't exist. By default, this is `true`.
			 *
			 * If `false`, this will throw an error if the directory doesn't exist.
			 *
			 * @default true
			 */
			createPath?: boolean;
		},
	): Promise<number>;

	/**
	 * Use the fastest syscalls available to copy from `input` into `destination`.
	 *
	 * If `destination` exists, it must be a regular file or symlink to a file.
	 *
	 * On Linux, this uses `copy_file_range`.
	 *
	 * On macOS, when the destination doesn't already exist, this uses
	 * [`clonefile()`](https://www.manpagez.com/man/2/clonefile/) and falls
	 * back to [`fcopyfile()`](https://www.manpagez.com/man/2/fcopyfile/)
	 *
	 * @param destinationPath The file path to write to. If the file doesn't
	 * exist, it will be created and if the file does exist, it will be
	 * overwritten. If `input`'s size is less than `destination`'s size,
	 * `destination` will be truncated.
	 * @param input The file to copy from.
	 * @returns A promise that resolves with the number of bytes written.
	 */
	// tslint:disable-next-line:unified-signatures
	function write(
		destinationPath: Bun.PathLike,
		input: BunFile,
		options?: {
			/**
			 * If `true`, create the parent directory if it doesn't exist. By default, this is `true`.
			 *
			 * If `false`, this will throw an error if the directory doesn't exist.
			 *
			 * @default true
			 */
			createPath?: boolean;
		},
	): Promise<number>;

	interface SystemError extends Error {
		errno?: number | undefined;
		code?: string | undefined;
		path?: string | undefined;
		syscall?: string | undefined;
	}

	/**
	 * Concatenate an array of typed arrays into a single `ArrayBuffer`. This is a fast path.
	 *
	 * You can do this manually if you'd like, but this function will generally
	 * be a little faster.
	 *
	 * If you want a `Uint8Array` instead, consider `Buffer.concat`.
	 *
	 * @param buffers An array of typed arrays to concatenate.
	 * @returns An `ArrayBuffer` with the data from all the buffers.
	 *
	 * Here is similar code to do it manually, except about 30% slower:
	 * ```js
	 *   var chunks = [...];
	 *   var size = 0;
	 *   for (const chunk of chunks) {
	 *     size += chunk.byteLength;
	 *   }
	 *   var buffer = new ArrayBuffer(size);
	 *   var view = new Uint8Array(buffer);
	 *   var offset = 0;
	 *   for (const chunk of chunks) {
	 *     view.set(chunk, offset);
	 *     offset += chunk.byteLength;
	 *   }
	 *   return buffer;
	 * ```
	 *
	 * This function is faster because it uses uninitialized memory when copying. Since the entire
	 * length of the buffer is known, it is safe to use uninitialized memory.
	 */
	function concatArrayBuffers(
		buffers: Array<ArrayBufferView | ArrayBufferLike>,
		maxLength?: number,
	): ArrayBuffer;
	function concatArrayBuffers(
		buffers: Array<ArrayBufferView | ArrayBufferLike>,
		maxLength: number,
		asUint8Array: false,
	): ArrayBuffer;
	function concatArrayBuffers(
		buffers: Array<ArrayBufferView | ArrayBufferLike>,
		maxLength: number,
		asUint8Array: true,
	): Uint8Array;

	/**
	 * Consume all data from a {@link ReadableStream} until it closes or errors.
	 *
	 * Concatenate the chunks into a single {@link ArrayBuffer}.
	 *
	 * Each chunk must be a TypedArray or an ArrayBuffer. If you need to support
	 * chunks of different types, consider {@link readableStreamToBlob}
	 *
	 * @param stream The stream to consume.
	 * @returns A promise that resolves with the concatenated chunks or the concatenated chunks as an `ArrayBuffer`.
	 */
	function readableStreamToArrayBuffer(
		stream: ReadableStream<ArrayBufferView | ArrayBufferLike>,
	): Promise<ArrayBuffer> | ArrayBuffer;

	/**
	 * Consume all data from a {@link ReadableStream} until it closes or errors.
	 *
	 * Concatenate the chunks into a single {@link ArrayBuffer}.
	 *
	 * Each chunk must be a TypedArray or an ArrayBuffer. If you need to support
	 * chunks of different types, consider {@link readableStreamToBlob}
	 *
	 * @param stream The stream to consume.
	 * @returns A promise that resolves with the concatenated chunks or the concatenated chunks as a {@link Uint8Array}.
	 */
	function readableStreamToBytes(
		stream: ReadableStream<ArrayBufferView | ArrayBufferLike>,
	): Promise<Uint8Array> | Uint8Array;

	/**
	 * Consume all data from a {@link ReadableStream} until it closes or errors.
	 *
	 * Concatenate the chunks into a single {@link Blob}.
	 *
	 * @param stream The stream to consume.
	 * @returns A promise that resolves with the concatenated chunks as a {@link Blob}.
	 */
	function readableStreamToBlob(stream: ReadableStream): Promise<Blob>;

	/**
	 * Consume all data from a {@link ReadableStream} until it closes or errors.
	 *
	 * Reads the multi-part or URL-encoded form data into a {@link FormData} object
	 *
	 * @param stream The stream to consume.
	 * @param multipartBoundaryExcludingDashes Optional boundary to use for multipart form data. If none is provided, assumes it is a URLEncoded form.
	 * @returns A promise that resolves with the data encoded into a {@link FormData} object.
	 *
	 * ## Multipart form data example
	 *
	 * ```ts
	 * // without dashes
	 * const boundary = "WebKitFormBoundary" + Math.random().toString(16).slice(2);
	 *
	 * const myStream = getStreamFromSomewhere() // ...
	 * const formData = await Bun.readableStreamToFormData(stream, boundary);
	 * formData.get("foo"); // "bar"
	 * ```
	 * ## URL-encoded form data example
	 *
	 * ```ts
	 * const stream = new Response("hello=123").body;
	 * const formData = await Bun.readableStreamToFormData(stream);
	 * formData.get("hello"); // "123"
	 * ```
	 */
	function readableStreamToFormData(
		stream: ReadableStream<string | NodeJS.TypedArray | ArrayBufferView>,
		multipartBoundaryExcludingDashes?:
			| string
			| NodeJS.TypedArray
			| ArrayBufferView,
	): Promise<FormData>;

	/**
	 * Consume all data from a {@link ReadableStream} until it closes or errors.
	 *
	 * Concatenate the chunks into a single string. Chunks must be a TypedArray or an ArrayBuffer. If you need to support chunks of different types, consider {@link readableStreamToBlob}.
	 *
	 * @param stream The stream to consume.
	 * @returns A promise that resolves with the concatenated chunks as a {@link String}.
	 */
	function readableStreamToText(stream: ReadableStream): Promise<string>;

	/**
	 * Consume all data from a {@link ReadableStream} until it closes or errors.
	 *
	 * Concatenate the chunks into a single string and parse as JSON. Chunks must be a TypedArray or an ArrayBuffer. If you need to support chunks of different types, consider {@link readableStreamToBlob}.
	 *
	 * @param stream The stream to consume.
	 * @returns A promise that resolves with the concatenated chunks as a {@link String}.
	 */
	function readableStreamToJSON(stream: ReadableStream): Promise<any>;

	/**
	 * Consume all data from a {@link ReadableStream} until it closes or errors.
	 *
	 * @param stream The stream to consume
	 * @returns A promise that resolves with the chunks as an array
	 */
	function readableStreamToArray<T>(
		stream: ReadableStream<T>,
	): Promise<T[]> | T[];

	/**
	 * Escape the following characters in a string:
	 *
	 * - `"` becomes `"&quot;"`
	 * - `&` becomes `"&amp;"`
	 * - `'` becomes `"&#x27;"`
	 * - `<` becomes `"&lt;"`
	 * - `>` becomes `"&gt;"`
	 *
	 * This function is optimized for large input. On an M1X, it processes 480 MB/s -
	 * 20 GB/s, depending on how much data is being escaped and whether there is non-ascii
	 * text.
	 *
	 * Non-string types will be converted to a string before escaping.
	 */
	function escapeHTML(input: string | object | number | boolean): string;

	/**
	 * Convert a filesystem path to a file:// URL.
	 *
	 * @param path The path to convert.
	 * @returns A {@link URL} with the file:// scheme.
	 *
	 * @example
	 * ```js
	 * const url = Bun.pathToFileURL("/foo/bar.txt");
	 * console.log(url.href); // "file:///foo/bar.txt"
	 * ```
	 *
	 * Internally, this function uses WebKit's URL API to
	 * convert the path to a file:// URL.
	 */
	function pathToFileURL(path: string): URL;

	interface Peek {
		<T = undefined>(promise: T | Promise<T>): Promise<T> | T;
		status<T = undefined>(
			promise: T | Promise<T>,
		): "pending" | "fulfilled" | "rejected";
	}
	/**
	 * Extract the value from the Promise in the same tick of the event loop
	 */
	const peek: Peek;

	/**
	 * Convert a {@link URL} to a filesystem path.
	 * @param url The URL to convert.
	 * @returns A filesystem path.
	 * @throws If the URL is not a URL.
	 * @example
	 * ```js
	 * const path = Bun.fileURLToPath(new URL("file:///foo/bar.txt"));
	 * console.log(path); // "/foo/bar.txt"
	 * ```
	 */
	function fileURLToPath(url: URL | string): string;

	/**
	 * Fast incremental writer that becomes an `ArrayBuffer` on end().
	 */
	class ArrayBufferSink {
		constructor();

		start(options?: {
			asUint8Array?: boolean;
			/**
			 * Preallocate an internal buffer of this size
			 * This can significantly improve performance when the chunk size is small
			 */
			highWaterMark?: number;
			/**
			 * On {@link ArrayBufferSink.flush}, return the written data as a `Uint8Array`.
			 * Writes will restart from the beginning of the buffer.
			 */
			stream?: boolean;
		}): void;

		write(
			chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
		): number;
		/**
		 * Flush the internal buffer
		 *
		 * If {@link ArrayBufferSink.start} was passed a `stream` option, this will return a `ArrayBuffer`
		 * If {@link ArrayBufferSink.start} was passed a `stream` option and `asUint8Array`, this will return a `Uint8Array`
		 * Otherwise, this will return the number of bytes written since the last flush
		 *
		 * This API might change later to separate Uint8ArraySink and ArrayBufferSink
		 */
		flush(): number | Uint8Array | ArrayBuffer;
		end(): ArrayBuffer | Uint8Array;
	}

	const dns: {
		/**
		 * Lookup the IP address for a hostname
		 *
		 * Uses non-blocking APIs by default
		 *
		 * @param hostname The hostname to lookup
		 * @param options Options for the lookup
		 *
		 * ## Example
		 *
		 * ```js
		 * const [{ address }] = await Bun.dns.lookup('example.com');
		 * ```
		 *
		 * ### Filter results to IPv4:
		 *
		 * ```js
		 * import { dns } from 'bun';
		 * const [{ address }] = await dns.lookup('example.com', {family: 4});
		 * console.log(address); // "123.122.22.126"
		 * ```
		 *
		 * ### Filter results to IPv6:
		 *
		 * ```js
		 * import { dns } from 'bun';
		 * const [{ address }] = await dns.lookup('example.com', {family: 6});
		 * console.log(address); // "2001:db8::1"
		 * ```
		 *
		 * #### DNS resolver client
		 *
		 * Bun supports three DNS resolvers:
		 * - `c-ares` - Uses the c-ares library to perform DNS resolution. This is the default on Linux.
		 * - `system` - Uses the system's non-blocking DNS resolver API if available, falls back to `getaddrinfo`. This is the default on macOS and the same as `getaddrinfo` on Linux.
		 * - `getaddrinfo` - Uses the posix standard `getaddrinfo` function. Will cause performance issues under concurrent loads.
		 *
		 * To customize the DNS resolver, pass a `backend` option to `dns.lookup`:
		 * ```js
		 * import { dns } from 'bun';
		 * const [{ address }] = await dns.lookup('example.com', {backend: 'getaddrinfo'});
		 * console.log(address); // "19.42.52.62"
		 * ```
		 */
		lookup(
			hostname: string,
			options?: {
				/**
				 * Limit results to either IPv4, IPv6, or both
				 */
				family?: 4 | 6 | 0 | "IPv4" | "IPv6" | "any";
				/**
				 * Limit results to either UDP or TCP
				 */
				socketType?: "udp" | "tcp";
				flags?: number;
				port?: number;

				/**
				 * The DNS resolver implementation to use
				 *
				 * Defaults to `"c-ares"` on Linux and `"system"` on macOS. This default
				 * may change in a future version of Bun if c-ares is not reliable
				 * enough.
				 *
				 * On macOS, `system` uses the builtin macOS [non-blocking DNS
				 * resolution
				 * API](https://opensource.apple.com/source/Libinfo/Libinfo-222.1/lookup.subproj/netdb_async.h.auto.html).
				 *
				 * On Linux, `system` is the same as `getaddrinfo`.
				 *
				 * `c-ares` is more performant on Linux in some high concurrency
				 * situations, but it lacks support support for mDNS (`*.local`,
				 * `*.localhost` domains) along with some other advanced features. If
				 * you run into issues using `c-ares`, you should try `system`. If the
				 * hostname ends with `.local` or `.localhost`, Bun will automatically
				 * use `system` instead of `c-ares`.
				 *
				 * [`getaddrinfo`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html)
				 * is the POSIX standard function for blocking DNS resolution. Bun runs
				 * it in Bun's thread pool, which is limited to `cpus / 2`. That means
				 * if you run a lot of concurrent DNS lookups, concurrent IO will
				 * potentially pause until the DNS lookups are done.
				 *
				 * On macOS, it shouldn't be necessary to use "`getaddrinfo`" because
				 * `"system"` uses the same API underneath (except non-blocking).
				 *
				 * On Windows, libuv's non-blocking DNS resolver is used by default, and
				 * when specifying backends "system", "libc", or "getaddrinfo". The c-ares
				 * backend isn't currently supported on Windows.
				 */
				backend?: "libc" | "c-ares" | "system" | "getaddrinfo";
			},
		): Promise<DNSLookup[]>;

		/**
		 *
		 * **Experimental API**
		 *
		 * Prefetch a hostname.
		 *
		 * This will be used by fetch() and Bun.connect() to avoid DNS lookups.
		 *
		 * @param hostname The hostname to prefetch
		 *
		 * @example
		 * ```js
		 * import { dns } from 'bun';
		 * dns.prefetch('example.com');
		 * // ... something expensive
		 * await fetch('https://example.com');
		 * ```
		 */
		prefetch(hostname: string): void;

		/**
		 * **Experimental API**
		 */
		getCacheStats(): {
			/**
			 * The number of times a cached DNS entry that was already resolved was used.
			 */
			cacheHitsCompleted: number;
			cacheHitsInflight: number;
			cacheMisses: number;
			size: number;
			errors: number;
			totalCount: number;
		};
	};

	interface DNSLookup {
		/**
		 * The IP address of the host as a string in IPv4 or IPv6 format.
		 *
		 * @example "127.0.0.1"
		 * @example "192.168.0.1"
		 * @example "2001:4860:4860::8888"
		 */
		address: string;
		family: 4 | 6;

		/**
		 * Time to live in seconds
		 *
		 * Only supported when using the `c-ares` DNS resolver via "backend" option
		 * to {@link dns.lookup}. Otherwise, it's 0.
		 */
		ttl: number;
	}

	/**
	 * Fast incremental writer for files and pipes.
	 *
	 * This uses the same interface as {@link ArrayBufferSink}, but writes to a file or pipe.
	 */
	interface FileSink {
		/**
		 * Write a chunk of data to the file.
		 *
		 * If the file descriptor is not writable yet, the data is buffered.
		 */
		write(
			chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
		): number;
		/**
		 * Flush the internal buffer, committing the data to disk or the pipe.
		 */
		flush(): number | Promise<number>;
		/**
		 * Close the file descriptor. This also flushes the internal buffer.
		 */
		end(error?: Error): number | Promise<number>;

		start(options?: {
			/**
			 * Preallocate an internal buffer of this size
			 * This can significantly improve performance when the chunk size is small
			 */
			highWaterMark?: number;
		}): void;

		/**
		 * For FIFOs & pipes, this lets you decide whether Bun's process should
		 * remain alive until the pipe is closed.
		 *
		 * By default, it is automatically managed. While the stream is open, the
		 * process remains alive and once the other end hangs up or the stream
		 * closes, the process exits.
		 *
		 * If you previously called {@link unref}, you can call this again to re-enable automatic management.
		 *
		 * Internally, it will reference count the number of times this is called. By default, that number is 1
		 *
		 * If the file is not a FIFO or pipe, {@link ref} and {@link unref} do
		 * nothing. If the pipe is already closed, this does nothing.
		 */
		ref(): void;

		/**
		 * For FIFOs & pipes, this lets you decide whether Bun's process should
		 * remain alive until the pipe is closed.
		 *
		 * If you want to allow Bun's process to terminate while the stream is open,
		 * call this.
		 *
		 * If the file is not a FIFO or pipe, {@link ref} and {@link unref} do
		 * nothing. If the pipe is already closed, this does nothing.
		 */
		unref(): void;
	}

	interface FileBlob extends BunFile {}
	/**
	 * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files.
	 *
	 * This Blob is lazy. That means it won't do any work until you read from it.
	 *
	 * - `size` will not be valid until the contents of the file are read at least once.
	 * - `type` is auto-set based on the file extension when possible
	 *
	 * @example
	 * ```js
	 * const file = Bun.file("./hello.json");
	 * console.log(file.type); // "application/json"
	 * console.log(await file.text()); // '{"hello":"world"}'
	 * ```
	 *
	 * @example
	 * ```js
	 * await Bun.write(
	 *   Bun.file("./hello.txt"),
	 *   "Hello, world!"
	 * );
	 * ```
	 */
	interface BunFile extends Blob {
		/**
		 * Offset any operation on the file starting at `begin` and ending at `end`. `end` is relative to 0
		 *
		 * Similar to [`TypedArray.subarray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray). Does not copy the file, open the file, or modify the file.
		 *
		 * If `begin` > 0, {@link Bun.write()} will be slower on macOS
		 *
		 * @param begin - start offset in bytes
		 * @param end - absolute offset in bytes (relative to 0)
		 * @param contentType - MIME type for the new BunFile
		 */
		slice(begin?: number, end?: number, contentType?: string): BunFile;

		/** */
		/**
		 * Offset any operation on the file starting at `begin`
		 *
		 * Similar to [`TypedArray.subarray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray). Does not copy the file, open the file, or modify the file.
		 *
		 * If `begin` > 0, {@link Bun.write()} will be slower on macOS
		 *
		 * @param begin - start offset in bytes
		 * @param contentType - MIME type for the new BunFile
		 */
		slice(begin?: number, contentType?: string): BunFile;

		/**
		 * @param contentType - MIME type for the new BunFile
		 */
		slice(contentType?: string): BunFile;

		/**
		 * Incremental writer for files and pipes.
		 */
		writer(options?: { highWaterMark?: number }): FileSink;

		readonly readable: ReadableStream;

		// TODO: writable: WritableStream;

		/**
		 * A UNIX timestamp indicating when the file was last modified.
		 */
		lastModified: number;
		/**
		 * The name or path of the file, as specified in the constructor.
		 */
		readonly name?: string;

		/**
		 * Does the file exist?
		 *
		 * This returns true for regular files and FIFOs. It returns false for
		 * directories. Note that a race condition can occur where the file is
		 * deleted or renamed after this is called but before you open it.
		 *
		 * This does a system call to check if the file exists, which can be
		 * slow.
		 *
		 * If using this in an HTTP server, it's faster to instead use `return new
		 * Response(Bun.file(path))` and then an `error` handler to handle
		 * exceptions.
		 *
		 * Instead of checking for a file's existence and then performing the
		 * operation, it is faster to just perform the operation and handle the
		 * error.
		 *
		 * For empty Blob, this always returns true.
		 */
		exists(): Promise<boolean>;
	}

	/**
	 *   This lets you use macros as regular imports
	 *   @example
	 *   ```
	 *   {
	 *     "react-relay": {
	 *       "graphql": "bun-macro-relay/bun-macro-relay.tsx"
	 *     }
	 *   }
	 *  ```
	 */
	type MacroMap = Record<string, Record<string, string>>;

	/**
	 * Hash a string or array buffer using Wyhash
	 *
	 * This is not a cryptographic hash function.
	 * @param data The data to hash.
	 * @param seed The seed to use.
	 */
	const hash: ((
		data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
		seed?: number | bigint,
	) => number | bigint) &
		Hash;

	interface Hash {
		wyhash: (
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
			seed?: bigint,
		) => bigint;
		adler32: (
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
		) => number;
		crc32: (
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
		) => number;
		cityHash32: (
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
		) => number;
		cityHash64: (
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
			seed?: bigint,
		) => bigint;
		murmur32v3: (
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
			seed?: number,
		) => number;
		murmur32v2: (
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
			seed?: number,
		) => number;
		murmur64v2: (
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
			seed?: bigint,
		) => bigint;
	}

	type JavaScriptLoader = "jsx" | "js" | "ts" | "tsx";

	/**
	 * Fast deep-equality check two objects.
	 *
	 * This also powers expect().toEqual in `bun:test`
	 */
	function deepEquals(
		a: any,
		b: any,
		/** @default false */
		strict?: boolean,
	): boolean;

	/**
	 * Returns true if all properties in the subset exist in the
	 * other and have equal values.
	 *
	 * This also powers expect().toMatchObject in `bun:test`
	 */
	function deepMatch(subset: unknown, a: unknown): boolean;

	/**
	 * tsconfig.json options supported by Bun
	 */
	interface TSConfig {
		extends?: string;
		compilerOptions?: {
			paths?: Record<string, string[]>;
			baseUrl?: string;
			/** "preserve" is not supported yet */
			jsx?: "preserve" | "react" | "react-jsx" | "react-jsxdev";
			jsxFactory?: string;
			jsxFragmentFactory?: string;
			jsxImportSource?: string;
			useDefineForClassFields?: boolean;
			importsNotUsedAsValues?: "remove" | "preserve" | "error";
			/** moduleSuffixes is not supported yet */
			moduleSuffixes?: any;
		};
	}

	interface TranspilerOptions {
		/**
		 * Replace key with value. Value must be a JSON string.
		 * @example
		 *  ```
		 *  { "process.env.NODE_ENV": "\"production\"" }
		 * ```
		 */
		define?: Record<string, string>;

		/** What is the default loader used for this transpiler?  */
		loader?: JavaScriptLoader;

		/**  What platform are we targeting? This may affect how import and/or require is used */
		/**  @example "browser" */
		target?: Target;

		/**
		 *  TSConfig.json file as stringified JSON or an object
		 *  Use this to set a custom JSX factory, fragment, or import source
		 *  For example, if you want to use Preact instead of React. Or if you want to use Emotion.
		 */
		tsconfig?: string | TSConfig;

		/**
		 *    Replace an import statement with a macro.
		 *
		 *    This will remove the import statement from the final output
		 *    and replace any function calls or template strings with the result returned by the macro
		 *
		 *    @example
		 *    ```json
		 *    {
		 *        "react-relay": {
		 *            "graphql": "bun-macro-relay"
		 *        }
		 *    }
		 *    ```
		 *
		 *    Code that calls `graphql` will be replaced with the result of the macro.
		 *
		 *    ```js
		 *    import {graphql} from "react-relay";
		 *
		 *    // Input:
		 *    const query = graphql`
		 *        query {
		 *            ... on User {
		 *                id
		 *            }
		 *        }
		 *    }`;
		 *    ```
		 *
		 *    Will be replaced with:
		 *
		 *    ```js
		 *    import UserQuery from "./UserQuery.graphql";
		 *    const query = UserQuery;
		 *    ```
		 */
		macro?: MacroMap;

		autoImportJSX?: boolean;
		allowBunRuntime?: boolean;
		exports?: {
			eliminate?: string[];
			replace?: Record<string, string>;
		};
		treeShaking?: boolean;
		trimUnusedImports?: boolean;
		jsxOptimizationInline?: boolean;

		/**
		 * **Experimental**
		 *
		 * Minify whitespace and comments from the output.
		 */
		minifyWhitespace?: boolean;
		/**
		 * **Experimental**
		 *
		 * Enabled by default, use this to disable dead code elimination.
		 *
		 * Some other transpiler options may still do some specific dead code elimination.
		 */
		deadCodeElimination?: boolean;

		/**
		 * This does two things (and possibly more in the future):
		 * 1. `const` declarations to primitive types (excluding Object/Array) at the top of a scope before any `let` or `var` declarations will be inlined into their usages.
		 * 2. `let` and `const` declarations only used once are inlined into their usages.
		 *
		 * JavaScript engines typically do these optimizations internally, however
		 * it might only happen much later in the compilation pipeline, after code
		 * has been executed many many times.
		 *
		 * This will typically shrink the output size of code, but it might increase
		 * it in some cases. Do your own benchmarks!
		 */
		inline?: boolean;

		/**
		 * @default "warn"
		 */
		logLevel?: "verbose" | "debug" | "info" | "warn" | "error";
	}

	/**
	 * Quickly transpile TypeScript, JSX, or JS to modern JavaScript.
	 *
	 * @example
	 * ```js
	 * const transpiler = new Bun.Transpiler();
	 * transpiler.transformSync(`
	 *   const App = () => <div>Hello World</div>;
	 * export default App;
	 * `);
	 * // This outputs:
	 * const output = `
	 * const App = () => jsx("div", {
	 *   children: "Hello World"
	 * }, undefined, false, undefined, this);
	 * export default App;
	 * `
	 * ```
	 */

	class Transpiler {
		constructor(options?: TranspilerOptions);

		/**
		 * Transpile code from TypeScript or JSX into valid JavaScript.
		 * This function does not resolve imports.
		 * @param code The code to transpile
		 */
		transform(
			code: Bun.StringOrBuffer,
			loader?: JavaScriptLoader,
		): Promise<string>;
		/**
		 * Transpile code from TypeScript or JSX into valid JavaScript.
		 * This function does not resolve imports.
		 * @param code The code to transpile
		 */
		transformSync(
			code: Bun.StringOrBuffer,
			loader: JavaScriptLoader,
			ctx: object,
		): string;
		/**
		 * Transpile code from TypeScript or JSX into valid JavaScript.
		 * This function does not resolve imports.
		 * @param code The code to transpile
		 * @param ctx An object to pass to macros
		 */
		transformSync(code: Bun.StringOrBuffer, ctx: object): string;

		/**
		 * Transpile code from TypeScript or JSX into valid JavaScript.
		 * This function does not resolve imports.
		 * @param code The code to transpile
		 */
		transformSync(code: Bun.StringOrBuffer, loader?: JavaScriptLoader): string;

		/**
		 * Get a list of import paths and paths from a TypeScript, JSX, TSX, or JavaScript file.
		 * @param code The code to scan
		 * @example
		 * ```js
		 * const {imports, exports} = transpiler.scan(`
		 * import {foo} from "baz";
		 * export const hello = "hi!";
		 * `);
		 *
		 * console.log(imports); // ["baz"]
		 * console.log(exports); // ["hello"]
		 * ```
		 */
		scan(code: Bun.StringOrBuffer): { exports: string[]; imports: Import[] };

		/**
		 *  Get a list of import paths from a TypeScript, JSX, TSX, or JavaScript file.
		 * @param code The code to scan
		 * @example
		 * ```js
		 * const imports = transpiler.scanImports(`
		 * import {foo} from "baz";
		 * import type {FooType} from "bar";
		 * import type {DogeType} from "wolf";
		 * `);
		 *
		 * console.log(imports); // ["baz"]
		 * ```
		 * This is a fast path which performs less work than `scan`.
		 */
		scanImports(code: Bun.StringOrBuffer): Import[];
	}

	type ImportKind =
		| "import-statement"
		| "require-call"
		| "require-resolve"
		| "dynamic-import"
		| "import-rule"
		| "url-token"
		| "internal"
		| "entry-point";

	interface Import {
		path: string;
		kind: ImportKind;
	}

	type ModuleFormat = "esm"; // later: "cjs", "iife"

	interface BuildConfig {
		entrypoints: string[]; // list of file path
		outdir?: string; // output directory
		target?: Target; // default: "browser"
		format?: ModuleFormat; // later: "cjs", "iife"
		naming?:
			| string
			| {
					chunk?: string;
					entry?: string;
					asset?: string;
			  }; // | string;
		root?: string; // project root
		splitting?: boolean; // default true, enable code splitting
		plugins?: BunPlugin[];
		// manifest?: boolean; // whether to return manifest
		external?: string[];
		packages?: "bundle" | "external";
		publicPath?: string;
		define?: Record<string, string>;
		// origin?: string; // e.g. http://mydomain.com
		loader?: { [k in string]: Loader };
		sourcemap?: "none" | "linked" | "inline" | "external" | "linked"; // default: "none", true -> "inline"
		/**
		 * package.json `exports` conditions used when resolving imports
		 *
		 * Equivalent to `--conditions` in `bun build` or `bun run`.
		 *
		 * https://nodejs.org/api/packages.html#exports
		 */
		conditions?: Array<string> | string;
		minify?:
			| boolean
			| {
					whitespace?: boolean;
					syntax?: boolean;
					identifiers?: boolean;
			  };
		/**
		 * Ignore dead code elimination/tree-shaking annotations such as @__PURE__ and package.json
		 * "sideEffects" fields. This should only be used as a temporary workaround for incorrect
		 * annotations in libraries.
		 */
		ignoreDCEAnnotations?: boolean;
		/**
		 * Force emitting @__PURE__ annotations even if minify.whitespace is true.
		 */
		emitDCEAnnotations?: boolean;
		// treeshaking?: boolean;

		// jsx?:
		//   | "automatic"
		//   | "classic"
		//   | /* later: "preserve" */ {
		//       runtime?: "automatic" | "classic"; // later: "preserve"
		//       /** Only works when runtime=classic */
		//       factory?: string; // default: "React.createElement"
		//       /** Only works when runtime=classic */
		//       fragment?: string; // default: "React.Fragment"
		//       /** Only works when runtime=automatic */
		//       importSource?: string; // default: "react"
		//     };
	}

	namespace Password {
		type AlgorithmLabel = "bcrypt" | "argon2id" | "argon2d" | "argon2i";

		interface Argon2Algorithm {
			algorithm: "argon2id" | "argon2d" | "argon2i";
			/**
			 * Memory cost, which defines the memory usage, given in kibibytes.
			 */
			memoryCost?: number;
			/**
			 * Defines the amount of computation realized and therefore the execution
			 * time, given in number of iterations.
			 */
			timeCost?: number;
		}

		interface BCryptAlgorithm {
			algorithm: "bcrypt";
			/**
			 * A number between 4 and 31. The default is 10.
			 */
			cost?: number;
		}
	}

	/**
	 * Hash and verify passwords using argon2 or bcrypt. The default is argon2.
	 * Password hashing functions are necessarily slow, and this object will
	 * automatically run in a worker thread.
	 *
	 * The underlying implementation of these functions are provided by the Zig
	 * Standard Library. Thanks to @jedisct1 and other Zig constributors for their
	 * work on this.
	 *
	 * ### Example with argon2
	 *
	 * ```ts
	 * import {password} from "bun";
	 *
	 * const hash = await password.hash("hello world");
	 * const verify = await password.verify("hello world", hash);
	 * console.log(verify); // true
	 * ```
	 *
	 * ### Example with bcrypt
	 * ```ts
	 * import {password} from "bun";
	 *
	 * const hash = await password.hash("hello world", "bcrypt");
	 * // algorithm is optional, will be inferred from the hash if not specified
	 * const verify = await password.verify("hello world", hash, "bcrypt");
	 *
	 * console.log(verify); // true
	 * ```
	 */
	const password: {
		/**
		 * Verify a password against a previously hashed password.
		 *
		 * @returns true if the password matches, false otherwise
		 *
		 * @example
		 * ```ts
		 * import {password} from "bun";
		 * await password.verify("hey", "$argon2id$v=19$m=65536,t=2,p=1$ddbcyBcbAcagei7wSkZFiouX6TqnUQHmTyS5mxGCzeM$+3OIaFatZ3n6LtMhUlfWbgJyNp7h8/oIsLK+LzZO+WI");
		 * // true
		 * ```
		 *
		 * @throws If the algorithm is specified and does not match the hash
		 * @throws If the algorithm is invalid
		 * @throws if the hash is invalid
		 */
		verify(
			/**
			 * The password to verify.
			 *
			 * If empty, always returns false
			 */
			password: Bun.StringOrBuffer,
			/**
			 * Previously hashed password.
			 * If empty, always returns false
			 */
			hash: Bun.StringOrBuffer,
			/**
			 * If not specified, the algorithm will be inferred from the hash.
			 *
			 * If specified and the algorithm does not match the hash, this function
			 * throws an error.
			 */
			algorithm?: Password.AlgorithmLabel,
		): Promise<boolean>;
		/**
		 * Asynchronously hash a password using argon2 or bcrypt. The default is argon2.
		 *
		 * @returns A promise that resolves to the hashed password
		 *
		 * ## Example with argon2
		 * ```ts
		 * import {password} from "bun";
		 * const hash = await password.hash("hello world");
		 * console.log(hash); // $argon2id$v=1...
		 * const verify = await password.verify("hello world", hash);
		 * ```
		 * ## Example with bcrypt
		 * ```ts
		 * import {password} from "bun";
		 * const hash = await password.hash("hello world", "bcrypt");
		 * console.log(hash); // $2b$10$...
		 * const verify = await password.verify("hello world", hash);
		 * ```
		 */
		hash(
			/**
			 * The password to hash
			 *
			 * If empty, this function throws an error. It is usually a programming
			 * mistake to hash an empty password.
			 */
			password: Bun.StringOrBuffer,
			/**
			 * @default "argon2id"
			 *
			 * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before
			 */
			algorithm?:
				| Password.AlgorithmLabel
				| Password.Argon2Algorithm
				| Password.BCryptAlgorithm,
		): Promise<string>;

		/**
		 * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2.
		 * Warning: password hashing is slow, consider using {@link Bun.password.verify}
		 * instead which runs in a worker thread.
		 *
		 * The underlying implementation of these functions are provided by the Zig
		 * Standard Library. Thanks to @jedisct1 and other Zig constributors for their
		 * work on this.
		 *
		 * ### Example with argon2
		 *
		 * ```ts
		 * import {password} from "bun";
		 *
		 * const hash = await password.hashSync("hello world");
		 * const verify = await password.verifySync("hello world", hash);
		 * console.log(verify); // true
		 * ```
		 *
		 * ### Example with bcrypt
		 * ```ts
		 * import {password} from "bun";
		 *
		 * const hash = await password.hashSync("hello world", "bcrypt");
		 * // algorithm is optional, will be inferred from the hash if not specified
		 * const verify = await password.verifySync("hello world", hash, "bcrypt");
		 *
		 * console.log(verify); // true
		 * ```
		 */
		verifySync(
			password: Bun.StringOrBuffer,
			hash: Bun.StringOrBuffer,
			/**
			 * If not specified, the algorithm will be inferred from the hash.
			 */
			algorithm?: Password.AlgorithmLabel,
		): boolean;

		/**
		 * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2.
		 * Warning: password hashing is slow, consider using {@link Bun.password.hash}
		 * instead which runs in a worker thread.
		 *
		 * The underlying implementation of these functions are provided by the Zig
		 * Standard Library. Thanks to @jedisct1 and other Zig constributors for their
		 * work on this.
		 *
		 * ### Example with argon2
		 *
		 * ```ts
		 * import {password} from "bun";
		 *
		 * const hash = await password.hashSync("hello world");
		 * const verify = await password.verifySync("hello world", hash);
		 * console.log(verify); // true
		 * ```
		 *
		 * ### Example with bcrypt
		 * ```ts
		 * import {password} from "bun";
		 *
		 * const hash = await password.hashSync("hello world", "bcrypt");
		 * // algorithm is optional, will be inferred from the hash if not specified
		 * const verify = await password.verifySync("hello world", hash, "bcrypt");
		 *
		 * console.log(verify); // true
		 * ```
		 */
		hashSync(
			/**
			 * The password to hash
			 *
			 * If empty, this function throws an error. It is usually a programming
			 * mistake to hash an empty password.
			 */
			password: Bun.StringOrBuffer,
			/**
			 * @default "argon2id"
			 *
			 * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before
			 */
			algorithm?:
				| Password.AlgorithmLabel
				| Password.Argon2Algorithm
				| Password.BCryptAlgorithm,
		): string;
	};

	interface BuildArtifact extends Blob {
		path: string;
		loader: Loader;
		hash: string | null;
		kind: "entry-point" | "chunk" | "asset" | "sourcemap";
		sourcemap: BuildArtifact | null;
	}

	interface BuildOutput {
		outputs: BuildArtifact[];
		success: boolean;
		logs: Array<BuildMessage | ResolveMessage>;
	}

	function build(config: BuildConfig): Promise<BuildOutput>;

	/**
	 * A status that represents the outcome of a sent message.
	 *
	 * - if **0**, the message was **dropped**.
	 * - if **-1**, there is **backpressure** of messages.
	 * - if **>0**, it represents the **number of bytes sent**.
	 *
	 * @example
	 * ```js
	 * const status = ws.send("Hello!");
	 * if (status === 0) {
	 *   console.log("Message was dropped");
	 * } else if (status === -1) {
	 *   console.log("Backpressure was applied");
	 * } else {
	 *   console.log(`Success! Sent ${status} bytes`);
	 * }
	 * ```
	 */
	type ServerWebSocketSendStatus = number;

	/**
	 * A state that represents if a WebSocket is connected.
	 *
	 * - `WebSocket.CONNECTING` is `0`, the connection is pending.
	 * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible.
	 * - `WebSocket.CLOSING` is `2`, the connection is closing.
	 * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened.
	 *
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
	 */
	type WebSocketReadyState = 0 | 1 | 2 | 3;

	/**
	 * A fast WebSocket designed for servers.
	 *
	 * Features:
	 * - **Message compression** - Messages can be compressed
	 * - **Backpressure** - If the client is not ready to receive data, the server will tell you.
	 * - **Dropped messages** - If the client cannot receive data, the server will tell you.
	 * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics
	 *
	 * This is slightly different than the browser {@link WebSocket} which Bun supports for clients.
	 *
	 * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets).
	 *
	 * @example
	 * import { serve } from "bun";
	 *
	 * serve({
	 *   websocket: {
	 *     open(ws) {
	 *       console.log("Connected", ws.remoteAddress);
	 *     },
	 *     message(ws, data) {
	 *       console.log("Received", data);
	 *       ws.send(data);
	 *     },
	 *     close(ws, code, reason) {
	 *       console.log("Disconnected", code, reason);
	 *     },
	 *   }
	 * });
	 */
	interface ServerWebSocket<T = undefined> {
		/**
		 * Sends a message to the client.
		 *
		 * @param data The data to send.
		 * @param compress Should the data be compressed? If the client does not support compression, this is ignored.
		 * @example
		 * ws.send("Hello!");
		 * ws.send("Compress this.", true);
		 * ws.send(new Uint8Array([1, 2, 3, 4]));
		 */
		send(
			data: string | Bun.BufferSource,
			compress?: boolean,
		): ServerWebSocketSendStatus;

		/**
		 * Sends a text message to the client.
		 *
		 * @param data The data to send.
		 * @param compress Should the data be compressed? If the client does not support compression, this is ignored.
		 * @example
		 * ws.send("Hello!");
		 * ws.send("Compress this.", true);
		 */
		sendText(data: string, compress?: boolean): ServerWebSocketSendStatus;

		/**
		 * Sends a binary message to the client.
		 *
		 * @param data The data to send.
		 * @param compress Should the data be compressed? If the client does not support compression, this is ignored.
		 * @example
		 * ws.send(new TextEncoder().encode("Hello!"));
		 * ws.send(new Uint8Array([1, 2, 3, 4]), true);
		 */
		sendBinary(
			data: Bun.BufferSource,
			compress?: boolean,
		): ServerWebSocketSendStatus;

		/**
		 * Closes the connection.
		 *
		 * Here is a list of close codes:
		 * - `1000` means "normal closure" **(default)**
		 * - `1009` means a message was too big and was rejected
		 * - `1011` means the server encountered an error
		 * - `1012` means the server is restarting
		 * - `1013` means the server is too busy or the client is rate-limited
		 * - `4000` through `4999` are reserved for applications (you can use it!)
		 *
		 * To close the connection abruptly, use `terminate()`.
		 *
		 * @param code The close code to send
		 * @param reason The close reason to send
		 */
		close(code?: number, reason?: string): void;

		/**
		 * Abruptly close the connection.
		 *
		 * To gracefully close the connection, use `close()`.
		 */
		terminate(): void;

		/**
		 * Sends a ping.
		 *
		 * @param data The data to send
		 */
		ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus;

		/**
		 * Sends a pong.
		 *
		 * @param data The data to send
		 */
		pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus;

		/**
		 * Sends a message to subscribers of the topic.
		 *
		 * @param topic The topic name.
		 * @param data The data to send.
		 * @param compress Should the data be compressed? If the client does not support compression, this is ignored.
		 * @example
		 * ws.publish("chat", "Hello!");
		 * ws.publish("chat", "Compress this.", true);
		 * ws.publish("chat", new Uint8Array([1, 2, 3, 4]));
		 */
		publish(
			topic: string,
			data: string | Bun.BufferSource,
			compress?: boolean,
		): ServerWebSocketSendStatus;

		/**
		 * Sends a text message to subscribers of the topic.
		 *
		 * @param topic The topic name.
		 * @param data The data to send.
		 * @param compress Should the data be compressed? If the client does not support compression, this is ignored.
		 * @example
		 * ws.publish("chat", "Hello!");
		 * ws.publish("chat", "Compress this.", true);
		 */
		publishText(
			topic: string,
			data: string,
			compress?: boolean,
		): ServerWebSocketSendStatus;

		/**
		 * Sends a binary message to subscribers of the topic.
		 *
		 * @param topic The topic name.
		 * @param data The data to send.
		 * @param compress Should the data be compressed? If the client does not support compression, this is ignored.
		 * @example
		 * ws.publish("chat", new TextEncoder().encode("Hello!"));
		 * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true);
		 */
		publishBinary(
			topic: string,
			data: Bun.BufferSource,
			compress?: boolean,
		): ServerWebSocketSendStatus;

		/**
		 * Subscribes a client to the topic.
		 *
		 * @param topic The topic name.
		 * @example
		 * ws.subscribe("chat");
		 */
		subscribe(topic: string): void;

		/**
		 * Unsubscribes a client to the topic.
		 *
		 * @param topic The topic name.
		 * @example
		 * ws.unsubscribe("chat");
		 */
		unsubscribe(topic: string): void;

		/**
		 * Is the client subscribed to a topic?
		 *
		 * @param topic The topic name.
		 * @example
		 * ws.subscribe("chat");
		 * console.log(ws.isSubscribed("chat")); // true
		 */
		isSubscribed(topic: string): boolean;

		/**
		 * Batches `send()` and `publish()` operations, which makes it faster to send data.
		 *
		 * The `message`, `open`, and `drain` callbacks are automatically corked, so
		 * you only need to call this if you are sending messages outside of those
		 * callbacks or in async functions.
		 *
		 * @param callback The callback to run.
		 * @example
		 * ws.cork((ctx) => {
		 *   ctx.send("These messages");
		 *   ctx.sendText("are sent");
		 *   ctx.sendBinary(new TextEncoder().encode("together!"));
		 * });
		 */
		cork<T = unknown>(callback: (ws: ServerWebSocket<T>) => T): T;

		/**
		 * The IP address of the client.
		 *
		 * @example
		 * console.log(socket.remoteAddress); // "127.0.0.1"
		 */
		readonly remoteAddress: string;

		/**
		 * The ready state of the client.
		 *
		 * - if `0`, the client is connecting.
		 * - if `1`, the client is connected.
		 * - if `2`, the client is closing.
		 * - if `3`, the client is closed.
		 *
		 * @example
		 * console.log(socket.readyState); // 1
		 */
		readonly readyState: WebSocketReadyState;

		/**
		 * Sets how binary data is returned in events.
		 *
		 * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)**
		 * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects.
		 * - if `uint8array`, binary data is returned as `Uint8Array` objects.
		 *
		 * @example
		 * let ws: WebSocket;
		 * ws.binaryType = "uint8array";
		 * ws.addEventListener("message", ({ data }) => {
		 *   console.log(data instanceof Uint8Array); // true
		 * });
		 */
		binaryType?: "nodebuffer" | "arraybuffer" | "uint8array";

		/**
		 * Custom data that you can assign to a client, can be read and written at any time.
		 *
		 * @example
		 * import { serve } from "bun";
		 *
		 * serve({
		 *   fetch(request, server) {
		 *     const data = {
		 *       accessToken: request.headers.get("Authorization"),
		 *     };
		 *     if (server.upgrade(request, { data })) {
		 *       return;
		 *     }
		 *     return new Response();
		 *   },
		 *   websocket: {
		 *     open(ws) {
		 *       console.log(ws.data.accessToken);
		 *     }
		 *   }
		 * });
		 */
		data: T;
	}

	/**
	 * Compression options for WebSocket messages.
	 */
	type WebSocketCompressor =
		| "disable"
		| "shared"
		| "dedicated"
		| "3KB"
		| "4KB"
		| "8KB"
		| "16KB"
		| "32KB"
		| "64KB"
		| "128KB"
		| "256KB";

	/**
	 * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve}
	 *
	 * @example
	 * ```ts
	 * import { websocket, serve } from "bun";
	 *
	 * serve<{name: string}>({
	 *   port: 3000,
	 *   websocket: {
	 *     open: (ws) => {
	 *       console.log("Client connected");
	 *    },
	 *     message: (ws, message) => {
	 *       console.log(`${ws.data.name}: ${message}`);
	 *    },
	 *     close: (ws) => {
	 *       console.log("Client disconnected");
	 *    },
	 *  },
	 *
	 *   fetch(req, server) {
	 *     const url = new URL(req.url);
	 *     if (url.pathname === "/chat") {
	 *       const upgraded = server.upgrade(req, {
	 *         data: {
	 *           name: new URL(req.url).searchParams.get("name"),
	 *        },
	 *      });
	 *       if (!upgraded) {
	 *         return new Response("Upgrade failed", { status: 400 });
	 *      }
	 *      return;
	 *    }
	 *     return new Response("Hello World");
	 *  },
	 * });
	 * ```
	 */
	interface WebSocketHandler<T = undefined> {
		/**
		 * Called when the server receives an incoming message.
		 *
		 * If the message is not a `string`, its type is based on the value of `binaryType`.
		 * - if `nodebuffer`, then the message is a `Buffer`.
		 * - if `arraybuffer`, then the message is an `ArrayBuffer`.
		 * - if `uint8array`, then the message is a `Uint8Array`.
		 *
		 * @param ws The websocket that sent the message
		 * @param message The message received
		 */
		message(
			ws: ServerWebSocket<T>,
			message: string | Buffer,
		): void | Promise<void>;

		/**
		 * Called when a connection is opened.
		 *
		 * @param ws The websocket that was opened
		 */
		open?(ws: ServerWebSocket<T>): void | Promise<void>;

		/**
		 * Called when a connection was previously under backpressure,
		 * meaning it had too many queued messages, but is now ready to receive more data.
		 *
		 * @param ws The websocket that is ready for more data
		 */
		drain?(ws: ServerWebSocket<T>): void | Promise<void>;

		/**
		 * Called when a connection is closed.
		 *
		 * @param ws The websocket that was closed
		 * @param code The close code
		 * @param message The close message
		 */
		close?(
			ws: ServerWebSocket<T>,
			code: number,
			reason: string,
		): void | Promise<void>;

		/**
		 * Called when a ping is sent.
		 *
		 * @param ws The websocket that received the ping
		 * @param data The data sent with the ping
		 */
		ping?(ws: ServerWebSocket<T>, data: Buffer): void | Promise<void>;

		/**
		 * Called when a pong is received.
		 *
		 * @param ws The websocket that received the ping
		 * @param data The data sent with the ping
		 */
		pong?(ws: ServerWebSocket<T>, data: Buffer): void | Promise<void>;

		/**
		 * Sets the maximum size of messages in bytes.
		 *
		 * Default is 16 MB, or `1024 * 1024 * 16` in bytes.
		 */
		maxPayloadLength?: number;

		/**
		 * Sets the maximum number of bytes that can be buffered on a single connection.
		 *
		 * Default is 16 MB, or `1024 * 1024 * 16` in bytes.
		 */
		backpressureLimit?: number;

		/**
		 * Sets if the connection should be closed if `backpressureLimit` is reached.
		 *
		 * Default is `false`.
		 */
		closeOnBackpressureLimit?: boolean;

		/**
		 * Sets the the number of seconds to wait before timing out a connection
		 * due to no messages or pings.
		 *
		 * Default is 2 minutes, or `120` in seconds.
		 */
		idleTimeout?: number;

		/**
		 * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed?
		 *
		 * Default is `false`.
		 */
		publishToSelf?: boolean;

		/**
		 * Should the server automatically send and respond to pings to clients?
		 *
		 * Default is `true`.
		 */
		sendPings?: boolean;

		/**
		 * Sets the compression level for messages, for clients that supports it. By default, compression is disabled.
		 *
		 * Default is `false`.
		 */
		perMessageDeflate?:
			| boolean
			| {
					/**
					 * Sets the compression level.
					 */
					compress?: WebSocketCompressor | boolean;
					/**
					 * Sets the decompression level.
					 */
					decompress?: WebSocketCompressor | boolean;
			  };
	}

	interface GenericServeOptions {
		/**
		 * What URI should be used to make {@link Request.url} absolute?
		 *
		 * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one
		 *
		 * @example
		 * ```js
		 * "http://my-app.com"
		 * ```
		 *
		 * @example
		 * ```js
		 * "https://wongmjane.com/"
		 * ```
		 *
		 * This should be the public, absolute URL – include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too.
		 *
		 * @example
		 * "http://localhost:3000"
		 */
		// baseURI?: string;

		/**
		 * What is the maximum size of a request body? (in bytes)
		 * @default 1024 * 1024 * 128 // 128MB
		 */
		maxRequestBodySize?: number;

		/**
		 * Render contextual errors? This enables bun's error page
		 * @default process.env.NODE_ENV !== 'production'
		 */
		development?: boolean;

		error?: (
			this: Server,
			request: ErrorLike,
		) => Response | Promise<Response> | undefined | Promise<undefined>;

		/**
		 * Uniquely identify a server instance with an ID
		 *
		 * ### When bun is started with the `--hot` flag
		 *
		 * This string will be used to hot reload the server without interrupting
		 * pending requests or websockets. If not provided, a value will be
		 * generated. To disable hot reloading, set this value to `null`.
		 *
		 * ### When bun is not started with the `--hot` flag
		 *
		 * This string will currently do nothing. But in the future it could be useful for logs or metrics.
		 */
		id?: string | null;
	}

	interface ServeOptions extends GenericServeOptions {
		/**
		 * What port should the server listen on?
		 * @default process.env.PORT || "3000"
		 */
		port?: string | number;

		/**
		 * If the `SO_REUSEPORT` flag should be set.
		 *
		 * This allows multiple processes to bind to the same port, which is useful for load balancing.
		 *
		 * @default false
		 */
		reusePort?: boolean;

		/**
		 * What hostname should the server listen on?
		 *
		 * @default
		 * ```js
		 * "0.0.0.0" // listen on all interfaces
		 * ```
		 * @example
		 *  ```js
		 * "127.0.0.1" // Only listen locally
		 * ```
		 * @example
		 * ```js
		 * "remix.run" // Only listen on remix.run
		 * ````
		 *
		 * note: hostname should not include a {@link port}
		 */
		hostname?: string;

		/**
		 * If set, the HTTP server will listen on a unix socket instead of a port.
		 * (Cannot be used with hostname+port)
		 */
		unix?: never;

		/**
		 * Handle HTTP requests
		 *
		 * Respond to {@link Request} objects with a {@link Response} object.
		 */
		fetch(
			this: Server,
			request: Request,
			server: Server,
		): Response | Promise<Response>;
	}

	interface UnixServeOptions extends GenericServeOptions {
		/**
		 * If set, the HTTP server will listen on a unix socket instead of a port.
		 * (Cannot be used with hostname+port)
		 */
		unix: string;
		/**
		 * Handle HTTP requests
		 *
		 * Respond to {@link Request} objects with a {@link Response} object.
		 */
		fetch(
			this: Server,
			request: Request,
			server: Server,
		): Response | Promise<Response>;
	}

	interface WebSocketServeOptions<WebSocketDataType = undefined>
		extends GenericServeOptions {
		/**
		 * What port should the server listen on?
		 * @default process.env.PORT || "3000"
		 */
		port?: string | number;

		/**
		 * What hostname should the server listen on?
		 *
		 * @default
		 * ```js
		 * "0.0.0.0" // listen on all interfaces
		 * ```
		 * @example
		 *  ```js
		 * "127.0.0.1" // Only listen locally
		 * ```
		 * @example
		 * ```js
		 * "remix.run" // Only listen on remix.run
		 * ````
		 *
		 * note: hostname should not include a {@link port}
		 */
		hostname?: string;

		/**
		 * Enable websockets with {@link Bun.serve}
		 *
		 * For simpler type safety, see {@link Bun.websocket}
		 *
		 * @example
		 * ```js
		 * import { serve } from "bun";
		 * serve({
		 *  websocket: {
		 *    open: (ws) => {
		 *      console.log("Client connected");
		 *    },
		 *    message: (ws, message) => {
		 *      console.log("Client sent message", message);
		 *    },
		 *    close: (ws) => {
		 *      console.log("Client disconnected");
		 *    },
		 *  },
		 *  fetch(req, server) {
		 *    const url = new URL(req.url);
		 *    if (url.pathname === "/chat") {
		 *      const upgraded = server.upgrade(req);
		 *      if (!upgraded) {
		 *        return new Response("Upgrade failed", { status: 400 });
		 *      }
		 *    }
		 *    return new Response("Hello World");
		 *  },
		 * });
		 * ```
		 * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade}
		 *
		 * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property
		 */
		websocket: WebSocketHandler<WebSocketDataType>;

		/**
		 * Handle HTTP requests or upgrade them to a {@link ServerWebSocket}
		 *
		 * Respond to {@link Request} objects with a {@link Response} object.
		 */
		fetch(
			this: Server,
			request: Request,
			server: Server,
		): Response | undefined | void | Promise<Response | undefined | void>;
	}

	interface UnixWebSocketServeOptions<WebSocketDataType = undefined>
		extends GenericServeOptions {
		/**
		 * If set, the HTTP server will listen on a unix socket instead of a port.
		 * (Cannot be used with hostname+port)
		 */
		unix: string;

		/**
		 * Enable websockets with {@link Bun.serve}
		 *
		 * For simpler type safety, see {@link Bun.websocket}
		 *
		 * @example
		 * ```js
		 * import { serve } from "bun";
		 * serve({
		 *  websocket: {
		 *    open: (ws) => {
		 *      console.log("Client connected");
		 *    },
		 *    message: (ws, message) => {
		 *      console.log("Client sent message", message);
		 *    },
		 *    close: (ws) => {
		 *      console.log("Client disconnected");
		 *    },
		 *  },
		 *  fetch(req, server) {
		 *    const url = new URL(req.url);
		 *    if (url.pathname === "/chat") {
		 *      const upgraded = server.upgrade(req);
		 *      if (!upgraded) {
		 *        return new Response("Upgrade failed", { status: 400 });
		 *      }
		 *    }
		 *    return new Response("Hello World");
		 *  },
		 * });
		 * ```
		 * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade}
		 *
		 * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property
		 */
		websocket: WebSocketHandler<WebSocketDataType>;

		/**
		 * Handle HTTP requests or upgrade them to a {@link ServerWebSocket}
		 *
		 * Respond to {@link Request} objects with a {@link Response} object.
		 */
		fetch(
			this: Server,
			request: Request,
			server: Server,
		): Response | undefined | Promise<Response | undefined>;
	}

	interface TLSWebSocketServeOptions<WebSocketDataType = undefined>
		extends WebSocketServeOptions<WebSocketDataType>,
			TLSOptions {
		unix?: never;
		tls?: TLSOptions | TLSOptions[];
	}
	interface UnixTLSWebSocketServeOptions<WebSocketDataType = undefined>
		extends UnixWebSocketServeOptions<WebSocketDataType>,
			TLSOptions {
		/**
		 * If set, the HTTP server will listen on a unix socket instead of a port.
		 * (Cannot be used with hostname+port)
		 */
		unix: string;
		tls?: TLSOptions | TLSOptions[];
	}
	interface ErrorLike extends Error {
		code?: string;
		errno?: number;
		syscall?: string;
	}

	interface TLSOptions {
		/**
		 * Passphrase for the TLS key
		 */
		passphrase?: string;

		/**
		 * File path to a .pem file custom Diffie Helman parameters
		 */
		dhParamsFile?: string;

		/**
		 * Explicitly set a server name
		 */
		serverName?: string;

		/**
		 * This sets `OPENSSL_RELEASE_BUFFERS` to 1.
		 * It reduces overall performance but saves some memory.
		 * @default false
		 */
		lowMemoryMode?: boolean;

		/**
		 * If set to `false`, any certificate is accepted.
		 * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set.
		 */
		rejectUnauthorized?: boolean;

		/**
		 * If set to `true`, the server will request a client certificate.
		 *
		 * Default is `false`.
		 */
		requestCert?: boolean;

		/**
		 * Optionally override the trusted CA certificates. Default is to trust
		 * the well-known CAs curated by Mozilla. Mozilla's CAs are completely
		 * replaced when CAs are explicitly specified using this option.
		 */
		ca?:
			| string
			| Buffer
			| BunFile
			| Array<string | Buffer | BunFile>
			| undefined;
		/**
		 *  Cert chains in PEM format. One cert chain should be provided per
		 *  private key. Each cert chain should consist of the PEM formatted
		 *  certificate for a provided private key, followed by the PEM
		 *  formatted intermediate certificates (if any), in order, and not
		 *  including the root CA (the root CA must be pre-known to the peer,
		 *  see ca). When providing multiple cert chains, they do not have to
		 *  be in the same order as their private keys in key. If the
		 *  intermediate certificates are not provided, the peer will not be
		 *  able to validate the certificate, and the handshake will fail.
		 */
		cert?:
			| string
			| Buffer
			| BunFile
			| Array<string | Buffer | BunFile>
			| undefined;
		/**
		 * Private keys in PEM format. PEM allows the option of private keys
		 * being encrypted. Encrypted keys will be decrypted with
		 * options.passphrase. Multiple keys using different algorithms can be
		 * provided either as an array of unencrypted key strings or buffers,
		 * or an array of objects in the form {pem: <string|buffer>[,
		 * passphrase: <string>]}. The object form can only occur in an array.
		 * object.passphrase is optional. Encrypted keys will be decrypted with
		 * object.passphrase if provided, or options.passphrase if it is not.
		 */
		key?:
			| string
			| Buffer
			| BunFile
			| Array<string | Buffer | BunFile>
			| undefined;
		/**
		 * Optionally affect the OpenSSL protocol behavior, which is not
		 * usually necessary. This should be used carefully if at all! Value is
		 * a numeric bitmask of the SSL_OP_* options from OpenSSL Options
		 */
		secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options
	}

	interface TLSServeOptions extends ServeOptions, TLSOptions {
		tls?: TLSOptions | TLSOptions[];
	}

	interface UnixTLSServeOptions extends UnixServeOptions, TLSOptions {
		tls?: TLSOptions | TLSOptions[];
	}

	interface SocketAddress {
		/**
		 * The IP address of the client.
		 */
		address: string;
		/**
		 * The port of the client.
		 */
		port: number;
		/**
		 * The IP family ("IPv4" or "IPv6").
		 */
		family: "IPv4" | "IPv6";
	}

	/**
	 * HTTP & HTTPS Server
	 *
	 * To start the server, see {@link serve}
	 *
	 * For performance, Bun pre-allocates most of the data for 2048 concurrent requests.
	 * That means starting a new server allocates about 500 KB of memory. Try to
	 * avoid starting and stopping the server often (unless it's a new instance of bun).
	 *
	 * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman.
	 */
	interface Server extends Disposable {
		/**
		 * Stop listening to prevent new connections from being accepted.
		 *
		 * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops.
		 *
		 * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections.
		 * @default false
		 */
		stop(closeActiveConnections?: boolean): void;

		/**
		 * Update the `fetch` and `error` handlers without restarting the server.
		 *
		 * This is useful if you want to change the behavior of your server without
		 * restarting it or for hot reloading.
		 *
		 * @example
		 *
		 * ```js
		 * // create the server
		 * const server = Bun.serve({
		 *  fetch(request) {
		 *    return new Response("Hello World v1")
		 *  }
		 * });
		 *
		 * // Update the server to return a different response
		 * server.reload({
		 *   fetch(request) {
		 *     return new Response("Hello World v2")
		 *   }
		 * });
		 * ```
		 *
		 * Passing other options such as `port` or `hostname` won't do anything.
		 */
		reload(options: Serve): void;

		/**
		 * Mock the fetch handler for a running server.
		 *
		 * This feature is not fully implemented yet. It doesn't normalize URLs
		 * consistently in all cases and it doesn't yet call the `error` handler
		 * consistently. This needs to be fixed
		 */
		fetch(request: Request | string): Response | Promise<Response>;

		/**
		 * Upgrade a {@link Request} to a {@link ServerWebSocket}
		 *
		 * @param request The {@link Request} to upgrade
		 * @param options Pass headers or attach data to the {@link ServerWebSocket}
		 *
		 * @returns `true` if the upgrade was successful and `false` if it failed
		 *
		 * @example
		 * ```js
		 * import { serve } from "bun";
		 *  serve({
		 *    websocket: {
		 *      open: (ws) => {
		 *        console.log("Client connected");
		 *      },
		 *      message: (ws, message) => {
		 *        console.log("Client sent message", message);
		 *      },
		 *      close: (ws) => {
		 *        console.log("Client disconnected");
		 *      },
		 *    },
		 *    fetch(req, server) {
		 *      const url = new URL(req.url);
		 *      if (url.pathname === "/chat") {
		 *        const upgraded = server.upgrade(req);
		 *        if (!upgraded) {
		 *          return new Response("Upgrade failed", { status: 400 });
		 *        }
		 *      }
		 *      return new Response("Hello World");
		 *    },
		 *  });
		 * ```
		 *  What you pass to `data` is available on the {@link ServerWebSocket.data} property
		 */
		// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
		upgrade<T = undefined>(
			request: Request,
			options?: {
				/**
				 * Send any additional headers while upgrading, like cookies
				 */
				headers?: Bun.HeadersInit;
				/**
				 * This value is passed to the {@link ServerWebSocket.data} property
				 */
				data?: T;
			},
		): boolean;

		/**
		 * Send a message to all connected {@link ServerWebSocket} subscribed to a topic
		 *
		 * @param topic The topic to publish to
		 * @param data The data to send
		 * @param compress Should the data be compressed? Ignored if the client does not support compression.
		 *
		 * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent.
		 *
		 * @example
		 *
		 * ```js
		 * server.publish("chat", "Hello World");
		 * ```
		 *
		 * @example
		 * ```js
		 * server.publish("chat", new Uint8Array([1, 2, 3, 4]));
		 * ```
		 *
		 * @example
		 * ```js
		 * server.publish("chat", new ArrayBuffer(4), true);
		 * ```
		 *
		 * @example
		 * ```js
		 * server.publish("chat", new DataView(new ArrayBuffer(4)));
		 * ```
		 */
		publish(
			topic: string,
			data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
			compress?: boolean,
		): ServerWebSocketSendStatus;

		/**
		 * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null.
		 *
		 * @example
		 * ```js
		 * export default {
		 *  async fetch(request, server) {
		 *    return new Response(server.requestIP(request));
		 *  }
		 * }
		 * ```
		 */
		requestIP(request: Request): SocketAddress | null;

		/**
		 * Undo a call to {@link Server.unref}
		 *
		 * If the Server has already been stopped, this does nothing.
		 *
		 * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle.
		 */
		ref(): void;

		/**
		 * Don't keep the process alive if this server is the only thing left.
		 * Active connections may continue to keep the process alive.
		 *
		 * By default, the server is ref'd.
		 *
		 * To prevent new connections from being accepted, use {@link Server.stop}
		 */
		unref(): void;

		/**
		 * How many requests are in-flight right now?
		 */
		readonly pendingRequests: number;

		/**
		 * How many {@link ServerWebSocket}s are in-flight right now?
		 */
		readonly pendingWebSockets: number;

		readonly url: URL;

		readonly port: number;
		/**
		 * The hostname the server is listening on. Does not include the port
		 * @example
		 * ```js
		 * "localhost"
		 * ```
		 */
		readonly hostname: string;
		/**
		 * Is the server running in development mode?
		 *
		 * In development mode, `Bun.serve()` returns rendered error messages with
		 * stack traces instead of a generic 500 error. This makes debugging easier,
		 * but development mode shouldn't be used in production or you will risk
		 * leaking sensitive information.
		 */
		readonly development: boolean;

		/**
		 * An identifier of the server instance
		 *
		 * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets.
		 *
		 * When bun is not started with the `--hot` flag, this ID is currently unused.
		 */
		readonly id: string;
	}

	/**
	 * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files.
	 *
	 * This Blob is lazy. That means it won't do any work until you read from it.
	 *
	 * - `size` will not be valid until the contents of the file are read at least once.
	 * - `type` is auto-set based on the file extension when possible
	 *
	 * @example
	 * ```js
	 * const file = Bun.file("./hello.json");
	 * console.log(file.type); // "application/json"
	 * console.log(await file.json()); // { hello: "world" }
	 * ```
	 *
	 * @example
	 * ```js
	 * await Bun.write(
	 *   Bun.file("./hello.txt"),
	 *   "Hello, world!"
	 * );
	 * ```
	 * @param path The path to the file (lazily loaded)
	 */
	// tslint:disable-next-line:unified-signatures
	function file(path: string | URL, options?: BlobPropertyBag): BunFile;

	/**
	 * A list of files embedded into the standalone executable. Lexigraphically sorted by name.
	 *
	 * If the process is not a standalone executable, this returns an empty array.
	 */
	const embeddedFiles: ReadonlyArray<Blob>;

	/**
	 * `Blob` that leverages the fastest system calls available to operate on files.
	 *
	 * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections.
	 *
	 * `Blob.size` will not be valid until the contents of the file are read at least once.
	 * `Blob.type` will have a default set based on the file extension
	 *
	 * @example
	 * ```js
	 * const file = Bun.file(new TextEncoder.encode("./hello.json"));
	 * console.log(file.type); // "application/json"
	 * ```
	 *
	 * @param path The path to the file as a byte buffer (the buffer is copied)
	 */
	// tslint:disable-next-line:unified-signatures
	function file(
		path: ArrayBufferLike | Uint8Array,
		options?: BlobPropertyBag,
	): BunFile;

	/**
	 * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files.
	 *
	 * This Blob is lazy. That means it won't do any work until you read from it.
	 *
	 * - `size` will not be valid until the contents of the file are read at least once.
	 *
	 * @example
	 * ```js
	 * const file = Bun.file(fd);
	 * ```
	 *
	 * @param fileDescriptor The file descriptor of the file
	 */
	// tslint:disable-next-line:unified-signatures
	function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile;

	/**
	 * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes.
	 *
	 * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory.
	 */
	function allocUnsafe(size: number): Uint8Array;

	interface BunInspectOptions {
		colors?: boolean;
		depth?: number;
		sorted?: boolean;
	}

	/**
	 * Pretty-print an object the same as {@link console.log} to a `string`
	 *
	 * Supports JSX
	 *
	 * @param args
	 */
	function inspect(arg: any, options?: BunInspectOptions): string;
	namespace inspect {
		/**
		 * That can be used to declare custom inspect functions.
		 */
		const custom: typeof import("util").inspect.custom;
	}

	interface MMapOptions {
		/**
		 * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support.
		 */
		sync?: boolean;
		/**
		 * Allow other processes to see results instantly?
		 * This enables MAP_SHARED. If false, it enables MAP_PRIVATE.
		 * @default true
		 */
		shared?: boolean;
	}
	/**
	 * Open a file as a live-updating `Uint8Array` without copying memory
	 * - Writing to the array writes to the file.
	 * - Reading from the array reads from the file.
	 *
	 * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood.
	 *
	 * ---
	 *
	 * This API inherently has some rough edges:
	 * - It does not support empty files. It will throw a `SystemError` with `EINVAL`
	 * - Usage on shared/networked filesystems is discouraged. It will be very slow.
	 * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault.
	 *
	 * ---
	 *
	 * To close the file, set the array to `null` and it will be garbage collected eventually.
	 */
	function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array;

	/** Write to stdout */
	const stdout: BunFile;
	/** Write to stderr */
	const stderr: BunFile;
	/**
	 * Read from stdin
	 *
	 * This is read-only
	 */
	const stdin: BunFile;

	type StringLike = string | { toString(): string };

	interface Semver {
		/**
		 * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`.
		 */
		satisfies(version: StringLike, range: StringLike): boolean;

		/**
		 * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater.
		 * Throws an error if either version is invalid.
		 */
		order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1;
	}
	var semver: Semver;

	interface Unsafe {
		/**
		 * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`.
		 *
		 * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`.
		 *
		 * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime.
		 */
		arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string;

		/**
		 * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array`
		 *
		 * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever.
		 *
		 * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime.
		 */
		// tslint:disable-next-line:unified-signatures
		arrayBufferToString(buffer: Uint16Array): string;

		/** Mock bun's segfault handler. You probably don't want to use this */
		segfault(): void;

		/**
		 * Force the garbage collector to run extremely often,
		 * especially inside `bun:test`.
		 *
		 * - `0`: default, disable
		 * - `1`: asynchronously call the garbage collector more often
		 * - `2`: synchronously call the garbage collector more often.
		 *
		 * This is a global setting. It's useful for debugging seemingly random crashes.
		 *
		 * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported.
		 *
		 * @param level
		 * @returns The previous level
		 */
		gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2;
	}
	const unsafe: Unsafe;

	type DigestEncoding = "hex" | "base64";

	/**
	 * Are ANSI colors enabled for stdin and stdout?
	 *
	 * Used for {@link console.log}
	 */
	const enableANSIColors: boolean;

	/**
	 * What script launched bun?
	 *
	 * Absolute file path
	 *
	 * @example "/never-gonna-give-you-up.js"
	 */
	const main: string;

	/**
	 * Manually trigger the garbage collector
	 *
	 * This does two things:
	 * 1. It tells JavaScriptCore to run the garbage collector
	 * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore.
	 *
	 * @param force Synchronously run the garbage collector
	 */
	function gc(force: boolean): void;

	/**
	 * JavaScriptCore engine's internal heap snapshot
	 *
	 * I don't know how to make this something Chrome or Safari can read.
	 *
	 * If you have any ideas, please file an issue https://github.com/oven-sh/bun
	 */
	interface HeapSnapshot {
		/** 2 */
		version: number;

		/** "Inspector" */
		type: string;

		nodes: number[];

		nodeClassNames: string[];
		edges: number[];
		edgeTypes: string[];
		edgeNames: string[];
	}

	/**
	 * Returns the number of nanoseconds since the process was started.
	 *
	 * This function uses a high-resolution monotonic system timer to provide precise time measurements.
	 * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754),
	 * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER).
	 *
	 * Due to this limitation, while the internal counter may continue beyond this point,
	 * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond
	 * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but
	 * with reduced precision, which might affect time calculations and comparisons in long-running applications.
	 *
	 * @returns {number} The number of nanoseconds since the process was started, with precise values up to
	 * Number.MAX_SAFE_INTEGER.
	 */
	function nanoseconds(): number;

	/**
	 * Generate a heap snapshot for seeing where the heap is being used
	 */
	function generateHeapSnapshot(): HeapSnapshot;

	/**
	 * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size.
	 */
	function shrink(): void;

	/**
	 * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR`
	 *
	 * @param path path to open
	 */
	function openInEditor(path: string, options?: EditorOptions): void;

	const fetch: typeof globalThis.fetch & {
		preconnect(url: string): void;
	};

	interface EditorOptions {
		editor?: "vscode" | "subl";
		line?: number;
		column?: number;
	}

	/**
	 * This class only exists in types
	 */
	abstract class CryptoHashInterface<T> {
		/**
		 * Update the hash with data
		 *
		 * @param data
		 */
		update(data: Bun.BlobOrStringOrBuffer): T;

		/**
		 * Finalize the hash
		 *
		 * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`.
		 */
		digest(encoding: DigestEncoding): string;

		/**
		 * Finalize the hash
		 *
		 * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time
		 */
		digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray;

		/**
		 * Run the hash over the given data
		 *
		 * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster.
		 *
		 * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time
		 */
		static hash(
			input: Bun.BlobOrStringOrBuffer,
			hashInto?: NodeJS.TypedArray,
		): NodeJS.TypedArray;

		/**
		 * Run the hash over the given data
		 *
		 * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster.
		 *
		 * @param encoding `DigestEncoding` to return the hash in
		 */
		static hash(
			input: Bun.BlobOrStringOrBuffer,
			encoding: DigestEncoding,
		): string;
	}

	type SupportedCryptoAlgorithms =
		| "blake2b256"
		| "blake2b512"
		| "md4"
		| "md5"
		| "ripemd160"
		| "sha1"
		| "sha224"
		| "sha256"
		| "sha384"
		| "sha512"
		| "sha512-224"
		| "sha512-256"
		| "sha3-224"
		| "sha3-256"
		| "sha3-384"
		| "sha3-512"
		| "shake128"
		| "shake256";

	/**
	 * Hardware-accelerated cryptographic hash functions
	 *
	 * Used for `crypto.createHash()`
	 */
	class CryptoHasher {
		/**
		 * The algorithm chosen to hash the data
		 */
		readonly algorithm: SupportedCryptoAlgorithms;

		/**
		 * The length of the output hash in bytes
		 */
		readonly byteLength: number;

		/**
		 * Create a new hasher
		 *
		 * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms
		 */
		constructor(algorithm: SupportedCryptoAlgorithms);

		/**
		 * Update the hash with data
		 *
		 * @param input
		 */
		update(
			input: Bun.BlobOrStringOrBuffer,
			inputEncoding?: CryptoEncoding,
		): CryptoHasher;

		/**
		 * Perform a deep copy of the hasher
		 */
		copy(): CryptoHasher;

		/**
		 * Finalize the hash. Resets the CryptoHasher so it can be reused.
		 *
		 * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`.
		 */
		digest(encoding: DigestEncoding): string;

		/**
		 * Finalize the hash
		 *
		 * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time
		 */
		digest(): Buffer;
		digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray;

		/**
		 * Run the hash over the given data
		 *
		 * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster.
		 *
		 * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time
		 */
		static hash(
			algorithm: SupportedCryptoAlgorithms,
			input: Bun.BlobOrStringOrBuffer,
		): Buffer;
		static hash(
			algorithm: SupportedCryptoAlgorithms,
			input: Bun.BlobOrStringOrBuffer,
			hashInto: NodeJS.TypedArray,
		): NodeJS.TypedArray;

		/**
		 * Run the hash over the given data
		 *
		 * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster.
		 *
		 * @param encoding `DigestEncoding` to return the hash in
		 */
		static hash(
			algorithm: SupportedCryptoAlgorithms,
			input: Bun.BlobOrStringOrBuffer,
			encoding: DigestEncoding,
		): string;

		/**
		 * List of supported hash algorithms
		 *
		 * These are hardware accelerated with BoringSSL
		 */
		static readonly algorithms: SupportedCryptoAlgorithms[];
	}

	/**
	 * Resolve a `Promise` after milliseconds. This is like
	 * {@link setTimeout} except it returns a `Promise`.
	 *
	 * @param ms milliseconds to delay resolving the promise. This is a minimum
	 * number. It may take longer. If a {@link Date} is passed, it will sleep until the
	 * {@link Date} is reached.
	 *
	 * @example
	 * ## Sleep for 1 second
	 * ```ts
	 * import { sleep } from "bun";
	 *
	 * await sleep(1000);
	 * ```
	 * ## Sleep for 10 milliseconds
	 * ```ts
	 * await Bun.sleep(10);
	 * ```
	 * ## Sleep until `Date`
	 *
	 * ```ts
	 * const target = new Date();
	 * target.setSeconds(target.getSeconds() + 1);
	 * await Bun.sleep(target);
	 * ```
	 * Internally, `Bun.sleep` is the equivalent of
	 * ```ts
	 * await new Promise((resolve) => setTimeout(resolve, ms));
	 * ```
	 * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably.
	 */
	function sleep(ms: number | Date): Promise<void>;

	/**
	 * Sleep the thread for a given number of milliseconds
	 *
	 * This is a blocking function.
	 *
	 * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html)
	 */
	function sleepSync(ms: number): void;

	/**
	 * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions)
	 *
	 * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster
	 * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum.
	 *
	 * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data.
	 *
	 * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go)
	 *
	 * The equivalent `openssl` command is:
	 *
	 * ```bash
	 * # You will need OpenSSL 3 or later
	 * openssl sha512-256 /path/to/file
	 * ```
	 */
	function sha(
		input: Bun.StringOrBuffer,
		hashInto?: NodeJS.TypedArray,
	): NodeJS.TypedArray;

	/**
	 * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions)
	 *
	 * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster
	 * @param encoding `DigestEncoding` to return the hash in
	 *
	 * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data.
	 *
	 * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go)
	 *
	 * The equivalent `openssl` command is:
	 *
	 * ```bash
	 * # You will need OpenSSL 3 or later
	 * openssl sha512-256 /path/to/file
	 * ```
	 */
	function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string;

	/**
	 * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512}
	 *
	 * Consider using the ugly-named {@link SHA512_256} instead
	 */
	class SHA1 extends CryptoHashInterface<SHA1> {
		constructor();

		/**
		 * The number of bytes the hash will produce
		 */
		static readonly byteLength: 20;
	}
	class MD5 extends CryptoHashInterface<MD5> {
		constructor();

		/**
		 * The number of bytes the hash will produce
		 */
		static readonly byteLength: 16;
	}
	class MD4 extends CryptoHashInterface<MD4> {
		constructor();

		/**
		 * The number of bytes the hash will produce
		 */
		static readonly byteLength: 16;
	}
	class SHA224 extends CryptoHashInterface<SHA224> {
		constructor();

		/**
		 * The number of bytes the hash will produce
		 */
		static readonly byteLength: 28;
	}
	class SHA512 extends CryptoHashInterface<SHA512> {
		constructor();

		/**
		 * The number of bytes the hash will produce
		 */
		static readonly byteLength: 64;
	}
	class SHA384 extends CryptoHashInterface<SHA384> {
		constructor();

		/**
		 * The number of bytes the hash will produce
		 */
		static readonly byteLength: 48;
	}
	class SHA256 extends CryptoHashInterface<SHA256> {
		constructor();

		/**
		 * The number of bytes the hash will produce
		 */
		static readonly byteLength: 32;
	}
	/**
	 * See also {@link sha}
	 */
	class SHA512_256 extends CryptoHashInterface<SHA512_256> {
		constructor();

		/**
		 * The number of bytes the hash will produce
		 */
		static readonly byteLength: 32;
	}

	/** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */
	interface ZlibCompressionOptions {
		/**
		 * The compression level to use. Must be between `-1` and `9`.
		 * - A value of `-1` uses the default compression level (Currently `6`)
		 * - A value of `0` gives no compression
		 * - A value of `1` gives least compression, fastest speed
		 * - A value of `9` gives best compression, slowest speed
		 */
		level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
		/**
		 * How much memory should be allocated for the internal compression state.
		 *
		 * A value of `1` uses minimum memory but is slow and reduces compression ratio.
		 *
		 * A value of `9` uses maximum memory for optimal speed. The default is `8`.
		 */
		memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
		/**
		 * The base 2 logarithm of the window size (the size of the history buffer).
		 *
		 * Larger values of this parameter result in better compression at the expense of memory usage.
		 *
		 * The following value ranges are supported:
		 * - `9..15`: The output will have a zlib header and footer (Deflate)
		 * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate)
		 * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip)
		 *
		 * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC.
		 */
		windowBits?:
			| -9
			| -10
			| -11
			| -12
			| -13
			| -14
			| -15
			| 9
			| 10
			| 11
			| 12
			| 13
			| 14
			| 15
			| 25
			| 26
			| 27
			| 28
			| 29
			| 30
			| 31;
		/**
		 * Tunes the compression algorithm.
		 *
		 * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)**
		 * - `Z_FILTERED`: For data produced by a filter or predictor
		 * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match)
		 * - `Z_RLE`: Limit match distances to one (run-length encoding)
		 * - `Z_FIXED` prevents the use of dynamic Huffman codes
		 *
		 * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data.
		 *
		 * `Z_FILTERED` forces more Huffman coding and less string matching, it is
		 * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`.
		 * Filtered data consists mostly of small values with a somewhat random distribution.
		 */
		strategy?: number;

		library?: "zlib";
	}

	interface LibdeflateCompressionOptions {
		level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
		library?: "libdeflate";
	}

	/**
	 * Compresses a chunk of data with `zlib` DEFLATE algorithm.
	 * @param data The buffer of data to compress
	 * @param options Compression options to use
	 * @returns The output buffer with the compressed data
	 */
	function deflateSync(
		data: Uint8Array | string | ArrayBuffer,
		options?: ZlibCompressionOptions | LibdeflateCompressionOptions,
	): Uint8Array;
	/**
	 * Compresses a chunk of data with `zlib` GZIP algorithm.
	 * @param data The buffer of data to compress
	 * @param options Compression options to use
	 * @returns The output buffer with the compressed data
	 */
	function gzipSync(
		data: Uint8Array | string | ArrayBuffer,
		options?: ZlibCompressionOptions | LibdeflateCompressionOptions,
	): Uint8Array;
	/**
	 * Decompresses a chunk of data with `zlib` INFLATE algorithm.
	 * @param data The buffer of data to decompress
	 * @returns The output buffer with the decompressed data
	 */
	function inflateSync(
		data: Uint8Array | string | ArrayBuffer,
		options?: ZlibCompressionOptions | LibdeflateCompressionOptions,
	): Uint8Array;
	/**
	 * Decompresses a chunk of data with `zlib` GUNZIP algorithm.
	 * @param data The buffer of data to decompress
	 * @returns The output buffer with the decompressed data
	 */
	function gunzipSync(
		data: Uint8Array | string | ArrayBuffer,
		options?: ZlibCompressionOptions | LibdeflateCompressionOptions,
	): Uint8Array;

	type Target =
		/**
		 * For generating bundles that are intended to be run by the Bun runtime. In many cases,
		 * it isn't necessary to bundle server-side code; you can directly execute the source code
		 * without modification. However, bundling your server code can reduce startup times and
		 * improve running performance.
		 *
		 * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which
		 * indicates to the Bun runtime that there's no need to re-transpile the file before execution.
		 */
		| "bun"
		/**
		 * The plugin will be applied to Node.js builds
		 */
		| "node"
		/**
		 * The plugin will be applied to browser builds
		 */
		| "browser";

	/** https://bun.sh/docs/bundler/loaders */
	type Loader =
		| "js"
		| "jsx"
		| "ts"
		| "tsx"
		| "json"
		| "toml"
		| "file"
		| "napi"
		| "wasm"
		| "text";

	interface PluginConstraints {
		/**
		 * Only apply the plugin when the import specifier matches this regular expression
		 *
		 * @example
		 * ```ts
		 * // Only apply the plugin when the import specifier matches the regex
		 * Bun.plugin({
		 *  setup(builder) {
		 *     builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => {
		 *      return { contents: "throw new Error('Please use lodash instead of underscore.')" };
		 *     });
		 *  }
		 * })
		 * ```
		 */
		filter: RegExp;

		/**
		 * Only apply the plugin when the import specifier has a namespace matching
		 * this string
		 *
		 * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"`
		 * has the namespace `"bun"`.
		 *
		 * The default namespace is `"file"` and it can be omitted from import
		 * specifiers.
		 */
		namespace?: string;
	}

	interface OnLoadResultSourceCode {
		/**
		 * The source code of the module
		 */
		contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer;
		/**
		 * The loader to use for this file
		 *
		 * "css" will be added in a future version of Bun.
		 */
		loader?: Loader;
	}

	interface OnLoadResultObject {
		/**
		 * The object to use as the module
		 * @example
		 * ```ts
		 * // In your loader
		 * builder.onLoad({ filter: /^hello:world$/ }, (args) => {
		 *    return { exports: { foo: "bar" }, loader: "object" };
		 * });
		 *
		 * // In your script
		 * import {foo} from "hello:world";
		 * console.log(foo); // "bar"
		 * ```
		 */
		exports: Record<string, unknown>;
		/**
		 * The loader to use for this file
		 */
		loader: "object";
	}

	interface OnLoadArgs {
		/**
		 * The resolved import specifier of the module being loaded
		 * @example
		 * ```ts
		 * builder.onLoad({ filter: /^hello:world$/ }, (args) => {
		 *   console.log(args.path); // "hello:world"
		 *   return { exports: { foo: "bar" }, loader: "object" };
		 * });
		 * ```
		 */
		path: string;
		/**
		 * The namespace of the module being loaded
		 */
		namespace: string;
		/**
		 * The default loader for this file extension
		 */
		loader: Loader;
	}

	type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject | undefined;
	type OnLoadCallback = (
		args: OnLoadArgs,
	) => OnLoadResult | Promise<OnLoadResult>;

	interface OnResolveArgs {
		/**
		 * The import specifier of the module being loaded
		 */
		path: string;
		/**
		 * The module that imported the module being resolved
		 */
		importer: string;
		/**
		 * The namespace of the importer.
		 */
		namespace: string;
		/**
		 * The kind of import this resolve is for.
		 */
		kind: ImportKind;
		// resolveDir: string;
		// pluginData: any;
	}

	interface OnResolveResult {
		/**
		 * The destination of the import
		 */
		path: string;
		/**
		 * The namespace of the destination
		 * It will be concatenated with `path` to form the final import specifier
		 * @example
		 * ```ts
		 * "foo" // "foo:bar"
		 * ```
		 */
		namespace?: string;
		external?: boolean;
	}

	type OnResolveCallback = (
		args: OnResolveArgs,
	) =>
		| OnResolveResult
		| Promise<OnResolveResult | undefined | null>
		| undefined
		| null;

	interface PluginBuilder {
		/**
		 * Register a callback to load imports with a specific import specifier
		 * @param constraints The constraints to apply the plugin to
		 * @param callback The callback to handle the import
		 * @example
		 * ```ts
		 * Bun.plugin({
		 *   setup(builder) {
		 *     builder.onLoad({ filter: /^hello:world$/ }, (args) => {
		 *       return { exports: { foo: "bar" }, loader: "object" };
		 *     });
		 *   },
		 * });
		 * ```
		 */
		onLoad(constraints: PluginConstraints, callback: OnLoadCallback): void;
		/**
		 * Register a callback to resolve imports matching a filter and/or namespace
		 * @param constraints The constraints to apply the plugin to
		 * @param callback The callback to handle the import
		 * @example
		 * ```ts
		 * Bun.plugin({
		 *   setup(builder) {
		 *     builder.onResolve({ filter: /^wat$/ }, (args) => {
		 *       return { path: "/tmp/woah.js" };
		 *     });
		 *   },
		 * });
		 * ```
		 */
		onResolve(
			constraints: PluginConstraints,
			callback: OnResolveCallback,
		): void;
		/**
		 * The config object passed to `Bun.build` as is. Can be mutated.
		 */
		config: BuildConfig & { plugins: BunPlugin[] };

		/**
		 * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules
		 *
		 * @param specifier The module specifier to register the callback for
		 * @param callback The function to run when the module is imported or required
		 *
		 * ### Example
		 * @example
		 * ```ts
		 * Bun.plugin({
		 *   setup(builder) {
		 *     builder.module("hello:world", () => {
		 *       return { exports: { foo: "bar" }, loader: "object" };
		 *     });
		 *   },
		 * });
		 *
		 * // sometime later
		 * const { foo } = await import("hello:world");
		 * console.log(foo); // "bar"
		 *
		 * // or
		 * const { foo } = require("hello:world");
		 * console.log(foo); // "bar"
		 * ```
		 */
		module(
			specifier: string,
			callback: () => OnLoadResult | Promise<OnLoadResult>,
		): void;
	}

	interface BunPlugin {
		/**
		 * Human-readable name of the plugin
		 *
		 * In a future version of Bun, this will be used in error messages.
		 */
		name?: string;

		/**
		 * The target JavaScript environment the plugin should be applied to.
		 * - `bun`: The default environment when using `bun run` or `bun` to load a script
		 * - `browser`: The plugin will be applied to browser builds
		 * - `node`: The plugin will be applied to Node.js builds
		 *
		 * If in Bun's runtime, the default target is `bun`.
		 *
		 * If unspecified, it is assumed that the plugin is compatible with the default target.
		 */
		target?: Target;
		/**
		 * A function that will be called when the plugin is loaded.
		 *
		 * This function may be called in the same tick that it is registered, or it may be called later. It could potentially be called multiple times for different targets.
		 */
		setup(
			/**
			 * A builder object that can be used to register plugin hooks
			 * @example
			 * ```ts
			 * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({
			 *   loader: "object",
			 *   exports: require("js-yaml").load(fs.readFileSync(path, "utf8")),
			 * }));
			 * ```
			 */
			build: PluginBuilder,
		): void | Promise<void>;
	}

	/**
	 * Extend Bun's module resolution and loading behavior
	 *
	 * Plugins are applied in the order they are defined.
	 *
	 * Today, there are two kinds of hooks:
	 * - `onLoad` lets you return source code or an object that will become the module's exports
	 * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain.
	 *
	 * Plugin hooks must define a `filter` RegExp and will only be matched if the
	 * import specifier contains a "." or a ":".
	 *
	 * ES Module resolution semantics mean that plugins may be initialized _after_
	 * a module is resolved. You might need to load plugins at the very beginning
	 * of the application and then use a dynamic import to load the rest of the
	 * application. A future version of Bun may also support specifying plugins
	 * via `bunfig.toml`.
	 *
	 * @example
	 * A YAML loader plugin
	 *
	 * ```js
	 * Bun.plugin({
	 *  setup(builder) {
	 *   builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({
	 *     loader: "object",
	 *     exports: require("js-yaml").load(fs.readFileSync(path, "utf8"))
	 *   }));
	 * });
	 *
	 * // You can use require()
	 * const {foo} = require("./file.yaml");
	 *
	 * // Or import
	 * await import("./file.yaml");
	 *
	 * ```
	 */
	interface BunRegisterPlugin {
		<T extends BunPlugin>(options: T): ReturnType<T["setup"]>;

		/**
		 * Deactivate all plugins
		 *
		 * This prevents registered plugins from being applied to future builds.
		 */
		clearAll(): void;
	}

	const plugin: BunRegisterPlugin;

	/**
	 * Is the current global scope the main thread?
	 */
	const isMainThread: boolean;

	interface Socket<Data = undefined> extends Disposable {
		/**
		 * Write `data` to the socket
		 *
		 * @param data The data to write to the socket
		 * @param byteOffset The offset in the buffer to start writing from (defaults to 0)
		 * @param byteLength The number of bytes to write (defaults to the length of the buffer)
		 *
		 * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset.
		 *
		 * This is unbuffered as of Bun v0.2.2. That means individual write() calls
		 * will be slow. In the future, Bun will buffer writes and flush them at the
		 * end of the tick, when the event loop is idle, or sooner if the buffer is full.
		 */
		write(
			data: string | Bun.BufferSource,
			byteOffset?: number,
			byteLength?: number,
		): number;

		/**
		 * The data context for the socket.
		 */
		data: Data;

		/**
		 * Like {@link Socket.write} except it includes a TCP FIN packet
		 *
		 * Use it to send your last message and close the connection.
		 */
		end(
			data?: string | Bun.BufferSource,
			byteOffset?: number,
			byteLength?: number,
		): number;

		/**
		 * Close the socket immediately
		 */
		end(): void;

		/**
		 * Keep Bun's process alive at least until this socket is closed
		 *
		 * After the socket has closed, the socket is unref'd, the process may exit,
		 * and this becomes a no-op
		 */
		ref(): void;

		/**
		 * Set a timeout until the socket automatically closes.
		 *
		 * To reset the timeout, call this function again.
		 *
		 * When a timeout happens, the `timeout` callback is called and the socket is closed.
		 */
		timeout(seconds: number): void;

		/**
		 * Forcefully close the socket. The other end may not receive all data, and
		 * the socket will be closed immediately.
		 *
		 * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to
		 * `0` and then calls `close(2)`.
		 */
		terminate(): void;

		/**
		 * Shutdown writes to a socket
		 *
		 * This makes the socket a half-closed socket. It can still receive data.
		 *
		 * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally
		 */
		shutdown(halfClose?: boolean): void;

		readonly readyState: "open" | "closing" | "closed";

		/**
		 * Allow Bun's process to exit even if this socket is still open
		 *
		 * After the socket has closed, this function does nothing.
		 */
		unref(): void;

		/**
		 * Flush any buffered data to the socket
		 */
		flush(): void;

		/**
		 * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading.
		 *
		 * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}.
		 */
		reload(handler: SocketHandler): void;

		/**
		 * Get the server that created this socket
		 *
		 * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed.
		 */
		readonly listener?: SocketListener;

		/**
		 * Remote IP address connected to the socket
		 */
		readonly remoteAddress: string;

		/**
		 * local port connected to the socket
		 */
		readonly localPort: number;

		/**
		 * This property is `true` if the peer certificate was signed by one of the CAs
		 * specified when creating the `Socket` instance, otherwise `false`.
		 */
		readonly authorized: boolean;

		/**
		 * String containing the selected ALPN protocol.
		 * Before a handshake has completed, this value is always null.
		 * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false.
		 */
		readonly alpnProtocol: string | false | null;

		/**
		 * Disables TLS renegotiation for this `Socket` instance. Once called, attempts
		 * to renegotiate will trigger an `error` handler on the `Socket`.
		 *
		 * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.)
		 */
		disableRenegotiation(): void;

		/**
		 * Keying material is used for validations to prevent different kind of attacks in
		 * network protocols, for example in the specifications of IEEE 802.1X.
		 *
		 * Example
		 *
		 * ```js
		 * const keyingMaterial = socket.exportKeyingMaterial(
		 *   128,
		 *   'client finished');
		 *
		 * /*
		 *  Example return value of keyingMaterial:
		 *  <Buffer 76 26 af 99 c5 56 8e 42 09 91 ef 9f 93 cb ad 6c 7b 65 f8 53 f1 d8 d9
		 *     12 5a 33 b8 b5 25 df 7b 37 9f e0 e2 4f b8 67 83 a3 2f cd 5d 41 42 4c 91
		 *     74 ef 2c ... 78 more bytes>
		 *
		 * ```
		 *
		 * @param length number of bytes to retrieve from keying material
		 * @param label an application specific label, typically this will be a value from the [IANA Exporter Label
		 * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels).
		 * @param context Optionally provide a context.
		 * @return requested bytes of the keying material
		 */
		exportKeyingMaterial(
			length: number,
			label: string,
			context: Buffer,
		): Buffer;

		/**
		 * Returns the reason why the peer's certificate was not been verified. This
		 * property is set only when `socket.authorized === false`.
		 */
		getAuthorizationError(): Error | null;

		/**
		 * Returns an object representing the local certificate. The returned object has
		 * some properties corresponding to the fields of the certificate.
		 *
		 * If there is no local certificate, an empty object will be returned. If the
		 * socket has been destroyed, `null` will be returned.
		 */
		getCertificate(): PeerCertificate | object | null;

		/**
		 * Returns an object containing information on the negotiated cipher suite.
		 *
		 * For example, a TLSv1.2 protocol with AES256-SHA cipher:
		 *
		 * ```json
		 * {
		 *     "name": "AES256-SHA",
		 *     "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA",
		 *     "version": "SSLv3"
		 * }
		 * ```
		 *
		 */
		getCipher(): CipherNameAndProtocol;

		/**
		 * Returns an object representing the type, name, and size of parameter of
		 * an ephemeral key exchange in `perfect forward secrecy` on a client
		 * connection. It returns an empty object when the key exchange is not
		 * ephemeral. As this is only supported on a client socket; `null` is returned
		 * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`.
		 *
		 * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`.
		 */
		getEphemeralKeyInfo(): EphemeralKeyInfo | object | null;

		/**
		 * Returns an object representing the peer's certificate. If the peer does not
		 * provide a certificate, an empty object will be returned. If the socket has been
		 * destroyed, `null` will be returned.
		 *
		 * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's
		 * certificate.
		 * @return A certificate object.
		 */
		getPeerCertificate(): PeerCertificate;

		/**
		 * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information.
		 * @since v12.11.0
		 * @return List of signature algorithms shared between the server and the client in the order of decreasing preference.
		 */
		getSharedSigalgs(): string[];

		/**
		 * As the `Finished` messages are message digests of the complete handshake
		 * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can
		 * be used for external authentication procedures when the authentication
		 * provided by SSL/TLS is not desired or is not enough.
		 *
		 * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet.
		 */
		getTLSFinishedMessage(): Buffer | undefined;

		/**
		 * As the `Finished` messages are message digests of the complete handshake
		 * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can
		 * be used for external authentication procedures when the authentication
		 * provided by SSL/TLS is not desired or is not enough.
		 *
		 * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so
		 * far.
		 */
		getTLSPeerFinishedMessage(): Buffer | undefined;

		/**
		 * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`.
		 *
		 * It may be useful for debugging.
		 *
		 * See `Session Resumption` for more information.
		 */
		getTLSTicket(): Buffer | undefined;

		/**
		 * Returns a string containing the negotiated SSL/TLS protocol version of the
		 * current connection. The value `'unknown'` will be returned for connected
		 * sockets that have not completed the handshaking process. The value `null` will
		 * be returned for server sockets or disconnected client sockets.
		 *
		 * Protocol versions are:
		 *
		 * * `'SSLv3'`
		 * * `'TLSv1'`
		 * * `'TLSv1.1'`
		 * * `'TLSv1.2'`
		 * * `'TLSv1.3'`
		 *
		 */
		getTLSVersion(): string;

		/**
		 * See `Session Resumption` for more information.
		 * @return `true` if the session was reused, `false` otherwise.
		 */
		isSessionReused(): boolean;

		/**
		 * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size.
		 * Returns `true` if setting the limit succeeded; `false` otherwise.
		 *
		 * Smaller fragment sizes decrease the buffering latency on the client: larger
		 * fragments are buffered by the TLS layer until the entire fragment is received
		 * and its integrity is verified; large fragments can span multiple roundtrips
		 * and their processing can be delayed due to packet loss or reordering. However,
		 * smaller fragments add extra TLS framing bytes and CPU overhead, which may
		 * decrease overall server throughput.
		 * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`.
		 */
		setMaxSendFragment(size: number): boolean;
	}

	interface SocketListener<Data = undefined> extends Disposable {
		stop(closeActiveConnections?: boolean): void;
		ref(): void;
		unref(): void;
		reload(options: Pick<Partial<SocketOptions>, "socket">): void;
		data: Data;
	}
	interface TCPSocketListener<Data = unknown> extends SocketListener<Data> {
		readonly port: number;
		readonly hostname: string;
	}
	interface UnixSocketListener<Data> extends SocketListener<Data> {
		readonly unix: string;
	}

	interface TCPSocket extends Socket {}
	interface TLSSocket extends Socket {}

	interface BinaryTypeList {
		arraybuffer: ArrayBuffer;
		buffer: Buffer;
		uint8array: Uint8Array;
		// TODO: DataView
		// dataview: DataView;
	}
	type BinaryType = keyof BinaryTypeList;

	interface SocketHandler<
		Data = unknown,
		DataBinaryType extends BinaryType = "buffer",
	> {
		/**
		 * Is called when the socket connects, or in case of TLS if no handshake is provided
		 * this will be called only after handshake
		 * @param socket
		 */
		open?(socket: Socket<Data>): void | Promise<void>;
		close?(socket: Socket<Data>): void | Promise<void>;
		error?(socket: Socket<Data>, error: Error): void | Promise<void>;
		data?(
			socket: Socket<Data>,
			data: BinaryTypeList[DataBinaryType],
		): void | Promise<void>;
		drain?(socket: Socket<Data>): void | Promise<void>;

		/**
		 * When handshake is completed, this functions is called.
		 * @param socket
		 * @param success Indicates if the server authorized despite the authorizationError.
		 * @param authorizationError Certificate Authorization Error or null.
		 */
		handshake?(
			socket: Socket<Data>,
			success: boolean,
			authorizationError: Error | null,
		): void;

		/**
		 * When the socket has been shutdown from the other end, this function is
		 * called. This is a TCP FIN packet.
		 */
		end?(socket: Socket<Data>): void | Promise<void>;

		/**
		 * When the socket fails to be created, this function is called.
		 *
		 * The promise returned by `Bun.connect` rejects **after** this function is
		 * called.
		 *
		 * When `connectError` is specified, the rejected promise will not be
		 * added to the promise rejection queue (so it won't be reported as an
		 * unhandled promise rejection, since connectError handles it).
		 *
		 * When `connectError` is not specified, the rejected promise will be added
		 * to the promise rejection queue.
		 */
		connectError?(socket: Socket<Data>, error: Error): void | Promise<void>;

		/**
		 * Called when a message times out.
		 */
		timeout?(socket: Socket<Data>): void | Promise<void>;
		/**
		 * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback.
		 *
		 * @default "buffer"
		 *
		 * @remarks
		 * This lets you select the desired binary type for the `data` callback.
		 * It's a small performance optimization to let you avoid creating extra
		 * ArrayBufferView objects when possible.
		 *
		 * Bun originally defaulted to `Uint8Array` but when dealing with network
		 * data, it's more useful to be able to directly read from the bytes which
		 * `Buffer` allows.
		 */
		binaryType?: BinaryType;
	}

	interface SocketOptions<Data = unknown> {
		socket: SocketHandler<Data>;
		data?: Data;
	}
	// interface TCPSocketOptions<Data = undefined> extends SocketOptions<Data> {
	//   hostname: string;
	//   port: number;
	// }

	interface TCPSocketListenOptions<Data = undefined>
		extends SocketOptions<Data> {
		hostname: string;
		port: number;
		tls?: TLSOptions;
	}

	interface TCPSocketConnectOptions<Data = undefined>
		extends SocketOptions<Data> {
		hostname: string;
		port: number;
		tls?: boolean;
	}

	interface UnixSocketOptions<Data = undefined> extends SocketOptions<Data> {
		unix: string;
	}

	/**
	 * Create a TCP client that connects to a server
	 *
	 * @param options The options to use when creating the client
	 * @param options.socket The socket handler to use
	 * @param options.data The per-instance data context
	 * @param options.hostname The hostname to connect to
	 * @param options.port The port to connect to
	 * @param options.tls The TLS configuration object
	 * @param options.unix The unix socket to connect to
	 */
	function connect<Data = undefined>(
		options: TCPSocketConnectOptions<Data>,
	): Promise<Socket<Data>>;
	function connect<Data = undefined>(
		options: UnixSocketOptions<Data>,
	): Promise<Socket<Data>>;

	/**
	 * Create a TCP server that listens on a port
	 *
	 * @param options The options to use when creating the server
	 * @param options.socket The socket handler to use
	 * @param options.data The per-instance data context
	 * @param options.hostname The hostname to connect to
	 * @param options.port The port to connect to
	 * @param options.tls The TLS configuration object
	 * @param options.unix The unix socket to connect to
	 */
	function listen<Data = undefined>(
		options: TCPSocketListenOptions<Data>,
	): TCPSocketListener<Data>;
	function listen<Data = undefined>(
		options: UnixSocketOptions<Data>,
	): UnixSocketListener<Data>;

	namespace udp {
		type Data = string | ArrayBufferView | ArrayBufferLike;

		export interface SocketHandler<DataBinaryType extends BinaryType> {
			data?(
				socket: Socket<DataBinaryType>,
				data: BinaryTypeList[DataBinaryType],
				port: number,
				address: string,
			): void | Promise<void>;
			drain?(socket: Socket<DataBinaryType>): void | Promise<void>;
			error?(
				socket: Socket<DataBinaryType>,
				error: Error,
			): void | Promise<void>;
		}

		export interface ConnectedSocketHandler<DataBinaryType extends BinaryType> {
			data?(
				socket: ConnectedSocket<DataBinaryType>,
				data: BinaryTypeList[DataBinaryType],
				port: number,
				address: string,
			): void | Promise<void>;
			drain?(socket: ConnectedSocket<DataBinaryType>): void | Promise<void>;
			error?(
				socket: ConnectedSocket<DataBinaryType>,
				error: Error,
			): void | Promise<void>;
		}

		export interface SocketOptions<DataBinaryType extends BinaryType> {
			hostname?: string;
			port?: number;
			binaryType?: DataBinaryType;
			socket?: SocketHandler<DataBinaryType>;
		}

		export interface ConnectSocketOptions<DataBinaryType extends BinaryType> {
			hostname?: string;
			port?: number;
			binaryType?: DataBinaryType;
			socket?: ConnectedSocketHandler<DataBinaryType>;
			connect: {
				hostname: string;
				port: number;
			};
		}

		export interface BaseUDPSocket {
			readonly hostname: string;
			readonly port: number;
			readonly address: SocketAddress;
			readonly binaryType: BinaryType;
			readonly closed: boolean;
			ref(): void;
			unref(): void;
			close(): void;
		}

		export interface ConnectedSocket<DataBinaryType extends BinaryType>
			extends BaseUDPSocket {
			readonly remoteAddress: SocketAddress;
			sendMany(packets: readonly Data[]): number;
			send(data: Data): boolean;
			reload(handler: ConnectedSocketHandler<DataBinaryType>): void;
		}

		export interface Socket<DataBinaryType extends BinaryType>
			extends BaseUDPSocket {
			sendMany(packets: readonly (Data | string | number)[]): number;
			send(data: Data, port: number, address: string): boolean;
			reload(handler: SocketHandler<DataBinaryType>): void;
		}
	}

	/**
	 * Create a UDP socket
	 *
	 * @param options The options to use when creating the server
	 * @param options.socket The socket handler to use
	 * @param options.hostname The hostname to listen on
	 * @param options.port The port to listen on
	 * @param options.binaryType The binary type to use for the socket
	 * @param options.connect The hostname and port to connect to
	 */
	export function udpSocket<DataBinaryType extends BinaryType = "buffer">(
		options: udp.SocketOptions<DataBinaryType>,
	): Promise<udp.Socket<DataBinaryType>>;
	export function udpSocket<DataBinaryType extends BinaryType = "buffer">(
		options: udp.ConnectSocketOptions<DataBinaryType>,
	): Promise<udp.ConnectedSocket<DataBinaryType>>;

	namespace SpawnOptions {
		/**
		 * Option for stdout/stderr
		 */
		type Readable =
			| "pipe"
			| "inherit"
			| "ignore"
			| null // equivalent to "ignore"
			| undefined // to use default
			| BunFile
			| ArrayBufferView
			| number;

		/**
		 * Option for stdin
		 */
		type Writable =
			| "pipe"
			| "inherit"
			| "ignore"
			| null // equivalent to "ignore"
			| undefined // to use default
			| BunFile
			| ArrayBufferView
			| number
			| ReadableStream
			| Blob
			| Response
			| Request;

		interface OptionsObject<
			In extends Writable = Writable,
			Out extends Readable = Readable,
			Err extends Readable = Readable,
		> {
			/**
			 * The current working directory of the process
			 *
			 * Defaults to `process.cwd()`
			 */
			cwd?: string;

			/**
			 * The environment variables of the process
			 *
			 * Defaults to `process.env` as it was when the current Bun process launched.
			 *
			 * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly.
			 */
			env?: Record<string, string | undefined>;

			/**
			 * The standard file descriptors of the process, in the form [stdin, stdout, stderr].
			 * This overrides the `stdin`, `stdout`, and `stderr` properties.
			 *
			 * For stdin you may pass:
			 *
			 * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default)
			 * - `"pipe"`: The process will have a new {@link FileSink} for standard input
			 * - `"inherit"`: The process will inherit the standard input of the current process
			 * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream.
			 * - `number`: The process will read from the file descriptor
			 *
			 * For stdout and stdin you may pass:
			 *
			 * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error
			 * - `"ignore"`, `null`: The process will have no standard output/error
			 * - `"inherit"`: The process will inherit the standard output/error of the current process
			 * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented.
			 * - `number`: The process will write to the file descriptor
			 *
			 * @default ["ignore", "pipe", "inherit"] for `spawn`
			 * ["ignore", "pipe", "pipe"] for `spawnSync`
			 */
			stdio?: [In, Out, Err];
			/**
			 * The file descriptor for the standard input. It may be:
			 *
			 * - `"ignore"`, `null`, `undefined`: The process will have no standard input
			 * - `"pipe"`: The process will have a new {@link FileSink} for standard input
			 * - `"inherit"`: The process will inherit the standard input of the current process
			 * - `ArrayBufferView`, `Blob`: The process will read from the buffer
			 * - `number`: The process will read from the file descriptor
			 *
			 * @default "ignore"
			 */
			stdin?: In;
			/**
			 * The file descriptor for the standard output. It may be:
			 *
			 * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error
			 * - `"ignore"`, `null`: The process will have no standard output/error
			 * - `"inherit"`: The process will inherit the standard output/error of the current process
			 * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented.
			 * - `number`: The process will write to the file descriptor
			 *
			 * @default "pipe"
			 */
			stdout?: Out;
			/**
			 * The file descriptor for the standard error. It may be:
			 *
			 * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error
			 * - `"ignore"`, `null`: The process will have no standard output/error
			 * - `"inherit"`: The process will inherit the standard output/error of the current process
			 * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented.
			 * - `number`: The process will write to the file descriptor
			 *
			 * @default "inherit" for `spawn`
			 * "pipe" for `spawnSync`
			 */
			stderr?: Err;

			/**
			 * Callback that runs when the {@link Subprocess} exits
			 *
			 * This is called even if the process exits with a non-zero exit code.
			 *
			 * Warning: this may run before the `Bun.spawn` function returns.
			 *
			 * A simple alternative is `await subprocess.exited`.
			 *
			 * @example
			 *
			 * ```ts
			 * const subprocess = spawn({
			 *  cmd: ["echo", "hello"],
			 *  onExit: (subprocess, code) => {
			 *    console.log(`Process exited with code ${code}`);
			 *   },
			 * });
			 * ```
			 */
			onExit?(
				subprocess: Subprocess<In, Out, Err>,
				exitCode: number | null,
				signalCode: number | null,
				/**
				 * If an error occurred in the call to waitpid2, this will be the error.
				 */
				error?: ErrorLike,
			): void | Promise<void>;

			/**
			 * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for
			 * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized
			 * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports.
			 *
			 * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`,
			 * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used.
			 *
			 * Currently, this is only compatible with processes that are other `bun` instances.
			 */
			ipc?(
				message: any,
				/**
				 * The {@link Subprocess} that sent the message
				 */
				subprocess: Subprocess<In, Out, Err>,
			): void;

			/**
			 * The serialization format to use for IPC messages. Defaults to `"advanced"`.
			 *
			 * To communicate with Node.js processes, use `"json"`.
			 *
			 * When `ipc` is not specified, this is ignored.
			 */
			serialization?: "json" | "advanced";

			/**
			 * If true, the subprocess will have a hidden window.
			 */
			windowsHide?: boolean;

			/**
			 * If true, no quoting or escaping of arguments is done on Windows.
			 */
			windowsVerbatimArguments?: boolean;

			/**
			 * Path to the executable to run in the subprocess. This defaults to `cmds[0]`.
			 *
			 * One use-case for this is for applications which wrap other applications or to simulate a symlink.
			 *
			 * @default cmds[0]
			 */
			argv0?: string;
		}

		type OptionsToSubprocess<Opts extends OptionsObject> =
			Opts extends OptionsObject<infer In, infer Out, infer Err>
				? Subprocess<
						// "Writable extends In" means "if In === Writable",
						// aka if true that means the user didn't specify anything
						Writable extends In ? "ignore" : In,
						Readable extends Out ? "pipe" : Out,
						Readable extends Err ? "inherit" : Err
					>
				: Subprocess<Writable, Readable, Readable>;

		type OptionsToSyncSubprocess<Opts extends OptionsObject> =
			Opts extends OptionsObject<any, infer Out, infer Err>
				? SyncSubprocess<
						Readable extends Out ? "pipe" : Out,
						Readable extends Err ? "pipe" : Err
					>
				: SyncSubprocess<Readable, Readable>;

		type ReadableIO = ReadableStream<Uint8Array> | number | undefined;

		type ReadableToIO<X extends Readable> = X extends "pipe" | undefined
			? ReadableStream<Uint8Array>
			: X extends BunFile | ArrayBufferView | number
				? number
				: undefined;

		type ReadableToSyncIO<X extends Readable> = X extends "pipe" | undefined
			? Buffer
			: undefined;

		type WritableIO = FileSink | number | undefined;

		type WritableToIO<X extends Writable> = X extends "pipe"
			? FileSink
			: X extends BunFile | ArrayBufferView | Blob | Request | Response | number
				? number
				: undefined;
	}

	interface ResourceUsage {
		/**
		 * The number of voluntary and involuntary context switches that the process made.
		 */
		contextSwitches: {
			/**
			 * Voluntary context switches (context switches that the process initiated).
			 */
			voluntary: number;
			/**
			 * Involuntary context switches (context switches initiated by the system scheduler).
			 */
			involuntary: number;
		};

		/**
		 * The amount of CPU time used by the process, in microseconds.
		 */
		cpuTime: {
			/**
			 * User CPU time used by the process, in microseconds.
			 */
			user: number;
			/**
			 * System CPU time used by the process, in microseconds.
			 */
			system: number;
			/**
			 * Total CPU time used by the process, in microseconds.
			 */
			total: number;
		};
		/**
		 * The maximum amount of resident set size (in bytes) used by the process during its lifetime.
		 */
		maxRSS: number;

		/**
		 * IPC messages sent and received by the process.
		 */
		messages: {
			/**
			 * The number of IPC messages sent.
			 */
			sent: number;
			/**
			 * The number of IPC messages received.
			 */
			received: number;
		};
		/**
		 * The number of IO operations done by the process.
		 */
		ops: {
			/**
			 * The number of input operations via the file system.
			 */
			in: number;
			/**
			 * The number of output operations via the file system.
			 */
			out: number;
		};
		/**
		 * The amount of shared memory that the process used.
		 */
		shmSize: number;
		/**
		 * The number of signals delivered to the process.
		 */
		signalCount: number;
		/**
		 *  The number of times the process was swapped out of main memory.
		 */
		swapCount: number;
	}

	/**
	 * A process created by {@link Bun.spawn}.
	 *
	 * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead:
	 * - {@link ReadableSubprocess} (any, pipe, pipe)
	 * - {@link WritableSubprocess} (pipe, any, any)
	 * - {@link PipedSubprocess} (pipe, pipe, pipe)
	 * - {@link NullSubprocess} (ignore, ignore, ignore)
	 */
	interface Subprocess<
		In extends SpawnOptions.Writable = SpawnOptions.Writable,
		Out extends SpawnOptions.Readable = SpawnOptions.Readable,
		Err extends SpawnOptions.Readable = SpawnOptions.Readable,
	> extends AsyncDisposable {
		readonly stdin: SpawnOptions.WritableToIO<In>;
		readonly stdout: SpawnOptions.ReadableToIO<Out>;
		readonly stderr: SpawnOptions.ReadableToIO<Err>;

		/**
		 * This returns the same value as {@link Subprocess.stdout}
		 *
		 * It exists for compatibility with {@link ReadableStream.pipeThrough}
		 */
		readonly readable: SpawnOptions.ReadableToIO<Out>;

		/**
		 * The process ID of the child process
		 * @example
		 * ```ts
		 * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] });
		 * console.log(pid); // 1234
		 * ```
		 */
		readonly pid: number;
		/**
		 * The exit code of the process
		 *
		 * The promise will resolve when the process exits
		 */
		readonly exited: Promise<number>;

		/**
		 * Synchronously get the exit code of the process
		 *
		 * If the process hasn't exited yet, this will return `null`
		 */
		readonly exitCode: number | null;

		/**
		 * Synchronously get the signal code of the process
		 *
		 * If the process never sent a signal code, this will return `null`
		 *
		 * To receive signal code changes, use the `onExit` callback.
		 *
		 * If the signal code is unknown, it will return the original signal code
		 * number, but that case should essentially never happen.
		 */
		readonly signalCode: NodeJS.Signals | null;

		/**
		 * Has the process exited?
		 */
		readonly killed: boolean;

		/**
		 * Kill the process
		 * @param exitCode The exitCode to send to the process
		 */
		kill(exitCode?: number | NodeJS.Signals): void;

		/**
		 * This method will tell Bun to wait for this process to exit after you already
		 * called `unref()`.
		 *
		 * Before shutting down, Bun will wait for all subprocesses to exit by default
		 */
		ref(): void;

		/**
		 * Before shutting down, Bun will wait for all subprocesses to exit by default
		 *
		 * This method will tell Bun to not wait for this process to exit before shutting down.
		 */
		unref(): void;

		/**
		 * Send a message to the subprocess. This is only supported if the subprocess
		 * was created with the `ipc` option, and is another instance of `bun`.
		 *
		 * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports.
		 */
		send(message: any): void;

		/**
		 * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess
		 * was created with the `ipc` option.
		 */
		disconnect(): void;

		/**
		 * Get the resource usage information of the process (max RSS, CPU time, etc)
		 *
		 * Only available after the process has exited
		 *
		 * If the process hasn't exited yet, this will return `undefined`
		 */
		resourceUsage(): ResourceUsage | undefined;
	}

	/**
	 * A process created by {@link Bun.spawnSync}.
	 *
	 * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead:
	 * - {@link ReadableSyncSubprocess} (pipe, pipe)
	 * - {@link NullSyncSubprocess} (ignore, ignore)
	 */
	interface SyncSubprocess<
		Out extends SpawnOptions.Readable = SpawnOptions.Readable,
		Err extends SpawnOptions.Readable = SpawnOptions.Readable,
	> {
		stdout: SpawnOptions.ReadableToSyncIO<Out>;
		stderr: SpawnOptions.ReadableToSyncIO<Err>;
		exitCode: number;
		success: boolean;
		/**
		 * Get the resource usage information of the process (max RSS, CPU time, etc)
		 */
		resourceUsage: ResourceUsage;

		signalCode?: string;
	}

	/**
	 * Spawn a new process
	 *
	 * ```js
	 * const subprocess = Bun.spawn({
	 *  cmd: ["echo", "hello"],
	 *  stdout: "pipe",
	 * });
	 * const text = await readableStreamToText(subprocess.stdout);
	 * console.log(text); // "hello\n"
	 * ```
	 *
	 * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html)
	 */
	function spawn<Opts extends SpawnOptions.OptionsObject>(
		options: Opts & {
			/**
			 * The command to run
			 *
			 * The first argument will be resolved to an absolute executable path. It must be a file, not a directory.
			 *
			 * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`.
			 *
			 * To check if the command exists before running it, use `Bun.which(bin)`.
			 *
			 * @example
			 * ```ts
			 * const subprocess = Bun.spawn(["echo", "hello"]);
			 * ```
			 */
			cmd: string[]; // to support dynamically constructed commands
		},
	): SpawnOptions.OptionsToSubprocess<Opts>;

	/**
	 * Spawn a new process
	 *
	 * ```js
	 * const {stdout} = Bun.spawn(["echo", "hello"]);
	 * const text = await readableStreamToText(stdout);
	 * console.log(text); // "hello\n"
	 * ```
	 *
	 * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html)
	 */
	function spawn<Opts extends SpawnOptions.OptionsObject>(
		/**
		 * The command to run
		 *
		 * The first argument will be resolved to an absolute executable path. It must be a file, not a directory.
		 *
		 * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`.
		 *
		 * To check if the command exists before running it, use `Bun.which(bin)`.
		 *
		 * @example
		 * ```ts
		 * const subprocess = Bun.spawn(["echo", "hello"]);
		 * ```
		 */
		cmds: string[],
		options?: Opts,
	): SpawnOptions.OptionsToSubprocess<Opts>;

	/**
	 * Spawn a new process
	 *
	 * ```js
	 * const {stdout} = Bun.spawnSync({
	 *  cmd: ["echo", "hello"],
	 * });
	 * console.log(stdout.toString()); // "hello\n"
	 * ```
	 *
	 * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html)
	 */
	function spawnSync<Opts extends SpawnOptions.OptionsObject>(
		options: Opts & {
			/**
			 * The command to run
			 *
			 * The first argument will be resolved to an absolute executable path. It must be a file, not a directory.
			 *
			 * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`.
			 *
			 * To check if the command exists before running it, use `Bun.which(bin)`.
			 *
			 * @example
			 * ```ts
			 * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] });
			 * ```
			 */
			cmd: string[];

			onExit?: never;
		},
	): SpawnOptions.OptionsToSyncSubprocess<Opts>;

	/**
	 * Synchronously spawn a new process
	 *
	 * ```js
	 * const {stdout} = Bun.spawnSync(["echo", "hello"]);
	 * console.log(stdout.toString()); // "hello\n"
	 * ```
	 *
	 * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html)
	 */
	function spawnSync<Opts extends SpawnOptions.OptionsObject>(
		/**
		 * The command to run
		 *
		 * The first argument will be resolved to an absolute executable path. It must be a file, not a directory.
		 *
		 * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`.
		 *
		 * To check if the command exists before running it, use `Bun.which(bin)`.
		 *
		 * @example
		 * ```ts
		 * const subprocess = Bun.spawnSync(["echo", "hello"]);
		 * ```
		 */
		cmds: string[],
		options?: Opts,
	): SpawnOptions.OptionsToSyncSubprocess<Opts>;

	/** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */
	type ReadableSubprocess = Subprocess<any, "pipe", "pipe">;
	/** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */
	type WritableSubprocess = Subprocess<"pipe", any, any>;
	/** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */
	type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">;
	/** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */
	type NullSubprocess = Subprocess<
		"ignore" | "inherit" | null | undefined,
		"ignore" | "inherit" | null | undefined,
		"ignore" | "inherit" | null | undefined
	>;
	/** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */
	type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">;
	/** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */
	type NullSyncSubprocess = SyncSubprocess<
		"ignore" | "inherit" | null | undefined,
		"ignore" | "inherit" | null | undefined
	>;

	// Blocked on https://github.com/oven-sh/bun/issues/8329
	// /**
	//  *
	//  * Count the visible width of a string, as it would be displayed in a terminal.
	//  *
	//  * By default, strips ANSI escape codes before measuring the string. This is
	//  * because ANSI escape codes are not visible characters. If passed a non-string,
	//  * it will return 0.
	//  *
	//  * @param str The string to measure
	//  * @param options
	//  */
	// function stringWidth(
	//   str: string,
	//   options?: {
	//     /**
	//      * Whether to include ANSI escape codes in the width calculation
	//      *
	//      * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes.
	//      * @default false
	//      */
	//     countAnsiEscapeCodes?: boolean;
	//   },
	// ): number;

	class FileSystemRouter {
		/**
		 * Create a new {@link FileSystemRouter}.
		 *
		 * @example
		 * ```ts
		 * const router = new FileSystemRouter({
		 *   dir: process.cwd() + "/pages",
		 *   style: "nextjs",
		 * });
		 *
		 * const {params} = router.match("/blog/2020/01/01/hello-world");
		 * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"}
		 * ```
		 * @param options The options to use when creating the router
		 * @param options.dir The root directory containing the files to route
		 * @param options.style The style of router to use (only "nextjs" supported
		 * for now)
		 */
		constructor(options: {
			/**
			 * The root directory containing the files to route
			 *
			 * There is no default value for this option.
			 *
			 * @example
			 *   ```ts
			 *   const router = new FileSystemRouter({
			 *   dir:
			 */
			dir: string;
			style: "nextjs";

			/** The base path to use when routing */
			assetPrefix?: string;
			origin?: string;
			/** Limit the pages to those with particular file extensions. */
			fileExtensions?: string[];
		});

		// todo: URL
		match(input: string | Request | Response): MatchedRoute | null;

		readonly assetPrefix: string;
		readonly origin: string;
		readonly style: string;
		readonly routes: Record<string, string>;

		reload(): void;
	}

	interface MatchedRoute {
		/**
		 * A map of the parameters from the route
		 *
		 * @example
		 * ```ts
		 * const router = new FileSystemRouter({
		 *   dir: "/path/to/files",
		 *   style: "nextjs",
		 * });
		 * const {params} = router.match("/blog/2020/01/01/hello-world");
		 * console.log(params.year); // "2020"
		 * console.log(params.month); // "01"
		 * console.log(params.day); // "01"
		 * console.log(params.slug); // "hello-world"
		 * ```
		 */
		readonly params: Record<string, string>;
		readonly filePath: string;
		readonly pathname: string;
		readonly query: Record<string, string>;
		readonly name: string;
		readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic";
		readonly src: string;
	}

	/**
	 * The current version of Bun
	 * @example
	 * "0.2.0"
	 */
	const version: string;

	/**
	 * The git sha at the time the currently-running version of Bun was compiled
	 * @example
	 * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
	 */
	const revision: string;

	/**
	 * Find the index of a newline character in potentially ill-formed UTF-8 text.
	 *
	 * This is sort of like readline() except without the IO.
	 */
	function indexOfLine(
		buffer: ArrayBufferView | ArrayBufferLike,
		offset?: number,
	): number;

	interface GlobScanOptions {
		/**
		 * The root directory to start matching from. Defaults to `process.cwd()`
		 */
		cwd?: string;

		/**
		 * Allow patterns to match entries that begin with a period (`.`).
		 *
		 * @default false
		 */
		dot?: boolean;

		/**
		 * Return the absolute path for entries.
		 *
		 * @default false
		 */
		absolute?: boolean;

		/**
		 * Indicates whether to traverse descendants of symbolic link directories.
		 *
		 * @default false
		 */
		followSymlinks?: boolean;

		/**
		 * Throw an error when symbolic link is broken
		 *
		 * @default false
		 */
		throwErrorOnBrokenSymlink?: boolean;

		/**
		 * Return only files.
		 *
		 * @default true
		 */
		onlyFiles?: boolean;
	}

	/**
	 * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)).
	 *
	 * The supported pattern syntax for is:
	 *
	 * - `?`
	 *     Matches any single character.
	 * - `*`
	 *     Matches zero or more characters, except for path separators ('/' or '\').
	 * - `**`
	 *     Matches zero or more characters, including path separators.
	 *     Must match a complete path segment, i.e. followed by a path separator or
	 *     at the end of the pattern.
	 * - `[ab]`
	 *     Matches one of the characters contained in the brackets.
	 *     Character ranges (e.g. "[a-z]") are also supported.
	 *     Use "[!ab]" or "[^ab]" to match any character *except* those contained
	 *     in the brackets.
	 * - `{a,b}`
	 *     Match one of the patterns contained in the braces.
	 *     Any of the wildcards listed above can be used in the sub patterns.
	 *     Braces may be nested up to 10 levels deep.
	 * - `!`
	 *     Negates the result when at the start of the pattern.
	 *     Multiple "!" characters negate the pattern multiple times.
	 * - `\`
	 *     Used to escape any of the special characters above.
	 *
	 * @example
	 * ```js
	 * const glob = new Glob("*.{ts,tsx}");
	 * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' }))
	 * ```
	 */
	export class Glob {
		constructor(pattern: string);

		/**
		 * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator.
		 *
		 * @throws {ENOTDIR} Given root cwd path must be a directory
		 *
		 * @example
		 * ```js
		 * const glob = new Glob("*.{ts,tsx}");
		 * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' }))
		 * ```
		 *
		 * @example
		 * ```js
		 * const glob = new Glob("*.{ts,tsx}");
		 * for await (const path of glob.scan()) {
		 *   // do something
		 * }
		 * ```
		 */
		scan(
			optionsOrCwd?: string | GlobScanOptions,
		): AsyncIterableIterator<string>;

		/**
		 * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator.
		 *
		 * @throws {ENOTDIR} Given root cwd path must be a directory
		 *
		 * @example
		 * ```js
		 * const glob = new Glob("*.{ts,tsx}");
		 * const scannedFiles = Array.from(glob.scan({ cwd: './src' }))
		 * ```
		 *
		 * @example
		 * ```js
		 * const glob = new Glob("*.{ts,tsx}");
		 * for (const path of glob.scan()) {
		 *   // do something
		 * }
		 * ```
		 */
		scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator<string>;

		/**
		 * Match the glob against a string
		 *
		 * @example
		 * ```js
		 * const glob = new Glob("*.{ts,tsx}");
		 * expect(glob.match('foo.ts')).toBeTrue();
		 * ```
		 */
		match(str: string): boolean;
	}
}

// extends lib.dom.d.ts
interface BufferEncodingOption {
	encoding?: BufferEncoding;
}
