bun-types
Version:
Type definitions and documentation for Bun, an incredibly fast JavaScript runtime
1,449 lines (1,324 loc) โข 258 kB
TypeScript
/**
* 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" {
type DistributedOmit<T, K extends PropertyKey> = T extends T ? Omit<T, K> : never;
type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL;
type ArrayBufferView<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> =
| NodeJS.TypedArray<TArrayBuffer>
| DataView<TArrayBuffer>;
type BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike;
type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike;
type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData | Iterable<Uint8Array>;
type ReadableStreamController<T> = ReadableStreamDefaultController<T>;
type ReadableStreamDefaultReadResult<T> =
| ReadableStreamDefaultReadValueResult<T>
| ReadableStreamDefaultReadDoneResult;
type ReadableStreamReader<T> = ReadableStreamDefaultReader<T>;
type Transferable = ArrayBuffer | MessagePort;
type MessageEventSource = Bun.__internal.UseLibDomIfAvailable<"MessageEventSource", undefined>;
type Encoding = "utf-8" | "windows-1252" | "utf-16";
type UncaughtExceptionOrigin = "uncaughtException" | "unhandledRejection";
type MultipleResolveType = "resolve" | "reject";
type BeforeExitListener = (code: number) => void;
type DisconnectListener = () => void;
type ExitListener = (code: number) => void;
type RejectionHandledListener = (promise: Promise<unknown>) => void;
type FormDataEntryValue = File | string;
type WarningListener = (warning: Error) => void;
type MessageListener = (message: unknown, sendHandle: unknown) => void;
type SignalsListener = (signal: NodeJS.Signals) => void;
type BlobPart = string | Blob | BufferSource;
type TimerHandler = (...args: any[]) => void;
type DOMHighResTimeStamp = number;
type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob;
type MaybePromise<T> = T | Promise<T>;
namespace __internal {
type LibDomIsLoaded = typeof globalThis extends { onabort: any } ? true : false;
/**
* Helper type for avoiding conflicts in types.
*
* Uses the lib.dom.d.ts definition if it exists, otherwise defines it locally.
*
* This is to avoid type conflicts between lib.dom.d.ts and \@types/bun.
*
* Unfortunately some symbols cannot be defined when both Bun types and lib.dom.d.ts types are loaded,
* and since we can't redeclare the symbol in a way that satisfies both, we need to fallback
* to the type that lib.dom.d.ts provides.
*/
type UseLibDomIfAvailable<GlobalThisKeyName extends PropertyKey, Otherwise> =
// `onabort` is defined in lib.dom.d.ts, so we can check to see if lib dom is loaded by checking if `onabort` is defined
LibDomIsLoaded extends true
? typeof globalThis extends { [K in GlobalThisKeyName]: infer T } // if it is loaded, infer it from `globalThis` and use that value
? T
: Otherwise // Not defined in lib dom (or anywhere else), so no conflict. We can safely use our own definition
: Otherwise; // Lib dom not loaded anyway, so no conflict. We can safely use our own definition
}
/** @deprecated This type is unused in Bun's types and might be removed in the near future */
type Platform =
| "aix"
| "android"
| "darwin"
| "freebsd"
| "haiku"
| "linux"
| "openbsd"
| "sunos"
| "win32"
| "cygwin"
| "netbsd";
/** @deprecated This type is unused in Bun's types and might be removed in the near future */
type Architecture = "arm" | "arm64" | "ia32" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x" | "x64";
/** @deprecated This type is unused in Bun's types and might be removed in the near future */
type UncaughtExceptionListener = (error: Error, origin: UncaughtExceptionOrigin) => void;
/**
* Most of the time the unhandledRejection will be an Error, but this should not be relied upon
* as *anything* can be thrown/rejected, it is therefore unsafe to assume that the value is an Error.
*
* @deprecated This type is unused in Bun's types and might be removed in the near future
*/
type UnhandledRejectionListener = (reason: unknown, promise: Promise<unknown>) => void;
/** @deprecated This type is unused in Bun's types and might be removed in the near future */
type MultipleResolveListener = (type: MultipleResolveType, promise: Promise<unknown>, value: unknown) => void;
interface ErrorEventInit extends EventInit {
colno?: number;
error?: any;
filename?: string;
lineno?: number;
message?: string;
}
interface CloseEventInit extends EventInit {
code?: number;
reason?: string;
wasClean?: boolean;
}
interface MessageEventInit<T = any> extends EventInit {
data?: T;
lastEventId?: string;
origin?: string;
source?: Bun.MessageEventSource | null;
}
interface EventInit {
bubbles?: boolean;
cancelable?: boolean;
composed?: boolean;
}
interface EventListenerOptions {
capture?: boolean;
}
interface CustomEventInit<T = any> extends Bun.EventInit {
detail?: T;
}
/** A message received by a target object. */
interface BunMessageEvent<T = any> extends Event {
/** Returns the data of the message. */
readonly data: T;
/** Returns the last event ID string, for server-sent events. */
readonly lastEventId: string;
/** Returns the origin of the message, for server-sent events and cross-document messaging. */
readonly origin: string;
/** Returns the MessagePort array sent with the message, for cross-document messaging and channel messaging. */
readonly ports: readonly MessagePort[]; // ReadonlyArray<typeof import("worker_threads").MessagePort["prototype"]>;
readonly source: Bun.MessageEventSource | null;
}
type MessageEvent<T = any> = Bun.__internal.UseLibDomIfAvailable<"MessageEvent", BunMessageEvent<T>>;
interface ReadableStreamDefaultReadManyResult<T> {
done: boolean;
/** Number of bytes */
size: number;
value: T[];
}
interface EventSourceEventMap {
error: Event;
message: MessageEvent;
open: Event;
}
interface AddEventListenerOptions extends EventListenerOptions {
/** When `true`, the listener is automatically removed when it is first invoked. Default: `false`. */
once?: boolean;
/** When `true`, serves as a hint that the listener will not call the `Event` object's `preventDefault()` method. Default: false. */
passive?: boolean;
signal?: AbortSignal;
}
interface EventListener {
(evt: Event): void;
}
interface EventListenerObject {
handleEvent(object: Event): void;
}
interface FetchEvent extends Event {
readonly request: Request;
readonly url: string;
waitUntil(promise: Promise<any>): void;
respondWith(response: Response | Promise<Response>): void;
}
interface EventMap {
fetch: FetchEvent;
message: MessageEvent;
messageerror: MessageEvent;
// exit: Event;
}
interface StructuredSerializeOptions {
transfer?: Bun.Transferable[];
}
interface EventSource extends EventTarget {
new (url: string | URL, eventSourceInitDict?: EventSourceInit): EventSource;
onerror: ((this: EventSource, ev: Event) => any) | null;
onmessage: ((this: EventSource, ev: MessageEvent) => any) | null;
onopen: ((this: EventSource, ev: Event) => any) | null;
/** Returns the state of this EventSource object's connection. It can have the values described below. */
readonly readyState: number;
/** Returns the URL providing the event stream. */
readonly url: string;
/** Returns true if the credentials mode for connection requests to the URL providing the event stream is set to "include", and false otherwise.
*
* Not supported in Bun
*/
readonly withCredentials: boolean;
/** Aborts any instances of the fetch algorithm started for this EventSource object, and sets the readyState attribute to CLOSED. */
close(): void;
readonly CLOSED: 2;
readonly CONNECTING: 0;
readonly OPEN: 1;
addEventListener<K extends keyof EventSourceEventMap>(
type: K,
listener: (this: EventSource, ev: EventSourceEventMap[K]) => any,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
type: string,
listener: (this: EventSource, event: MessageEvent) => any,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
): void;
removeEventListener<K extends keyof EventSourceEventMap>(
type: K,
listener: (this: EventSource, ev: EventSourceEventMap[K]) => any,
options?: boolean | EventListenerOptions,
): void;
removeEventListener(
type: string,
listener: (this: EventSource, event: MessageEvent) => any,
options?: boolean | EventListenerOptions,
): void;
removeEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | EventListenerOptions,
): void;
/**
* Keep the event loop alive while connection is open or reconnecting
*
* Not available in browsers
*/
ref(): void;
/**
* Do not keep the event loop alive while connection is open or reconnecting
*
* Not available in browsers
*/
unref(): void;
}
interface TransformerFlushCallback<O> {
(controller: TransformStreamDefaultController<O>): void | PromiseLike<void>;
}
interface TransformerStartCallback<O> {
(controller: TransformStreamDefaultController<O>): any;
}
interface TransformerTransformCallback<I, O> {
(chunk: I, controller: TransformStreamDefaultController<O>): void | PromiseLike<void>;
}
interface UnderlyingSinkAbortCallback {
(reason?: any): void | PromiseLike<void>;
}
interface UnderlyingSinkCloseCallback {
(): void | PromiseLike<void>;
}
interface UnderlyingSinkStartCallback {
(controller: WritableStreamDefaultController): any;
}
interface UnderlyingSinkWriteCallback<W> {
(chunk: W, controller: WritableStreamDefaultController): void | PromiseLike<void>;
}
interface UnderlyingSourceCancelCallback {
(reason?: any): void | PromiseLike<void>;
}
interface UnderlyingSink<W = any> {
abort?: UnderlyingSinkAbortCallback;
close?: UnderlyingSinkCloseCallback;
start?: UnderlyingSinkStartCallback;
type?: undefined | "default" | "bytes";
write?: UnderlyingSinkWriteCallback<W>;
}
interface UnderlyingSource<R = any> {
cancel?: UnderlyingSourceCancelCallback;
pull?: UnderlyingSourcePullCallback<R>;
start?: UnderlyingSourceStartCallback<R>;
/**
* Mode "bytes" is not currently supported.
*/
type?: undefined;
}
interface DirectUnderlyingSource<R = any> {
cancel?: UnderlyingSourceCancelCallback;
pull: (controller: ReadableStreamDirectController) => void | PromiseLike<void>;
type: "direct";
}
interface UnderlyingSourcePullCallback<R> {
(controller: ReadableStreamController<R>): void | PromiseLike<void>;
}
interface UnderlyingSourceStartCallback<R> {
(controller: ReadableStreamController<R>): any;
}
interface GenericTransformStream {
readonly readable: ReadableStream;
readonly writable: WritableStream;
}
interface AbstractWorkerEventMap {
error: ErrorEvent;
}
interface WorkerEventMap extends AbstractWorkerEventMap {
message: MessageEvent;
messageerror: MessageEvent;
close: CloseEvent;
open: Event;
}
type WorkerType = "classic" | "module";
/**
* This type-only interface is identical at runtime to {@link ReadableStream},
* and exists to document types that do not exist yet in libdom.
*/
interface BunReadableStream<T = any> extends ReadableStream<T> {
text(): Promise<string>;
bytes(): Promise<Uint8Array>;
json(): Promise<any>;
blob(): Promise<Blob>;
}
interface AbstractWorker {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ServiceWorker/error_event) */
onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
addEventListener<K extends keyof AbstractWorkerEventMap>(
type: K,
listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
): void;
removeEventListener<K extends keyof AbstractWorkerEventMap>(
type: K,
listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any,
options?: boolean | EventListenerOptions,
): void;
removeEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | EventListenerOptions,
): void;
}
/**
* Bun's Web Worker constructor supports some extra options on top of the API browsers have.
*/
interface WorkerOptions {
/**
* A string specifying an identifying name for the DedicatedWorkerGlobalScope representing the scope of
* the worker, which is mainly useful for debugging purposes.
*/
name?: string;
/**
* Use less memory, but make the worker slower.
*
* Internally, this sets the heap size configuration in JavaScriptCore to be
* the small heap instead of the large heap.
*/
smol?: boolean;
/**
* When `true`, the worker will keep the parent thread alive until the worker is terminated or `unref`'d.
* When `false`, the worker will not keep the parent thread alive.
*
* By default, this is `false`.
*/
ref?: boolean;
/**
* In Bun, this does nothing.
*/
type?: Bun.WorkerType | undefined;
/**
* List of arguments which would be stringified and appended to
* `Bun.argv` / `process.argv` in the worker. This is mostly similar to the `data`
* but the values will be available on the global `Bun.argv` as if they
* were passed as CLI options to the script.
*/
argv?: any[] | undefined;
/** If `true` and the first argument is a string, interpret the first argument to the constructor as a script that is executed once the worker is online. */
// eval?: boolean | undefined;
/**
* If set, specifies the initial value of process.env inside the Worker thread. As a special value, worker.SHARE_ENV may be used to specify that the parent thread and the child thread should share their environment variables; in that case, changes to one thread's process.env object affect the other thread as well. Default: process.env.
*/
env?: Record<string, string> | (typeof import("node:worker_threads"))["SHARE_ENV"] | undefined;
/**
* In Bun, this does nothing.
*/
credentials?: import("undici-types").RequestCredentials | undefined;
/**
* @default true
*/
// trackUnmanagedFds?: boolean;
// resourceLimits?: import("worker_threads").ResourceLimits;
/**
* An array of module specifiers to preload in the worker.
*
* These modules load before the worker's entry point is executed.
*
* Equivalent to passing the `--preload` CLI argument, but only for this Worker.
*/
preload?: string[] | string | undefined;
}
interface Worker extends EventTarget, AbstractWorker {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/message_event) */
onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/messageerror_event) */
onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
/**
* Clones message and transmits it to worker's global environment. transfer can be passed as a list of objects that are to be transferred rather than cloned.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/postMessage)
*/
postMessage(message: any, transfer: Transferable[]): void;
postMessage(message: any, options?: StructuredSerializeOptions): void;
/**
* Aborts worker's associated global environment.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/terminate)
*/
terminate(): void;
addEventListener<K extends keyof WorkerEventMap>(
type: K,
listener: (this: Worker, ev: WorkerEventMap[K]) => any,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
): void;
removeEventListener<K extends keyof WorkerEventMap>(
type: K,
listener: (this: Worker, ev: WorkerEventMap[K]) => any,
options?: boolean | EventListenerOptions,
): void;
removeEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | EventListenerOptions,
): void;
/**
* Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker does _not_ let the program exit if it's the only active handle left (the default
* behavior). If the worker is `ref()`ed, calling `ref()` again has
* no effect.
* @since v10.5.0
*/
ref(): void;
/**
* Calling `unref()` on a worker allows the thread to exit if this is the only
* active handle in the event system. If the worker is already `unref()`ed calling`unref()` again has no effect.
* @since v10.5.0
*/
unref(): void;
/**
* An integer identifier for the referenced thread. Inside the worker thread,
* it is available as `require('node:worker_threads').threadId`.
* This value is unique for each `Worker` instance inside a single process.
* @since v10.5.0
*/
threadId: number;
}
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: Env & NodeJS.ProcessEnv & ImportMetaEnv;
/**
* 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[];
interface WhichOptions {
/**
* Overrides the PATH environment variable
*/
PATH?: string;
/**
* When given a relative path, use this path to join it.
*/
cwd?: string;
}
/**
* Find the path to an executable, similar to typing which in your terminal. Reads the `PATH` environment variable unless overridden with `options.PATH`.
*
* @category Utilities
*
* @param command The name of the executable or script to find
* @param options Options for the search
*/
function which(command: string, options?: WhichOptions): string | null;
interface StringWidthOptions {
/**
* 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;
}
/**
* 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
*
* @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?: StringWidthOptions,
): number;
/**
* TOML related APIs
*/
namespace TOML {
/**
* Parse a TOML string into a JavaScript object.
*
* @category Utilities
*
* @param input The TOML string to parse
* @returns A JavaScript object
*/
export function parse(input: string): object;
}
/**
* Synchronously resolve a `moduleId` as though it were imported from `parent`
*
* On failure, throws a `ResolveMessage`
*/
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.
*/
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.
*
* @category File System
*
* @param destination The file or file path to write to
* @param input The data to copy into `destination`.
* @param options Options for the write
*
* @returns A promise that resolves with the number of bytes written.
*/
function write(
destination: BunFile | S3File | PathLike,
input: Blob | NodeJS.TypedArray | ArrayBufferLike | string | 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
* @param options Options for the write
*
* @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.
*/
function write(
destinationPath: 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.
*/
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.
*/
function write(
destinationPath: 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.
*
* @example
* **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:
*
* @category Security
*
* - `"` becomes `"""`
* - `&` becomes `"&"`
* - `'` becomes `"'"`
* - `<` becomes `"<"`
* - `>` becomes `">"`
*
* 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.
*
* @category File System
*
* @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;
/**
* Extract the value from the Promise in the same tick of the event loop
*/
function peek<T = undefined>(promise: T | Promise<T>): Promise<T> | T;
namespace peek {
function status<T = undefined>(promise: T | Promise<T>): "pending" | "fulfilled" | "rejected";
}
/**
* 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.
*
* @category File System
*
* @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 {@link ArrayBuffer} on end().
*/
class ArrayBufferSink {
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;
}
/** DNS Related APIs */
namespace 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
* ## Basic usage
* ```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"
* ```
*/
function 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
* @param port The port to prefetch. Default is 443. Port helps distinguish between IPv6 vs IPv4-only connections.
*
* @example
* ```js
* import { dns } from 'bun';
* dns.prefetch('example.com');
* // ... something expensive
* await fetch('https://example.com');
* ```
*/
function prefetch(hostname: string, port?: number): void;
/**
* **Experimental API**
*/
function 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;
};
const ADDRCONFIG: number;
const ALL: number;
const V4MAPPED: 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;
}
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
*
* @category File System
*
* @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;
/**
* Slice the file from the beginning to the end, optionally with a new MIME type.
*
* @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: BunReadableStream;
// 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>;
/**
* Write data to the file. This is equivalent to using {@link Bun.write} with a {@link BunFile}.
* @param data - The data to write.
* @param options - The options to use for the write.
*/
write(
data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | Request | Response | BunFile,
options?: { highWaterMark?: number },
): Promise<number>;
/**
* Deletes the file.
*/
unlink(): Promise<void>;
/**
* Deletes the file (same as unlink)
*/
delete(): Promise<void>;
/**
* Provides useful information about the file.
*/
stat(): Promise<import("node:fs").Stats>;
}
/**
* Configuration options for SQL client connection and behavior
* @example
* const config: SQLOptions = {
* host: 'localhost',
* port: 5432,
* user: 'dbuser',
* password: 'secretpass',
* database: 'myapp',
* idleTimeout: 30,
* max: 20,
* onconnect: (client) => {
* console.log('Connected to database');
* }
* };
*/
interface SQLOptions {
/** Connection URL (can be string or URL object) */
url?: URL | string;
/** Database server hostname */
host?: string;
/** Database server hostname (alias for host) */
hostname?: string;
/** Database server port number */
port?: number | string;
/** Database user for authentication */
username?: string;
/** Database user for authentication (alias for username) */
user?: string;
/** Database password for authentication */
password?: string | (() => Promise<string>);
/** Database password for authentication (alias for password) */
pass?: string | (() => Promise<string>);
/** Name of the database to connect to */
database?: string;
/** Name of the database to connect to (alias for database) */
db?: string;
/** Database adapter/driver to use */
adapter?: string;
/** Maximum time in seconds to wait for connection to become available */
idleTimeout?: number;
/** Maximum time in seconds to wait for connection to become available (alias for idleTimeout) */
idle_timeout?: number;
/** Maximum time in seconds to wait when establishing a connection */
connectionTimeout?: number;
/** Maximum time in seconds to wait when establishing a connection (alias for connectionTimeout) */
connection_timeout?: number;
/** Maximum lifetime in seconds of a connection */
maxLifetime?: number;
/** Maximum lifetime in seconds of a connection (alias for maxLifetime) */
max_lifetime?: number;
/** Whether to use TLS/SSL for the connection */
tls?: TLSOptions | boolean;
/** Whether to use TLS/SSL for the connection (alias for tls) */
ssl?: TLSOptions | boolean;
/** Callback function executed when a connection is established */
onconnect?: (client: SQL) => void;
/** Callback function executed when a connection is closed */
onclose?: (client: SQL) => void;
/** Maximum number of connections in the pool */
max?: number;
/** By default values outside i32 range are returned as strings. If this is true, values outside i32 range are returned as BigInts. */
bigint?: boolean;
/** Automatic creation of prepared statements, defaults to true */
prepare?: boolean;
}
/**
* Represents a SQL query that can be executed, with additional control methods
* Extends Promise to allow for async/await usage
*/
interface SQLQuery<T = any> extends Promise<T> {
/** Indicates if the query is currently executing */
active: boolean;
/** Indicates if the query has been cancelled */
cancelled: boolean;
/** Cancels the executing query */
cancel(): SQLQuery<T>;
/** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */
simple(): SQLQuery<T>;
/** Executes the query */
execute(): SQLQuery<T>;
/** Returns the raw query result */
raw(): SQLQuery<T>;
/** Returns only the values from the query result */
values(): SQLQuery<T>;
}
/**
* Callback function type for transaction contexts
* @param sql Function to execute SQL queries within the transaction
*/
type SQLTransactionContextCallback = (sql: TransactionSQL) => Promise<any> | Array<SQLQuery>;
/**
* Callback function type for savepoint contexts
* @param sql Function to execute SQL queries within the savepoint
*/
type SQLSavepointContextCallback = (sql: SavepointSQL) => Promise<any> | Array<SQLQuery>;
/**
* Main SQL client interface providing connection and transaction management
*/
interface SQL {
/**
* Executes a SQL query using template literals
* @example
* ```ts
* const [user] = await sql`select * from users where id = ${1}`;
* ```
*/
(strings: string[] | TemplateStringsArray, ...values: any[]): SQLQuery;
/**
* Helper function for inserting an object into a query
*
* @example
* ```ts
* // Insert an object
* const result = await sql`insert into users ${sql(users)} RETURNING *`;
*
* // Or pick specific columns
* const result = await sql`insert into users ${sql(users, "id", "name")} RETURNING *`;
*
* // Or a single object
* const result = await sql`insert into users ${s