UNPKG

strongly-typed-test

Version:

Library to help developers identify type mismatches

1,754 lines (1,642 loc) โ€ข 165 kB
/** * 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; } interface BuildConfig { entrypoints: string[]; // list of file path outdir?: string; // output directory target?: Target; // default: "browser" /** * Output module format. Top-level await is only supported for `"esm"`. * * Can be: * - `"esm"` * - `"cjs"` (**experimental**) * - `"iife"` (**experimental**) * * @default "esm" */ format?: /** * ECMAScript Module format */ | "esm" /** * CommonJS format * **Experimental** */ | "cjs" /** * IIFE format * **Experimental** */ | "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" // }; /** * Generate bytecode for the output. This can dramatically improve cold * start times, but will make the final output larger and slightly increase * memory usage. * * Bytecode is currently only supported for CommonJS (`format: "cjs"`). * * Must be `target: "bun"` * @default false */ bytecode?: boolean; /** * Add a banner to the bundled code such as "use client"; */ banner?: string; /** * Add a footer to the bundled code such as a comment block like * * `// made with bun!` */ footer?: string; /** * **Experimental** * * Enable CSS support. */ experimentalCss?: boolean; /** * Drop function calls to matching property accesses. */ drop?: string[]; } 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 contributors 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 pas