bun-types
Version:
Type definitions and documentation for Bun, an incredibly fast JavaScript runtime
1,482 lines (1,356 loc) โข 215 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 PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL;
type ArrayBufferView<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> =
| NodeJS.TypedArray<TArrayBuffer>
| DataView<TArrayBuffer>;
type BufferSource = NodeJS.TypedArray<ArrayBufferLike> | DataView<ArrayBufferLike> | ArrayBufferLike;
type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike;
type XMLHttpRequestBodyInit = Blob | BufferSource | FormData | URLSearchParams | string;
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
/**
* Like Omit, but correctly distributes over unions. Most useful for removing
* properties from union options objects, like {@link Bun.SQL.Options}
*
* @example
* ```ts
* type X = Bun.DistributedOmit<{type?: 'a', url?: string} | {type?: 'b', flag?: boolean}, "url">
* // `{type?: 'a'} | {type?: 'b', flag?: boolean}` (Omit applied to each union item instead of entire type)
*
* type X = Omit<{type?: 'a', url?: string} | {type?: 'b', flag?: boolean}, "url">;
* // `{type?: "a" | "b" | undefined}` (Missing `flag` property and no longer a union)
* ```
*/
type DistributedOmit<T, K extends PropertyKey> = T extends T ? Omit<T, K> : never;
type KeysInBoth<A, B> = Extract<keyof A, keyof B>;
type MergeInner<A, B> = Omit<A, KeysInBoth<A, B>> &
Omit<B, KeysInBoth<A, B>> & {
[Key in KeysInBoth<A, B>]: A[Key] | B[Key];
};
type Merge<A, B> = MergeInner<A, B> & MergeInner<B, A>;
type DistributedMerge<T, Else = T> = T extends T ? Merge<T, Exclude<Else, T>> : never;
type Without<A, B> = A & {
[Key in Exclude<keyof B, keyof A>]?: never;
};
type XOR<A, B> = Without<A, B> | Without<B, A>;
}
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";
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;
/**
* Remove ANSI escape codes from a string.
*
* @category Utilities
*
* @param input The string to remove ANSI escape codes from.
* @returns The string with ANSI escape codes removed.
*
* @example
* ```ts
* import { stripANSI } from "bun";
*
* console.log(stripANSI("\u001b[31mhello\u001b[39m")); // "hello"
* ```
*/
function stripANSI(input: string): string;
/**
* 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;
}
/**
* YAML related APIs
*/
namespace YAML {
/**
* Parse a YAML string into a JavaScript value
*
* @category Utilities
*
* @param input The YAML string to parse
* @returns A JavaScript value
*
* @example
* ```ts
* import { YAML } from "bun";
*
* console.log(YAML.parse("123")) // 123
* console.log(YAML.parse("null")) // null
* console.log(YAML.parse("false")) // false
* console.log(YAML.parse("abc")) // "abc"
* console.log(YAML.parse("- abc")) // [ "abc" ]
* console.log(YAML.parse("abc: def")) // { "abc": "def" }
* ```
*/
export function parse(input: string): unknown;
/**
* Convert a JavaScript value into a YAML string. Strings are double quoted if they contain keywords, non-printable or
* escaped characters, or if a YAML parser would parse them as numbers. Anchors and aliases are inferred from objects, allowing cycles.
*
* @category Utilities
*
* @param input The JavaScript value to stringify.
* @param replacer Currently not supported.
* @param space A number for how many spaces each level of indentation gets, or a string used as indentation.
* Without this parameter, outputs flow-style (single-line) YAML.
* With this parameter, outputs block-style (multi-line) YAML.
* The number is clamped between 0 and 10, and the first 10 characters of the string are used.
* @returns A string containing the YAML document.
*
* @example
* ```ts
* import { YAML } from "bun";
*
* const input = {
* abc: "def",
* num: 123
* };
*
* // Without space - flow style (single-line)
* console.log(YAML.stringify(input));
* // {abc: def,num: 123}
*
* // With space - block style (multi-line)
* console.log(YAML.stringify(input, null, 2));
* // abc: def
* // num: 123
*
* const cycle = {};
* cycle.obj = cycle;
* console.log(YAML.stringify(cycle, null, 2));
* // &1
* // obj: *1
*/
export function stringify(input: unknown, replacer?: undefined | null, space?: string | number): string;
}
/**
* 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<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 an `ArrayBuffer`.
*/
function readableStreamToArrayBuffer(
stream: ReadableStream<ArrayBufferView | ArrayBufferLike>,
): Promise<ArrayBuffer> | ArrayBuffer;
/**
* 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.
*
* @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> | ArrayBuffer;
end(): ArrayBuffer | Uint8Array<ArrayBuffer>;
}
/** 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;
// TODO
// readonly readable: ReadableStream<Uint8Array>;
// readonly writable: WritableStream<Uint8Array>;
/**
* 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>;
}
type CSRFAlgorithm = "blake2b256" | "blake2b512" | "sha256" | "sha384" | "sha512" | "sha512-256";
interface CSRFGenerateOptions {
/**
* The number of milliseconds until the token expires. 0 means the token never expires.
* @default 24 * 60 * 60 * 1000 (24 hours)
*/
expiresIn?: number;
/**
* The encoding of the token.
* @default "base64url"
*/
encoding?: "base64" | "base64url" | "hex";
/**
* The algorithm to use for the token.
* @default "sha256"
*/
algorithm?: CSRFAlgorithm;
}
interface CSRFVerifyOptions {
/**
* The secret to use for the token. If not provided, a random default secret will be generated in memory and used.
*/
secret?: string;
/**
* The encoding of the token.
* @default "base64url"
*/
encoding?: "base64" | "base64url" | "hex";
/**
* The algorithm to use for the token.
* @default "sha256"
*/
algorithm?: CSRFAlgorithm;
/**
* The number of milliseconds until the token expires. 0 means the token never expires.
* @default 24 * 60 * 60 * 1000 (24 hours)
*/
maxAge?: number;
}
/**
* Generate and verify CSRF tokens
*
* @category Security
*/
namespace CSRF {
/**
* Generate a CSRF token.
* @param secret The secret to use for the token. If not provided, a random default secret will be generated in memory and used.
* @param options The options for the token.
* @returns The generated token.
*/
function generate(secret?: string, options?: CSRFGenerateOptions): string;
/**
* Verify a CSRF token.
* @param token The token to verify.
* @param options The options for the token.
* @returns True if the token is valid, false otherwise.
*/
function verify(token: string, options?: CSRFVerifyOptions): 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;
xxHash32: (data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, seed?: number) => number;
xxHash64: (data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, seed?: bigint) => bigint;
xxHash3: (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;
rapidhash: (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, str