From 459248baffeb62bc6930b4c24c476a54608c114a Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Wed, 5 Mar 2025 21:10:18 +0000 Subject: [PATCH 01/72] changes --- package.json | 3 +- packages/bun-types/.eslintrc.cjs | 68 +- packages/bun-types/ambient.d.ts | 28 +- packages/bun-types/bun.d.ts | 14516 +++++++++-------- packages/bun-types/deprecated.d.ts | 105 +- packages/bun-types/devserver.d.ts | 40 +- packages/bun-types/fetch.d.ts | 256 +- packages/bun-types/ffi.d.ts | 2196 +-- packages/bun-types/globals.d.ts | 3625 ++-- packages/bun-types/html-rewriter.d.ts | 297 +- packages/bun-types/jsc.d.ts | 446 +- packages/bun-types/new/index.d.ts | 449 + packages/bun-types/overrides.d.ts | 112 +- packages/bun-types/package.json | 4 +- packages/bun-types/sqlite.d.ts | 2167 +-- packages/bun-types/test.d.ts | 4360 ++--- packages/bun-types/test/array-buffer.test.ts | 2 +- packages/bun-types/test/array.test.ts | 30 +- packages/bun-types/test/broadcast.test.ts | 6 +- packages/bun-types/test/bun.test.ts | 62 +- packages/bun-types/test/console.test.ts | 26 +- packages/bun-types/test/diag.test.ts | 2 +- packages/bun-types/test/dom.test.ts | 16 +- packages/bun-types/test/env.test.ts | 18 +- packages/bun-types/test/events.test.ts | 6 +- packages/bun-types/test/ffi.test.ts | 223 +- packages/bun-types/test/fs.test.ts | 8 +- packages/bun-types/test/fsrouter.test.ts | 4 +- packages/bun-types/test/globals.test.ts | 170 +- packages/bun-types/test/http.test.ts | 2 +- packages/bun-types/test/jsc.test.ts | 2 +- packages/bun-types/test/mocks.test.ts | 2 +- packages/bun-types/test/net.test.ts | 8 +- packages/bun-types/test/process.test.ts | 12 +- packages/bun-types/test/readline.test.ts | 10 +- packages/bun-types/test/serve.test.ts | 246 +- packages/bun-types/test/spawn.test.ts | 243 +- packages/bun-types/test/sqlite.test.ts | 14 +- packages/bun-types/test/streams.test.ts | 32 +- packages/bun-types/test/tcp.test.ts | 216 +- packages/bun-types/test/test.test.ts | 171 +- packages/bun-types/test/tls.test.ts | 34 +- packages/bun-types/test/tty.test.ts | 8 +- packages/bun-types/test/utilities.test.ts | 4 +- packages/bun-types/test/wasm.test.ts | 80 +- packages/bun-types/test/worker.test.ts | 38 +- packages/bun-types/test/ws.test.ts | 4 +- packages/bun-types/wasm.d.ts | 509 +- src/cli/init/tsconfig.default.json | 2 +- test/integration/bun-types/fixture/bun.lock | 2 +- test/integration/bun-types/fixture/index.ts | 6 +- 51 files changed, 16023 insertions(+), 14867 deletions(-) create mode 100644 packages/bun-types/new/index.d.ts diff --git a/package.json b/package.json index a1ff4f9f8b7ecb..ce1c608c3927d2 100644 --- a/package.json +++ b/package.json @@ -75,5 +75,6 @@ "prettier:extra": "bun run analysis:no-llvm --target prettier-extra", "prettier:diff": "bun run analysis:no-llvm --target prettier-diff", "node:test": "node ./scripts/runner.node.mjs --quiet --exec-path=$npm_execpath --node-tests " - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/packages/bun-types/.eslintrc.cjs b/packages/bun-types/.eslintrc.cjs index d4f69448614574..ab4bfc9a79b0a5 100644 --- a/packages/bun-types/.eslintrc.cjs +++ b/packages/bun-types/.eslintrc.cjs @@ -1,36 +1,36 @@ module.exports = { - root: true, - parser: "@typescript-eslint/parser", - parserOptions: { - tsconfigRootDir: __dirname, - project: ["./tsconfig.json"], - }, - plugins: ["@typescript-eslint"], - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "prettier", - "plugin:@definitelytyped/all", - ], - rules: { - "no-var": "off", // global variables - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-empty-interface": "off", - "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-misused-new": "off", - "@typescript-eslint/triple-slash-reference": "off", - "@typescript-eslint/no-empty-interface": "off", - "@definitelytyped/no-single-declare-module": "off", - "@definitelytyped/no-self-import": "off", - "@definitelytyped/no-unnecessary-generics": "off", - "@typescript-eslint/no-duplicate-enum-values": "off", - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-invalid-void-type": "off", - "@definitelytyped/no-single-element-tuple-type": "off", - "@typescript-eslint/no-non-null-asserted-optional-chain": "off", - "@typescript-eslint/unbound-method": "off", - }, + root: true, + parser: "@typescript-eslint/parser", + parserOptions: { + tsconfigRootDir: __dirname, + project: ["./tsconfig.json"], + }, + plugins: ["@typescript-eslint"], + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking", + "prettier", + "plugin:@definitelytyped/all", + ], + rules: { + "no-var": "off", // global variables + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-misused-new": "off", + "@typescript-eslint/triple-slash-reference": "off", + "@typescript-eslint/no-empty-interface": "off", + "@definitelytyped/no-single-declare-module": "off", + "@definitelytyped/no-self-import": "off", + "@definitelytyped/no-unnecessary-generics": "off", + "@typescript-eslint/no-duplicate-enum-values": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-invalid-void-type": "off", + "@definitelytyped/no-single-element-tuple-type": "off", + "@typescript-eslint/no-non-null-asserted-optional-chain": "off", + "@typescript-eslint/unbound-method": "off", + }, }; diff --git a/packages/bun-types/ambient.d.ts b/packages/bun-types/ambient.d.ts index 05d908557716b6..db712274c46e99 100644 --- a/packages/bun-types/ambient.d.ts +++ b/packages/bun-types/ambient.d.ts @@ -1,31 +1,31 @@ declare module "*.txt" { - var text: string; - export = text; + var text: string; + export = text; } declare module "*.toml" { - var contents: any; - export = contents; + var contents: any; + export = contents; } declare module "*.jsonc" { - var contents: any; - export = contents; + var contents: any; + export = contents; } declare module "*/bun.lock" { - var contents: import("bun").BunLockFile; - export = contents; + var contents: import("bun").BunLockFile; + export = contents; } declare module "*.html" { - // In Bun v1.2, we might change this to Bun.HTMLBundle - var contents: any; - export = contents; + // In Bun v1.2, we might change this to Bun.HTMLBundle + var contents: any; + export = contents; } declare module "*.svg" { - // Bun 1.2.3 added support for frontend dev server - var contents: `${string}.svg`; - export = contents; + // Bun 1.2.3 added support for frontend dev server + var contents: `${string}.svg`; + export = contents; } diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index bc50aefc82b134..53da987d07911c 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -1,72 +1,72 @@ declare 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; - - bytes(): Uint8Array; + 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; + + bytes(): Uint8Array; } /** @@ -85,2992 +85,3087 @@ declare class _ShellError extends Error implements ShellOutput { * This module aliases `globalThis.Bun`. */ declare module "bun" { - import type { FFIFunctionCallableSymbol } from "bun:ffi"; - import type { Encoding as CryptoEncoding } from "crypto"; - import type { X509Certificate } from "node:crypto"; - import type { Stats } from "node:fs"; - import type { CipherNameAndProtocol, EphemeralKeyInfo, PeerCertificate } from "tls"; - - type DistributedOmit = T extends T ? Omit : never; - type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; - - 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 - | string - | { raw: string } - | Subprocess - | SpawnOptions.Readable - | SpawnOptions.Writable - | ReadableStream; - - class ShellPromise extends Promise { - 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 | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - } - - type ShellError = _ShellError; - - export interface Shell { - (strings: TemplateStringsArray, ...expressions: ShellExpression[]): ShellPromise; - - readonly ShellError: typeof _ShellError; - - /** - * 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): 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; + import type { FFIFunctionCallableSymbol } from "bun:ffi"; + import type { Encoding as CryptoEncoding } from "crypto"; + import type { X509Certificate } from "node:crypto"; + import type { Stats } from "node:fs"; + import type { + CipherNameAndProtocol, + EphemeralKeyInfo, + PeerCertificate, + } from "tls"; + + type DistributedOmit = T extends T ? Omit : never; + type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; + + 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 + | string + | { raw: string } + | Subprocess + | SpawnOptions.Readable + | SpawnOptions.Writable + | ReadableStream; + + class ShellPromise extends Promise { + 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 | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + } + + type ShellError = _ShellError; + + export interface Shell { + ( + strings: TemplateStringsArray, + ...expressions: ShellExpression[] + ): ShellPromise; + + readonly ShellError: typeof _ShellError; + + /** + * 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): 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; + + /** + * 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; + + /** + * 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 | S3File | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + 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, + maxLength?: number, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + maxLength: number, + asUint8Array: false, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + 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, + ): Promise | 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, + ): Promise | 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; + + /** + * 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, + multipartBoundaryExcludingDashes?: + | string + | NodeJS.TypedArray + | ArrayBufferView, + ): Promise; + + /** + * 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; + + /** + * 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; + + /** + * 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( + stream: ReadableStream, + ): Promise | T[]; + + /** + * Escape the following characters in a string: + * + * - `"` 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. + * + * @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 { + (promise: T | Promise): Promise | T; + status( + promise: T | Promise, + ): "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; + + /** + * + * **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; + }; + + ADDRCONFIG: number; + ALL: number; + 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; + } + + /** + * 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; + /** + * Close the file descriptor. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; + + 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; + + /** + * 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; + + /** + * Deletes the file. + */ + unlink(): Promise; + + /** + * Deletes the file. ( same as unlink ) + */ + delete(): Promise; + + /** + * Provides useful information about the file. + */ + stat(): Promise; + } + interface NetworkSink extends FileSink { + /** + * Write a chunk of data to the network. + * + * If the network is not writable yet, the data is buffered. + */ + write( + chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + ): number; + /** + * Flush the internal buffer, committing the data to the network. + */ + flush(): number | Promise; + /** + * Finish the upload. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; + + /** + * Get the stat of the file. + */ + stat(): Promise; + } + + var S3Client: S3Client; + var s3: S3Client; + + /** + * Configuration options for S3 operations + */ + interface S3Options extends BlobPropertyBag { + /** + * The Access Control List (ACL) policy for the file. + * Controls who can access the file and what permissions they have. + * + * @example + * // Setting public read access + * const file = s3("public-file.txt", { + * acl: "public-read", + * bucket: "my-bucket" + * }); + * + * @example + * // Using with presigned URLs + * const url = file.presign({ + * acl: "public-read", + * expiresIn: 3600 + * }); + */ + acl?: + | "private" + | "public-read" + | "public-read-write" + | "aws-exec-read" + | "authenticated-read" + | "bucket-owner-read" + | "bucket-owner-full-control" + | "log-delivery-write"; + + /** + * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. + * + * @example + * // Using explicit bucket + * const file = s3("my-file.txt", { bucket: "my-bucket" }); + * + * @example + * // Using environment variables + * // With S3_BUCKET=my-bucket in .env + * const file = s3("my-file.txt"); + */ + bucket?: string; + + /** + * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. + * + * @example + * const file = s3("my-file.txt", { + * bucket: "my-bucket", + * region: "us-west-2" + * }); + */ + region?: string; + + /** + * The access key ID for authentication. + * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. + */ + accessKeyId?: string; + + /** + * The secret access key for authentication. + * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. + */ + secretAccessKey?: string; + + /** + * Optional session token for temporary credentials. + * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. + * + * @example + * // Using temporary credentials + * const file = s3("my-file.txt", { + * accessKeyId: tempAccessKey, + * secretAccessKey: tempSecretKey, + * sessionToken: tempSessionToken + * }); + */ + sessionToken?: string; + + /** + * The S3-compatible service endpoint URL. + * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. + * + * @example + * // AWS S3 + * const file = s3("my-file.txt", { + * endpoint: "https://s3.us-east-1.amazonaws.com" + * }); + * + * @example + * // Cloudflare R2 + * const file = s3("my-file.txt", { + * endpoint: "https://.r2.cloudflarestorage.com" + * }); + * + * @example + * // DigitalOcean Spaces + * const file = s3("my-file.txt", { + * endpoint: "https://.digitaloceanspaces.com" + * }); + * + * @example + * // MinIO (local development) + * const file = s3("my-file.txt", { + * endpoint: "http://localhost:9000" + * }); + */ + endpoint?: string; + + /** + * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` + * + * @example + * // Using virtual hosted style + * const file = s3("my-file.txt", { + * virtualHostedStyle: true, + * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" + * }); + */ + virtualHostedStyle?: boolean; + + /** + * The size of each part in multipart uploads (in bytes). + * - Minimum: 5 MiB + * - Maximum: 5120 MiB + * - Default: 5 MiB + * + * @example + * // Configuring multipart uploads + * const file = s3("large-file.dat", { + * partSize: 10 * 1024 * 1024, // 10 MiB parts + * queueSize: 4 // Upload 4 parts in parallel + * }); + * + * const writer = file.writer(); + * // ... write large file in chunks + */ + partSize?: number; + + /** + * Number of parts to upload in parallel for multipart uploads. + * - Default: 5 + * - Maximum: 255 + * + * Increasing this value can improve upload speeds for large files + * but will use more memory. + */ + queueSize?: number; + + /** + * Number of retry attempts for failed uploads. + * - Default: 3 + * - Maximum: 255 + * + * @example + * // Setting retry attempts + * const file = s3("my-file.txt", { + * retry: 5 // Retry failed uploads up to 5 times + * }); + */ + retry?: number; + + /** + * The Content-Type of the file. + * Automatically set based on file extension when possible. + * + * @example + * // Setting explicit content type + * const file = s3("data.bin", { + * type: "application/octet-stream" + * }); + */ + type?: string; + + /** + * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. + * + * @example + * // Setting explicit Storage class + * const file = s3("my-file.json", { + * storageClass: "STANDARD_IA" + * }); + */ + storageClass?: + | "STANDARD" + | "DEEP_ARCHIVE" + | "EXPRESS_ONEZONE" + | "GLACIER" + | "GLACIER_IR" + | "INTELLIGENT_TIERING" + | "ONEZONE_IA" + | "OUTPOSTS" + | "REDUCED_REDUNDANCY" + | "SNOW" + | "STANDARD_IA"; + + /** + * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. + */ + highWaterMark?: number; + } + + /** + * Options for generating presigned URLs + */ + interface S3FilePresignOptions extends S3Options { + /** + * Number of seconds until the presigned URL expires. + * - Default: 86400 (1 day) + * + * @example + * // Short-lived URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Long-lived public URL + * const url = file.presign({ + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + expiresIn?: number; + + /** + * The HTTP method allowed for the presigned URL. + * + * @example + * // GET URL for downloads + * const downloadUrl = file.presign({ + * method: "GET", + * expiresIn: 3600 + * }); + * + * @example + * // PUT URL for uploads + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "application/json" + * }); + */ + method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; + } + + interface S3Stats { + size: number; + lastModified: Date; + etag: string; + type: string; + } + + /** + * Represents a file in an S3-compatible storage service. + * Extends the Blob interface for compatibility with web APIs. + */ + interface S3File extends Blob { + /** + * The size of the file in bytes. + * This is a Promise because it requires a network request to determine the size. + * + * @example + * // Getting file size + * const size = await file.size; + * console.log(`File size: ${size} bytes`); + * + * @example + * // Check if file is larger than 1MB + * if (await file.size > 1024 * 1024) { + * console.log("Large file detected"); + * } + */ + /** + * TODO: figure out how to get the typescript types to not error for this property. + */ + // size: Promise; + + /** + * Creates a new S3File representing a slice of the original file. + * Uses HTTP Range headers for efficient partial downloads. + * + * @param begin - Starting byte offset + * @param end - Ending byte offset (exclusive) + * @param contentType - Optional MIME type for the slice + * @returns A new S3File representing the specified range + * + * @example + * // Reading file header + * const header = file.slice(0, 1024); + * const headerText = await header.text(); + * + * @example + * // Reading with content type + * const jsonSlice = file.slice(1024, 2048, "application/json"); + * const data = await jsonSlice.json(); + * + * @example + * // Reading from offset to end + * const remainder = file.slice(1024); + * const content = await remainder.text(); + */ + slice(begin?: number, end?: number, contentType?: string): S3File; + slice(begin?: number, contentType?: string): S3File; + slice(contentType?: string): S3File; + + /** + * Creates a writable stream for uploading data. + * Suitable for large files as it uses multipart upload. + * + * @param options - Configuration for the upload + * @returns A NetworkSink for writing data + * + * @example + * // Basic streaming write + * const writer = file.writer({ + * type: "application/json" + * }); + * writer.write('{"hello": '); + * writer.write('"world"}'); + * await writer.end(); + * + * @example + * // Optimized large file upload + * const writer = file.writer({ + * partSize: 10 * 1024 * 1024, // 10MB parts + * queueSize: 4, // Upload 4 parts in parallel + * retry: 3 // Retry failed parts + * }); + * + * // Write large chunks of data efficiently + * for (const chunk of largeDataChunks) { + * writer.write(chunk); + * } + * await writer.end(); + * + * @example + * // Error handling + * const writer = file.writer(); + * try { + * writer.write(data); + * await writer.end(); + * } catch (err) { + * console.error('Upload failed:', err); + * // Writer will automatically abort multipart upload on error + * } + */ + writer(options?: S3Options): NetworkSink; + + /** + * Gets a readable stream of the file's content. + * Useful for processing large files without loading them entirely into memory. + * + * @returns A ReadableStream for the file content + * + * @example + * // Basic streaming read + * const stream = file.stream(); + * for await (const chunk of stream) { + * console.log('Received chunk:', chunk); + * } + * + * @example + * // Piping to response + * const stream = file.stream(); + * return new Response(stream, { + * headers: { 'Content-Type': file.type } + * }); + * + * @example + * // Processing large files + * const stream = file.stream(); + * const textDecoder = new TextDecoder(); + * for await (const chunk of stream) { + * const text = textDecoder.decode(chunk); + * // Process text chunk by chunk + * } + */ + readonly readable: ReadableStream; + stream(): ReadableStream; + + /** + * The name or path of the file in the bucket. + * + * @example + * const file = s3("folder/image.jpg"); + * console.log(file.name); // "folder/image.jpg" + */ + readonly name?: string; + + /** + * The bucket name containing the file. + * + * @example + * const file = s3("s3://my-bucket/file.txt"); + * console.log(file.bucket); // "my-bucket" + */ + readonly bucket?: string; + + /** + * Checks if the file exists in S3. + * Uses HTTP HEAD request to efficiently check existence without downloading. + * + * @returns Promise resolving to true if file exists, false otherwise + * + * @example + * // Basic existence check + * if (await file.exists()) { + * console.log("File exists in S3"); + * } + * + * @example + * // With error handling + * try { + * const exists = await file.exists(); + * if (!exists) { + * console.log("File not found"); + * } + * } catch (err) { + * console.error("Error checking file:", err); + * } + */ + exists(): Promise; + + /** + * Uploads data to S3. + * Supports various input types and automatically handles large files. + * + * @param data - The data to upload + * @param options - Upload configuration options + * @returns Promise resolving to number of bytes written + * + * @example + * // Writing string data + * await file.write("Hello World", { + * type: "text/plain" + * }); + * + * @example + * // Writing JSON + * const data = { hello: "world" }; + * await file.write(JSON.stringify(data), { + * type: "application/json" + * }); + * + * @example + * // Writing from Response + * const response = await fetch("https://example.com/data"); + * await file.write(response); + * + * @example + * // Writing with ACL + * await file.write(data, { + * acl: "public-read", + * type: "application/octet-stream" + * }); + */ + write( + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob, + options?: S3Options, + ): Promise; + + /** + * Generates a presigned URL for the file. + * Allows temporary access to the file without exposing credentials. + * + * @param options - Configuration for the presigned URL + * @returns Presigned URL string + * + * @example + * // Basic download URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Upload URL with specific content type + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * @example + * // URL with custom permissions + * const url = file.presign({ + * method: "GET", + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(options?: S3FilePresignOptions): string; + + /** + * Deletes the file from S3. + * + * @returns Promise that resolves when deletion is complete + * + * @example + * // Basic deletion + * await file.delete(); + * + * @example + * // With error handling + * try { + * await file.delete(); + * console.log("File deleted successfully"); + * } catch (err) { + * console.error("Failed to delete file:", err); + * } + */ + delete(): Promise; + + /** + * Alias for delete() method. + * Provided for compatibility with Node.js fs API naming. + * + * @example + * await file.unlink(); + */ + unlink: S3File["delete"]; + + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @returns Promise resolving to S3Stat + */ + stat(): Promise; + } + + /** + * A configured S3 bucket instance for managing files. + * The instance is callable to create S3File instances and provides methods + * for common operations. + * + * @example + * // Basic bucket setup + * const bucket = new S3Client({ + * bucket: "my-bucket", + * accessKeyId: "key", + * secretAccessKey: "secret" + * }); + * + * // Get file instance + * const file = bucket("image.jpg"); + * + * // Common operations + * await bucket.write("data.json", JSON.stringify({hello: "world"})); + * const url = bucket.presign("file.pdf"); + * await bucket.unlink("old.txt"); + */ + type S3Client = { + /** + * Create a new instance of an S3 bucket so that credentials can be managed + * from a single instance instead of being passed to every method. + * + * @param options The default options to use for the S3 client. Can be + * overriden by passing options to the methods. + * + * ## Keep S3 credentials in a single instance + * + * @example + * const bucket = new Bun.S3Client({ + * accessKeyId: "your-access-key", + * secretAccessKey: "your-secret-key", + * bucket: "my-bucket", + * endpoint: "https://s3.us-east-1.amazonaws.com", + * sessionToken: "your-session-token", + * }); + * + * // S3Client is callable, so you can do this: + * const file = bucket.file("my-file.txt"); + * + * // or this: + * await file.write("Hello Bun!"); + * await file.text(); + * + * // To delete the file: + * await bucket.delete("my-file.txt"); + * + * // To write a file without returning the instance: + * await bucket.write("my-file.txt", "Hello Bun!"); + * + */ + new (options?: S3Options): S3Client; + + /** + * Creates an S3File instance for the given path. + * + * @example + * const file = bucket.file("image.jpg"); + * await file.write(imageData); + * const configFile = bucket("config.json", { + * type: "application/json", + * acl: "private" + * }); + */ + file(path: string, options?: S3Options): S3File; + + /** + * Writes data directly to a path in the bucket. + * Supports strings, buffers, streams, and web API types. + * + * @example + * // Write string + * await bucket.write("hello.txt", "Hello World"); + * + * // Write JSON with type + * await bucket.write( + * "data.json", + * JSON.stringify({hello: "world"}), + * {type: "application/json"} + * ); + * + * // Write from fetch + * const res = await fetch("https://example.com/data"); + * await bucket.write("data.bin", res); + * + * // Write with ACL + * await bucket.write("public.html", html, { + * acl: "public-read", + * type: "text/html" + * }); + */ + write( + path: string, + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob + | File, + options?: S3Options, + ): Promise; + + /** + * Generate a presigned URL for temporary access to a file. + * Useful for generating upload/download URLs without exposing credentials. + * + * @example + * // Download URL + * const downloadUrl = bucket.presign("file.pdf", { + * expiresIn: 3600 // 1 hour + * }); + * + * // Upload URL + * const uploadUrl = bucket.presign("uploads/image.jpg", { + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * // Long-lived public URL + * const publicUrl = bucket.presign("public/doc.pdf", { + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(path: string, options?: S3FilePresignOptions): string; + + /** + * Delete a file from the bucket. + * + * @example + * // Simple delete + * await bucket.unlink("old-file.txt"); + * + * // With error handling + * try { + * await bucket.unlink("file.dat"); + * console.log("File deleted"); + * } catch (err) { + * console.error("Delete failed:", err); + * } + */ + unlink(path: string, options?: S3Options): Promise; + delete: S3Client["unlink"]; + + /** + * Get the size of a file in bytes. + * Uses HEAD request to efficiently get size. + * + * @example + * // Get size + * const bytes = await bucket.size("video.mp4"); + * console.log(`Size: ${bytes} bytes`); + * + * // Check if file is large + * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { + * console.log("File is larger than 100MB"); + * } + */ + size(path: string, options?: S3Options): Promise; + + /** + * Check if a file exists in the bucket. + * Uses HEAD request to check existence. + * + * @example + * // Check existence + * if (await bucket.exists("config.json")) { + * const file = bucket("config.json"); + * const config = await file.json(); + * } + * + * // With error handling + * try { + * if (!await bucket.exists("required.txt")) { + * throw new Error("Required file missing"); + * } + * } catch (err) { + * console.error("Check failed:", err); + * } + */ + exists(path: string, options?: S3Options): Promise; + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @param path The path to the file. + * @param options The options to use for the S3 client. + */ + stat(path: string, options?: S3Options): Promise; + }; + /** + * Configuration options for SQL client connection and behavior + * @example + * const config: SQLOptions = { + * host: 'localhost', + * port: 5432, + * user: 'dbuser', + * password: 'secretpass', + * database: 'myapp', + * idleTimeout: 30000, + * max: 20, + * onconnect: (client) => { + * console.log('Connected to database'); + * } + * }; + */ + type 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); + /** Database password for authentication (alias for password) */ + pass?: string | (() => Promise); + /** 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 extends Promise { + /** Indicates if the query is currently executing */ + active: boolean; + /** Indicates if the query has been cancelled */ + cancelled: boolean; + /** Cancels the executing query */ + cancel(): SQLQuery; + /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ + simple(): SQLQuery; + /** Executes the query */ + execute(): SQLQuery; + /** Returns the raw query result */ + raw(): SQLQuery; + /** Returns only the values from the query result */ + values(): SQLQuery; + } + + /** + * Callback function type for transaction contexts + * @param sql Function to execute SQL queries within the transaction + */ + type SQLTransactionContextCallback = ( + sql: TransactionSQL, + ) => Promise | Array; + /** + * Callback function type for savepoint contexts + * @param sql Function to execute SQL queries within the savepoint + */ + type SQLSavepointContextCallback = ( + sql: SavepointSQL, + ) => Promise | Array; + + /** + * Main SQL client interface providing connection and transaction management + */ + interface SQL { + /** Creates a new SQL client instance + * @example + * const sql = new SQL("postgres://localhost:5432/mydb"); + * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); + */ + new (connectionString: string | URL): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); + */ + new (connectionString: string | URL, options: SQLOptions): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); + */ + new (options?: SQLOptions): SQL; + /** Executes a SQL query using template literals + * @example + * const [user] = await sql`select * from users where id = ${1}`; + */ + (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; + /** + * Helper function to allow easy use to insert values into a query + * @example + * const result = await sql`insert into users ${sql(users)} RETURNING *`; + */ + (obj: any): SQLQuery; + /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.commitDistributed("my_distributed_transaction"); + */ + commitDistributed(name: string): Promise; + /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.rollbackDistributed("my_distributed_transaction"); + */ + rollbackDistributed(name: string): Promise; + /** Waits for the database connection to be established + * @example + * await sql.connect(); + */ + connect(): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @example + * await sql.close({ timeout: 1 }); + */ + close(options?: { timeout?: number }): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @alias close + * @example + * await sql.end({ timeout: 1 }); + */ + end(options?: { timeout?: number }): Promise; + /** Flushes any pending operations */ + flush(): void; + /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. + * This can be used for running queries on an isolated connection. + * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). + * @example + * const reserved = await sql.reserve(); + * await reserved`select * from users`; + * await reserved.release(); + * // with in a production scenario would be something more like + * const reserved = await sql.reserve(); + * try { + * // ... queries + * } finally { + * await reserved.release(); + * } + * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose + * { + * // always release after context (safer) + * using reserved = await sql.reserve() + * await reserved`select * from users` + * } + */ + reserve(): Promise; + /** Begins a new transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(fn: SQLTransactionContextCallback): Promise; + /** Begins a new transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(options: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction( + options: string, + fn: SQLTransactionContextCallback, + ): Promise; + /** Begins a distributed transaction + * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. + * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. + * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. + * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. + * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. + * @example + * await sql.beginDistributed("numbers", async sql => { + * await sql`create table if not exists numbers (a int)`; + * await sql`insert into numbers values(1)`; + * }); + * // later you can call + * await sql.commitDistributed("numbers"); + * // or await sql.rollbackDistributed("numbers"); + */ + beginDistributed( + name: string, + fn: SQLTransactionContextCallback, + ): Promise; + /** Alternative method to begin a distributed transaction + * @alias beginDistributed + */ + distributed(name: string, fn: SQLTransactionContextCallback): Promise; + /**If you know what you're doing, you can use unsafe to pass any string you'd like. + * Please note that this can lead to SQL injection if you're not careful. + * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. + * @example + * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) + */ + unsafe(string: string, values?: any[]): SQLQuery; + /** + * Reads a file and uses the contents as a query. + * Optional parameters can be used if the file includes $1, $2, etc + * @example + * const result = await sql.file("query.sql", [1, 2, 3]); + */ + file(filename: string, values?: any[]): SQLQuery; + + /** Current client options */ + options: SQLOptions; + + [Symbol.asyncDispose](): Promise; + } + + /** + * Represents a reserved connection from the connection pool + * Extends SQL with additional release functionality + */ + interface ReservedSQL extends SQL { + /** Releases the client back to the connection pool */ + release(): void; + [Symbol.dispose](): void; + } + + /** + * Represents a client within a transaction context + * Extends SQL with savepoint functionality + */ + interface TransactionSQL extends SQL { + /** Creates a savepoint within the current transaction */ + savepoint(name: string, fn: SQLSavepointContextCallback): Promise; + savepoint(fn: SQLSavepointContextCallback): Promise; + } + /** + * Represents a savepoint within a transaction + */ + interface SavepointSQL extends SQL {} + + var sql: SQL; + var postgres: SQL; + var SQL: SQL; + + /** + * This lets you use macros as regular imports + * @example + * ``` + * { + * "react-relay": { + * "graphql": "bun-macro-relay/bun-macro-relay.tsx" + * } + * } + * ``` + */ + type MacroMap = Record>; + + /** + * 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; + } + + 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; + 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; + + /** 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; + }; + 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 = () =>
Hello World
; + * 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; + /** + * 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-run" + | "entry-point-build"; + + 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?: /** - /** - * 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 + * ECMAScript Module format */ - parse(input: string): object; - } - const TOML: TOML; - - /** - * 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; - - /** - * 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 | S3File | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - 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, maxLength?: number): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - maxLength: number, - asUint8Array: false, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - 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, - ): Promise | 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, - ): Promise | 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; - - /** - * 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, - multipartBoundaryExcludingDashes?: string | NodeJS.TypedArray | ArrayBufferView, - ): Promise; - - /** - * 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; - - /** - * 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; - - /** - * 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(stream: ReadableStream): Promise | T[]; - - /** - * Escape the following characters in a string: - * - * - `"` becomes `"""` - * - `&` becomes `"&"` - * - `'` becomes `"'"` - * - `<` becomes `"<"` - * - `>` becomes `">"` + | "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; + // origin?: string; // e.g. http://mydomain.com + loader?: { [k in string]: Loader }; + sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; // 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; + + /** + * Controls how environment variables are handled during bundling. + * + * Can be one of: + * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` + * references to string literals containing the actual environment variable values + * - `"disable"`: Disables environment variable injection entirely + * - A string ending in `*`: Inlines environment variables that match the given prefix. + * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" + * + * @example + * ```ts + * Bun.build({ + * env: "MY_PUBLIC_*", + * entrypoints: ["src/index.ts"], + * }) + * ``` + */ + env?: "inline" | "disable" | `${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; + + /** + * Drop function calls to matching property accesses. + */ + drop?: string[]; + + /** + * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. + * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. + * This defaults to `true`. + */ + throw?: boolean; + } + + 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 password. + * If empty, always returns false + */ + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + * + * If specified and the algorithm does not match the hash, this function + * throws an error. + */ + algorithm?: Password.AlgorithmLabel, + ): Promise; + /** + * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. + * + * @returns A promise that resolves to the hashed password + * + * ## Example with argon2 + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world"); + * console.log(hash); // $argon2id$v=1... + * const verify = await password.verify("hello world", hash); + * ``` + * ## Example with bcrypt + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world", "bcrypt"); + * console.log(hash); // $2b$10$... + * const verify = await password.verify("hello world", hash); + * ``` + */ + hash( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before + */ + algorithm?: + | Password.AlgorithmLabel + | Password.Argon2Algorithm + | Password.BCryptAlgorithm, + ): Promise; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.verify} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + verifySync( + password: Bun.StringOrBuffer, + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + */ + algorithm?: Password.AlgorithmLabel, + ): boolean; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.hash} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + hashSync( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before + */ + algorithm?: + | Password.AlgorithmLabel + | Password.Argon2Algorithm + | Password.BCryptAlgorithm, + ): string; + }; + + interface BuildArtifact extends Blob { + path: string; + loader: Loader; + hash: string | null; + kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; + sourcemap: BuildArtifact | null; + } + + interface BuildOutput { + outputs: BuildArtifact[]; + success: boolean; + logs: Array; + } + + /** + * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. * - * 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. + * @param {Object} config - Build configuration options + * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status + * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) * - * Non-string types will be converted to a string before escaping. - */ - function escapeHTML(input: string | object | number | boolean): string; + * @example Basic usage - Bundle a single entrypoint and check results + ```ts + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist' + }); - /** - * 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 { - (promise: T | Promise): Promise | T; - status(promise: T | Promise): "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"; + if (!result.success) { + console.error('Build failed:', result.logs); + process.exit(1); + } + ``` + * + * @example Set up multiple entrypoints with code splitting enabled + ```ts + await Bun.build({ + entrypoints: ['./src/app.tsx', './src/admin.tsx'], + outdir: './dist', + splitting: true, + sourcemap: "external" + }); + ``` + * + * @example Configure minification and optimization settings + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + minify: { + whitespace: true, + identifiers: true, + syntax: true }, - ): Promise; - - /** - * - * **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; - }; - - ADDRCONFIG: number; - ALL: number; - 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; - } - - /** - * 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; - /** - * Close the file descriptor. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; - - 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; - - /** - * 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; - - /** - * Deletes the file. - */ - unlink(): Promise; - - /** - * Deletes the file. ( same as unlink ) - */ - delete(): Promise; - - /** - * Provides useful information about the file. - */ - stat(): Promise; - } - interface NetworkSink extends FileSink { - /** - * Write a chunk of data to the network. - * - * If the network is not writable yet, the data is buffered. - */ - write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number; - /** - * Flush the internal buffer, committing the data to the network. - */ - flush(): number | Promise; - /** - * Finish the upload. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; + drop: ['console', 'debugger'] + }); + ``` + * + * @example Set up custom loaders and mark packages as external + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + loader: { + '.png': 'dataurl', + '.svg': 'file', + '.txt': 'text', + '.json': 'json' + }, + external: ['react', 'react-dom'] + }); + ``` + * + * @example Configure environment variable handling with different modes + ```ts + // Inline all environment variables + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + env: 'inline' + }); - /** - * Get the stat of the file. - */ - stat(): Promise; - } - - var S3Client: S3Client; - var s3: S3Client; - - /** - * Configuration options for S3 operations - */ - interface S3Options extends BlobPropertyBag { - /** - * The Access Control List (ACL) policy for the file. - * Controls who can access the file and what permissions they have. - * - * @example - * // Setting public read access - * const file = s3("public-file.txt", { - * acl: "public-read", - * bucket: "my-bucket" - * }); - * - * @example - * // Using with presigned URLs - * const url = file.presign({ - * acl: "public-read", - * expiresIn: 3600 - * }); - */ - acl?: - | "private" - | "public-read" - | "public-read-write" - | "aws-exec-read" - | "authenticated-read" - | "bucket-owner-read" - | "bucket-owner-full-control" - | "log-delivery-write"; - - /** - * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. - * - * @example - * // Using explicit bucket - * const file = s3("my-file.txt", { bucket: "my-bucket" }); - * - * @example - * // Using environment variables - * // With S3_BUCKET=my-bucket in .env - * const file = s3("my-file.txt"); - */ - bucket?: string; - - /** - * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. - * - * @example - * const file = s3("my-file.txt", { - * bucket: "my-bucket", - * region: "us-west-2" - * }); - */ - region?: string; + // Only include specific env vars + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + env: 'PUBLIC_*' + }); + ``` + * + * @example Set up custom naming patterns for all output types + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + naming: { + entry: '[dir]/[name]-[hash].[ext]', + chunk: 'chunks/[name]-[hash].[ext]', + asset: 'assets/[name]-[hash].[ext]' + } + }); + ``` + @example Work with build artifacts in different formats + ```ts + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'] + }); - /** - * The access key ID for authentication. - * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. - */ - accessKeyId?: string; - - /** - * The secret access key for authentication. - * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. - */ - secretAccessKey?: string; - - /** - * Optional session token for temporary credentials. - * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. - * - * @example - * // Using temporary credentials - * const file = s3("my-file.txt", { - * accessKeyId: tempAccessKey, - * secretAccessKey: tempSecretKey, - * sessionToken: tempSessionToken - * }); - */ - sessionToken?: string; - - /** - * The S3-compatible service endpoint URL. - * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. - * - * @example - * // AWS S3 - * const file = s3("my-file.txt", { - * endpoint: "https://s3.us-east-1.amazonaws.com" - * }); - * - * @example - * // Cloudflare R2 - * const file = s3("my-file.txt", { - * endpoint: "https://.r2.cloudflarestorage.com" - * }); - * - * @example - * // DigitalOcean Spaces - * const file = s3("my-file.txt", { - * endpoint: "https://.digitaloceanspaces.com" - * }); - * - * @example - * // MinIO (local development) - * const file = s3("my-file.txt", { - * endpoint: "http://localhost:9000" - * }); - */ - endpoint?: string; - - /** - * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` - * - * @example - * // Using virtual hosted style - * const file = s3("my-file.txt", { - * virtualHostedStyle: true, - * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" - * }); - */ - virtualHostedStyle?: boolean; - - /** - * The size of each part in multipart uploads (in bytes). - * - Minimum: 5 MiB - * - Maximum: 5120 MiB - * - Default: 5 MiB - * - * @example - * // Configuring multipart uploads - * const file = s3("large-file.dat", { - * partSize: 10 * 1024 * 1024, // 10 MiB parts - * queueSize: 4 // Upload 4 parts in parallel - * }); - * - * const writer = file.writer(); - * // ... write large file in chunks - */ - partSize?: number; - - /** - * Number of parts to upload in parallel for multipart uploads. - * - Default: 5 - * - Maximum: 255 - * - * Increasing this value can improve upload speeds for large files - * but will use more memory. - */ - queueSize?: number; - - /** - * Number of retry attempts for failed uploads. - * - Default: 3 - * - Maximum: 255 - * - * @example - * // Setting retry attempts - * const file = s3("my-file.txt", { - * retry: 5 // Retry failed uploads up to 5 times - * }); - */ - retry?: number; - - /** - * The Content-Type of the file. - * Automatically set based on file extension when possible. - * - * @example - * // Setting explicit content type - * const file = s3("data.bin", { - * type: "application/octet-stream" - * }); - */ - type?: string; - - /** - * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. - * - * @example - * // Setting explicit Storage class - * const file = s3("my-file.json", { - * storageClass: "STANDARD_IA" - * }); - */ - storageClass?: - | "STANDARD" - | "DEEP_ARCHIVE" - | "EXPRESS_ONEZONE" - | "GLACIER" - | "GLACIER_IR" - | "INTELLIGENT_TIERING" - | "ONEZONE_IA" - | "OUTPOSTS" - | "REDUCED_REDUNDANCY" - | "SNOW" - | "STANDARD_IA"; - - /** - * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. - */ - highWaterMark?: number; - } - - /** - * Options for generating presigned URLs - */ - interface S3FilePresignOptions extends S3Options { - /** - * Number of seconds until the presigned URL expires. - * - Default: 86400 (1 day) - * - * @example - * // Short-lived URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Long-lived public URL - * const url = file.presign({ - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - expiresIn?: number; - - /** - * The HTTP method allowed for the presigned URL. - * - * @example - * // GET URL for downloads - * const downloadUrl = file.presign({ - * method: "GET", - * expiresIn: 3600 - * }); - * - * @example - * // PUT URL for uploads - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "application/json" - * }); - */ - method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; - } - - interface S3Stats { - size: number; - lastModified: Date; - etag: string; - type: string; - } - - /** - * Represents a file in an S3-compatible storage service. - * Extends the Blob interface for compatibility with web APIs. - */ - interface S3File extends Blob { - /** - * The size of the file in bytes. - * This is a Promise because it requires a network request to determine the size. - * - * @example - * // Getting file size - * const size = await file.size; - * console.log(`File size: ${size} bytes`); - * - * @example - * // Check if file is larger than 1MB - * if (await file.size > 1024 * 1024) { - * console.log("Large file detected"); - * } - */ - /** - * TODO: figure out how to get the typescript types to not error for this property. - */ - // size: Promise; - - /** - * Creates a new S3File representing a slice of the original file. - * Uses HTTP Range headers for efficient partial downloads. - * - * @param begin - Starting byte offset - * @param end - Ending byte offset (exclusive) - * @param contentType - Optional MIME type for the slice - * @returns A new S3File representing the specified range - * - * @example - * // Reading file header - * const header = file.slice(0, 1024); - * const headerText = await header.text(); - * - * @example - * // Reading with content type - * const jsonSlice = file.slice(1024, 2048, "application/json"); - * const data = await jsonSlice.json(); - * - * @example - * // Reading from offset to end - * const remainder = file.slice(1024); - * const content = await remainder.text(); - */ - slice(begin?: number, end?: number, contentType?: string): S3File; - slice(begin?: number, contentType?: string): S3File; - slice(contentType?: string): S3File; - - /** - * Creates a writable stream for uploading data. - * Suitable for large files as it uses multipart upload. - * - * @param options - Configuration for the upload - * @returns A NetworkSink for writing data - * - * @example - * // Basic streaming write - * const writer = file.writer({ - * type: "application/json" - * }); - * writer.write('{"hello": '); - * writer.write('"world"}'); - * await writer.end(); - * - * @example - * // Optimized large file upload - * const writer = file.writer({ - * partSize: 10 * 1024 * 1024, // 10MB parts - * queueSize: 4, // Upload 4 parts in parallel - * retry: 3 // Retry failed parts - * }); - * - * // Write large chunks of data efficiently - * for (const chunk of largeDataChunks) { - * writer.write(chunk); - * } - * await writer.end(); - * - * @example - * // Error handling - * const writer = file.writer(); - * try { - * writer.write(data); - * await writer.end(); - * } catch (err) { - * console.error('Upload failed:', err); - * // Writer will automatically abort multipart upload on error - * } - */ - writer(options?: S3Options): NetworkSink; - - /** - * Gets a readable stream of the file's content. - * Useful for processing large files without loading them entirely into memory. - * - * @returns A ReadableStream for the file content - * - * @example - * // Basic streaming read - * const stream = file.stream(); - * for await (const chunk of stream) { - * console.log('Received chunk:', chunk); - * } - * - * @example - * // Piping to response - * const stream = file.stream(); - * return new Response(stream, { - * headers: { 'Content-Type': file.type } - * }); - * - * @example - * // Processing large files - * const stream = file.stream(); - * const textDecoder = new TextDecoder(); - * for await (const chunk of stream) { - * const text = textDecoder.decode(chunk); - * // Process text chunk by chunk - * } - */ - readonly readable: ReadableStream; - stream(): ReadableStream; - - /** - * The name or path of the file in the bucket. - * - * @example - * const file = s3("folder/image.jpg"); - * console.log(file.name); // "folder/image.jpg" - */ - readonly name?: string; - - /** - * The bucket name containing the file. - * - * @example - * const file = s3("s3://my-bucket/file.txt"); - * console.log(file.bucket); // "my-bucket" - */ - readonly bucket?: string; - - /** - * Checks if the file exists in S3. - * Uses HTTP HEAD request to efficiently check existence without downloading. - * - * @returns Promise resolving to true if file exists, false otherwise - * - * @example - * // Basic existence check - * if (await file.exists()) { - * console.log("File exists in S3"); - * } - * - * @example - * // With error handling - * try { - * const exists = await file.exists(); - * if (!exists) { - * console.log("File not found"); - * } - * } catch (err) { - * console.error("Error checking file:", err); - * } - */ - exists(): Promise; - - /** - * Uploads data to S3. - * Supports various input types and automatically handles large files. - * - * @param data - The data to upload - * @param options - Upload configuration options - * @returns Promise resolving to number of bytes written - * - * @example - * // Writing string data - * await file.write("Hello World", { - * type: "text/plain" - * }); - * - * @example - * // Writing JSON - * const data = { hello: "world" }; - * await file.write(JSON.stringify(data), { - * type: "application/json" - * }); - * - * @example - * // Writing from Response - * const response = await fetch("https://example.com/data"); - * await file.write(response); - * - * @example - * // Writing with ACL - * await file.write(data, { - * acl: "public-read", - * type: "application/octet-stream" - * }); - */ - write( - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | Request | Response | BunFile | S3File | Blob, - options?: S3Options, - ): Promise; - - /** - * Generates a presigned URL for the file. - * Allows temporary access to the file without exposing credentials. - * - * @param options - Configuration for the presigned URL - * @returns Presigned URL string - * - * @example - * // Basic download URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Upload URL with specific content type - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * @example - * // URL with custom permissions - * const url = file.presign({ - * method: "GET", - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(options?: S3FilePresignOptions): string; - - /** - * Deletes the file from S3. - * - * @returns Promise that resolves when deletion is complete - * - * @example - * // Basic deletion - * await file.delete(); - * - * @example - * // With error handling - * try { - * await file.delete(); - * console.log("File deleted successfully"); - * } catch (err) { - * console.error("Failed to delete file:", err); - * } - */ - delete(): Promise; - - /** - * Alias for delete() method. - * Provided for compatibility with Node.js fs API naming. - * - * @example - * await file.unlink(); - */ - unlink: S3File["delete"]; - - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @returns Promise resolving to S3Stat - */ - stat(): Promise; - } - - /** - * A configured S3 bucket instance for managing files. - * The instance is callable to create S3File instances and provides methods - * for common operations. - * - * @example - * // Basic bucket setup - * const bucket = new S3Client({ - * bucket: "my-bucket", - * accessKeyId: "key", - * secretAccessKey: "secret" - * }); - * - * // Get file instance - * const file = bucket("image.jpg"); - * - * // Common operations - * await bucket.write("data.json", JSON.stringify({hello: "world"})); - * const url = bucket.presign("file.pdf"); - * await bucket.unlink("old.txt"); - */ - type S3Client = { - /** - * Create a new instance of an S3 bucket so that credentials can be managed - * from a single instance instead of being passed to every method. - * - * @param options The default options to use for the S3 client. Can be - * overriden by passing options to the methods. - * - * ## Keep S3 credentials in a single instance - * - * @example - * const bucket = new Bun.S3Client({ - * accessKeyId: "your-access-key", - * secretAccessKey: "your-secret-key", - * bucket: "my-bucket", - * endpoint: "https://s3.us-east-1.amazonaws.com", - * sessionToken: "your-session-token", - * }); - * - * // S3Client is callable, so you can do this: - * const file = bucket.file("my-file.txt"); - * - * // or this: - * await file.write("Hello Bun!"); - * await file.text(); - * - * // To delete the file: - * await bucket.delete("my-file.txt"); - * - * // To write a file without returning the instance: - * await bucket.write("my-file.txt", "Hello Bun!"); - * - */ - new (options?: S3Options): S3Client; - - /** - * Creates an S3File instance for the given path. - * - * @example - * const file = bucket.file("image.jpg"); - * await file.write(imageData); - * const configFile = bucket("config.json", { - * type: "application/json", - * acl: "private" - * }); - */ - file(path: string, options?: S3Options): S3File; - - /** - * Writes data directly to a path in the bucket. - * Supports strings, buffers, streams, and web API types. - * - * @example - * // Write string - * await bucket.write("hello.txt", "Hello World"); - * - * // Write JSON with type - * await bucket.write( - * "data.json", - * JSON.stringify({hello: "world"}), - * {type: "application/json"} - * ); - * - * // Write from fetch - * const res = await fetch("https://example.com/data"); - * await bucket.write("data.bin", res); - * - * // Write with ACL - * await bucket.write("public.html", html, { - * acl: "public-read", - * type: "text/html" - * }); - */ - write( - path: string, - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob - | File, - options?: S3Options, - ): Promise; - - /** - * Generate a presigned URL for temporary access to a file. - * Useful for generating upload/download URLs without exposing credentials. - * - * @example - * // Download URL - * const downloadUrl = bucket.presign("file.pdf", { - * expiresIn: 3600 // 1 hour - * }); - * - * // Upload URL - * const uploadUrl = bucket.presign("uploads/image.jpg", { - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * // Long-lived public URL - * const publicUrl = bucket.presign("public/doc.pdf", { - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(path: string, options?: S3FilePresignOptions): string; - - /** - * Delete a file from the bucket. - * - * @example - * // Simple delete - * await bucket.unlink("old-file.txt"); - * - * // With error handling - * try { - * await bucket.unlink("file.dat"); - * console.log("File deleted"); - * } catch (err) { - * console.error("Delete failed:", err); - * } - */ - unlink(path: string, options?: S3Options): Promise; - delete: S3Client["unlink"]; - - /** - * Get the size of a file in bytes. - * Uses HEAD request to efficiently get size. - * - * @example - * // Get size - * const bytes = await bucket.size("video.mp4"); - * console.log(`Size: ${bytes} bytes`); - * - * // Check if file is large - * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { - * console.log("File is larger than 100MB"); - * } - */ - size(path: string, options?: S3Options): Promise; - - /** - * Check if a file exists in the bucket. - * Uses HEAD request to check existence. - * - * @example - * // Check existence - * if (await bucket.exists("config.json")) { - * const file = bucket("config.json"); - * const config = await file.json(); - * } - * - * // With error handling - * try { - * if (!await bucket.exists("required.txt")) { - * throw new Error("Required file missing"); - * } - * } catch (err) { - * console.error("Check failed:", err); - * } - */ - exists(path: string, options?: S3Options): Promise; - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @param path The path to the file. - * @param options The options to use for the S3 client. - */ - stat(path: string, options?: S3Options): Promise; - }; - /** - * Configuration options for SQL client connection and behavior - * @example - * const config: SQLOptions = { - * host: 'localhost', - * port: 5432, - * user: 'dbuser', - * password: 'secretpass', - * database: 'myapp', - * idleTimeout: 30000, - * max: 20, - * onconnect: (client) => { - * console.log('Connected to database'); - * } - * }; - */ - type 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); - /** Database password for authentication (alias for password) */ - pass?: string | (() => Promise); - /** 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 extends Promise { - /** Indicates if the query is currently executing */ - active: boolean; - /** Indicates if the query has been cancelled */ - cancelled: boolean; - /** Cancels the executing query */ - cancel(): SQLQuery; - /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ - simple(): SQLQuery; - /** Executes the query */ - execute(): SQLQuery; - /** Returns the raw query result */ - raw(): SQLQuery; - /** Returns only the values from the query result */ - values(): SQLQuery; - } - - /** - * Callback function type for transaction contexts - * @param sql Function to execute SQL queries within the transaction - */ - type SQLTransactionContextCallback = (sql: TransactionSQL) => Promise | Array; - /** - * Callback function type for savepoint contexts - * @param sql Function to execute SQL queries within the savepoint - */ - type SQLSavepointContextCallback = (sql: SavepointSQL) => Promise | Array; - - /** - * Main SQL client interface providing connection and transaction management - */ - interface SQL { - /** Creates a new SQL client instance - * @example - * const sql = new SQL("postgres://localhost:5432/mydb"); - * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); - */ - new (connectionString: string | URL): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); - */ - new (connectionString: string | URL, options: SQLOptions): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); - */ - new (options?: SQLOptions): SQL; - /** Executes a SQL query using template literals - * @example - * const [user] = await sql`select * from users where id = ${1}`; - */ - (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; - /** - * Helper function to allow easy use to insert values into a query - * @example - * const result = await sql`insert into users ${sql(users)} RETURNING *`; - */ - (obj: any): SQLQuery; - /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.commitDistributed("my_distributed_transaction"); - */ - commitDistributed(name: string): Promise; - /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.rollbackDistributed("my_distributed_transaction"); - */ - rollbackDistributed(name: string): Promise; - /** Waits for the database connection to be established - * @example - * await sql.connect(); - */ - connect(): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @example - * await sql.close({ timeout: 1 }); - */ - close(options?: { timeout?: number }): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @alias close - * @example - * await sql.end({ timeout: 1 }); - */ - end(options?: { timeout?: number }): Promise; - /** Flushes any pending operations */ - flush(): void; - /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. - * This can be used for running queries on an isolated connection. - * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). - * @example - * const reserved = await sql.reserve(); - * await reserved`select * from users`; - * await reserved.release(); - * // with in a production scenario would be something more like - * const reserved = await sql.reserve(); - * try { - * // ... queries - * } finally { - * await reserved.release(); - * } - * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose - * { - * // always release after context (safer) - * using reserved = await sql.reserve() - * await reserved`select * from users` - * } - */ - reserve(): Promise; - /** Begins a new transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(fn: SQLTransactionContextCallback): Promise; - /** Begins a new transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(options: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(options: string, fn: SQLTransactionContextCallback): Promise; - /** Begins a distributed transaction - * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. - * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. - * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. - * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. - * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. - * @example - * await sql.beginDistributed("numbers", async sql => { - * await sql`create table if not exists numbers (a int)`; - * await sql`insert into numbers values(1)`; - * }); - * // later you can call - * await sql.commitDistributed("numbers"); - * // or await sql.rollbackDistributed("numbers"); - */ - beginDistributed(name: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a distributed transaction - * @alias beginDistributed - */ - distributed(name: string, fn: SQLTransactionContextCallback): Promise; - /**If you know what you're doing, you can use unsafe to pass any string you'd like. - * Please note that this can lead to SQL injection if you're not careful. - * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. - * @example - * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) - */ - unsafe(string: string, values?: any[]): SQLQuery; - /** - * Reads a file and uses the contents as a query. - * Optional parameters can be used if the file includes $1, $2, etc - * @example - * const result = await sql.file("query.sql", [1, 2, 3]); - */ - file(filename: string, values?: any[]): SQLQuery; - - /** Current client options */ - options: SQLOptions; - - [Symbol.asyncDispose](): Promise; - } - - /** - * Represents a reserved connection from the connection pool - * Extends SQL with additional release functionality - */ - interface ReservedSQL extends SQL { - /** Releases the client back to the connection pool */ - release(): void; - [Symbol.dispose](): void; - } - - /** - * Represents a client within a transaction context - * Extends SQL with savepoint functionality - */ - interface TransactionSQL extends SQL { - /** Creates a savepoint within the current transaction */ - savepoint(name: string, fn: SQLSavepointContextCallback): Promise; - savepoint(fn: SQLSavepointContextCallback): Promise; - } - /** - * Represents a savepoint within a transaction - */ - interface SavepointSQL extends SQL {} - - var sql: SQL; - var postgres: SQL; - var SQL: SQL; - - /** - * This lets you use macros as regular imports - * @example - * ``` - * { - * "react-relay": { - * "graphql": "bun-macro-relay/bun-macro-relay.tsx" - * } - * } - * ``` - */ - type MacroMap = Record>; - - /** - * 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; - } - - 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; - 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; - - /** 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; - }; - 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 = () =>
Hello World
; - * 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; - /** - * 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-run" - | "entry-point-build"; - - 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; - // origin?: string; // e.g. http://mydomain.com - loader?: { [k in string]: Loader }; - sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; // 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; - - /** - * Controls how environment variables are handled during bundling. - * - * Can be one of: - * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` - * references to string literals containing the actual environment variable values - * - `"disable"`: Disables environment variable injection entirely - * - A string ending in `*`: Inlines environment variables that match the given prefix. - * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" - * - * @example - * ```ts - * Bun.build({ - * env: "MY_PUBLIC_*", - * entrypoints: ["src/index.ts"], - * }) - * ``` - */ - env?: "inline" | "disable" | `${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; - - /** - * Drop function calls to matching property accesses. - */ - drop?: string[]; - - /** - * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. - * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. - * This defaults to `true`. - */ - throw?: boolean; - } - - 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 password. - * If empty, always returns false - */ - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - * - * If specified and the algorithm does not match the hash, this function - * throws an error. - */ - algorithm?: Password.AlgorithmLabel, - ): Promise; - /** - * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. - * - * @returns A promise that resolves to the hashed password - * - * ## Example with argon2 - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world"); - * console.log(hash); // $argon2id$v=1... - * const verify = await password.verify("hello world", hash); - * ``` - * ## Example with bcrypt - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world", "bcrypt"); - * console.log(hash); // $2b$10$... - * const verify = await password.verify("hello world", hash); - * ``` - */ - hash( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before - */ - algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, - ): Promise; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.verify} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - verifySync( - password: Bun.StringOrBuffer, - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - */ - algorithm?: Password.AlgorithmLabel, - ): boolean; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.hash} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - hashSync( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before - */ - algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, - ): string; - }; - - interface BuildArtifact extends Blob { - path: string; - loader: Loader; - hash: string | null; - kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; - sourcemap: BuildArtifact | null; - } - - interface BuildOutput { - outputs: BuildArtifact[]; - success: boolean; - logs: Array; - } - - /** - * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. - * - * @param {Object} config - Build configuration options - * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status - * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) - * - * @example Basic usage - Bundle a single entrypoint and check results - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist' - }); - - if (!result.success) { - console.error('Build failed:', result.logs); - process.exit(1); - } - ``` - * - * @example Set up multiple entrypoints with code splitting enabled - ```ts - await Bun.build({ - entrypoints: ['./src/app.tsx', './src/admin.tsx'], - outdir: './dist', - splitting: true, - sourcemap: "external" - }); - ``` - * - * @example Configure minification and optimization settings - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - minify: { - whitespace: true, - identifiers: true, - syntax: true - }, - drop: ['console', 'debugger'] - }); - ``` - * - * @example Set up custom loaders and mark packages as external - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - loader: { - '.png': 'dataurl', - '.svg': 'file', - '.txt': 'text', - '.json': 'json' - }, - external: ['react', 'react-dom'] - }); - ``` - * - * @example Configure environment variable handling with different modes - ```ts - // Inline all environment variables - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'inline' - }); - - // Only include specific env vars - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'PUBLIC_*' - }); - ``` - * - * @example Set up custom naming patterns for all output types - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - naming: { - entry: '[dir]/[name]-[hash].[ext]', - chunk: 'chunks/[name]-[hash].[ext]', - asset: 'assets/[name]-[hash].[ext]' - } - }); - ``` - @example Work with build artifacts in different formats - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'] - }); - - for (const artifact of result.outputs) { - const text = await artifact.text(); - const buffer = await artifact.arrayBuffer(); - const bytes = await artifact.bytes(); + for (const artifact of result.outputs) { + const text = await artifact.text(); + const buffer = await artifact.arrayBuffer(); + const bytes = await artifact.bytes(); new Response(artifact); await Bun.write(artifact.path, artifact); @@ -3194,1283 +3289,1380 @@ declare module "bun" { }); ``` */ - function build(config: BuildConfig): Promise; - /** - * A status that represents the outcome of a sent message. - * - * - if **0**, the message was **dropped**. - * - if **-1**, there is **backpressure** of messages. - * - if **>0**, it represents the **number of bytes sent**. - * - * @example - * ```js - * const status = ws.send("Hello!"); - * if (status === 0) { - * console.log("Message was dropped"); - * } else if (status === -1) { - * console.log("Backpressure was applied"); - * } else { - * console.log(`Success! Sent ${status} bytes`); - * } - * ``` - */ - type ServerWebSocketSendStatus = number; - - /** - * A state that represents if a WebSocket is connected. - * - * - `WebSocket.CONNECTING` is `0`, the connection is pending. - * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. - * - `WebSocket.CLOSING` is `2`, the connection is closing. - * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState - */ - type WebSocketReadyState = 0 | 1 | 2 | 3; - - /** - * A fast WebSocket designed for servers. - * - * Features: - * - **Message compression** - Messages can be compressed - * - **Backpressure** - If the client is not ready to receive data, the server will tell you. - * - **Dropped messages** - If the client cannot receive data, the server will tell you. - * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics - * - * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. - * - * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). - * - * @example - * import { serve } from "bun"; - * - * serve({ - * websocket: { - * open(ws) { - * console.log("Connected", ws.remoteAddress); - * }, - * message(ws, data) { - * console.log("Received", data); - * ws.send(data); - * }, - * close(ws, code, reason) { - * console.log("Disconnected", code, reason); - * }, - * } - * }); - */ - interface ServerWebSocket { - /** - * Sends a message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - * ws.send(new Uint8Array([1, 2, 3, 4])); - */ - send(data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a text message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - */ - sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send(new TextEncoder().encode("Hello!")); - * ws.send(new Uint8Array([1, 2, 3, 4]), true); - */ - sendBinary(data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Closes the connection. - * - * Here is a list of close codes: - * - `1000` means "normal closure" **(default)** - * - `1009` means a message was too big and was rejected - * - `1011` means the server encountered an error - * - `1012` means the server is restarting - * - `1013` means the server is too busy or the client is rate-limited - * - `4000` through `4999` are reserved for applications (you can use it!) - * - * To close the connection abruptly, use `terminate()`. - * - * @param code The close code to send - * @param reason The close reason to send - */ - close(code?: number, reason?: string): void; - - /** - * Abruptly close the connection. - * - * To gracefully close the connection, use `close()`. - */ - terminate(): void; - - /** - * Sends a ping. - * - * @param data The data to send - */ - ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a pong. - * - * @param data The data to send - */ - pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); - */ - publish(topic: string, data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a text message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - */ - publishText(topic: string, data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", new TextEncoder().encode("Hello!")); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); - */ - publishBinary(topic: string, data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Subscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - */ - subscribe(topic: string): void; - - /** - * Unsubscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.unsubscribe("chat"); - */ - unsubscribe(topic: string): void; - - /** - * Is the client subscribed to a topic? - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - * console.log(ws.isSubscribed("chat")); // true - */ - isSubscribed(topic: string): boolean; - - /** - * Batches `send()` and `publish()` operations, which makes it faster to send data. - * - * The `message`, `open`, and `drain` callbacks are automatically corked, so - * you only need to call this if you are sending messages outside of those - * callbacks or in async functions. - * - * @param callback The callback to run. - * @example - * ws.cork((ctx) => { - * ctx.send("These messages"); - * ctx.sendText("are sent"); - * ctx.sendBinary(new TextEncoder().encode("together!")); - * }); - */ - cork(callback: (ws: ServerWebSocket) => T): T; - - /** - * The IP address of the client. - * - * @example - * console.log(socket.remoteAddress); // "127.0.0.1" - */ - readonly remoteAddress: string; - - /** - * The ready state of the client. - * - * - if `0`, the client is connecting. - * - if `1`, the client is connected. - * - if `2`, the client is closing. - * - if `3`, the client is closed. - * - * @example - * console.log(socket.readyState); // 1 - */ - readonly readyState: WebSocketReadyState; - - /** - * Sets how binary data is returned in events. - * - * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** - * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. - * - if `uint8array`, binary data is returned as `Uint8Array` objects. - * - * @example - * let ws: WebSocket; - * ws.binaryType = "uint8array"; - * ws.addEventListener("message", ({ data }) => { - * console.log(data instanceof Uint8Array); // true - * }); - */ - binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; - - /** - * Custom data that you can assign to a client, can be read and written at any time. - * - * @example - * import { serve } from "bun"; - * - * serve({ - * fetch(request, server) { - * const data = { - * accessToken: request.headers.get("Authorization"), - * }; - * if (server.upgrade(request, { data })) { - * return; - * } - * return new Response(); - * }, - * websocket: { - * open(ws) { - * console.log(ws.data.accessToken); - * } - * } - * }); - */ - data: T; - - getBufferedAmount(): number; - } - - /** - * Compression options for WebSocket messages. - */ - type WebSocketCompressor = - | "disable" - | "shared" - | "dedicated" - | "3KB" - | "4KB" - | "8KB" - | "16KB" - | "32KB" - | "64KB" - | "128KB" - | "256KB"; - - /** - * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} - * - * @example - * ```ts - * import { websocket, serve } from "bun"; - * - * serve<{name: string}>({ - * port: 3000, - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log(`${ws.data.name}: ${message}`); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req, { - * data: { - * name: new URL(req.url).searchParams.get("name"), - * }, - * }); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * return; - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - */ - interface WebSocketHandler { - /** - * Called when the server receives an incoming message. - * - * If the message is not a `string`, its type is based on the value of `binaryType`. - * - if `nodebuffer`, then the message is a `Buffer`. - * - if `arraybuffer`, then the message is an `ArrayBuffer`. - * - if `uint8array`, then the message is a `Uint8Array`. - * - * @param ws The websocket that sent the message - * @param message The message received - */ - message(ws: ServerWebSocket, message: string | Buffer): void | Promise; + function build(config: BuildConfig): Promise; + /** + * A status that represents the outcome of a sent message. + * + * - if **0**, the message was **dropped**. + * - if **-1**, there is **backpressure** of messages. + * - if **>0**, it represents the **number of bytes sent**. + * + * @example + * ```js + * const status = ws.send("Hello!"); + * if (status === 0) { + * console.log("Message was dropped"); + * } else if (status === -1) { + * console.log("Backpressure was applied"); + * } else { + * console.log(`Success! Sent ${status} bytes`); + * } + * ``` + */ + type ServerWebSocketSendStatus = number; + + /** + * A state that represents if a WebSocket is connected. + * + * - `WebSocket.CONNECTING` is `0`, the connection is pending. + * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. + * - `WebSocket.CLOSING` is `2`, the connection is closing. + * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState + */ + type WebSocketReadyState = 0 | 1 | 2 | 3; + + /** + * A fast WebSocket designed for servers. + * + * Features: + * - **Message compression** - Messages can be compressed + * - **Backpressure** - If the client is not ready to receive data, the server will tell you. + * - **Dropped messages** - If the client cannot receive data, the server will tell you. + * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics + * + * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. + * + * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). + * + * @example + * import { serve } from "bun"; + * + * serve({ + * websocket: { + * open(ws) { + * console.log("Connected", ws.remoteAddress); + * }, + * message(ws, data) { + * console.log("Received", data); + * ws.send(data); + * }, + * close(ws, code, reason) { + * console.log("Disconnected", code, reason); + * }, + * } + * }); + */ + interface ServerWebSocket { + /** + * Sends a message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + * ws.send(new Uint8Array([1, 2, 3, 4])); + */ + send( + data: string | Bun.BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a text message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + */ + sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send(new TextEncoder().encode("Hello!")); + * ws.send(new Uint8Array([1, 2, 3, 4]), true); + */ + sendBinary( + data: Bun.BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Closes the connection. + * + * Here is a list of close codes: + * - `1000` means "normal closure" **(default)** + * - `1009` means a message was too big and was rejected + * - `1011` means the server encountered an error + * - `1012` means the server is restarting + * - `1013` means the server is too busy or the client is rate-limited + * - `4000` through `4999` are reserved for applications (you can use it!) + * + * To close the connection abruptly, use `terminate()`. + * + * @param code The close code to send + * @param reason The close reason to send + */ + close(code?: number, reason?: string): void; + + /** + * Abruptly close the connection. + * + * To gracefully close the connection, use `close()`. + */ + terminate(): void; + + /** + * Sends a ping. + * + * @param data The data to send + */ + ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a pong. + * + * @param data The data to send + */ + pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); + */ + publish( + topic: string, + data: string | Bun.BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a text message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + */ + publishText( + topic: string, + data: string, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a binary message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", new TextEncoder().encode("Hello!")); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); + */ + publishBinary( + topic: string, + data: Bun.BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Subscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + */ + subscribe(topic: string): void; + + /** + * Unsubscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.unsubscribe("chat"); + */ + unsubscribe(topic: string): void; + + /** + * Is the client subscribed to a topic? + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + * console.log(ws.isSubscribed("chat")); // true + */ + isSubscribed(topic: string): boolean; + + /** + * Batches `send()` and `publish()` operations, which makes it faster to send data. + * + * The `message`, `open`, and `drain` callbacks are automatically corked, so + * you only need to call this if you are sending messages outside of those + * callbacks or in async functions. + * + * @param callback The callback to run. + * @example + * ws.cork((ctx) => { + * ctx.send("These messages"); + * ctx.sendText("are sent"); + * ctx.sendBinary(new TextEncoder().encode("together!")); + * }); + */ + cork(callback: (ws: ServerWebSocket) => T): T; + + /** + * The IP address of the client. + * + * @example + * console.log(socket.remoteAddress); // "127.0.0.1" + */ + readonly remoteAddress: string; + + /** + * The ready state of the client. + * + * - if `0`, the client is connecting. + * - if `1`, the client is connected. + * - if `2`, the client is closing. + * - if `3`, the client is closed. + * + * @example + * console.log(socket.readyState); // 1 + */ + readonly readyState: WebSocketReadyState; + + /** + * Sets how binary data is returned in events. + * + * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** + * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. + * - if `uint8array`, binary data is returned as `Uint8Array` objects. + * + * @example + * let ws: WebSocket; + * ws.binaryType = "uint8array"; + * ws.addEventListener("message", ({ data }) => { + * console.log(data instanceof Uint8Array); // true + * }); + */ + binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; + + /** + * Custom data that you can assign to a client, can be read and written at any time. + * + * @example + * import { serve } from "bun"; + * + * serve({ + * fetch(request, server) { + * const data = { + * accessToken: request.headers.get("Authorization"), + * }; + * if (server.upgrade(request, { data })) { + * return; + * } + * return new Response(); + * }, + * websocket: { + * open(ws) { + * console.log(ws.data.accessToken); + * } + * } + * }); + */ + data: T; + + getBufferedAmount(): number; + } + + /** + * Compression options for WebSocket messages. + */ + type WebSocketCompressor = + | "disable" + | "shared" + | "dedicated" + | "3KB" + | "4KB" + | "8KB" + | "16KB" + | "32KB" + | "64KB" + | "128KB" + | "256KB"; + + /** + * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} + * + * @example + * ```ts + * import { websocket, serve } from "bun"; + * + * serve<{name: string}>({ + * port: 3000, + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log(`${ws.data.name}: ${message}`); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req, { + * data: { + * name: new URL(req.url).searchParams.get("name"), + * }, + * }); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * return; + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + */ + interface WebSocketHandler { + /** + * Called when the server receives an incoming message. + * + * If the message is not a `string`, its type is based on the value of `binaryType`. + * - if `nodebuffer`, then the message is a `Buffer`. + * - if `arraybuffer`, then the message is an `ArrayBuffer`. + * - if `uint8array`, then the message is a `Uint8Array`. + * + * @param ws The websocket that sent the message + * @param message The message received + */ + message( + ws: ServerWebSocket, + message: string | Buffer, + ): void | Promise; + + /** + * Called when a connection is opened. + * + * @param ws The websocket that was opened + */ + open?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection was previously under backpressure, + * meaning it had too many queued messages, but is now ready to receive more data. + * + * @param ws The websocket that is ready for more data + */ + drain?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection is closed. + * + * @param ws The websocket that was closed + * @param code The close code + * @param message The close message + */ + close?( + ws: ServerWebSocket, + code: number, + reason: string, + ): void | Promise; + + /** + * Called when a ping is sent. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + ping?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Called when a pong is received. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + pong?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Sets the maximum size of messages in bytes. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + maxPayloadLength?: number; + + /** + * Sets the maximum number of bytes that can be buffered on a single connection. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + backpressureLimit?: number; + + /** + * Sets if the connection should be closed if `backpressureLimit` is reached. + * + * Default is `false`. + */ + closeOnBackpressureLimit?: boolean; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to no messages or pings. + * + * Default is 2 minutes, or `120` in seconds. + */ + idleTimeout?: number; + + /** + * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? + * + * Default is `false`. + */ + publishToSelf?: boolean; + + /** + * Should the server automatically send and respond to pings to clients? + * + * Default is `true`. + */ + sendPings?: boolean; + + /** + * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. + * + * Default is `false`. + */ + perMessageDeflate?: + | boolean + | { + /** + * Sets the compression level. + */ + compress?: WebSocketCompressor | boolean; + /** + * Sets the decompression level. + */ + decompress?: WebSocketCompressor | boolean; + }; + } + + namespace RouterTypes { + type ExtractRouteParams = + T extends `${string}:${infer Param}/${infer Rest}` + ? { [K in Param]: string } & ExtractRouteParams + : T extends `${string}:${infer Param}` + ? { [K in Param]: string } + : T extends `${string}*` + ? {} + : {}; + + type RouteHandler = ( + req: BunRequest, + server: Server, + ) => Response | Promise; + + type HTTPMethod = + | "GET" + | "POST" + | "PUT" + | "DELETE" + | "PATCH" + | "HEAD" + | "OPTIONS"; + + type RouteHandlerObject = { + [K in HTTPMethod]?: RouteHandler; + }; + + type RouteValue = + | Response + | false + | RouteHandler + | RouteHandlerObject; + } + + interface BunRequest extends Request { + params: RouterTypes.ExtractRouteParams; + } + + interface GenericServeOptions { + /** + * What URI should be used to make {@link Request.url} absolute? + * + * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one + * + * @example + * ```js + * "http://my-app.com" + * ``` + * + * @example + * ```js + * "https://wongmjane.com/" + * ``` + * + * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. + * + * @example + * "http://localhost:3000" + */ + // baseURI?: string; + + /** + * What is the maximum size of a request body? (in bytes) + * @default 1024 * 1024 * 128 // 128MB + */ + maxRequestBodySize?: number; + + /** + * Render contextual errors? This enables bun's error page + * @default process.env.NODE_ENV !== 'production' + */ + development?: + | boolean + | { + /** + * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) + * + * @default true if process.env.NODE_ENV !== 'production' + * + */ + hmr?: boolean; + }; + + error?: ( + this: Server, + error: ErrorLike, + ) => Response | Promise | undefined | Promise; + + /** + * Uniquely identify a server instance with an ID + * + * ### When bun is started with the `--hot` flag + * + * This string will be used to hot reload the server without interrupting + * pending requests or websockets. If not provided, a value will be + * generated. To disable hot reloading, set this value to `null`. + * + * ### When bun is not started with the `--hot` flag + * + * This string will currently do nothing. But in the future it could be useful for logs or metrics. + */ + id?: string | null; + } + + interface ServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * Whether the `SO_REUSEPORT` flag should be set. + * + * This allows multiple processes to bind to the same port, which is useful for load balancing. + * + * @default false + */ + reusePort?: boolean; + + /** + * Whether the `IPV6_V6ONLY` flag should be set. + * @default false + */ + ipv6Only?: boolean; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix?: never; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to inactivity. + * + * Default is `10` seconds. + */ + idleTimeout?: number; + + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | Promise; + } + + interface UnixServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | Promise; + } + + interface WebSocketServeOptions + extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | void | Promise; + } + + interface UnixWebSocketServeOptions + extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | Promise; + } + + interface TLSWebSocketServeOptions + extends WebSocketServeOptions, + TLSOptionsAsDeprecated { + unix?: never; + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSWebSocketServeOptions + extends UnixWebSocketServeOptions, + TLSOptionsAsDeprecated { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + tls?: TLSOptions | TLSOptions[]; + } + + interface ErrorLike extends Error { + code?: string; + errno?: number; + syscall?: string; + } + + interface TLSOptions { + /** + * Passphrase for the TLS key + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + // Note for contributors: TLSOptionsAsDeprecated should be considered immutable + // and new TLS option keys should only be supported on the `.tls` property (which comes + // from the TLSOptions interface above). + /** + * This exists because Bun.serve() extends the TLSOptions object, but + * they're now considered deprecated. You should be passing the + * options on `.tls` instead. + * + * @example + * ```ts + * //// OLD //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * passphrase: "secret", + * }); + * + * //// NEW //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * tls: { + * passphrase: "secret", + * }, + * }); + * ``` + */ + interface TLSOptionsAsDeprecated { + /** + * Passphrase for the TLS key + * + * @deprecated Use `.tls.passphrase` instead + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + * + * @deprecated Use `.tls.dhParamsFile` instead + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + * + * @deprecated Use `.tls.serverName` instead + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + * + * @deprecated Use `.tls.lowMemoryMode` instead + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + * + * @deprecated Use `.tls.rejectUnauthorized` instead + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + * + * @deprecated Use `.tls.requestCert` instead + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + * + * @deprecated Use `.tls.ca` instead + */ + ca?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + * + * @deprecated Use `.tls.cert` instead + */ + cert?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + * + * @deprecated Use `.tls.key` instead + */ + key?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + * + * @deprecated `Use .tls.secureOptions` instead + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSServeOptions + extends UnixServeOptions, + TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface SocketAddress { + /** + * The IP address of the client. + */ + address: string; + /** + * The port of the client. + */ + port: number; + /** + * The IP family ("IPv4" or "IPv6"). + */ + family: "IPv4" | "IPv6"; + } + + /** + * HTTP & HTTPS Server + * + * To start the server, see {@link serve} + * + * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. + * That means starting a new server allocates about 500 KB of memory. Try to + * avoid starting and stopping the server often (unless it's a new instance of bun). + * + * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. + */ + interface Server extends Disposable { + /** + * Stop listening to prevent new connections from being accepted. + * + * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. + * + * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. + * @default false + */ + stop(closeActiveConnections?: boolean): Promise; + + /** + * Update the `fetch` and `error` handlers without restarting the server. + * + * This is useful if you want to change the behavior of your server without + * restarting it or for hot reloading. + * + * @example + * + * ```js + * // create the server + * const server = Bun.serve({ + * fetch(request) { + * return new Response("Hello World v1") + * } + * }); + * + * // Update the server to return a different response + * server.reload({ + * fetch(request) { + * return new Response("Hello World v2") + * } + * }); + * ``` + * + * Passing other options such as `port` or `hostname` won't do anything. + */ + reload }>( + options: ( + | (Omit & { + routes: R; + fetch?: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | (Omit & { + routes?: never; + fetch: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. + */ + static?: R; + }, + ): Server; + + /** + * Mock the fetch handler for a running server. + * + * This feature is not fully implemented yet. It doesn't normalize URLs + * consistently in all cases and it doesn't yet call the `error` handler + * consistently. This needs to be fixed + */ + fetch(request: Request | string): Response | Promise; + + /** + * Upgrade a {@link Request} to a {@link ServerWebSocket} + * + * @param request The {@link Request} to upgrade + * @param options Pass headers or attach data to the {@link ServerWebSocket} + * + * @returns `true` if the upgrade was successful and `false` if it failed + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * What you pass to `data` is available on the {@link ServerWebSocket.data} property + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + upgrade( + request: Request, + options?: { + /** + * Send any additional headers while upgrading, like cookies + */ + headers?: Bun.HeadersInit; + /** + * This value is passed to the {@link ServerWebSocket.data} property + */ + data?: T; + }, + ): boolean; + + /** + * Send a message to all connected {@link ServerWebSocket} subscribed to a topic + * + * @param topic The topic to publish to + * @param data The data to send + * @param compress Should the data be compressed? Ignored if the client does not support compression. + * + * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. + * + * @example + * + * ```js + * server.publish("chat", "Hello World"); + * ``` + * + * @example + * ```js + * server.publish("chat", new Uint8Array([1, 2, 3, 4])); + * ``` + * + * @example + * ```js + * server.publish("chat", new ArrayBuffer(4), true); + * ``` + * + * @example + * ```js + * server.publish("chat", new DataView(new ArrayBuffer(4))); + * ``` + */ + publish( + topic: string, + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * A count of connections subscribed to a given topic + * + * This operation will loop through each topic internally to get the count. + * + * @param topic the websocket topic to check how many subscribers are connected to + * @returns the number of subscribers + */ + subscriberCount(topic: string): number; + + /** + * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * return new Response(server.requestIP(request)); + * } + * } + * ``` + */ + requestIP(request: Request): SocketAddress | null; + + /** + * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * server.timeout(request, 60); + * await Bun.sleep(30000); + * return new Response("30 seconds have passed"); + * } + * } + * ``` + */ + timeout(request: Request, seconds: number): void; + /** + * Undo a call to {@link Server.unref} + * + * If the Server has already been stopped, this does nothing. + * + * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. + */ + ref(): void; + + /** + * Don't keep the process alive if this server is the only thing left. + * Active connections may continue to keep the process alive. + * + * By default, the server is ref'd. + * + * To prevent new connections from being accepted, use {@link Server.stop} + */ + unref(): void; + + /** + * How many requests are in-flight right now? + */ + readonly pendingRequests: number; + + /** + * How many {@link ServerWebSocket}s are in-flight right now? + */ + readonly pendingWebSockets: number; + + readonly url: URL; + + readonly port: number; + /** + * The hostname the server is listening on. Does not include the port + * @example + * ```js + * "localhost" + * ``` + */ + readonly hostname: string; + /** + * Is the server running in development mode? + * + * In development mode, `Bun.serve()` returns rendered error messages with + * stack traces instead of a generic 500 error. This makes debugging easier, + * but development mode shouldn't be used in production or you will risk + * leaking sensitive information. + */ + readonly development: boolean; + + /** + * An identifier of the server instance + * + * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. + * + * When bun is not started with the `--hot` flag, this ID is currently unused. + */ + readonly id: string; + } + + type Serve = + | ServeOptions + | TLSServeOptions + | UnixServeOptions + | UnixTLSServeOptions + | WebSocketServeOptions + | TLSWebSocketServeOptions + | UnixWebSocketServeOptions + | UnixTLSWebSocketServeOptions; + + /** + Bun.serve provides a high-performance HTTP server with built-in routing support. + It enables both function-based and object-based route handlers with type-safe + parameters and method-specific handling. - /** - * Called when a connection is opened. - * - * @param ws The websocket that was opened - */ - open?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection was previously under backpressure, - * meaning it had too many queued messages, but is now ready to receive more data. - * - * @param ws The websocket that is ready for more data - */ - drain?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection is closed. - * - * @param ws The websocket that was closed - * @param code The close code - * @param message The close message - */ - close?(ws: ServerWebSocket, code: number, reason: string): void | Promise; - - /** - * Called when a ping is sent. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - ping?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Called when a pong is received. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - pong?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Sets the maximum size of messages in bytes. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - maxPayloadLength?: number; - - /** - * Sets the maximum number of bytes that can be buffered on a single connection. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - backpressureLimit?: number; - - /** - * Sets if the connection should be closed if `backpressureLimit` is reached. - * - * Default is `false`. - */ - closeOnBackpressureLimit?: boolean; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to no messages or pings. - * - * Default is 2 minutes, or `120` in seconds. - */ - idleTimeout?: number; - - /** - * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? - * - * Default is `false`. - */ - publishToSelf?: boolean; - - /** - * Should the server automatically send and respond to pings to clients? - * - * Default is `true`. - */ - sendPings?: boolean; - - /** - * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. - * - * Default is `false`. - */ - perMessageDeflate?: - | boolean - | { - /** - * Sets the compression level. - */ - compress?: WebSocketCompressor | boolean; - /** - * Sets the decompression level. - */ - decompress?: WebSocketCompressor | boolean; - }; - } - - namespace RouterTypes { - type ExtractRouteParams = T extends `${string}:${infer Param}/${infer Rest}` - ? { [K in Param]: string } & ExtractRouteParams - : T extends `${string}:${infer Param}` - ? { [K in Param]: string } - : T extends `${string}*` - ? {} - : {}; - - type RouteHandler = (req: BunRequest, server: Server) => Response | Promise; - - type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; - - type RouteHandlerObject = { - [K in HTTPMethod]?: RouteHandler; - }; - - type RouteValue = Response | false | RouteHandler | RouteHandlerObject; - } - - interface BunRequest extends Request { - params: RouterTypes.ExtractRouteParams; - } - - interface GenericServeOptions { - /** - * What URI should be used to make {@link Request.url} absolute? - * - * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one - * - * @example - * ```js - * "http://my-app.com" - * ``` - * - * @example - * ```js - * "https://wongmjane.com/" - * ``` - * - * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. - * - * @example - * "http://localhost:3000" - */ - // baseURI?: string; - - /** - * What is the maximum size of a request body? (in bytes) - * @default 1024 * 1024 * 128 // 128MB - */ - maxRequestBodySize?: number; - - /** - * Render contextual errors? This enables bun's error page - * @default process.env.NODE_ENV !== 'production' - */ - development?: - | boolean - | { - /** - * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) - * - * @default true if process.env.NODE_ENV !== 'production' - * - */ - hmr?: boolean; - }; - - error?: (this: Server, error: ErrorLike) => Response | Promise | undefined | Promise; - - /** - * Uniquely identify a server instance with an ID - * - * ### When bun is started with the `--hot` flag - * - * This string will be used to hot reload the server without interrupting - * pending requests or websockets. If not provided, a value will be - * generated. To disable hot reloading, set this value to `null`. - * - * ### When bun is not started with the `--hot` flag - * - * This string will currently do nothing. But in the future it could be useful for logs or metrics. - */ - id?: string | null; - } - - interface ServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * Whether the `SO_REUSEPORT` flag should be set. - * - * This allows multiple processes to bind to the same port, which is useful for load balancing. - * - * @default false - */ - reusePort?: boolean; - - /** - * Whether the `IPV6_V6ONLY` flag should be set. - * @default false - */ - ipv6Only?: boolean; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix?: never; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to inactivity. - * - * Default is `10` seconds. - */ - idleTimeout?: number; - - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | Promise; - } - - interface UnixServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | Promise; - } - - interface WebSocketServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | void | Promise; - } - - interface UnixWebSocketServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | undefined | Promise; - } - - interface TLSWebSocketServeOptions - extends WebSocketServeOptions, - TLSOptionsAsDeprecated { - unix?: never; - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSWebSocketServeOptions - extends UnixWebSocketServeOptions, - TLSOptionsAsDeprecated { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - tls?: TLSOptions | TLSOptions[]; - } - - interface ErrorLike extends Error { - code?: string; - errno?: number; - syscall?: string; - } - - interface TLSOptions { - /** - * Passphrase for the TLS key - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: string | Buffer | BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: string | Buffer | BunFile | Array | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: string | Buffer | BunFile | Array | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - // Note for contributors: TLSOptionsAsDeprecated should be considered immutable - // and new TLS option keys should only be supported on the `.tls` property (which comes - // from the TLSOptions interface above). - /** - * This exists because Bun.serve() extends the TLSOptions object, but - * they're now considered deprecated. You should be passing the - * options on `.tls` instead. - * - * @example - * ```ts - * //// OLD //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * passphrase: "secret", - * }); - * - * //// NEW //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * tls: { - * passphrase: "secret", - * }, - * }); - * ``` - */ - interface TLSOptionsAsDeprecated { - /** - * Passphrase for the TLS key - * - * @deprecated Use `.tls.passphrase` instead - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - * - * @deprecated Use `.tls.dhParamsFile` instead - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - * - * @deprecated Use `.tls.serverName` instead - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - * - * @deprecated Use `.tls.lowMemoryMode` instead - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - * - * @deprecated Use `.tls.rejectUnauthorized` instead - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - * - * @deprecated Use `.tls.requestCert` instead - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - * - * @deprecated Use `.tls.ca` instead - */ - ca?: string | Buffer | BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - * - * @deprecated Use `.tls.cert` instead - */ - cert?: string | Buffer | BunFile | Array | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - * - * @deprecated Use `.tls.key` instead - */ - key?: string | Buffer | BunFile | Array | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - * - * @deprecated `Use .tls.secureOptions` instead - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSServeOptions extends UnixServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface SocketAddress { - /** - * The IP address of the client. - */ - address: string; - /** - * The port of the client. - */ - port: number; - /** - * The IP family ("IPv4" or "IPv6"). - */ - family: "IPv4" | "IPv6"; - } - - /** - * HTTP & HTTPS Server - * - * To start the server, see {@link serve} - * - * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. - * That means starting a new server allocates about 500 KB of memory. Try to - * avoid starting and stopping the server often (unless it's a new instance of bun). - * - * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. - */ - interface Server extends Disposable { - /** - * Stop listening to prevent new connections from being accepted. - * - * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. - * - * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. - * @default false - */ - stop(closeActiveConnections?: boolean): Promise; - - /** - * Update the `fetch` and `error` handlers without restarting the server. - * - * This is useful if you want to change the behavior of your server without - * restarting it or for hot reloading. - * - * @example - * - * ```js - * // create the server - * const server = Bun.serve({ - * fetch(request) { - * return new Response("Hello World v1") - * } - * }); - * - * // Update the server to return a different response - * server.reload({ - * fetch(request) { - * return new Response("Hello World v2") - * } - * }); - * ``` - * - * Passing other options such as `port` or `hostname` won't do anything. - */ - reload }>( - options: ( - | (Omit & { - routes: R; - fetch?: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | (Omit & { - routes?: never; - fetch: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. - */ - static?: R; - }, - ): Server; - - /** - * Mock the fetch handler for a running server. - * - * This feature is not fully implemented yet. It doesn't normalize URLs - * consistently in all cases and it doesn't yet call the `error` handler - * consistently. This needs to be fixed - */ - fetch(request: Request | string): Response | Promise; - - /** - * Upgrade a {@link Request} to a {@link ServerWebSocket} - * - * @param request The {@link Request} to upgrade - * @param options Pass headers or attach data to the {@link ServerWebSocket} - * - * @returns `true` if the upgrade was successful and `false` if it failed - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * What you pass to `data` is available on the {@link ServerWebSocket.data} property - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - upgrade( - request: Request, - options?: { - /** - * Send any additional headers while upgrading, like cookies - */ - headers?: Bun.HeadersInit; - /** - * This value is passed to the {@link ServerWebSocket.data} property - */ - data?: T; - }, - ): boolean; - - /** - * Send a message to all connected {@link ServerWebSocket} subscribed to a topic - * - * @param topic The topic to publish to - * @param data The data to send - * @param compress Should the data be compressed? Ignored if the client does not support compression. - * - * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. - * - * @example - * - * ```js - * server.publish("chat", "Hello World"); - * ``` - * - * @example - * ```js - * server.publish("chat", new Uint8Array([1, 2, 3, 4])); - * ``` - * - * @example - * ```js - * server.publish("chat", new ArrayBuffer(4), true); - * ``` - * - * @example - * ```js - * server.publish("chat", new DataView(new ArrayBuffer(4))); - * ``` - */ - publish( - topic: string, - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * A count of connections subscribed to a given topic - * - * This operation will loop through each topic internally to get the count. - * - * @param topic the websocket topic to check how many subscribers are connected to - * @returns the number of subscribers - */ - subscriberCount(topic: string): number; - - /** - * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * return new Response(server.requestIP(request)); - * } - * } - * ``` - */ - requestIP(request: Request): SocketAddress | null; - - /** - * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * server.timeout(request, 60); - * await Bun.sleep(30000); - * return new Response("30 seconds have passed"); - * } - * } - * ``` - */ - timeout(request: Request, seconds: number): void; - /** - * Undo a call to {@link Server.unref} - * - * If the Server has already been stopped, this does nothing. - * - * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. - */ - ref(): void; - - /** - * Don't keep the process alive if this server is the only thing left. - * Active connections may continue to keep the process alive. - * - * By default, the server is ref'd. - * - * To prevent new connections from being accepted, use {@link Server.stop} - */ - unref(): void; - - /** - * How many requests are in-flight right now? - */ - readonly pendingRequests: number; - - /** - * How many {@link ServerWebSocket}s are in-flight right now? - */ - readonly pendingWebSockets: number; - - readonly url: URL; - - readonly port: number; - /** - * The hostname the server is listening on. Does not include the port - * @example - * ```js - * "localhost" - * ``` - */ - readonly hostname: string; - /** - * Is the server running in development mode? - * - * In development mode, `Bun.serve()` returns rendered error messages with - * stack traces instead of a generic 500 error. This makes debugging easier, - * but development mode shouldn't be used in production or you will risk - * leaking sensitive information. - */ - readonly development: boolean; - - /** - * An identifier of the server instance - * - * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. - * - * When bun is not started with the `--hot` flag, this ID is currently unused. - */ - readonly id: string; - } - - type Serve = - | ServeOptions - | TLSServeOptions - | UnixServeOptions - | UnixTLSServeOptions - | WebSocketServeOptions - | TLSWebSocketServeOptions - | UnixWebSocketServeOptions - | UnixTLSWebSocketServeOptions; - - /** - Bun.serve provides a high-performance HTTP server with built-in routing support. - It enables both function-based and object-based route handlers with type-safe - parameters and method-specific handling. - - @example Basic Usage - ```ts - Bun.serve({ - port: 3000, - fetch(req) { - return new Response("Hello World"); - } - }); - ``` + @example Basic Usage + ```ts + Bun.serve({ + port: 3000, + fetch(req) { + return new Response("Hello World"); + } + }); + ``` @example Route-based Handlers ```ts @@ -4620,2779 +4812,2909 @@ declare module "bun" { @param options - Server configuration options @param options.routes - Route definitions mapping paths to handlers */ - function serve }>( - options: ( - | (DistributedOmit & { - routes: R; - fetch?: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | (DistributedOmit & { - routes?: never; - fetch: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for a while though. - */ - static?: R; - }, - ): Server; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - `type` is auto-set based on the file extension when possible - * - * @example - * ```js - * const file = Bun.file("./hello.json"); - * console.log(file.type); // "application/json" - * console.log(await file.json()); // { hello: "world" } - * ``` - * - * @example - * ```js - * await Bun.write( - * Bun.file("./hello.txt"), - * "Hello, world!" - * ); - * ``` - * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file(path: string | URL, options?: BlobPropertyBag): BunFile; - - /** - * A list of files embedded into the standalone executable. Lexigraphically sorted by name. - * - * If the process is not a standalone executable, this returns an empty array. - */ - const embeddedFiles: ReadonlyArray; - - /** - * `Blob` that leverages the fastest system calls available to operate on files. - * - * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. - * - * `Blob.size` will not be valid until the contents of the file are read at least once. - * `Blob.type` will have a default set based on the file extension - * - * @example - * ```js - * const file = Bun.file(new TextEncoder.encode("./hello.json")); - * console.log(file.type); // "application/json" - * ``` - * - * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - * @example - * ```js - * const file = Bun.file(fd); - * ``` - * - * @param fileDescriptor The file descriptor of the file - */ - // tslint:disable-next-line:unified-signatures - function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; - - /** - * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. - * - * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. - */ - function allocUnsafe(size: number): Uint8Array; - - interface BunInspectOptions { - colors?: boolean; - depth?: number; - sorted?: boolean; - compact?: boolean; - } - - /** - * Pretty-print an object the same as {@link console.log} to a `string` - * - * Supports JSX - * - * @param args - */ - function inspect(arg: any, options?: BunInspectOptions): string; - namespace inspect { - /** - * That can be used to declare custom inspect functions. - */ - const custom: typeof import("util").inspect.custom; - - /** - * Pretty-print an object or array as a table - * - * Like {@link console.table}, except it returns a string - */ - function table(tabularData: object | unknown[], properties?: string[], options?: { colors?: boolean }): string; - function table(tabularData: object | unknown[], options?: { colors?: boolean }): string; - } - - interface MMapOptions { - /** - * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. - */ - sync?: boolean; - /** - * Allow other processes to see results instantly? - * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. - * @default true - */ - shared?: boolean; - } - /** - * Open a file as a live-updating `Uint8Array` without copying memory - * - Writing to the array writes to the file. - * - Reading from the array reads from the file. - * - * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. - * - * --- - * - * This API inherently has some rough edges: - * - It does not support empty files. It will throw a `SystemError` with `EINVAL` - * - Usage on shared/networked filesystems is discouraged. It will be very slow. - * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. - * - * --- - * - * To close the file, set the array to `null` and it will be garbage collected eventually. - */ - function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; - - /** Write to stdout */ - const stdout: BunFile; - /** Write to stderr */ - const stderr: BunFile; - /** - * Read from stdin - * - * This is read-only - */ - const stdin: BunFile; - - type StringLike = string | { toString(): string }; - - type ColorInput = - | { r: number; g: number; b: number; a?: number } - | [number, number, number] - | [number, number, number, number] - | Uint8Array - | Uint8ClampedArray - | Float32Array - | Float64Array - | string - | number - | { toString(): string }; - - function color( - input: ColorInput, - outputFormat?: /** - * True color ANSI color string, for use in terminals - * @example \x1b[38;2;100;200;200m - */ - | "ansi" - | "ansi-16" - | "ansi-16m" - /** - * 256 color ANSI color string, for use in terminals which don't support true color - * - * Tries to match closest 24-bit color to 256 color palette - */ - | "ansi-256" - /** - * Picks the format that produces the shortest output - */ - | "css" - /** - * Lowercase hex color string without alpha - * @example #ff9800 - */ - | "hex" - /** - * Uppercase hex color string without alpha - * @example #FF9800 - */ - | "HEX" - /** - * @example hsl(35.764706, 1, 0.5) - */ - | "hsl" - /** - * @example lab(0.72732764, 33.938198, -25.311619) - */ - | "lab" - /** - * @example 16750592 - */ - | "number" - /** - * RGB color string without alpha - * @example rgb(255, 152, 0) - */ - | "rgb" - /** - * RGB color string with alpha - * @example rgba(255, 152, 0, 1) - */ - | "rgba", - ): string | null; - - function color( - input: ColorInput, - /** - * An array of numbers representing the RGB color - * @example [100, 200, 200] - */ - outputFormat: "[rgb]", - ): [number, number, number] | null; - function color( - input: ColorInput, - /** - * An array of numbers representing the RGBA color - * @example [100, 200, 200, 255] - */ - outputFormat: "[rgba]", - ): [number, number, number, number] | null; - function color( - input: ColorInput, - /** - * An object representing the RGB color - * @example { r: 100, g: 200, b: 200 } - */ - outputFormat: "{rgb}", - ): { r: number; g: number; b: number } | null; - function color( - input: ColorInput, - /** - * An object representing the RGBA color - * @example { r: 100, g: 200, b: 200, a: 0.5 } - */ - outputFormat: "{rgba}", - ): { r: number; g: number; b: number; a: number } | null; - function color(input: ColorInput, outputFormat: "number"): number | null; - - interface Semver { - /** - * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. - */ - satisfies(version: StringLike, range: StringLike): boolean; - - /** - * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. - * Throws an error if either version is invalid. - */ - order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; - } - var semver: Semver; - - interface Unsafe { - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. - * - * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; - - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` - * - * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - // tslint:disable-next-line:unified-signatures - arrayBufferToString(buffer: Uint16Array): string; - - /** Mock bun's segfault handler. You probably don't want to use this */ - segfault(): void; - - /** - * Force the garbage collector to run extremely often, - * especially inside `bun:test`. - * - * - `0`: default, disable - * - `1`: asynchronously call the garbage collector more often - * - `2`: synchronously call the garbage collector more often. - * - * This is a global setting. It's useful for debugging seemingly random crashes. - * - * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. - * - * @param level - * @returns The previous level - */ - gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; - } - const unsafe: Unsafe; - - type DigestEncoding = "utf8" | "ucs2" | "utf16le" | "latin1" | "ascii" | "base64" | "base64url" | "hex"; - - /** - * Are ANSI colors enabled for stdin and stdout? - * - * Used for {@link console.log} - */ - const enableANSIColors: boolean; - - /** - * What script launched bun? - * - * Absolute file path - * - * @example "/never-gonna-give-you-up.js" - */ - const main: string; - - /** - * Manually trigger the garbage collector - * - * This does two things: - * 1. It tells JavaScriptCore to run the garbage collector - * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. - * - * @param force Synchronously run the garbage collector - */ - function gc(force: boolean): void; - - /** - * JavaScriptCore engine's internal heap snapshot - * - * I don't know how to make this something Chrome or Safari can read. - * - * If you have any ideas, please file an issue https://github.com/oven-sh/bun - */ - interface HeapSnapshot { - /** 2 */ - version: number; - - /** "Inspector" */ - type: string; - - nodes: number[]; - - nodeClassNames: string[]; - edges: number[]; - edgeTypes: string[]; - edgeNames: string[]; - } - - /** - * Returns the number of nanoseconds since the process was started. - * - * This function uses a high-resolution monotonic system timer to provide precise time measurements. - * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), - * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). - * - * Due to this limitation, while the internal counter may continue beyond this point, - * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond - * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but - * with reduced precision, which might affect time calculations and comparisons in long-running applications. - * - * @returns {number} The number of nanoseconds since the process was started, with precise values up to - * Number.MAX_SAFE_INTEGER. - */ - function nanoseconds(): number; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector - */ - function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code - * - * This is a JSON string that can be saved to a file. - * ```ts - * const snapshot = Bun.generateHeapSnapshot("v8"); - * await Bun.write("heap.heapsnapshot", snapshot); - * ``` - */ - function generateHeapSnapshot(format: "v8"): string; - - /** - * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. - */ - function shrink(): void; - - /** - * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` - * - * @param path path to open - */ - function openInEditor(path: string, options?: EditorOptions): void; - - var fetch: typeof globalThis.fetch & { - preconnect(url: string): void; - }; - - interface EditorOptions { - editor?: "vscode" | "subl"; - line?: number; - column?: number; - } - - /** - * This class only exists in types - */ - abstract class CryptoHashInterface { - /** - * Update the hash with data - * - * @param data - */ - update(data: Bun.BlobOrStringOrBuffer): T; - - /** - * Finalize the hash - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash(input: Bun.BlobOrStringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash(input: Bun.BlobOrStringOrBuffer, encoding: DigestEncoding): string; - } - - type SupportedCryptoAlgorithms = - | "blake2b256" - | "blake2b512" - | "md4" - | "md5" - | "ripemd160" - | "sha1" - | "sha224" - | "sha256" - | "sha384" - | "sha512" - | "sha512-224" - | "sha512-256" - | "sha3-224" - | "sha3-256" - | "sha3-384" - | "sha3-512" - | "shake128" - | "shake256"; - - /** - * Hardware-accelerated cryptographic hash functions - * - * Used for `crypto.createHash()` - */ - class CryptoHasher { - /** - * The algorithm chosen to hash the data - */ - readonly algorithm: SupportedCryptoAlgorithms; - - /** - * The length of the output hash in bytes - */ - readonly byteLength: number; - - /** - * Create a new hasher - * - * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms - * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. - */ - constructor(algorithm: SupportedCryptoAlgorithms, hmacKey?: string | NodeJS.TypedArray); - - /** - * Update the hash with data - * - * @param input - */ - update(input: Bun.BlobOrStringOrBuffer, inputEncoding?: CryptoEncoding): CryptoHasher; - - /** - * Perform a deep copy of the hasher - */ - copy(): CryptoHasher; - - /** - * Finalize the hash. Resets the CryptoHasher so it can be reused. - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(): Buffer; - digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash(algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer): Buffer; - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - hashInto: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - - /** - * List of supported hash algorithms - * - * These are hardware accelerated with BoringSSL - */ - static readonly algorithms: SupportedCryptoAlgorithms[]; - } - - /** - * Resolve a `Promise` after milliseconds. This is like - * {@link setTimeout} except it returns a `Promise`. - * - * @param ms milliseconds to delay resolving the promise. This is a minimum - * number. It may take longer. If a {@link Date} is passed, it will sleep until the - * {@link Date} is reached. - * - * @example - * ## Sleep for 1 second - * ```ts - * import { sleep } from "bun"; - * - * await sleep(1000); - * ``` - * ## Sleep for 10 milliseconds - * ```ts - * await Bun.sleep(10); - * ``` - * ## Sleep until `Date` - * - * ```ts - * const target = new Date(); - * target.setSeconds(target.getSeconds() + 1); - * await Bun.sleep(target); - * ``` - * Internally, `Bun.sleep` is the equivalent of - * ```ts - * await new Promise((resolve) => setTimeout(resolve, ms)); - * ``` - * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. - */ - function sleep(ms: number | Date): Promise; - - /** - * Sleep the thread for a given number of milliseconds - * - * This is a blocking function. - * - * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) - */ - function sleepSync(ms: number): void; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param encoding `DigestEncoding` to return the hash in - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; - - /** - * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} - * - * Consider using the ugly-named {@link SHA512_256} instead - */ - class SHA1 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 20; - } - class MD5 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class MD4 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class SHA224 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 28; - } - class SHA512 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 64; - } - class SHA384 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 48; - } - class SHA256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - /** - * See also {@link sha} - */ - class SHA512_256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - - /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ - interface ZlibCompressionOptions { - /** - * The compression level to use. Must be between `-1` and `9`. - * - A value of `-1` uses the default compression level (Currently `6`) - * - A value of `0` gives no compression - * - A value of `1` gives least compression, fastest speed - * - A value of `9` gives best compression, slowest speed - */ - level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * How much memory should be allocated for the internal compression state. - * - * A value of `1` uses minimum memory but is slow and reduces compression ratio. - * - * A value of `9` uses maximum memory for optimal speed. The default is `8`. - */ - memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * The base 2 logarithm of the window size (the size of the history buffer). - * - * Larger values of this parameter result in better compression at the expense of memory usage. - * - * The following value ranges are supported: - * - `9..15`: The output will have a zlib header and footer (Deflate) - * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) - * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) - * - * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. - */ - windowBits?: - | -9 - | -10 - | -11 - | -12 - | -13 - | -14 - | -15 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 25 - | 26 - | 27 - | 28 - | 29 - | 30 - | 31; - /** - * Tunes the compression algorithm. - * - * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** - * - `Z_FILTERED`: For data produced by a filter or predictor - * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) - * - `Z_RLE`: Limit match distances to one (run-length encoding) - * - `Z_FIXED` prevents the use of dynamic Huffman codes - * - * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. - * - * `Z_FILTERED` forces more Huffman coding and less string matching, it is - * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. - * Filtered data consists mostly of small values with a somewhat random distribution. - */ - strategy?: number; - - library?: "zlib"; - } - - interface LibdeflateCompressionOptions { - level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; - library?: "libdeflate"; - } - - /** - * Compresses a chunk of data with `zlib` DEFLATE algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function deflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Compresses a chunk of data with `zlib` GZIP algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function gzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` INFLATE algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function inflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` GUNZIP algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function gunzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - - type Target = - /** - * For generating bundles that are intended to be run by the Bun runtime. In many cases, - * it isn't necessary to bundle server-side code; you can directly execute the source code - * without modification. However, bundling your server code can reduce startup times and - * improve running performance. - * - * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which - * indicates to the Bun runtime that there's no need to re-transpile the file before execution. - */ - | "bun" - /** - * The plugin will be applied to Node.js builds - */ - | "node" - /** - * The plugin will be applied to browser builds - */ - | "browser"; - - /** https://bun.sh/docs/bundler/loaders */ - type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "file" | "napi" | "wasm" | "text" | "css" | "html"; - - interface PluginConstraints { - /** - * Only apply the plugin when the import specifier matches this regular expression - * - * @example - * ```ts - * // Only apply the plugin when the import specifier matches the regex - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { - * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; - * }); - * } - * }) - * ``` - */ - filter: RegExp; - - /** - * Only apply the plugin when the import specifier has a namespace matching - * this string - * - * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` - * has the namespace `"bun"`. - * - * The default namespace is `"file"` and it can be omitted from import - * specifiers. - */ - namespace?: string; - } - - interface OnLoadResultSourceCode { - /** - * The source code of the module - */ - contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; - /** - * The loader to use for this file - * - * "css" will be added in a future version of Bun. - */ - loader?: Loader; - } - - interface OnLoadResultObject { - /** - * The object to use as the module - * @example - * ```ts - * // In your loader - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * - * // In your script - * import {foo} from "hello:world"; - * console.log(foo); // "bar" - * ``` - */ - exports: Record; - /** - * The loader to use for this file - */ - loader: "object"; - } - - interface OnLoadArgs { - /** - * The resolved import specifier of the module being loaded - * @example - * ```ts - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * console.log(args.path); // "hello:world" - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * ``` - */ - path: string; - /** - * The namespace of the module being loaded - */ - namespace: string; - /** - * The default loader for this file extension - */ - loader: Loader; - /** - * Defer the execution of this callback until all other modules have been parsed. - * - * @returns Promise which will be resolved when all modules have been parsed - */ - defer: () => Promise; - } - - type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject | undefined | void; - type OnLoadCallback = (args: OnLoadArgs) => OnLoadResult | Promise; - type OnStartCallback = () => void | Promise; - - interface OnResolveArgs { - /** - * The import specifier of the module being loaded - */ - path: string; - /** - * The module that imported the module being resolved - */ - importer: string; - /** - * The namespace of the importer. - */ - namespace: string; - /** - * The directory to perform file-based resolutions in. - */ - resolveDir: string; - /** - * The kind of import this resolve is for. - */ - kind: ImportKind; - // resolveDir: string; - // pluginData: any; - } - - interface OnResolveResult { - /** - * The destination of the import - */ - path: string; - /** - * The namespace of the destination - * It will be concatenated with `path` to form the final import specifier - * @example - * ```ts - * "foo" // "foo:bar" - * ``` - */ - namespace?: string; - external?: boolean; - } - - type OnResolveCallback = ( - args: OnResolveArgs, - ) => OnResolveResult | Promise | undefined | null; - - type FFIFunctionCallable = Function & { - // Making a nominally typed function so that the user must get it from dlopen - readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - - interface PluginBuilder { - /** - * Register a callback which will be invoked when bundling starts. When - * using hot module reloading, this is called at the start of each - * incremental rebuild. - * - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onStart(() => { - * console.log("bundle just started!!") - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onStart(callback: OnStartCallback): this; - onBeforeParse( - constraints: PluginConstraints, - callback: { - napiModule: unknown; - symbol: string; - external?: unknown | undefined; - }, - ): this; - /** - * Register a callback to load imports with a specific import specifier - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; - /** - * Register a callback to resolve imports matching a filter and/or namespace - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onResolve({ filter: /^wat$/ }, (args) => { - * return { path: "/tmp/woah.js" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onResolve(constraints: PluginConstraints, callback: OnResolveCallback): this; - /** - * The config object passed to `Bun.build` as is. Can be mutated. - */ - config: BuildConfig & { plugins: BunPlugin[] }; - - /** - * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules - * - * @param specifier The module specifier to register the callback for - * @param callback The function to run when the module is imported or required - * - * ### Example - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.module("hello:world", () => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * - * // sometime later - * const { foo } = await import("hello:world"); - * console.log(foo); // "bar" - * - * // or - * const { foo } = require("hello:world"); - * console.log(foo); // "bar" - * ``` - * - * @returns `this` for method chaining - */ - module(specifier: string, callback: () => OnLoadResult | Promise): this; - } - - interface BunPlugin { - /** - * Human-readable name of the plugin - * - * In a future version of Bun, this will be used in error messages. - */ - name: string; - - /** - * The target JavaScript environment the plugin should be applied to. - * - `bun`: The default environment when using `bun run` or `bun` to load a script - * - `browser`: The plugin will be applied to browser builds - * - `node`: The plugin will be applied to Node.js builds - * - * If unspecified, it is assumed that the plugin is compatible with all targets. - * - * This field is not read by Bun.plugin - */ - target?: Target; - /** - * A function that will be called when the plugin is loaded. - * - * This function may be called in the same tick that it is registered, or it may be called later. It could potentially be called multiple times for different targets. - */ - setup( - /** - * A builder object that can be used to register plugin hooks - * @example - * ```ts - * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), - * })); - * ``` - */ - build: PluginBuilder, - ): void | Promise; - } - - /** - * Extend Bun's module resolution and loading behavior - * - * Plugins are applied in the order they are defined. - * - * Today, there are two kinds of hooks: - * - `onLoad` lets you return source code or an object that will become the module's exports - * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. - * - * Plugin hooks must define a `filter` RegExp and will only be matched if the - * import specifier contains a "." or a ":". - * - * ES Module resolution semantics mean that plugins may be initialized _after_ - * a module is resolved. You might need to load plugins at the very beginning - * of the application and then use a dynamic import to load the rest of the - * application. A future version of Bun may also support specifying plugins - * via `bunfig.toml`. - * - * @example - * A YAML loader plugin - * - * ```js - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) - * })); - * }); - * - * // You can use require() - * const {foo} = require("./file.yaml"); - * - * // Or import - * await import("./file.yaml"); - * - * ``` - */ - interface BunRegisterPlugin { - (options: T): ReturnType; - - /** - * Deactivate all plugins - * - * This prevents registered plugins from being applied to future builds. - */ - clearAll(): void; - } - - const plugin: BunRegisterPlugin; - - /** - * Is the current global scope the main thread? - */ - const isMainThread: boolean; - - /** - * Used when importing an HTML file at runtime. - * - * @example - * - * ```ts - * import app from "./index.html"; - * ``` - * - * Bun.build support for this isn't imlpemented yet. - */ - interface HTMLBundle { - index: string; - } - - interface Socket extends Disposable { - /** - * Write `data` to the socket - * - * @param data The data to write to the socket - * @param byteOffset The offset in the buffer to start writing from (defaults to 0) - * @param byteLength The number of bytes to write (defaults to the length of the buffer) - * - * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. - * - * This is unbuffered as of Bun v0.2.2. That means individual write() calls - * will be slow. In the future, Bun will buffer writes and flush them at the - * end of the tick, when the event loop is idle, or sooner if the buffer is full. - */ - write(data: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; - - /** - * The data context for the socket. - */ - data: Data; - - /** - * Like {@link Socket.write} except it includes a TCP FIN packet - * - * Use it to send your last message and close the connection. - */ - end(data?: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; - - /** - * Close the socket immediately - */ - end(): void; - - /** - * Keep Bun's process alive at least until this socket is closed - * - * After the socket has closed, the socket is unref'd, the process may exit, - * and this becomes a no-op - */ - ref(): void; - - /** - * Set a timeout until the socket automatically closes. - * - * To reset the timeout, call this function again. - * - * When a timeout happens, the `timeout` callback is called and the socket is closed. - */ - timeout(seconds: number): void; - - /** - * Forcefully close the socket. The other end may not receive all data, and - * the socket will be closed immediately. - * - * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to - * `0` and then calls `close(2)`. - */ - terminate(): void; - - /** - * Shutdown writes to a socket - * - * This makes the socket a half-closed socket. It can still receive data. - * - * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally - */ - shutdown(halfClose?: boolean): void; - - readonly readyState: "open" | "closing" | "closed"; - - /** - * Allow Bun's process to exit even if this socket is still open - * - * After the socket has closed, this function does nothing. - */ - unref(): void; - - /** - * Flush any buffered data to the socket - */ - flush(): void; - - /** - * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. - * - * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. - */ - reload(handler: SocketHandler): void; - - /** - * Get the server that created this socket - * - * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. - */ - readonly listener?: SocketListener; - - /** - * Remote IP address connected to the socket - */ - readonly remoteAddress: string; - - /** - * local port connected to the socket - */ - readonly localPort: number; - - /** - * This property is `true` if the peer certificate was signed by one of the CAs - * specified when creating the `Socket` instance, otherwise `false`. - */ - readonly authorized: boolean; - - /** - * String containing the selected ALPN protocol. - * Before a handshake has completed, this value is always null. - * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. - */ - readonly alpnProtocol: string | false | null; - - /** - * Disables TLS renegotiation for this `Socket` instance. Once called, attempts - * to renegotiate will trigger an `error` handler on the `Socket`. - * - * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) - */ - disableRenegotiation(): void; - - /** - * Keying material is used for validations to prevent different kind of attacks in - * network protocols, for example in the specifications of IEEE 802.1X. - * - * Example - * - * ```js - * const keyingMaterial = socket.exportKeyingMaterial( - * 128, - * 'client finished'); - * - * /* - * Example return value of keyingMaterial: - * - * - * ``` - * - * @param length number of bytes to retrieve from keying material - * @param label an application specific label, typically this will be a value from the [IANA Exporter Label - * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). - * @param context Optionally provide a context. - * @return requested bytes of the keying material - */ - exportKeyingMaterial(length: number, label: string, context: Buffer): Buffer; - - /** - * Returns the reason why the peer's certificate was not been verified. This - * property is set only when `socket.authorized === false`. - */ - getAuthorizationError(): Error | null; - - /** - * Returns an object representing the local certificate. The returned object has - * some properties corresponding to the fields of the certificate. - * - * If there is no local certificate, an empty object will be returned. If the - * socket has been destroyed, `null` will be returned. - */ - getCertificate(): PeerCertificate | object | null; - getX509Certificate(): X509Certificate | undefined; - - /** - * Returns an object containing information on the negotiated cipher suite. - * - * For example, a TLSv1.2 protocol with AES256-SHA cipher: - * - * ```json - * { - * "name": "AES256-SHA", - * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", - * "version": "SSLv3" - * } - * ``` - * - */ - getCipher(): CipherNameAndProtocol; - - /** - * Returns an object representing the type, name, and size of parameter of - * an ephemeral key exchange in `perfect forward secrecy` on a client - * connection. It returns an empty object when the key exchange is not - * ephemeral. As this is only supported on a client socket; `null` is returned - * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. - * - * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. - */ - getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; - - /** - * Returns an object representing the peer's certificate. If the peer does not - * provide a certificate, an empty object will be returned. If the socket has been - * destroyed, `null` will be returned. - * - * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's - * certificate. - * @return A certificate object. - */ - getPeerCertificate(): PeerCertificate; - getPeerX509Certificate(): X509Certificate; - - /** - * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. - * @since v12.11.0 - * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. - */ - getSharedSigalgs(): string[]; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. - */ - getTLSFinishedMessage(): Buffer | undefined; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so - * far. - */ - getTLSPeerFinishedMessage(): Buffer | undefined; - - /** - * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. - * - * It may be useful for debugging. - * - * See `Session Resumption` for more information. - */ - getTLSTicket(): Buffer | undefined; - - /** - * Returns a string containing the negotiated SSL/TLS protocol version of the - * current connection. The value `'unknown'` will be returned for connected - * sockets that have not completed the handshaking process. The value `null` will - * be returned for server sockets or disconnected client sockets. - * - * Protocol versions are: - * - * * `'SSLv3'` - * * `'TLSv1'` - * * `'TLSv1.1'` - * * `'TLSv1.2'` - * * `'TLSv1.3'` - * - */ - getTLSVersion(): string; - - /** - * See `Session Resumption` for more information. - * @return `true` if the session was reused, `false` otherwise. - */ - isSessionReused(): boolean; - - /** - * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. - * Returns `true` if setting the limit succeeded; `false` otherwise. - * - * Smaller fragment sizes decrease the buffering latency on the client: larger - * fragments are buffered by the TLS layer until the entire fragment is received - * and its integrity is verified; large fragments can span multiple roundtrips - * and their processing can be delayed due to packet loss or reordering. However, - * smaller fragments add extra TLS framing bytes and CPU overhead, which may - * decrease overall server throughput. - * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. - */ - setMaxSendFragment(size: number): boolean; - - /** - * Enable/disable the use of Nagle's algorithm. - * Only available for already connected sockets, will return false otherwise - * @param noDelay Default: `true` - * @returns true if is able to setNoDelay and false if it fails. - */ - setNoDelay(noDelay?: boolean): boolean; - - /** - * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. - * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. - * Only available for already connected sockets, will return false otherwise. - * - * Enabling the keep-alive functionality will set the following socket options: - * SO_KEEPALIVE=1 - * TCP_KEEPIDLE=initialDelay - * TCP_KEEPCNT=10 - * TCP_KEEPINTVL=1 - * @param enable Default: `false` - * @param initialDelay Default: `0` - * @returns true if is able to setNoDelay and false if it fails. - */ - setKeepAlive(enable?: boolean, initialDelay?: number): boolean; - - /** - * The number of bytes written to the socket. - */ - readonly bytesWritten: number; - } - - interface SocketListener extends Disposable { - stop(closeActiveConnections?: boolean): void; - ref(): void; - unref(): void; - reload(options: Pick, "socket">): void; - data: Data; - } - interface TCPSocketListener extends SocketListener { - readonly port: number; - readonly hostname: string; - } - interface UnixSocketListener extends SocketListener { - readonly unix: string; - } - - interface TCPSocket extends Socket {} - interface TLSSocket extends Socket {} - - interface BinaryTypeList { - arraybuffer: ArrayBuffer; - buffer: Buffer; - uint8array: Uint8Array; - // TODO: DataView - // dataview: DataView; - } - type BinaryType = keyof BinaryTypeList; - - interface SocketHandler { - /** - * Is called when the socket connects, or in case of TLS if no handshake is provided - * this will be called only after handshake - * @param socket - */ - open?(socket: Socket): void | Promise; - close?(socket: Socket): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - data?(socket: Socket, data: BinaryTypeList[DataBinaryType]): void | Promise; - drain?(socket: Socket): void | Promise; - - /** - * When handshake is completed, this functions is called. - * @param socket - * @param success Indicates if the server authorized despite the authorizationError. - * @param authorizationError Certificate Authorization Error or null. - */ - handshake?(socket: Socket, success: boolean, authorizationError: Error | null): void; - - /** - * When the socket has been shutdown from the other end, this function is - * called. This is a TCP FIN packet. - */ - end?(socket: Socket): void | Promise; - - /** - * When the socket fails to be created, this function is called. - * - * The promise returned by `Bun.connect` rejects **after** this function is - * called. - * - * When `connectError` is specified, the rejected promise will not be - * added to the promise rejection queue (so it won't be reported as an - * unhandled promise rejection, since connectError handles it). - * - * When `connectError` is not specified, the rejected promise will be added - * to the promise rejection queue. - */ - connectError?(socket: Socket, error: Error): void | Promise; - - /** - * Called when a message times out. - */ - timeout?(socket: Socket): void | Promise; - /** - * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. - * - * @default "buffer" - * - * @remarks - * This lets you select the desired binary type for the `data` callback. - * It's a small performance optimization to let you avoid creating extra - * ArrayBufferView objects when possible. - * - * Bun originally defaulted to `Uint8Array` but when dealing with network - * data, it's more useful to be able to directly read from the bytes which - * `Buffer` allows. - */ - binaryType?: BinaryType; - } - - interface SocketOptions { - socket: SocketHandler; - data?: Data; - } - // interface TCPSocketOptions extends SocketOptions { - // hostname: string; - // port: number; - // } - - interface TCPSocketListenOptions extends SocketOptions { - hostname: string; - port: number; - tls?: TLSOptions; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface TCPSocketConnectOptions extends SocketOptions { - hostname: string; - port: number; - tls?: boolean; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface UnixSocketOptions extends SocketOptions { - tls?: TLSOptions; - unix: string; - } - - interface FdSocketOptions extends SocketOptions { - tls?: TLSOptions; - fd: number; - } - - /** - * Create a TCP client that connects to a server - * - * @param options The options to use when creating the client - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function connect(options: TCPSocketConnectOptions): Promise>; - function connect(options: UnixSocketOptions): Promise>; - - /** - * Create a TCP server that listens on a port - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function listen(options: TCPSocketListenOptions): TCPSocketListener; - function listen(options: UnixSocketOptions): UnixSocketListener; - - namespace udp { - type Data = string | ArrayBufferView | ArrayBufferLike; - - export interface SocketHandler { - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: Socket): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - } - - export interface ConnectedSocketHandler { - data?( - socket: ConnectedSocket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: ConnectedSocket): void | Promise; - error?(socket: ConnectedSocket, error: Error): void | Promise; - } - - export interface SocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: SocketHandler; - } - - export interface ConnectSocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: ConnectedSocketHandler; - connect: { - hostname: string; - port: number; - }; - } - - export interface BaseUDPSocket { - readonly hostname: string; - readonly port: number; - readonly address: SocketAddress; - readonly binaryType: BinaryType; - readonly closed: boolean; - ref(): void; - unref(): void; - close(): void; - } - - export interface ConnectedSocket extends BaseUDPSocket { - readonly remoteAddress: SocketAddress; - sendMany(packets: readonly Data[]): number; - send(data: Data): boolean; - reload(handler: ConnectedSocketHandler): void; - } - - export interface Socket extends BaseUDPSocket { - sendMany(packets: readonly (Data | string | number)[]): number; - send(data: Data, port: number, address: string): boolean; - reload(handler: SocketHandler): void; - } - } - - /** - * Create a UDP socket - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.hostname The hostname to listen on - * @param options.port The port to listen on - * @param options.binaryType The binary type to use for the socket - * @param options.connect The hostname and port to connect to - */ - export function udpSocket( - options: udp.SocketOptions, - ): Promise>; - export function udpSocket( - options: udp.ConnectSocketOptions, - ): Promise>; - - namespace SpawnOptions { - /** - * Option for stdout/stderr - */ - type Readable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number; - - /** - * Option for stdin - */ - type Writable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number - | ReadableStream - | Blob - | Response - | Request; - - interface OptionsObject< - In extends Writable = Writable, - Out extends Readable = Readable, - Err extends Readable = Readable, - > { - /** - * The current working directory of the process - * - * Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * The environment variables of the process - * - * Defaults to `process.env` as it was when the current Bun process launched. - * - * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. - */ - env?: Record; - - /** - * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. - * This overrides the `stdin`, `stdout`, and `stderr` properties. - * - * For stdin you may pass: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. - * - `number`: The process will read from the file descriptor - * - * For stdout and stdin you may pass: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default ["ignore", "pipe", "inherit"] for `spawn` - * ["ignore", "pipe", "pipe"] for `spawnSync` - */ - stdio?: [In, Out, Err]; - /** - * The file descriptor for the standard input. It may be: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`: The process will read from the buffer - * - `number`: The process will read from the file descriptor - * - * @default "ignore" - */ - stdin?: In; - /** - * The file descriptor for the standard output. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "pipe" - */ - stdout?: Out; - /** - * The file descriptor for the standard error. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "inherit" for `spawn` - * "pipe" for `spawnSync` - */ - stderr?: Err; - - /** - * Callback that runs when the {@link Subprocess} exits - * - * This is called even if the process exits with a non-zero exit code. - * - * Warning: this may run before the `Bun.spawn` function returns. - * - * A simple alternative is `await subprocess.exited`. - * - * @example - * - * ```ts - * const subprocess = spawn({ - * cmd: ["echo", "hello"], - * onExit: (subprocess, code) => { - * console.log(`Process exited with code ${code}`); - * }, - * }); - * ``` - */ - onExit?( - subprocess: Subprocess, - exitCode: number | null, - signalCode: number | null, - /** - * If an error occurred in the call to waitpid2, this will be the error. - */ - error?: ErrorLike, - ): void | Promise; - - /** - * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for - * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized - * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - * - * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, - * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. - * - * Currently, this is only compatible with processes that are other `bun` instances. - */ - ipc?( - message: any, - /** - * The {@link Subprocess} that sent the message - */ - subprocess: Subprocess, - ): void; - - /** - * The serialization format to use for IPC messages. Defaults to `"advanced"`. - * - * To communicate with Node.js processes, use `"json"`. - * - * When `ipc` is not specified, this is ignored. - */ - serialization?: "json" | "advanced"; - - /** - * If true, the subprocess will have a hidden window. - */ - windowsHide?: boolean; - - /** - * If true, no quoting or escaping of arguments is done on Windows. - */ - windowsVerbatimArguments?: boolean; - - /** - * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. - * - * One use-case for this is for applications which wrap other applications or to simulate a symlink. - * - * @default cmds[0] - */ - argv0?: string; - - /** - * An {@link AbortSignal} that can be used to abort the subprocess. - * - * This is useful for aborting a subprocess when some other part of the - * program is aborted, such as a `fetch` response. - * - * Internally, this works by calling `subprocess.kill(1)`. - * - * @example - * ```ts - * const controller = new AbortController(); - * const { signal } = controller; - * const start = performance.now(); - * const subprocess = Bun.spawn({ - * cmd: ["sleep", "100"], - * signal, - * }); - * await Bun.sleep(1); - * controller.abort(); - * await subprocess.exited; - * const end = performance.now(); - * console.log(end - start); // 1ms instead of 101ms - * ``` - */ - signal?: AbortSignal; - } - - type OptionsToSubprocess = - Opts extends OptionsObject - ? Subprocess< - // "Writable extends In" means "if In === Writable", - // aka if true that means the user didn't specify anything - Writable extends In ? "ignore" : In, - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "inherit" : Err - > - : Subprocess; - - type OptionsToSyncSubprocess = - Opts extends OptionsObject - ? SyncSubprocess - : SyncSubprocess; - - type ReadableIO = ReadableStream | number | undefined; - - type ReadableToIO = X extends "pipe" | undefined - ? ReadableStream - : X extends BunFile | ArrayBufferView | number - ? number - : undefined; - - type ReadableToSyncIO = X extends "pipe" | undefined ? Buffer : undefined; - - type WritableIO = FileSink | number | undefined; - - type WritableToIO = X extends "pipe" - ? FileSink - : X extends BunFile | ArrayBufferView | Blob | Request | Response | number - ? number - : undefined; - } - - interface ResourceUsage { - /** - * The number of voluntary and involuntary context switches that the process made. - */ - contextSwitches: { - /** - * Voluntary context switches (context switches that the process initiated). - */ - voluntary: number; - /** - * Involuntary context switches (context switches initiated by the system scheduler). - */ - involuntary: number; - }; - - /** - * The amount of CPU time used by the process, in microseconds. - */ - cpuTime: { - /** - * User CPU time used by the process, in microseconds. - */ - user: number; - /** - * System CPU time used by the process, in microseconds. - */ - system: number; - /** - * Total CPU time used by the process, in microseconds. - */ - total: number; - }; - /** - * The maximum amount of resident set size (in bytes) used by the process during its lifetime. - */ - maxRSS: number; - - /** - * IPC messages sent and received by the process. - */ - messages: { - /** - * The number of IPC messages sent. - */ - sent: number; - /** - * The number of IPC messages received. - */ - received: number; - }; - /** - * The number of IO operations done by the process. - */ - ops: { - /** - * The number of input operations via the file system. - */ - in: number; - /** - * The number of output operations via the file system. - */ - out: number; - }; - /** - * The amount of shared memory that the process used. - */ - shmSize: number; - /** - * The number of signals delivered to the process. - */ - signalCount: number; - /** - * The number of times the process was swapped out of main memory. - */ - swapCount: number; - } - - /** - * A process created by {@link Bun.spawn}. - * - * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSubprocess} (any, pipe, pipe) - * - {@link WritableSubprocess} (pipe, any, any) - * - {@link PipedSubprocess} (pipe, pipe, pipe) - * - {@link NullSubprocess} (ignore, ignore, ignore) - */ - interface Subprocess< - In extends SpawnOptions.Writable = SpawnOptions.Writable, - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > extends AsyncDisposable { - readonly stdin: SpawnOptions.WritableToIO; - readonly stdout: SpawnOptions.ReadableToIO; - readonly stderr: SpawnOptions.ReadableToIO; - - /** - * This returns the same value as {@link Subprocess.stdout} - * - * It exists for compatibility with {@link ReadableStream.pipeThrough} - */ - readonly readable: SpawnOptions.ReadableToIO; - - /** - * The process ID of the child process - * @example - * ```ts - * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); - * console.log(pid); // 1234 - * ``` - */ - readonly pid: number; - /** - * The exit code of the process - * - * The promise will resolve when the process exits - */ - readonly exited: Promise; - - /** - * Synchronously get the exit code of the process - * - * If the process hasn't exited yet, this will return `null` - */ - readonly exitCode: number | null; - - /** - * Synchronously get the signal code of the process - * - * If the process never sent a signal code, this will return `null` - * - * To receive signal code changes, use the `onExit` callback. - * - * If the signal code is unknown, it will return the original signal code - * number, but that case should essentially never happen. - */ - readonly signalCode: NodeJS.Signals | null; - - /** - * Has the process exited? - */ - readonly killed: boolean; - - /** - * Kill the process - * @param exitCode The exitCode to send to the process - */ - kill(exitCode?: number | NodeJS.Signals): void; - - /** - * This method will tell Bun to wait for this process to exit after you already - * called `unref()`. - * - * Before shutting down, Bun will wait for all subprocesses to exit by default - */ - ref(): void; - - /** - * Before shutting down, Bun will wait for all subprocesses to exit by default - * - * This method will tell Bun to not wait for this process to exit before shutting down. - */ - unref(): void; - - /** - * Send a message to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option, and is another instance of `bun`. - * - * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - */ - send(message: any): void; - - /** - * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option. - */ - disconnect(): void; - - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - * - * Only available after the process has exited - * - * If the process hasn't exited yet, this will return `undefined` - */ - resourceUsage(): ResourceUsage | undefined; - } - - /** - * A process created by {@link Bun.spawnSync}. - * - * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSyncSubprocess} (pipe, pipe) - * - {@link NullSyncSubprocess} (ignore, ignore) - */ - interface SyncSubprocess< - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > { - stdout: SpawnOptions.ReadableToSyncIO; - stderr: SpawnOptions.ReadableToSyncIO; - exitCode: number; - success: boolean; - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - */ - resourceUsage: ResourceUsage; - - signalCode?: string; - } - - /** - * Spawn a new process - * - * ```js - * const subprocess = Bun.spawn({ - * cmd: ["echo", "hello"], - * stdout: "pipe", - * }); - * const text = await readableStreamToText(subprocess.stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmd: string[]; // to support dynamically constructed commands - }, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawn(["echo", "hello"]); - * const text = await readableStreamToText(stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync({ - * cmd: ["echo", "hello"], - * }); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); - * ``` - */ - cmd: string[]; - - onExit?: never; - }, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** - * Synchronously spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync(["echo", "hello"]); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ - type ReadableSubprocess = Subprocess; - /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ - type WritableSubprocess = Subprocess<"pipe", any, any>; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ - type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ - type NullSubprocess = Subprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ - type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ - type NullSyncSubprocess = SyncSubprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - - // Blocked on https://github.com/oven-sh/bun/issues/8329 - // /** - // * - // * Count the visible width of a string, as it would be displayed in a terminal. - // * - // * By default, strips ANSI escape codes before measuring the string. This is - // * because ANSI escape codes are not visible characters. If passed a non-string, - // * it will return 0. - // * - // * @param str The string to measure - // * @param options - // */ - // function stringWidth( - // str: string, - // options?: { - // /** - // * Whether to include ANSI escape codes in the width calculation - // * - // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. - // * @default false - // */ - // countAnsiEscapeCodes?: boolean; - // }, - // ): number; - - class FileSystemRouter { - /** - * Create a new {@link FileSystemRouter}. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: process.cwd() + "/pages", - * style: "nextjs", - * }); - * - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} - * ``` - * @param options The options to use when creating the router - * @param options.dir The root directory containing the files to route - * @param options.style The style of router to use (only "nextjs" supported - * for now) - */ - constructor(options: { - /** - * The root directory containing the files to route - * - * There is no default value for this option. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: - */ - dir: string; - style: "nextjs"; - - /** The base path to use when routing */ - assetPrefix?: string; - origin?: string; - /** Limit the pages to those with particular file extensions. */ - fileExtensions?: string[]; - }); - - // todo: URL - match(input: string | Request | Response): MatchedRoute | null; - - readonly assetPrefix: string; - readonly origin: string; - readonly style: string; - readonly routes: Record; - - reload(): void; - } - - interface MatchedRoute { - /** - * A map of the parameters from the route - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: "/path/to/files", - * style: "nextjs", - * }); - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params.year); // "2020" - * console.log(params.month); // "01" - * console.log(params.day); // "01" - * console.log(params.slug); // "hello-world" - * ``` - */ - readonly params: Record; - readonly filePath: string; - readonly pathname: string; - readonly query: Record; - readonly name: string; - readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; - readonly src: string; - } - - /** - * The current version of Bun - * @example - * "0.2.0" - */ - const version: string; - - /** - * The current version of Bun with the shortened commit sha of the build - * @example "v1.1.30 (d09df1af)" - */ - const version_with_sha: string; - - /** - * The git sha at the time the currently-running version of Bun was compiled - * @example - * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" - */ - const revision: string; - - /** - * Find the index of a newline character in potentially ill-formed UTF-8 text. - * - * This is sort of like readline() except without the IO. - */ - function indexOfLine(buffer: ArrayBufferView | ArrayBufferLike, offset?: number): number; - - interface GlobScanOptions { - /** - * The root directory to start matching from. Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * Allow patterns to match entries that begin with a period (`.`). - * - * @default false - */ - dot?: boolean; - - /** - * Return the absolute path for entries. - * - * @default false - */ - absolute?: boolean; - - /** - * Indicates whether to traverse descendants of symbolic link directories. - * - * @default false - */ - followSymlinks?: boolean; - - /** - * Throw an error when symbolic link is broken - * - * @default false - */ - throwErrorOnBrokenSymlink?: boolean; - - /** - * Return only files. - * - * @default true - */ - onlyFiles?: boolean; - } - - /** - * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). - * - * The supported pattern syntax for is: - * - * - `?` - * Matches any single character. - * - `*` - * Matches zero or more characters, except for path separators ('/' or '\'). - * - `**` - * Matches zero or more characters, including path separators. - * Must match a complete path segment, i.e. followed by a path separator or - * at the end of the pattern. - * - `[ab]` - * Matches one of the characters contained in the brackets. - * Character ranges (e.g. "[a-z]") are also supported. - * Use "[!ab]" or "[^ab]" to match any character *except* those contained - * in the brackets. - * - `{a,b}` - * Match one of the patterns contained in the braces. - * Any of the wildcards listed above can be used in the sub patterns. - * Braces may be nested up to 10 levels deep. - * - `!` - * Negates the result when at the start of the pattern. - * Multiple "!" characters negate the pattern multiple times. - * - `\` - * Used to escape any of the special characters above. - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - */ - export class Glob { - constructor(pattern: string); - - /** - * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for await (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scan(optionsOrCwd?: string | GlobScanOptions): AsyncIterableIterator; - - /** - * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; - - /** - * Match the glob against a string - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * expect(glob.match('foo.ts')).toBeTrue(); - * ``` - */ - match(str: string): boolean; - } - - /** - * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. - * - * When the same timestamp is used multiple times, a monotonically increasing - * counter is appended to allow sorting. The final 8 bytes are - * cryptographically random. When the timestamp changes, the counter resets to - * a psuedo-random integer. - * - * @param encoding "hex" | "base64" | "base64url" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - * - * @example - * ```js - * import { randomUUIDv7 } from "bun"; - * const array = [ - * randomUUIDv7(), - * randomUUIDv7(), - * randomUUIDv7(), - * ] - * [ - * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", - * "0192ce07-8c4f-7d67-805f-0f71581b5622", - * "0192ce07-8c4f-7d68-8170-6816e4451a58" - * ] - * ``` - */ - function randomUUIDv7( - /** - * @default "hex" - */ - encoding?: "hex" | "base64" | "base64url", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): string; - - /** - * Generate a UUIDv7 as a Buffer - * - * @param encoding "buffer" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - */ - function randomUUIDv7( - encoding: "buffer", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): Buffer; - - /** - * Types for `bun.lock` - */ - type BunLockFile = { - lockfileVersion: 0 | 1; - workspaces: { - [workspace: string]: BunLockFileWorkspacePackage; - }; - overrides?: Record; - patchedDependencies?: Record; - trustedDependencies?: string[]; - - /** - * ``` - * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } - * - * // first index is resolution for each type of package - * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] - * symlink -> [ "name@link:path", INFO ] - * folder -> [ "name@file:path", INFO ] - * workspace -> [ "name@workspace:path" ] // workspace is only path - * tarball -> [ "name@tarball", INFO ] - * root -> [ "name@root:", { bin, binDir } ] - * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] - * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] - * ``` - * */ - packages: { - [pkg: string]: BunLockFilePackageArray; - }; - }; - - type BunLockFileBasePackageInfo = { - dependencies?: Record; - devDependencies?: Record; - optionalDependencies?: Record; - peerDependencies?: Record; - optionalPeers?: string[]; - bin?: string | Record; - binDir?: string; - }; - - type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { - name?: string; - version?: string; - }; - - type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { - os?: string | string[]; - cpu?: string | string[]; - bundled?: true; - }; - - /** @see {@link BunLockFile.packages} for more info */ - type BunLockFilePackageArray = - /** npm */ - | [pkg: string, registry: string, info: BunLockFilePackageInfo, integrity: string] - /** symlink, folder, tarball */ - | [pkg: string, info: BunLockFilePackageInfo] - /** workspace */ - | [pkg: string] - /** git, github */ - | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] - /** root */ - | [pkg: string, info: Pick]; + function serve< + T, + R extends { [K in keyof R]: RouterTypes.RouteValue }, + >( + options: ( + | (DistributedOmit & { + routes: R; + fetch?: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | (DistributedOmit & { + routes?: never; + fetch: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for a while though. + */ + static?: R; + }, + ): Server; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * - `type` is auto-set based on the file extension when possible + * + * @example + * ```js + * const file = Bun.file("./hello.json"); + * console.log(file.type); // "application/json" + * console.log(await file.json()); // { hello: "world" } + * ``` + * + * @example + * ```js + * await Bun.write( + * Bun.file("./hello.txt"), + * "Hello, world!" + * ); + * ``` + * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: string | URL, options?: BlobPropertyBag): BunFile; + + /** + * A list of files embedded into the standalone executable. Lexigraphically sorted by name. + * + * If the process is not a standalone executable, this returns an empty array. + */ + const embeddedFiles: ReadonlyArray; + + /** + * `Blob` that leverages the fastest system calls available to operate on files. + * + * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. + * + * `Blob.size` will not be valid until the contents of the file are read at least once. + * `Blob.type` will have a default set based on the file extension + * + * @example + * ```js + * const file = Bun.file(new TextEncoder.encode("./hello.json")); + * console.log(file.type); // "application/json" + * ``` + * + * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file( + path: ArrayBufferLike | Uint8Array, + options?: BlobPropertyBag, + ): BunFile; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * + * @example + * ```js + * const file = Bun.file(fd); + * ``` + * + * @param fileDescriptor The file descriptor of the file + */ + // tslint:disable-next-line:unified-signatures + function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; + + /** + * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. + * + * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. + */ + function allocUnsafe(size: number): Uint8Array; + + interface BunInspectOptions { + colors?: boolean; + depth?: number; + sorted?: boolean; + compact?: boolean; + } + + /** + * Pretty-print an object the same as {@link console.log} to a `string` + * + * Supports JSX + * + * @param args + */ + function inspect(arg: any, options?: BunInspectOptions): string; + namespace inspect { + /** + * That can be used to declare custom inspect functions. + */ + const custom: typeof import("util").inspect.custom; + + /** + * Pretty-print an object or array as a table + * + * Like {@link console.table}, except it returns a string + */ + function table( + tabularData: object | unknown[], + properties?: string[], + options?: { colors?: boolean }, + ): string; + function table( + tabularData: object | unknown[], + options?: { colors?: boolean }, + ): string; + } + + interface MMapOptions { + /** + * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. + */ + sync?: boolean; + /** + * Allow other processes to see results instantly? + * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. + * @default true + */ + shared?: boolean; + } + /** + * Open a file as a live-updating `Uint8Array` without copying memory + * - Writing to the array writes to the file. + * - Reading from the array reads from the file. + * + * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. + * + * --- + * + * This API inherently has some rough edges: + * - It does not support empty files. It will throw a `SystemError` with `EINVAL` + * - Usage on shared/networked filesystems is discouraged. It will be very slow. + * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. + * + * --- + * + * To close the file, set the array to `null` and it will be garbage collected eventually. + */ + function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; + + /** Write to stdout */ + const stdout: BunFile; + /** Write to stderr */ + const stderr: BunFile; + /** + * Read from stdin + * + * This is read-only + */ + const stdin: BunFile; + + type StringLike = string | { toString(): string }; + + type ColorInput = + | { r: number; g: number; b: number; a?: number } + | [number, number, number] + | [number, number, number, number] + | Uint8Array + | Uint8ClampedArray + | Float32Array + | Float64Array + | string + | number + | { toString(): string }; + + function color( + input: ColorInput, + outputFormat?: /** + * True color ANSI color string, for use in terminals + * @example \x1b[38;2;100;200;200m + */ + | "ansi" + | "ansi-16" + | "ansi-16m" + /** + * 256 color ANSI color string, for use in terminals which don't support true color + * + * Tries to match closest 24-bit color to 256 color palette + */ + | "ansi-256" + /** + * Picks the format that produces the shortest output + */ + | "css" + /** + * Lowercase hex color string without alpha + * @example #ff9800 + */ + | "hex" + /** + * Uppercase hex color string without alpha + * @example #FF9800 + */ + | "HEX" + /** + * @example hsl(35.764706, 1, 0.5) + */ + | "hsl" + /** + * @example lab(0.72732764, 33.938198, -25.311619) + */ + | "lab" + /** + * @example 16750592 + */ + | "number" + /** + * RGB color string without alpha + * @example rgb(255, 152, 0) + */ + | "rgb" + /** + * RGB color string with alpha + * @example rgba(255, 152, 0, 1) + */ + | "rgba", + ): string | null; + + function color( + input: ColorInput, + /** + * An array of numbers representing the RGB color + * @example [100, 200, 200] + */ + outputFormat: "[rgb]", + ): [number, number, number] | null; + function color( + input: ColorInput, + /** + * An array of numbers representing the RGBA color + * @example [100, 200, 200, 255] + */ + outputFormat: "[rgba]", + ): [number, number, number, number] | null; + function color( + input: ColorInput, + /** + * An object representing the RGB color + * @example { r: 100, g: 200, b: 200 } + */ + outputFormat: "{rgb}", + ): { r: number; g: number; b: number } | null; + function color( + input: ColorInput, + /** + * An object representing the RGBA color + * @example { r: 100, g: 200, b: 200, a: 0.5 } + */ + outputFormat: "{rgba}", + ): { r: number; g: number; b: number; a: number } | null; + function color(input: ColorInput, outputFormat: "number"): number | null; + + interface Semver { + /** + * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. + */ + satisfies(version: StringLike, range: StringLike): boolean; + + /** + * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. + * Throws an error if either version is invalid. + */ + order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; + } + var semver: Semver; + + interface Unsafe { + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. + * + * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; + + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` + * + * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + // tslint:disable-next-line:unified-signatures + arrayBufferToString(buffer: Uint16Array): string; + + /** Mock bun's segfault handler. You probably don't want to use this */ + segfault(): void; + + /** + * Force the garbage collector to run extremely often, + * especially inside `bun:test`. + * + * - `0`: default, disable + * - `1`: asynchronously call the garbage collector more often + * - `2`: synchronously call the garbage collector more often. + * + * This is a global setting. It's useful for debugging seemingly random crashes. + * + * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. + * + * @param level + * @returns The previous level + */ + gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; + } + const unsafe: Unsafe; + + type DigestEncoding = + | "utf8" + | "ucs2" + | "utf16le" + | "latin1" + | "ascii" + | "base64" + | "base64url" + | "hex"; + + /** + * Are ANSI colors enabled for stdin and stdout? + * + * Used for {@link console.log} + */ + const enableANSIColors: boolean; + + /** + * What script launched bun? + * + * Absolute file path + * + * @example "/never-gonna-give-you-up.js" + */ + const main: string; + + /** + * Manually trigger the garbage collector + * + * This does two things: + * 1. It tells JavaScriptCore to run the garbage collector + * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. + * + * @param force Synchronously run the garbage collector + */ + function gc(force: boolean): void; + + /** + * JavaScriptCore engine's internal heap snapshot + * + * I don't know how to make this something Chrome or Safari can read. + * + * If you have any ideas, please file an issue https://github.com/oven-sh/bun + */ + interface HeapSnapshot { + /** 2 */ + version: number; + + /** "Inspector" */ + type: string; + + nodes: number[]; + + nodeClassNames: string[]; + edges: number[]; + edgeTypes: string[]; + edgeNames: string[]; + } + + /** + * Returns the number of nanoseconds since the process was started. + * + * This function uses a high-resolution monotonic system timer to provide precise time measurements. + * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), + * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). + * + * Due to this limitation, while the internal counter may continue beyond this point, + * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond + * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but + * with reduced precision, which might affect time calculations and comparisons in long-running applications. + * + * @returns {number} The number of nanoseconds since the process was started, with precise values up to + * Number.MAX_SAFE_INTEGER. + */ + function nanoseconds(): number; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector + */ + function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code + * + * This is a JSON string that can be saved to a file. + * ```ts + * const snapshot = Bun.generateHeapSnapshot("v8"); + * await Bun.write("heap.heapsnapshot", snapshot); + * ``` + */ + function generateHeapSnapshot(format: "v8"): string; + + /** + * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. + */ + function shrink(): void; + + /** + * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` + * + * @param path path to open + */ + function openInEditor(path: string, options?: EditorOptions): void; + + var fetch: typeof globalThis.fetch & { + preconnect(url: string): void; + }; + + interface EditorOptions { + editor?: "vscode" | "subl"; + line?: number; + column?: number; + } + + /** + * This class only exists in types + */ + abstract class CryptoHashInterface { + /** + * Update the hash with data + * + * @param data + */ + update(data: Bun.BlobOrStringOrBuffer): T; + + /** + * Finalize the hash + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash( + input: Bun.BlobOrStringOrBuffer, + hashInto?: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + } + + type SupportedCryptoAlgorithms = + | "blake2b256" + | "blake2b512" + | "md4" + | "md5" + | "ripemd160" + | "sha1" + | "sha224" + | "sha256" + | "sha384" + | "sha512" + | "sha512-224" + | "sha512-256" + | "sha3-224" + | "sha3-256" + | "sha3-384" + | "sha3-512" + | "shake128" + | "shake256"; + + /** + * Hardware-accelerated cryptographic hash functions + * + * Used for `crypto.createHash()` + */ + class CryptoHasher { + /** + * The algorithm chosen to hash the data + */ + readonly algorithm: SupportedCryptoAlgorithms; + + /** + * The length of the output hash in bytes + */ + readonly byteLength: number; + + /** + * Create a new hasher + * + * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms + * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. + */ + constructor( + algorithm: SupportedCryptoAlgorithms, + hmacKey?: string | NodeJS.TypedArray, + ); + + /** + * Update the hash with data + * + * @param input + */ + update( + input: Bun.BlobOrStringOrBuffer, + inputEncoding?: CryptoEncoding, + ): CryptoHasher; + + /** + * Perform a deep copy of the hasher + */ + copy(): CryptoHasher; + + /** + * Finalize the hash. Resets the CryptoHasher so it can be reused. + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(): Buffer; + digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + ): Buffer; + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + hashInto: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + + /** + * List of supported hash algorithms + * + * These are hardware accelerated with BoringSSL + */ + static readonly algorithms: SupportedCryptoAlgorithms[]; + } + + /** + * Resolve a `Promise` after milliseconds. This is like + * {@link setTimeout} except it returns a `Promise`. + * + * @param ms milliseconds to delay resolving the promise. This is a minimum + * number. It may take longer. If a {@link Date} is passed, it will sleep until the + * {@link Date} is reached. + * + * @example + * ## Sleep for 1 second + * ```ts + * import { sleep } from "bun"; + * + * await sleep(1000); + * ``` + * ## Sleep for 10 milliseconds + * ```ts + * await Bun.sleep(10); + * ``` + * ## Sleep until `Date` + * + * ```ts + * const target = new Date(); + * target.setSeconds(target.getSeconds() + 1); + * await Bun.sleep(target); + * ``` + * Internally, `Bun.sleep` is the equivalent of + * ```ts + * await new Promise((resolve) => setTimeout(resolve, ms)); + * ``` + * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. + */ + function sleep(ms: number | Date): Promise; + + /** + * Sleep the thread for a given number of milliseconds + * + * This is a blocking function. + * + * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) + */ + function sleepSync(ms: number): void; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha( + input: Bun.StringOrBuffer, + hashInto?: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param encoding `DigestEncoding` to return the hash in + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; + + /** + * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} + * + * Consider using the ugly-named {@link SHA512_256} instead + */ + class SHA1 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 20; + } + class MD5 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class MD4 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class SHA224 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 28; + } + class SHA512 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 64; + } + class SHA384 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 48; + } + class SHA256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + /** + * See also {@link sha} + */ + class SHA512_256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + + /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ + interface ZlibCompressionOptions { + /** + * The compression level to use. Must be between `-1` and `9`. + * - A value of `-1` uses the default compression level (Currently `6`) + * - A value of `0` gives no compression + * - A value of `1` gives least compression, fastest speed + * - A value of `9` gives best compression, slowest speed + */ + level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * How much memory should be allocated for the internal compression state. + * + * A value of `1` uses minimum memory but is slow and reduces compression ratio. + * + * A value of `9` uses maximum memory for optimal speed. The default is `8`. + */ + memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * The base 2 logarithm of the window size (the size of the history buffer). + * + * Larger values of this parameter result in better compression at the expense of memory usage. + * + * The following value ranges are supported: + * - `9..15`: The output will have a zlib header and footer (Deflate) + * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) + * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) + * + * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. + */ + windowBits?: + | -9 + | -10 + | -11 + | -12 + | -13 + | -14 + | -15 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 25 + | 26 + | 27 + | 28 + | 29 + | 30 + | 31; + /** + * Tunes the compression algorithm. + * + * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** + * - `Z_FILTERED`: For data produced by a filter or predictor + * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) + * - `Z_RLE`: Limit match distances to one (run-length encoding) + * - `Z_FIXED` prevents the use of dynamic Huffman codes + * + * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. + * + * `Z_FILTERED` forces more Huffman coding and less string matching, it is + * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. + * Filtered data consists mostly of small values with a somewhat random distribution. + */ + strategy?: number; + + library?: "zlib"; + } + + interface LibdeflateCompressionOptions { + level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; + library?: "libdeflate"; + } + + /** + * Compresses a chunk of data with `zlib` DEFLATE algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function deflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Compresses a chunk of data with `zlib` GZIP algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function gzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` INFLATE algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function inflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` GUNZIP algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function gunzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + + type Target = + /** + * For generating bundles that are intended to be run by the Bun runtime. In many cases, + * it isn't necessary to bundle server-side code; you can directly execute the source code + * without modification. However, bundling your server code can reduce startup times and + * improve running performance. + * + * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which + * indicates to the Bun runtime that there's no need to re-transpile the file before execution. + */ + | "bun" + /** + * The plugin will be applied to Node.js builds + */ + | "node" + /** + * The plugin will be applied to browser builds + */ + | "browser"; + + /** https://bun.sh/docs/bundler/loaders */ + type Loader = + | "js" + | "jsx" + | "ts" + | "tsx" + | "json" + | "toml" + | "file" + | "napi" + | "wasm" + | "text" + | "css" + | "html"; + + interface PluginConstraints { + /** + * Only apply the plugin when the import specifier matches this regular expression + * + * @example + * ```ts + * // Only apply the plugin when the import specifier matches the regex + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { + * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; + * }); + * } + * }) + * ``` + */ + filter: RegExp; + + /** + * Only apply the plugin when the import specifier has a namespace matching + * this string + * + * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` + * has the namespace `"bun"`. + * + * The default namespace is `"file"` and it can be omitted from import + * specifiers. + */ + namespace?: string; + } + + interface OnLoadResultSourceCode { + /** + * The source code of the module + */ + contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; + /** + * The loader to use for this file + * + * "css" will be added in a future version of Bun. + */ + loader?: Loader; + } + + interface OnLoadResultObject { + /** + * The object to use as the module + * @example + * ```ts + * // In your loader + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * + * // In your script + * import {foo} from "hello:world"; + * console.log(foo); // "bar" + * ``` + */ + exports: Record; + /** + * The loader to use for this file + */ + loader: "object"; + } + + interface OnLoadArgs { + /** + * The resolved import specifier of the module being loaded + * @example + * ```ts + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * console.log(args.path); // "hello:world" + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * ``` + */ + path: string; + /** + * The namespace of the module being loaded + */ + namespace: string; + /** + * The default loader for this file extension + */ + loader: Loader; + /** + * Defer the execution of this callback until all other modules have been parsed. + * + * @returns Promise which will be resolved when all modules have been parsed + */ + defer: () => Promise; + } + + type OnLoadResult = + | OnLoadResultSourceCode + | OnLoadResultObject + | undefined + | void; + type OnLoadCallback = ( + args: OnLoadArgs, + ) => OnLoadResult | Promise; + type OnStartCallback = () => void | Promise; + + interface OnResolveArgs { + /** + * The import specifier of the module being loaded + */ + path: string; + /** + * The module that imported the module being resolved + */ + importer: string; + /** + * The namespace of the importer. + */ + namespace: string; + /** + * The directory to perform file-based resolutions in. + */ + resolveDir: string; + /** + * The kind of import this resolve is for. + */ + kind: ImportKind; + // resolveDir: string; + // pluginData: any; + } + + interface OnResolveResult { + /** + * The destination of the import + */ + path: string; + /** + * The namespace of the destination + * It will be concatenated with `path` to form the final import specifier + * @example + * ```ts + * "foo" // "foo:bar" + * ``` + */ + namespace?: string; + external?: boolean; + } + + type OnResolveCallback = ( + args: OnResolveArgs, + ) => + | OnResolveResult + | Promise + | undefined + | null; + + type FFIFunctionCallable = Function & { + // Making a nominally typed function so that the user must get it from dlopen + readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + + interface PluginBuilder { + /** + * Register a callback which will be invoked when bundling starts. When + * using hot module reloading, this is called at the start of each + * incremental rebuild. + * + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onStart(() => { + * console.log("bundle just started!!") + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onStart(callback: OnStartCallback): this; + onBeforeParse( + constraints: PluginConstraints, + callback: { + napiModule: unknown; + symbol: string; + external?: unknown | undefined; + }, + ): this; + /** + * Register a callback to load imports with a specific import specifier + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; + /** + * Register a callback to resolve imports matching a filter and/or namespace + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onResolve({ filter: /^wat$/ }, (args) => { + * return { path: "/tmp/woah.js" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onResolve( + constraints: PluginConstraints, + callback: OnResolveCallback, + ): this; + /** + * The config object passed to `Bun.build` as is. Can be mutated. + */ + config: BuildConfig & { plugins: BunPlugin[] }; + + /** + * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules + * + * @param specifier The module specifier to register the callback for + * @param callback The function to run when the module is imported or required + * + * ### Example + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.module("hello:world", () => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * + * // sometime later + * const { foo } = await import("hello:world"); + * console.log(foo); // "bar" + * + * // or + * const { foo } = require("hello:world"); + * console.log(foo); // "bar" + * ``` + * + * @returns `this` for method chaining + */ + module( + specifier: string, + callback: () => OnLoadResult | Promise, + ): this; + } + + interface BunPlugin { + /** + * Human-readable name of the plugin + * + * In a future version of Bun, this will be used in error messages. + */ + name: string; + + /** + * The target JavaScript environment the plugin should be applied to. + * - `bun`: The default environment when using `bun run` or `bun` to load a script + * - `browser`: The plugin will be applied to browser builds + * - `node`: The plugin will be applied to Node.js builds + * + * If unspecified, it is assumed that the plugin is compatible with all targets. + * + * This field is not read by Bun.plugin + */ + target?: Target; + /** + * A function that will be called when the plugin is loaded. + * + * This function may be called in the same tick that it is registered, or it may be called later. It could potentially be called multiple times for different targets. + */ + setup( + /** + * A builder object that can be used to register plugin hooks + * @example + * ```ts + * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), + * })); + * ``` + */ + build: PluginBuilder, + ): void | Promise; + } + + /** + * Extend Bun's module resolution and loading behavior + * + * Plugins are applied in the order they are defined. + * + * Today, there are two kinds of hooks: + * - `onLoad` lets you return source code or an object that will become the module's exports + * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. + * + * Plugin hooks must define a `filter` RegExp and will only be matched if the + * import specifier contains a "." or a ":". + * + * ES Module resolution semantics mean that plugins may be initialized _after_ + * a module is resolved. You might need to load plugins at the very beginning + * of the application and then use a dynamic import to load the rest of the + * application. A future version of Bun may also support specifying plugins + * via `bunfig.toml`. + * + * @example + * A YAML loader plugin + * + * ```js + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) + * })); + * }); + * + * // You can use require() + * const {foo} = require("./file.yaml"); + * + * // Or import + * await import("./file.yaml"); + * + * ``` + */ + interface BunRegisterPlugin { + (options: T): ReturnType; + + /** + * Deactivate all plugins + * + * This prevents registered plugins from being applied to future builds. + */ + clearAll(): void; + } + + const plugin: BunRegisterPlugin; + + /** + * Is the current global scope the main thread? + */ + const isMainThread: boolean; + + /** + * Used when importing an HTML file at runtime. + * + * @example + * + * ```ts + * import app from "./index.html"; + * ``` + * + * Bun.build support for this isn't imlpemented yet. + */ + interface HTMLBundle { + index: string; + } + + interface Socket extends Disposable { + /** + * Write `data` to the socket + * + * @param data The data to write to the socket + * @param byteOffset The offset in the buffer to start writing from (defaults to 0) + * @param byteLength The number of bytes to write (defaults to the length of the buffer) + * + * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. + * + * This is unbuffered as of Bun v0.2.2. That means individual write() calls + * will be slow. In the future, Bun will buffer writes and flush them at the + * end of the tick, when the event loop is idle, or sooner if the buffer is full. + */ + write( + data: string | Bun.BufferSource, + byteOffset?: number, + byteLength?: number, + ): number; + + /** + * The data context for the socket. + */ + data: Data; + + /** + * Like {@link Socket.write} except it includes a TCP FIN packet + * + * Use it to send your last message and close the connection. + */ + end( + data?: string | Bun.BufferSource, + byteOffset?: number, + byteLength?: number, + ): number; + + /** + * Close the socket immediately + */ + end(): void; + + /** + * Keep Bun's process alive at least until this socket is closed + * + * After the socket has closed, the socket is unref'd, the process may exit, + * and this becomes a no-op + */ + ref(): void; + + /** + * Set a timeout until the socket automatically closes. + * + * To reset the timeout, call this function again. + * + * When a timeout happens, the `timeout` callback is called and the socket is closed. + */ + timeout(seconds: number): void; + + /** + * Forcefully close the socket. The other end may not receive all data, and + * the socket will be closed immediately. + * + * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to + * `0` and then calls `close(2)`. + */ + terminate(): void; + + /** + * Shutdown writes to a socket + * + * This makes the socket a half-closed socket. It can still receive data. + * + * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally + */ + shutdown(halfClose?: boolean): void; + + readonly readyState: "open" | "closing" | "closed"; + + /** + * Allow Bun's process to exit even if this socket is still open + * + * After the socket has closed, this function does nothing. + */ + unref(): void; + + /** + * Flush any buffered data to the socket + */ + flush(): void; + + /** + * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. + * + * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. + */ + reload(handler: SocketHandler): void; + + /** + * Get the server that created this socket + * + * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. + */ + readonly listener?: SocketListener; + + /** + * Remote IP address connected to the socket + */ + readonly remoteAddress: string; + + /** + * local port connected to the socket + */ + readonly localPort: number; + + /** + * This property is `true` if the peer certificate was signed by one of the CAs + * specified when creating the `Socket` instance, otherwise `false`. + */ + readonly authorized: boolean; + + /** + * String containing the selected ALPN protocol. + * Before a handshake has completed, this value is always null. + * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. + */ + readonly alpnProtocol: string | false | null; + + /** + * Disables TLS renegotiation for this `Socket` instance. Once called, attempts + * to renegotiate will trigger an `error` handler on the `Socket`. + * + * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) + */ + disableRenegotiation(): void; + + /** + * Keying material is used for validations to prevent different kind of attacks in + * network protocols, for example in the specifications of IEEE 802.1X. + * + * Example + * + * ```js + * const keyingMaterial = socket.exportKeyingMaterial( + * 128, + * 'client finished'); + * + * /* + * Example return value of keyingMaterial: + * + * + * ``` + * + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the [IANA Exporter Label + * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context Optionally provide a context. + * @return requested bytes of the keying material + */ + exportKeyingMaterial( + length: number, + label: string, + context: Buffer, + ): Buffer; + + /** + * Returns the reason why the peer's certificate was not been verified. This + * property is set only when `socket.authorized === false`. + */ + getAuthorizationError(): Error | null; + + /** + * Returns an object representing the local certificate. The returned object has + * some properties corresponding to the fields of the certificate. + * + * If there is no local certificate, an empty object will be returned. If the + * socket has been destroyed, `null` will be returned. + */ + getCertificate(): PeerCertificate | object | null; + getX509Certificate(): X509Certificate | undefined; + + /** + * Returns an object containing information on the negotiated cipher suite. + * + * For example, a TLSv1.2 protocol with AES256-SHA cipher: + * + * ```json + * { + * "name": "AES256-SHA", + * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", + * "version": "SSLv3" + * } + * ``` + * + */ + getCipher(): CipherNameAndProtocol; + + /** + * Returns an object representing the type, name, and size of parameter of + * an ephemeral key exchange in `perfect forward secrecy` on a client + * connection. It returns an empty object when the key exchange is not + * ephemeral. As this is only supported on a client socket; `null` is returned + * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. + * + * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. + */ + getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; + + /** + * Returns an object representing the peer's certificate. If the peer does not + * provide a certificate, an empty object will be returned. If the socket has been + * destroyed, `null` will be returned. + * + * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's + * certificate. + * @return A certificate object. + */ + getPeerCertificate(): PeerCertificate; + getPeerX509Certificate(): X509Certificate; + + /** + * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. + * @since v12.11.0 + * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. + */ + getSharedSigalgs(): string[]; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. + */ + getTLSFinishedMessage(): Buffer | undefined; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so + * far. + */ + getTLSPeerFinishedMessage(): Buffer | undefined; + + /** + * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. + * + * It may be useful for debugging. + * + * See `Session Resumption` for more information. + */ + getTLSTicket(): Buffer | undefined; + + /** + * Returns a string containing the negotiated SSL/TLS protocol version of the + * current connection. The value `'unknown'` will be returned for connected + * sockets that have not completed the handshaking process. The value `null` will + * be returned for server sockets or disconnected client sockets. + * + * Protocol versions are: + * + * * `'SSLv3'` + * * `'TLSv1'` + * * `'TLSv1.1'` + * * `'TLSv1.2'` + * * `'TLSv1.3'` + * + */ + getTLSVersion(): string; + + /** + * See `Session Resumption` for more information. + * @return `true` if the session was reused, `false` otherwise. + */ + isSessionReused(): boolean; + + /** + * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. + * Returns `true` if setting the limit succeeded; `false` otherwise. + * + * Smaller fragment sizes decrease the buffering latency on the client: larger + * fragments are buffered by the TLS layer until the entire fragment is received + * and its integrity is verified; large fragments can span multiple roundtrips + * and their processing can be delayed due to packet loss or reordering. However, + * smaller fragments add extra TLS framing bytes and CPU overhead, which may + * decrease overall server throughput. + * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. + */ + setMaxSendFragment(size: number): boolean; + + /** + * Enable/disable the use of Nagle's algorithm. + * Only available for already connected sockets, will return false otherwise + * @param noDelay Default: `true` + * @returns true if is able to setNoDelay and false if it fails. + */ + setNoDelay(noDelay?: boolean): boolean; + + /** + * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. + * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. + * Only available for already connected sockets, will return false otherwise. + * + * Enabling the keep-alive functionality will set the following socket options: + * SO_KEEPALIVE=1 + * TCP_KEEPIDLE=initialDelay + * TCP_KEEPCNT=10 + * TCP_KEEPINTVL=1 + * @param enable Default: `false` + * @param initialDelay Default: `0` + * @returns true if is able to setNoDelay and false if it fails. + */ + setKeepAlive(enable?: boolean, initialDelay?: number): boolean; + + /** + * The number of bytes written to the socket. + */ + readonly bytesWritten: number; + } + + interface SocketListener extends Disposable { + stop(closeActiveConnections?: boolean): void; + ref(): void; + unref(): void; + reload(options: Pick, "socket">): void; + data: Data; + } + interface TCPSocketListener extends SocketListener { + readonly port: number; + readonly hostname: string; + } + interface UnixSocketListener extends SocketListener { + readonly unix: string; + } + + interface TCPSocket extends Socket {} + interface TLSSocket extends Socket {} + + interface BinaryTypeList { + arraybuffer: ArrayBuffer; + buffer: Buffer; + uint8array: Uint8Array; + // TODO: DataView + // dataview: DataView; + } + type BinaryType = keyof BinaryTypeList; + + interface SocketHandler< + Data = unknown, + DataBinaryType extends BinaryType = "buffer", + > { + /** + * Is called when the socket connects, or in case of TLS if no handshake is provided + * this will be called only after handshake + * @param socket + */ + open?(socket: Socket): void | Promise; + close?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + ): void | Promise; + drain?(socket: Socket): void | Promise; + + /** + * When handshake is completed, this functions is called. + * @param socket + * @param success Indicates if the server authorized despite the authorizationError. + * @param authorizationError Certificate Authorization Error or null. + */ + handshake?( + socket: Socket, + success: boolean, + authorizationError: Error | null, + ): void; + + /** + * When the socket has been shutdown from the other end, this function is + * called. This is a TCP FIN packet. + */ + end?(socket: Socket): void | Promise; + + /** + * When the socket fails to be created, this function is called. + * + * The promise returned by `Bun.connect` rejects **after** this function is + * called. + * + * When `connectError` is specified, the rejected promise will not be + * added to the promise rejection queue (so it won't be reported as an + * unhandled promise rejection, since connectError handles it). + * + * When `connectError` is not specified, the rejected promise will be added + * to the promise rejection queue. + */ + connectError?(socket: Socket, error: Error): void | Promise; + + /** + * Called when a message times out. + */ + timeout?(socket: Socket): void | Promise; + /** + * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. + * + * @default "buffer" + * + * @remarks + * This lets you select the desired binary type for the `data` callback. + * It's a small performance optimization to let you avoid creating extra + * ArrayBufferView objects when possible. + * + * Bun originally defaulted to `Uint8Array` but when dealing with network + * data, it's more useful to be able to directly read from the bytes which + * `Buffer` allows. + */ + binaryType?: BinaryType; + } + + interface SocketOptions { + socket: SocketHandler; + data?: Data; + } + // interface TCPSocketOptions extends SocketOptions { + // hostname: string; + // port: number; + // } + + interface TCPSocketListenOptions + extends SocketOptions { + hostname: string; + port: number; + tls?: TLSOptions; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface TCPSocketConnectOptions + extends SocketOptions { + hostname: string; + port: number; + tls?: boolean; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface UnixSocketOptions extends SocketOptions { + tls?: TLSOptions; + unix: string; + } + + interface FdSocketOptions extends SocketOptions { + tls?: TLSOptions; + fd: number; + } + + /** + * Create a TCP client that connects to a server + * + * @param options The options to use when creating the client + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function connect( + options: TCPSocketConnectOptions, + ): Promise>; + function connect( + options: UnixSocketOptions, + ): Promise>; + + /** + * Create a TCP server that listens on a port + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function listen( + options: TCPSocketListenOptions, + ): TCPSocketListener; + function listen( + options: UnixSocketOptions, + ): UnixSocketListener; + + namespace udp { + type Data = string | ArrayBufferView | ArrayBufferLike; + + export interface SocketHandler { + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: Socket): void | Promise; + error?( + socket: Socket, + error: Error, + ): void | Promise; + } + + export interface ConnectedSocketHandler { + data?( + socket: ConnectedSocket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: ConnectedSocket): void | Promise; + error?( + socket: ConnectedSocket, + error: Error, + ): void | Promise; + } + + export interface SocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: SocketHandler; + } + + export interface ConnectSocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: ConnectedSocketHandler; + connect: { + hostname: string; + port: number; + }; + } + + export interface BaseUDPSocket { + readonly hostname: string; + readonly port: number; + readonly address: SocketAddress; + readonly binaryType: BinaryType; + readonly closed: boolean; + ref(): void; + unref(): void; + close(): void; + } + + export interface ConnectedSocket + extends BaseUDPSocket { + readonly remoteAddress: SocketAddress; + sendMany(packets: readonly Data[]): number; + send(data: Data): boolean; + reload(handler: ConnectedSocketHandler): void; + } + + export interface Socket + extends BaseUDPSocket { + sendMany(packets: readonly (Data | string | number)[]): number; + send(data: Data, port: number, address: string): boolean; + reload(handler: SocketHandler): void; + } + } + + /** + * Create a UDP socket + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.hostname The hostname to listen on + * @param options.port The port to listen on + * @param options.binaryType The binary type to use for the socket + * @param options.connect The hostname and port to connect to + */ + export function udpSocket( + options: udp.SocketOptions, + ): Promise>; + export function udpSocket( + options: udp.ConnectSocketOptions, + ): Promise>; + + namespace SpawnOptions { + /** + * Option for stdout/stderr + */ + type Readable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number; + + /** + * Option for stdin + */ + type Writable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number + | ReadableStream + | Blob + | Response + | Request; + + interface OptionsObject< + In extends Writable = Writable, + Out extends Readable = Readable, + Err extends Readable = Readable, + > { + /** + * The current working directory of the process + * + * Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * The environment variables of the process + * + * Defaults to `process.env` as it was when the current Bun process launched. + * + * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. + */ + env?: Record; + + /** + * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. + * This overrides the `stdin`, `stdout`, and `stderr` properties. + * + * For stdin you may pass: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. + * - `number`: The process will read from the file descriptor + * + * For stdout and stdin you may pass: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default ["ignore", "pipe", "inherit"] for `spawn` + * ["ignore", "pipe", "pipe"] for `spawnSync` + */ + stdio?: [In, Out, Err]; + /** + * The file descriptor for the standard input. It may be: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`: The process will read from the buffer + * - `number`: The process will read from the file descriptor + * + * @default "ignore" + */ + stdin?: In; + /** + * The file descriptor for the standard output. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "pipe" + */ + stdout?: Out; + /** + * The file descriptor for the standard error. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "inherit" for `spawn` + * "pipe" for `spawnSync` + */ + stderr?: Err; + + /** + * Callback that runs when the {@link Subprocess} exits + * + * This is called even if the process exits with a non-zero exit code. + * + * Warning: this may run before the `Bun.spawn` function returns. + * + * A simple alternative is `await subprocess.exited`. + * + * @example + * + * ```ts + * const subprocess = spawn({ + * cmd: ["echo", "hello"], + * onExit: (subprocess, code) => { + * console.log(`Process exited with code ${code}`); + * }, + * }); + * ``` + */ + onExit?( + subprocess: Subprocess, + exitCode: number | null, + signalCode: number | null, + /** + * If an error occurred in the call to waitpid2, this will be the error. + */ + error?: ErrorLike, + ): void | Promise; + + /** + * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for + * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized + * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + * + * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, + * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. + * + * Currently, this is only compatible with processes that are other `bun` instances. + */ + ipc?( + message: any, + /** + * The {@link Subprocess} that sent the message + */ + subprocess: Subprocess, + ): void; + + /** + * The serialization format to use for IPC messages. Defaults to `"advanced"`. + * + * To communicate with Node.js processes, use `"json"`. + * + * When `ipc` is not specified, this is ignored. + */ + serialization?: "json" | "advanced"; + + /** + * If true, the subprocess will have a hidden window. + */ + windowsHide?: boolean; + + /** + * If true, no quoting or escaping of arguments is done on Windows. + */ + windowsVerbatimArguments?: boolean; + + /** + * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. + * + * One use-case for this is for applications which wrap other applications or to simulate a symlink. + * + * @default cmds[0] + */ + argv0?: string; + + /** + * An {@link AbortSignal} that can be used to abort the subprocess. + * + * This is useful for aborting a subprocess when some other part of the + * program is aborted, such as a `fetch` response. + * + * Internally, this works by calling `subprocess.kill(1)`. + * + * @example + * ```ts + * const controller = new AbortController(); + * const { signal } = controller; + * const start = performance.now(); + * const subprocess = Bun.spawn({ + * cmd: ["sleep", "100"], + * signal, + * }); + * await Bun.sleep(1); + * controller.abort(); + * await subprocess.exited; + * const end = performance.now(); + * console.log(end - start); // 1ms instead of 101ms + * ``` + */ + signal?: AbortSignal; + } + + type OptionsToSubprocess = + Opts extends OptionsObject + ? Subprocess< + // "Writable extends In" means "if In === Writable", + // aka if true that means the user didn't specify anything + Writable extends In ? "ignore" : In, + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "inherit" : Err + > + : Subprocess; + + type OptionsToSyncSubprocess = + Opts extends OptionsObject + ? SyncSubprocess< + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "pipe" : Err + > + : SyncSubprocess; + + type ReadableIO = ReadableStream | number | undefined; + + type ReadableToIO = X extends "pipe" | undefined + ? ReadableStream + : X extends BunFile | ArrayBufferView | number + ? number + : undefined; + + type ReadableToSyncIO = X extends "pipe" | undefined + ? Buffer + : undefined; + + type WritableIO = FileSink | number | undefined; + + type WritableToIO = X extends "pipe" + ? FileSink + : X extends BunFile | ArrayBufferView | Blob | Request | Response | number + ? number + : undefined; + } + + interface ResourceUsage { + /** + * The number of voluntary and involuntary context switches that the process made. + */ + contextSwitches: { + /** + * Voluntary context switches (context switches that the process initiated). + */ + voluntary: number; + /** + * Involuntary context switches (context switches initiated by the system scheduler). + */ + involuntary: number; + }; + + /** + * The amount of CPU time used by the process, in microseconds. + */ + cpuTime: { + /** + * User CPU time used by the process, in microseconds. + */ + user: number; + /** + * System CPU time used by the process, in microseconds. + */ + system: number; + /** + * Total CPU time used by the process, in microseconds. + */ + total: number; + }; + /** + * The maximum amount of resident set size (in bytes) used by the process during its lifetime. + */ + maxRSS: number; + + /** + * IPC messages sent and received by the process. + */ + messages: { + /** + * The number of IPC messages sent. + */ + sent: number; + /** + * The number of IPC messages received. + */ + received: number; + }; + /** + * The number of IO operations done by the process. + */ + ops: { + /** + * The number of input operations via the file system. + */ + in: number; + /** + * The number of output operations via the file system. + */ + out: number; + }; + /** + * The amount of shared memory that the process used. + */ + shmSize: number; + /** + * The number of signals delivered to the process. + */ + signalCount: number; + /** + * The number of times the process was swapped out of main memory. + */ + swapCount: number; + } + + /** + * A process created by {@link Bun.spawn}. + * + * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSubprocess} (any, pipe, pipe) + * - {@link WritableSubprocess} (pipe, any, any) + * - {@link PipedSubprocess} (pipe, pipe, pipe) + * - {@link NullSubprocess} (ignore, ignore, ignore) + */ + interface Subprocess< + In extends SpawnOptions.Writable = SpawnOptions.Writable, + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > extends AsyncDisposable { + readonly stdin: SpawnOptions.WritableToIO; + readonly stdout: SpawnOptions.ReadableToIO; + readonly stderr: SpawnOptions.ReadableToIO; + + /** + * This returns the same value as {@link Subprocess.stdout} + * + * It exists for compatibility with {@link ReadableStream.pipeThrough} + */ + readonly readable: SpawnOptions.ReadableToIO; + + /** + * The process ID of the child process + * @example + * ```ts + * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); + * console.log(pid); // 1234 + * ``` + */ + readonly pid: number; + /** + * The exit code of the process + * + * The promise will resolve when the process exits + */ + readonly exited: Promise; + + /** + * Synchronously get the exit code of the process + * + * If the process hasn't exited yet, this will return `null` + */ + readonly exitCode: number | null; + + /** + * Synchronously get the signal code of the process + * + * If the process never sent a signal code, this will return `null` + * + * To receive signal code changes, use the `onExit` callback. + * + * If the signal code is unknown, it will return the original signal code + * number, but that case should essentially never happen. + */ + readonly signalCode: NodeJS.Signals | null; + + /** + * Has the process exited? + */ + readonly killed: boolean; + + /** + * Kill the process + * @param exitCode The exitCode to send to the process + */ + kill(exitCode?: number | NodeJS.Signals): void; + + /** + * This method will tell Bun to wait for this process to exit after you already + * called `unref()`. + * + * Before shutting down, Bun will wait for all subprocesses to exit by default + */ + ref(): void; + + /** + * Before shutting down, Bun will wait for all subprocesses to exit by default + * + * This method will tell Bun to not wait for this process to exit before shutting down. + */ + unref(): void; + + /** + * Send a message to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option, and is another instance of `bun`. + * + * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + */ + send(message: any): void; + + /** + * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option. + */ + disconnect(): void; + + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + * + * Only available after the process has exited + * + * If the process hasn't exited yet, this will return `undefined` + */ + resourceUsage(): ResourceUsage | undefined; + } + + /** + * A process created by {@link Bun.spawnSync}. + * + * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSyncSubprocess} (pipe, pipe) + * - {@link NullSyncSubprocess} (ignore, ignore) + */ + interface SyncSubprocess< + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > { + stdout: SpawnOptions.ReadableToSyncIO; + stderr: SpawnOptions.ReadableToSyncIO; + exitCode: number; + success: boolean; + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + */ + resourceUsage: ResourceUsage; + + signalCode?: string; + } + + /** + * Spawn a new process + * + * ```js + * const subprocess = Bun.spawn({ + * cmd: ["echo", "hello"], + * stdout: "pipe", + * }); + * const text = await readableStreamToText(subprocess.stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmd: string[]; // to support dynamically constructed commands + }, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawn(["echo", "hello"]); + * const text = await readableStreamToText(stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync({ + * cmd: ["echo", "hello"], + * }); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); + * ``` + */ + cmd: string[]; + + onExit?: never; + }, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** + * Synchronously spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync(["echo", "hello"]); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ + type ReadableSubprocess = Subprocess; + /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ + type WritableSubprocess = Subprocess<"pipe", any, any>; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ + type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ + type NullSubprocess = Subprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ + type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ + type NullSyncSubprocess = SyncSubprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + + // Blocked on https://github.com/oven-sh/bun/issues/8329 + // /** + // * + // * Count the visible width of a string, as it would be displayed in a terminal. + // * + // * By default, strips ANSI escape codes before measuring the string. This is + // * because ANSI escape codes are not visible characters. If passed a non-string, + // * it will return 0. + // * + // * @param str The string to measure + // * @param options + // */ + // function stringWidth( + // str: string, + // options?: { + // /** + // * Whether to include ANSI escape codes in the width calculation + // * + // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. + // * @default false + // */ + // countAnsiEscapeCodes?: boolean; + // }, + // ): number; + + class FileSystemRouter { + /** + * Create a new {@link FileSystemRouter}. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: process.cwd() + "/pages", + * style: "nextjs", + * }); + * + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} + * ``` + * @param options The options to use when creating the router + * @param options.dir The root directory containing the files to route + * @param options.style The style of router to use (only "nextjs" supported + * for now) + */ + constructor(options: { + /** + * The root directory containing the files to route + * + * There is no default value for this option. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: + */ + dir: string; + style: "nextjs"; + + /** The base path to use when routing */ + assetPrefix?: string; + origin?: string; + /** Limit the pages to those with particular file extensions. */ + fileExtensions?: string[]; + }); + + // todo: URL + match(input: string | Request | Response): MatchedRoute | null; + + readonly assetPrefix: string; + readonly origin: string; + readonly style: string; + readonly routes: Record; + + reload(): void; + } + + interface MatchedRoute { + /** + * A map of the parameters from the route + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: "/path/to/files", + * style: "nextjs", + * }); + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params.year); // "2020" + * console.log(params.month); // "01" + * console.log(params.day); // "01" + * console.log(params.slug); // "hello-world" + * ``` + */ + readonly params: Record; + readonly filePath: string; + readonly pathname: string; + readonly query: Record; + readonly name: string; + readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; + readonly src: string; + } + + /** + * The current version of Bun + * @example + * "0.2.0" + */ + const version: string; + + /** + * The current version of Bun with the shortened commit sha of the build + * @example "v1.1.30 (d09df1af)" + */ + const version_with_sha: string; + + /** + * The git sha at the time the currently-running version of Bun was compiled + * @example + * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" + */ + const revision: string; + + /** + * Find the index of a newline character in potentially ill-formed UTF-8 text. + * + * This is sort of like readline() except without the IO. + */ + function indexOfLine( + buffer: ArrayBufferView | ArrayBufferLike, + offset?: number, + ): number; + + interface GlobScanOptions { + /** + * The root directory to start matching from. Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * Allow patterns to match entries that begin with a period (`.`). + * + * @default false + */ + dot?: boolean; + + /** + * Return the absolute path for entries. + * + * @default false + */ + absolute?: boolean; + + /** + * Indicates whether to traverse descendants of symbolic link directories. + * + * @default false + */ + followSymlinks?: boolean; + + /** + * Throw an error when symbolic link is broken + * + * @default false + */ + throwErrorOnBrokenSymlink?: boolean; + + /** + * Return only files. + * + * @default true + */ + onlyFiles?: boolean; + } + + /** + * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). + * + * The supported pattern syntax for is: + * + * - `?` + * Matches any single character. + * - `*` + * Matches zero or more characters, except for path separators ('/' or '\'). + * - `**` + * Matches zero or more characters, including path separators. + * Must match a complete path segment, i.e. followed by a path separator or + * at the end of the pattern. + * - `[ab]` + * Matches one of the characters contained in the brackets. + * Character ranges (e.g. "[a-z]") are also supported. + * Use "[!ab]" or "[^ab]" to match any character *except* those contained + * in the brackets. + * - `{a,b}` + * Match one of the patterns contained in the braces. + * Any of the wildcards listed above can be used in the sub patterns. + * Braces may be nested up to 10 levels deep. + * - `!` + * Negates the result when at the start of the pattern. + * Multiple "!" characters negate the pattern multiple times. + * - `\` + * Used to escape any of the special characters above. + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + */ + export class Glob { + constructor(pattern: string); + + /** + * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for await (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scan( + optionsOrCwd?: string | GlobScanOptions, + ): AsyncIterableIterator; + + /** + * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; + + /** + * Match the glob against a string + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * expect(glob.match('foo.ts')).toBeTrue(); + * ``` + */ + match(str: string): boolean; + } + + /** + * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. + * + * When the same timestamp is used multiple times, a monotonically increasing + * counter is appended to allow sorting. The final 8 bytes are + * cryptographically random. When the timestamp changes, the counter resets to + * a psuedo-random integer. + * + * @param encoding "hex" | "base64" | "base64url" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + * + * @example + * ```js + * import { randomUUIDv7 } from "bun"; + * const array = [ + * randomUUIDv7(), + * randomUUIDv7(), + * randomUUIDv7(), + * ] + * [ + * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", + * "0192ce07-8c4f-7d67-805f-0f71581b5622", + * "0192ce07-8c4f-7d68-8170-6816e4451a58" + * ] + * ``` + */ + function randomUUIDv7( + /** + * @default "hex" + */ + encoding?: "hex" | "base64" | "base64url", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): string; + + /** + * Generate a UUIDv7 as a Buffer + * + * @param encoding "buffer" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + */ + function randomUUIDv7( + encoding: "buffer", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): Buffer; + + /** + * Types for `bun.lock` + */ + type BunLockFile = { + lockfileVersion: 0 | 1; + workspaces: { + [workspace: string]: BunLockFileWorkspacePackage; + }; + overrides?: Record; + patchedDependencies?: Record; + trustedDependencies?: string[]; + + /** + * ``` + * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } + * + * // first index is resolution for each type of package + * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] + * symlink -> [ "name@link:path", INFO ] + * folder -> [ "name@file:path", INFO ] + * workspace -> [ "name@workspace:path" ] // workspace is only path + * tarball -> [ "name@tarball", INFO ] + * root -> [ "name@root:", { bin, binDir } ] + * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] + * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] + * ``` + * */ + packages: { + [pkg: string]: BunLockFilePackageArray; + }; + }; + + type BunLockFileBasePackageInfo = { + dependencies?: Record; + devDependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; + optionalPeers?: string[]; + bin?: string | Record; + binDir?: string; + }; + + type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { + name?: string; + version?: string; + }; + + type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { + os?: string | string[]; + cpu?: string | string[]; + bundled?: true; + }; + + /** @see {@link BunLockFile.packages} for more info */ + type BunLockFilePackageArray = + /** npm */ + | [ + pkg: string, + registry: string, + info: BunLockFilePackageInfo, + integrity: string, + ] + /** symlink, folder, tarball */ + | [pkg: string, info: BunLockFilePackageInfo] + /** workspace */ + | [pkg: string] + /** git, github */ + | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] + /** root */ + | [pkg: string, info: Pick]; } diff --git a/packages/bun-types/deprecated.d.ts b/packages/bun-types/deprecated.d.ts index 5a90164689ded8..3eb174db4ded5a 100644 --- a/packages/bun-types/deprecated.d.ts +++ b/packages/bun-types/deprecated.d.ts @@ -1,66 +1,71 @@ declare module "bun" { - /** - * @deprecated Renamed to `ErrorLike` - */ - type Errorlike = ErrorLike; - interface TLSOptions { - /** - * File path to a TLS key - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. - */ - keyFile?: string; - /** - * File path to a TLS certificate - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. - */ - certFile?: string; - /** - * File path to a .pem file for a custom root CA - * - * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. - */ - caFile?: string; - } + /** + * @deprecated Renamed to `ErrorLike` + */ + type Errorlike = ErrorLike; + interface TLSOptions { + /** + * File path to a TLS key + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. + */ + keyFile?: string; + /** + * File path to a TLS certificate + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. + */ + certFile?: string; + /** + * File path to a .pem file for a custom root CA + * + * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. + */ + caFile?: string; + } } declare namespace NodeJS { - interface Process { - /** - * @deprecated This is deprecated; use the "node:assert" module instead. - */ - assert(value: unknown, message?: string | Error): asserts value; - } + interface Process { + /** + * @deprecated This is deprecated; use the "node:assert" module instead. + */ + assert(value: unknown, message?: string | Error): asserts value; + } } declare namespace Bun { - interface MessageEvent { - /** @deprecated */ - initMessageEvent( - type: string, - bubbles?: boolean, - cancelable?: boolean, - data?: any, - origin?: string, - lastEventId?: string, - source?: null, - ): void; - } + interface MessageEvent { + /** @deprecated */ + initMessageEvent( + type: string, + bubbles?: boolean, + cancelable?: boolean, + data?: any, + origin?: string, + lastEventId?: string, + source?: null, + ): void; + } } interface CustomEvent { - /** @deprecated */ - initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void; + /** @deprecated */ + initCustomEvent( + type: string, + bubbles?: boolean, + cancelable?: boolean, + detail?: T, + ): void; } interface DOMException { - /** @deprecated */ - readonly code: number; + /** @deprecated */ + readonly code: number; } /** diff --git a/packages/bun-types/devserver.d.ts b/packages/bun-types/devserver.d.ts index a6ff7d1437b34b..e6b44c040f7127 100644 --- a/packages/bun-types/devserver.d.ts +++ b/packages/bun-types/devserver.d.ts @@ -1,24 +1,24 @@ export {}; declare global { - interface ImportMeta { - /** - * Hot module replacement - * - * https://bun.sh/docs/bundler/fullstack - */ - hot: { - /** - * import.meta.hot.data maintains state between module instances during hot replacement, enabling data transfer from previous to new versions. - * - * @example - * ```ts - * import.meta.hot.data = { - * bun: 'is cool', - * }; - * ``` - */ - data: any; - }; - } + interface ImportMeta { + /** + * Hot module replacement + * + * https://bun.sh/docs/bundler/fullstack + */ + hot: { + /** + * import.meta.hot.data maintains state between module instances during hot replacement, enabling data transfer from previous to new versions. + * + * @example + * ```ts + * import.meta.hot.data = { + * bun: 'is cool', + * }; + * ``` + */ + data: any; + }; + } } diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 58e138bbad8c93..599ffa198190b9 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,114 +1,119 @@ interface Headers { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; } var Headers: { - prototype: Headers; - new (init?: Bun.HeadersInit): Headers; + prototype: Headers; + new (init?: Bun.HeadersInit): Headers; }; interface Request { - headers: Headers; + headers: Headers; } var Request: { - prototype: Request; - new (requestInfo: string, requestInit?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, requestInit?: RequestInit): Request; + prototype: Request; + new (requestInfo: string, requestInit?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, requestInit?: RequestInit): Request; }; var Response: { - new (body?: Bun.BodyInit | null | undefined, init?: Bun.ResponseInit | undefined): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: Bun.ResponseInit | number): Response; + new ( + body?: Bun.BodyInit | null | undefined, + init?: Bun.ResponseInit | undefined, + ): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, options?: Bun.ResponseInit | number): Response; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, status?: number): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, status?: number): Response; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, options?: Bun.ResponseInit): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, options?: Bun.ResponseInit): Response; - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; }; type _BunTLSOptions = import("bun").TLSOptions; interface BunFetchRequestInitTLS extends _BunTLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable; + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable< + import("node:tls").ConnectionOptions["checkServerIdentity"] + >; } /** @@ -119,43 +124,46 @@ interface BunFetchRequestInitTLS extends _BunTLSOptions { * if passed to `new Request()`. This is why it's a separate type. */ interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; + /** + * Override the default TLS options + */ + tls?: BunFetchRequestInitTLS; } var fetch: { - /** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ - (request: Request, init?: BunFetchRequestInit): Promise; + /** + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ + (request: Request, init?: BunFetchRequestInit): Promise; - /** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ - (url: string | URL | Request, init?: BunFetchRequestInit): Promise; + /** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ + (url: string | URL | Request, init?: BunFetchRequestInit): Promise; - (input: string | URL | globalThis.Request, init?: BunFetchRequestInit): Promise; + ( + input: string | URL | globalThis.Request, + init?: BunFetchRequestInit, + ): Promise; - /** - * Start the DNS resolution, TCP connection, and TLS handshake for a request - * before the request is actually sent. - * - * This can reduce the latency of a request when you know there's some - * long-running task that will delay the request starting. - * - * This is a bun-specific API and is not part of the Fetch API specification. - */ - preconnect(url: string | URL): void; + /** + * Start the DNS resolution, TCP connection, and TLS handshake for a request + * before the request is actually sent. + * + * This can reduce the latency of a request when you know there's some + * long-running task that will delay the request starting. + * + * This is a bun-specific API and is not part of the Fetch API specification. + */ + preconnect(url: string | URL): void; }; diff --git a/packages/bun-types/ffi.d.ts b/packages/bun-types/ffi.d.ts index 1f0c1ffdfe8b78..c705348c8298bf 100644 --- a/packages/bun-types/ffi.d.ts +++ b/packages/bun-types/ffi.d.ts @@ -15,1144 +15,1162 @@ * goes to Fabrice Bellard and TinyCC maintainers for making this possible. */ declare module "bun:ffi" { - enum FFIType { - char = 0, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int8_t = 1, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i8 = 1, + enum FFIType { + char = 0, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int8_t = 1, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i8 = 1, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint8_t = 2, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u8 = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint8_t = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u8 = 2, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int16_t = 3, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i16 = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int16_t = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i16 = 3, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint16_t = 4, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u16 = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint16_t = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u16 = 4, - /** - * 32-bit signed integer - */ - int32_t = 5, + /** + * 32-bit signed integer + */ + int32_t = 5, - /** - * 32-bit signed integer - * - * Alias of {@link FFIType.int32_t} - */ - i32 = 5, - /** - * 32-bit signed integer - * - * The same as `int` in C - * - * ```c - * int - * ``` - */ - int = 5, + /** + * 32-bit signed integer + * + * Alias of {@link FFIType.int32_t} + */ + i32 = 5, + /** + * 32-bit signed integer + * + * The same as `int` in C + * + * ```c + * int + * ``` + */ + int = 5, - /** - * 32-bit unsigned integer - * - * The same as `unsigned int` in C (on x64 & arm64) - * - * C: - * ```c - * unsigned int - * ``` - * JavaScript: - * ```js - * ptr(new Uint32Array(1)) - * ``` - */ - uint32_t = 6, - /** - * 32-bit unsigned integer - * - * Alias of {@link FFIType.uint32_t} - */ - u32 = 6, + /** + * 32-bit unsigned integer + * + * The same as `unsigned int` in C (on x64 & arm64) + * + * C: + * ```c + * unsigned int + * ``` + * JavaScript: + * ```js + * ptr(new Uint32Array(1)) + * ``` + */ + uint32_t = 6, + /** + * 32-bit unsigned integer + * + * Alias of {@link FFIType.uint32_t} + */ + u32 = 6, - /** - * int64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - int64_t = 7, - /** - * i64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - i64 = 7, + /** + * int64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + int64_t = 7, + /** + * i64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + i64 = 7, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - uint64_t = 8, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - u64 = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + uint64_t = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + u64 = 8, - /** - * Doubles are not supported yet! - */ - double = 9, - /** - * Doubles are not supported yet! - */ - f64 = 9, - /** - * Floats are not supported yet! - */ - float = 10, - /** - * Floats are not supported yet! - */ - f32 = 10, + /** + * Doubles are not supported yet! + */ + double = 9, + /** + * Doubles are not supported yet! + */ + f64 = 9, + /** + * Floats are not supported yet! + */ + float = 10, + /** + * Floats are not supported yet! + */ + f32 = 10, - /** - * Boolean value - * - * Must be `true` or `false`. `0` and `1` type coercion is not supported. - * - * In C, this corresponds to: - * ```c - * bool - * _Bool - * ``` - */ - bool = 11, + /** + * Boolean value + * + * Must be `true` or `false`. `0` and `1` type coercion is not supported. + * + * In C, this corresponds to: + * ```c + * bool + * _Bool + * ``` + */ + bool = 11, - /** - * Pointer value - * - * See {@link Bun.FFI.ptr} for more information - * - * In C: - * ```c - * void* - * ``` - * - * In JavaScript: - * ```js - * ptr(new Uint8Array(1)) - * ``` - */ - ptr = 12, - /** - * Pointer value - * - * alias of {@link FFIType.ptr} - */ - pointer = 12, + /** + * Pointer value + * + * See {@link Bun.FFI.ptr} for more information + * + * In C: + * ```c + * void* + * ``` + * + * In JavaScript: + * ```js + * ptr(new Uint8Array(1)) + * ``` + */ + ptr = 12, + /** + * Pointer value + * + * alias of {@link FFIType.ptr} + */ + pointer = 12, - /** - * void value - * - * void arguments are not supported - * - * void return type is the default return type - * - * In C: - * ```c - * void - * ``` - */ - void = 13, + /** + * void value + * + * void arguments are not supported + * + * void return type is the default return type + * + * In C: + * ```c + * void + * ``` + */ + void = 13, - /** - * When used as a `returns`, this will automatically become a {@link CString}. - * - * When used in `args` it is equivalent to {@link FFIType.pointer} - */ - cstring = 14, + /** + * When used as a `returns`, this will automatically become a {@link CString}. + * + * When used in `args` it is equivalent to {@link FFIType.pointer} + */ + cstring = 14, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `int64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - i64_fast = 15, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `int64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + i64_fast = 15, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `uint64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - u64_fast = 16, - function = 17, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `uint64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + u64_fast = 16, + function = 17, - napi_env = 18, - napi_value = 19, - buffer = 20, - } + napi_env = 18, + napi_value = 19, + buffer = 20, + } - type Pointer = number & { __pointer__: null }; + type Pointer = number & { __pointer__: null }; - interface FFITypeToArgsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: number | bigint; - [FFIType.i64]: number | bigint; - [FFIType.uint64_t]: number | bigint; - [FFIType.u64]: number | bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.void]: undefined; - [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | JSCallback; // cannot be null - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeToReturnsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: bigint; - [FFIType.i64]: bigint; - [FFIType.uint64_t]: bigint; - [FFIType.u64]: bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: Pointer | null; - [FFIType.pointer]: Pointer | null; - [FFIType.void]: undefined; - [FFIType.cstring]: CString; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | null; - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeStringToType { - ["char"]: FFIType.char; - ["int8_t"]: FFIType.int8_t; - ["i8"]: FFIType.i8; - ["uint8_t"]: FFIType.uint8_t; - ["u8"]: FFIType.u8; - ["int16_t"]: FFIType.int16_t; - ["i16"]: FFIType.i16; - ["uint16_t"]: FFIType.uint16_t; - ["u16"]: FFIType.u16; - ["int32_t"]: FFIType.int32_t; - ["i32"]: FFIType.i32; - ["int"]: FFIType.int; - ["uint32_t"]: FFIType.uint32_t; - ["u32"]: FFIType.u32; - ["int64_t"]: FFIType.int64_t; - ["i64"]: FFIType.i64; - ["uint64_t"]: FFIType.uint64_t; - ["u64"]: FFIType.u64; - ["double"]: FFIType.double; - ["f64"]: FFIType.f64; - ["float"]: FFIType.float; - ["f32"]: FFIType.f32; - ["bool"]: FFIType.bool; - ["ptr"]: FFIType.ptr; - ["pointer"]: FFIType.pointer; - ["void"]: FFIType.void; - ["cstring"]: FFIType.cstring; - ["function"]: FFIType.pointer; // for now - ["usize"]: FFIType.uint64_t; // for now - ["callback"]: FFIType.pointer; // for now - ["napi_env"]: FFIType.napi_env; - ["napi_value"]: FFIType.napi_value; - ["buffer"]: FFIType.buffer; - } + interface FFITypeToArgsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: number | bigint; + [FFIType.i64]: number | bigint; + [FFIType.uint64_t]: number | bigint; + [FFIType.u64]: number | bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.void]: undefined; + [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | JSCallback; // cannot be null + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeToReturnsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: bigint; + [FFIType.i64]: bigint; + [FFIType.uint64_t]: bigint; + [FFIType.u64]: bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: Pointer | null; + [FFIType.pointer]: Pointer | null; + [FFIType.void]: undefined; + [FFIType.cstring]: CString; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | null; + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeStringToType { + ["char"]: FFIType.char; + ["int8_t"]: FFIType.int8_t; + ["i8"]: FFIType.i8; + ["uint8_t"]: FFIType.uint8_t; + ["u8"]: FFIType.u8; + ["int16_t"]: FFIType.int16_t; + ["i16"]: FFIType.i16; + ["uint16_t"]: FFIType.uint16_t; + ["u16"]: FFIType.u16; + ["int32_t"]: FFIType.int32_t; + ["i32"]: FFIType.i32; + ["int"]: FFIType.int; + ["uint32_t"]: FFIType.uint32_t; + ["u32"]: FFIType.u32; + ["int64_t"]: FFIType.int64_t; + ["i64"]: FFIType.i64; + ["uint64_t"]: FFIType.uint64_t; + ["u64"]: FFIType.u64; + ["double"]: FFIType.double; + ["f64"]: FFIType.f64; + ["float"]: FFIType.float; + ["f32"]: FFIType.f32; + ["bool"]: FFIType.bool; + ["ptr"]: FFIType.ptr; + ["pointer"]: FFIType.pointer; + ["void"]: FFIType.void; + ["cstring"]: FFIType.cstring; + ["function"]: FFIType.pointer; // for now + ["usize"]: FFIType.uint64_t; // for now + ["callback"]: FFIType.pointer; // for now + ["napi_env"]: FFIType.napi_env; + ["napi_value"]: FFIType.napi_value; + ["buffer"]: FFIType.buffer; + } - type FFITypeOrString = FFIType | keyof FFITypeStringToType; + type FFITypeOrString = FFIType | keyof FFITypeStringToType; - interface FFIFunction { - /** - * Arguments to a FFI function (C ABI) - * - * Defaults to an empty array, which means no arguments. - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, FFIType, suffix } from "bun:ffi" - * - * const lib = dlopen(`adder.${suffix}`, { - * add: { - * // FFIType can be used or you can pass string labels. - * args: [FFIType.i32, "i32"], - * returns: "i32", - * }, - * }) - * lib.symbols.add(1, 2) - * ``` - * In C: - * ```c - * int add(int a, int b) { - * return a + b; - * } - * ``` - */ - readonly args?: readonly FFITypeOrString[]; - /** - * Return type to a FFI function (C ABI) - * - * Defaults to {@link FFIType.void} - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, CString } from "bun:ffi" - * - * const lib = dlopen('z', { - * version: { - * returns: "ptr", - * } - * }); - * console.log(new CString(lib.symbols.version())); - * ``` - * In C: - * ```c - * char* version() - * { - * return "1.0.0"; - * } - * ``` - */ - readonly returns?: FFITypeOrString; + interface FFIFunction { + /** + * Arguments to a FFI function (C ABI) + * + * Defaults to an empty array, which means no arguments. + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, FFIType, suffix } from "bun:ffi" + * + * const lib = dlopen(`adder.${suffix}`, { + * add: { + * // FFIType can be used or you can pass string labels. + * args: [FFIType.i32, "i32"], + * returns: "i32", + * }, + * }) + * lib.symbols.add(1, 2) + * ``` + * In C: + * ```c + * int add(int a, int b) { + * return a + b; + * } + * ``` + */ + readonly args?: readonly FFITypeOrString[]; + /** + * Return type to a FFI function (C ABI) + * + * Defaults to {@link FFIType.void} + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, CString } from "bun:ffi" + * + * const lib = dlopen('z', { + * version: { + * returns: "ptr", + * } + * }); + * console.log(new CString(lib.symbols.version())); + * ``` + * In C: + * ```c + * char* version() + * { + * return "1.0.0"; + * } + * ``` + */ + readonly returns?: FFITypeOrString; - /** - * Function pointer to the native function - * - * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. - * This pointer should not be null (0). - * - * This is useful if the library has already been loaded - * or if the module is also using Node-API. - */ - readonly ptr?: Pointer | bigint; + /** + * Function pointer to the native function + * + * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. + * This pointer should not be null (0). + * + * This is useful if the library has already been loaded + * or if the module is also using Node-API. + */ + readonly ptr?: Pointer | bigint; - /** - * Can C/FFI code call this function from a separate thread? - * - * Only supported with {@link JSCallback}. - * - * This does not make the function run in a separate thread. It is still up to the application/library - * to run their code in a separate thread. - * - * By default, {@link JSCallback} calls are not thread-safe. Turning this on - * incurs a small performance penalty for every function call. That small - * performance penalty needs to be less than the performance gain from - * running the function in a separate thread. - * - * @default false - */ - readonly threadsafe?: boolean; - } + /** + * Can C/FFI code call this function from a separate thread? + * + * Only supported with {@link JSCallback}. + * + * This does not make the function run in a separate thread. It is still up to the application/library + * to run their code in a separate thread. + * + * By default, {@link JSCallback} calls are not thread-safe. Turning this on + * incurs a small performance penalty for every function call. That small + * performance penalty needs to be less than the performance gain from + * running the function in a separate thread. + * + * @default false + */ + readonly threadsafe?: boolean; + } - type Symbols = Readonly>; + type Symbols = Readonly>; - // /** - // * Compile a callback function - // * - // * Returns a function pointer - // * - // */ - // export function callback(ffi: FFIFunction, cb: Function): number; + // /** + // * Compile a callback function + // * + // * Returns a function pointer + // * + // */ + // export function callback(ffi: FFIFunction, cb: Function): number; - interface Library { - symbols: ConvertFns; + interface Library { + symbols: ConvertFns; - /** - * `dlclose` the library, unloading the symbols and freeing allocated memory. - * - * Once called, the library is no longer usable. - * - * Calling a function from a library that has been closed is undefined behavior. - */ - close(): void; - } + /** + * `dlclose` the library, unloading the symbols and freeing allocated memory. + * + * Once called, the library is no longer usable. + * + * Calling a function from a library that has been closed is undefined behavior. + */ + close(): void; + } - type ToFFIType = T extends FFIType ? T : T extends string ? FFITypeStringToType[T] : never; + type ToFFIType = T extends FFIType + ? T + : T extends string + ? FFITypeStringToType[T] + : never; - const FFIFunctionCallableSymbol: unique symbol; - type ConvertFns = { - [K in keyof Fns]: { - ( - ...args: Fns[K]["args"] extends infer A extends readonly FFITypeOrString[] - ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } - : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [unknown] extends [Fns[K]["args"]] - ? [] - : never - ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - ? undefined - : FFITypeToReturnsType[ToFFIType>]; - __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - }; + const FFIFunctionCallableSymbol: unique symbol; + type ConvertFns = { + [K in keyof Fns]: { + ( + ...args: Fns[K]["args"] extends infer A extends + readonly FFITypeOrString[] + ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } + : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [unknown] extends [Fns[K]["args"]] + ? [] + : never + ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + ? undefined + : FFITypeToReturnsType[ToFFIType>]; + __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + }; - /** - * Open a library using `"bun:ffi"` - * - * @param name The name of the library or file path. This will be passed to `dlopen()` - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import {dlopen} from 'bun:ffi'; - * - * const lib = dlopen("duckdb.dylib", { - * get_version: { - * returns: "cstring", - * args: [], - * }, - * }); - * lib.symbols.get_version(); - * // "1.0.0" - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function dlopen>( - name: string | import("bun").BunFile | URL, - symbols: Fns, - ): Library; + /** + * Open a library using `"bun:ffi"` + * + * @param name The name of the library or file path. This will be passed to `dlopen()` + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import {dlopen} from 'bun:ffi'; + * + * const lib = dlopen("duckdb.dylib", { + * get_version: { + * returns: "cstring", + * args: [], + * }, + * }); + * lib.symbols.get_version(); + * // "1.0.0" + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function dlopen>( + name: string | import("bun").BunFile | URL, + symbols: Fns, + ): Library; - /** - * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. - * - * @param options - * @returns Library - * - * @example - * ## Hello, World! - * - * JavaScript: - * ```js - * import { cc } from "bun:ffi"; - * import hello from "./hello.c" with {type: "file"}; - * const {symbols: {hello}} = cc({ - * source: hello, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * // "Hello, World!" - * console.log(hello()); - * ``` - * - * `./hello.c`: - * ```c - * #include - * const char* hello() { - * return "Hello, World!"; - * } - * ``` - */ - function cc>(options: { - /** - * File path to an ISO C11 source file to compile and link - */ - source: string | import("bun").BunFile | URL; + /** + * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. + * + * @param options + * @returns Library + * + * @example + * ## Hello, World! + * + * JavaScript: + * ```js + * import { cc } from "bun:ffi"; + * import hello from "./hello.c" with {type: "file"}; + * const {symbols: {hello}} = cc({ + * source: hello, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * // "Hello, World!" + * console.log(hello()); + * ``` + * + * `./hello.c`: + * ```c + * #include + * const char* hello() { + * return "Hello, World!"; + * } + * ``` + */ + function cc>(options: { + /** + * File path to an ISO C11 source file to compile and link + */ + source: string | import("bun").BunFile | URL; - /** - * Library names to link against - * - * Equivalent to `-l` option in gcc/clang. - */ - library?: string[] | string; + /** + * Library names to link against + * + * Equivalent to `-l` option in gcc/clang. + */ + library?: string[] | string; - /** - * Include directories to pass to the compiler - * - * Equivalent to `-I` option in gcc/clang. - */ - include?: string[] | string; + /** + * Include directories to pass to the compiler + * + * Equivalent to `-I` option in gcc/clang. + */ + include?: string[] | string; - /** - * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - */ - symbols: Fns; + /** + * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + */ + symbols: Fns; - /** - * Map of symbols to define where the key is the symbol name and the value is the symbol value - * - * Equivalent to `-D` option in gcc/clang. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * define: { - * "NDEBUG": "1", - * }, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - define?: Record; + /** + * Map of symbols to define where the key is the symbol name and the value is the symbol value + * + * Equivalent to `-D` option in gcc/clang. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * define: { + * "NDEBUG": "1", + * }, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + define?: Record; - /** - * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. - * - * @default "-std=c11 -Wl,--export-all-symbols -g -O2" - * - * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * flags: ["-framework CoreFoundation", "-framework Security"], - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - flags?: string | string[]; - }): Library; + /** + * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. + * + * @default "-std=c11 -Wl,--export-all-symbols -g -O2" + * + * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * flags: ["-framework CoreFoundation", "-framework Security"], + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + flags?: string | string[]; + }): Library; - /** - * Turn a native library's function pointer into a JavaScript function - * - * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. - * - * @param fn {@link FFIFunction} declaration. `ptr` is required - * - * @example - * - * ```js - * import {CFunction} from 'bun:ffi'; - * - * const getVersion = new CFunction({ - * returns: "cstring", - * args: [], - * ptr: myNativeLibraryGetVersion, - * }); - * getVersion(); - * getVersion.close(); - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { - /** - * Free the memory allocated by the wrapping function - */ - close(): void; - }; + /** + * Turn a native library's function pointer into a JavaScript function + * + * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. + * + * @param fn {@link FFIFunction} declaration. `ptr` is required + * + * @example + * + * ```js + * import {CFunction} from 'bun:ffi'; + * + * const getVersion = new CFunction({ + * returns: "cstring", + * args: [], + * ptr: myNativeLibraryGetVersion, + * }); + * getVersion(); + * getVersion.close(); + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { + /** + * Free the memory allocated by the wrapping function + */ + close(): void; + }; - /** - * Link a map of symbols to JavaScript functions - * - * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. - * - * You could use this with Node-API to skip loading a second time. - * - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import { linkSymbols } from "bun:ffi"; - * - * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); - * - * const lib = linkSymbols({ - * // Unlike with dlopen(), the names here can be whatever you want - * getMajor: { - * returns: "cstring", - * args: [], - * - * // Since this doesn't use dlsym(), you have to provide a valid ptr - * // That ptr could be a number or a bigint - * // An invalid pointer will crash your program. - * ptr: majorPtr, - * }, - * getMinor: { - * returns: "cstring", - * args: [], - * ptr: minorPtr, - * }, - * getPatch: { - * returns: "cstring", - * args: [], - * ptr: patchPtr, - * }, - * }); - * - * const [major, minor, patch] = [ - * lib.symbols.getMajor(), - * lib.symbols.getMinor(), - * lib.symbols.getPatch(), - * ]; - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function linkSymbols>(symbols: Fns): Library; + /** + * Link a map of symbols to JavaScript functions + * + * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. + * + * You could use this with Node-API to skip loading a second time. + * + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import { linkSymbols } from "bun:ffi"; + * + * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); + * + * const lib = linkSymbols({ + * // Unlike with dlopen(), the names here can be whatever you want + * getMajor: { + * returns: "cstring", + * args: [], + * + * // Since this doesn't use dlsym(), you have to provide a valid ptr + * // That ptr could be a number or a bigint + * // An invalid pointer will crash your program. + * ptr: majorPtr, + * }, + * getMinor: { + * returns: "cstring", + * args: [], + * ptr: minorPtr, + * }, + * getPatch: { + * returns: "cstring", + * args: [], + * ptr: patchPtr, + * }, + * }); + * + * const [major, minor, patch] = [ + * lib.symbols.getMajor(), + * lib.symbols.getMinor(), + * lib.symbols.getPatch(), + * ]; + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function linkSymbols>( + symbols: Fns, + ): Library; - /** - * Read a pointer as a {@link Buffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): Buffer; + /** + * Read a pointer as a {@link Buffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toBuffer( + ptr: Pointer, + byteOffset?: number, + byteLength?: number, + ): Buffer; - /** - * Read a pointer as an {@link ArrayBuffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toArrayBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): ArrayBuffer; + /** + * Read a pointer as an {@link ArrayBuffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toArrayBuffer( + ptr: Pointer, + byteOffset?: number, + byteLength?: number, + ): ArrayBuffer; - namespace read { - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f64(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function ptr(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function intptr(ptr: Pointer, byteOffset?: number): number; - } + namespace read { + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f64(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function ptr(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function intptr(ptr: Pointer, byteOffset?: number): number; + } - /** - * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} - * - * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. - * - * This is for use with FFI functions. For performance reasons, FFI will - * not automatically convert typed arrays to C pointers. - * - * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for - * @param {number} byteOffset optional offset into the view in bytes - * - * @example - * - * From JavaScript: - * ```js - * const array = new Uint8Array(10); - * const rawPtr = ptr(array); - * myFFIFunction(rawPtr); - * ``` - * To C: - * ```c - * void myFFIFunction(char* rawPtr) { - * // Do something with rawPtr - * } - * ``` - */ - function ptr(view: NodeJS.TypedArray | ArrayBufferLike | DataView, byteOffset?: number): Pointer; + /** + * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} + * + * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. + * + * This is for use with FFI functions. For performance reasons, FFI will + * not automatically convert typed arrays to C pointers. + * + * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for + * @param {number} byteOffset optional offset into the view in bytes + * + * @example + * + * From JavaScript: + * ```js + * const array = new Uint8Array(10); + * const rawPtr = ptr(array); + * myFFIFunction(rawPtr); + * ``` + * To C: + * ```c + * void myFFIFunction(char* rawPtr) { + * // Do something with rawPtr + * } + * ``` + */ + function ptr( + view: NodeJS.TypedArray | ArrayBufferLike | DataView, + byteOffset?: number, + ): Pointer; - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ - class CString extends String { - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @param ptr The pointer to the C string - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); + class CString extends String { + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @param ptr The pointer to the C string + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); - /** - * The ptr to the C string - * - * This `CString` instance is a clone of the string, so it - * is safe to continue using this instance after the `ptr` has been - * freed. - */ - ptr: Pointer; - byteOffset?: number; - byteLength?: number; + /** + * The ptr to the C string + * + * This `CString` instance is a clone of the string, so it + * is safe to continue using this instance after the `ptr` has been + * freed. + */ + ptr: Pointer; + byteOffset?: number; + byteLength?: number; - /** - * Get the {@link ptr} as an `ArrayBuffer` - * - * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 - */ - get arrayBuffer(): ArrayBuffer; - } + /** + * Get the {@link ptr} as an `ArrayBuffer` + * + * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 + */ + get arrayBuffer(): ArrayBuffer; + } - /** - * Pass a JavaScript function to FFI (Foreign Function Interface) - */ - class JSCallback { - /** - * Enable a JavaScript callback function to be passed to C with bun:ffi - * - * @param callback The JavaScript function to be called - * @param definition The C function definition - */ - constructor(callback: (...args: any[]) => any, definition: FFIFunction); + /** + * Pass a JavaScript function to FFI (Foreign Function Interface) + */ + class JSCallback { + /** + * Enable a JavaScript callback function to be passed to C with bun:ffi + * + * @param callback The JavaScript function to be called + * @param definition The C function definition + */ + constructor(callback: (...args: any[]) => any, definition: FFIFunction); - /** - * The pointer to the C function - * - * Becomes `null` once {@link JSCallback.prototype.close} is called - */ - readonly ptr: Pointer | null; + /** + * The pointer to the C function + * + * Becomes `null` once {@link JSCallback.prototype.close} is called + */ + readonly ptr: Pointer | null; - /** - * Can the callback be called from a different thread? - */ - readonly threadsafe: boolean; + /** + * Can the callback be called from a different thread? + */ + readonly threadsafe: boolean; - /** - * Free the memory allocated for the callback - * - * If called multiple times, does nothing after the first call. - */ - close(): void; - } + /** + * Free the memory allocated for the callback + * + * If called multiple times, does nothing after the first call. + */ + close(): void; + } - /** - * View the generated C code for FFI bindings - * - * You probably won't need this unless there's a bug in the FFI bindings - * generator or you're just curious. - */ - function viewSource(symbols: Symbols, is_callback?: false): string[]; - function viewSource(callback: FFIFunction, is_callback: true): string; + /** + * View the generated C code for FFI bindings + * + * You probably won't need this unless there's a bug in the FFI bindings + * generator or you're just curious. + */ + function viewSource(symbols: Symbols, is_callback?: false): string[]; + function viewSource(callback: FFIFunction, is_callback: true): string; - /** - * Platform-specific file extension name for dynamic libraries - * - * "." is not included - * - * @example - * ```js - * "dylib" // macOS - * ``` - * - * @example - * ```js - * "so" // linux - * ``` - */ - const suffix: string; + /** + * Platform-specific file extension name for dynamic libraries + * + * "." is not included + * + * @example + * ```js + * "dylib" // macOS + * ``` + * + * @example + * ```js + * "so" // linux + * ``` + */ + const suffix: string; } diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index cade6dc3be4798..f8c1bab554eea7 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1,1770 +1,1875 @@ export {}; type _Event = { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly bubbles: boolean; + /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ + cancelBubble: () => void; + /** True if the event was created with the cancelable option */ + readonly cancelable: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly composed: boolean; + /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ + composedPath(): [EventTarget?]; + /** Alias for event.target. */ + readonly currentTarget: EventTarget | null; + /** Is true if cancelable is true and event.preventDefault() has been called. */ + readonly defaultPrevented: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly eventPhase: 0 | 2; + /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ + readonly isTrusted: boolean; + /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ + preventDefault(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + returnValue: boolean; + /** Alias for event.target. */ + readonly srcElement: EventTarget | null; + /** Stops the invocation of event listeners after the current one completes. */ + stopImmediatePropagation(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + stopPropagation(): void; + /** The `EventTarget` dispatching the event */ + readonly target: EventTarget | null; + /** The millisecond timestamp when the Event object was created. */ + readonly timeStamp: number; + /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ + readonly type: string; }; type _EventTarget = { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; + /** + * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. + * + * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. + * + * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. + * Specifically, the `capture` option is used as part of the key when registering a `listener`. + * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. + */ + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ + dispatchEvent(event: Event): boolean; + /** Removes the event listener in target's event listener list with the same type, callback, and options. */ + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; }; declare global { - var Bun: typeof import("bun"); - - namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - - /** Whether you are using Bun */ - isBun: true; - /** The current git sha of Bun **/ - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - } - - namespace Bun { - type ArrayBufferView = NodeJS.TypedArray | DataView; - type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type PathLike = import("bun").PathLike; - type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; - type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; - type ReadableStreamController = ReadableStreamDefaultController; - type ReadableStreamDefaultReadResult = - | ReadableStreamDefaultReadValueResult - | ReadableStreamDefaultReadDoneResult; - type ReadableStreamReader = ReadableStreamDefaultReader; - type Transferable = ArrayBuffer | import("worker_threads").MessagePort; - type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; - type DOMHighResTimeStamp = number; - type EventListenerOrEventListenerObject = EventListener | EventListenerObject; - - type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob; - - type Platform = - | "aix" - | "android" - | "darwin" - | "freebsd" - | "haiku" - | "linux" - | "openbsd" - | "sunos" - | "win32" - | "cygwin" - | "netbsd"; - type Architecture = "arm" | "arm64" | "ia32" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x" | "x64"; - - 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. - */ - type UnhandledRejectionListener = (reason: unknown, promise: Promise) => void; - - type MultipleResolveListener = (type: MultipleResolveType, promise: Promise, value: unknown) => void; - - type HeadersInit = Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; - - type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; - - type _TextEncoder = import("util").TextEncoder; - interface TextEncoder extends _TextEncoder { - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; - /** - * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object - * containing the read Unicode code units and written UTF-8 bytes. - * - * ```js - * const encoder = new TextEncoder(); - * const src = 'this is some data'; - * const dest = new Uint8Array(10); - * const { read, written } = encoder.encodeInto(src, dest); - * ``` - * @param src The text to encode. - * @param dest The array to hold the encode result. - */ - encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; - } - - type _TextDecoder = import("util").TextDecoder; - interface TextDecoder extends _TextDecoder { - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextDecoder; - } - - 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 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 extends Bun.EventInit { - detail?: T; - } - - /** A message received by a target object. */ - interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; - readonly source: Bun.MessageEventSource | null; - } - - interface ReadableStreamDefaultReadManyResult { - done: boolean; - /** Number of bytes */ - size: number; - value: T[]; - } - - interface ResponseInit { - headers?: HeadersInit; - /** @default 200 */ - status?: number; - - /** @default "OK" */ - statusText?: string; - } - - interface EventSourceEventMap { - error: Event; - message: MessageEvent; - open: Event; - } - - interface EventInit { - bubbles?: boolean; - cancelable?: boolean; - composed?: boolean; - } - - interface EventListenerOptions { - /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ - capture?: boolean; - } - - 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): void; - respondWith(response: Response | Promise): 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( - 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( - 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 { - (controller: TransformStreamDefaultController): void | PromiseLike; - } - - interface TransformerStartCallback { - (controller: TransformStreamDefaultController): any; - } - - interface TransformerTransformCallback { - (chunk: I, controller: TransformStreamDefaultController): void | PromiseLike; - } - - interface UnderlyingSinkAbortCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSinkCloseCallback { - (): void | PromiseLike; - } - - interface UnderlyingSinkStartCallback { - (controller: WritableStreamDefaultController): any; - } - - interface UnderlyingSinkWriteCallback { - (chunk: W, controller: WritableStreamDefaultController): void | PromiseLike; - } - - interface UnderlyingSourceCancelCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSink { - abort?: UnderlyingSinkAbortCallback; - close?: UnderlyingSinkCloseCallback; - start?: UnderlyingSinkStartCallback; - type?: undefined | "default" | "bytes"; - write?: UnderlyingSinkWriteCallback; - } - - interface UnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull?: UnderlyingSourcePullCallback; - start?: UnderlyingSourceStartCallback; - /** - * Mode "bytes" is not currently supported. - */ - type?: undefined; - } - - interface DirectUnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull: (controller: ReadableStreamDirectController) => void | PromiseLike; - type: "direct"; - } - - interface UnderlyingSourcePullCallback { - (controller: ReadableStreamController): void | PromiseLike; - } - - interface UnderlyingSourceStartCallback { - (controller: ReadableStreamController): 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( - type: K, - listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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 | (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( - type: K, - listener: (this: Worker, ev: WorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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; - } - } - - type _ReadableStream = import("stream/web").ReadableStream; - interface ReadableStream extends _ReadableStream {} - var ReadableStream: { - prototype: ReadableStream; - new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - }; - - type _WritableStream = import("stream/web").WritableStream; - interface WritableStream extends _WritableStream {} - var WritableStream: { - prototype: WritableStream; - new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; - }; - - type _Worker = import("worker_threads").Worker; - interface Worker extends _Worker {} - var Worker: { - prototype: Worker; - new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; - }; - - var WebSocket: typeof import("ws").WebSocket; - - type _Crypto = import("crypto").webcrypto.Crypto; - interface Crypto extends _Crypto {} - var Crypto: { - prototype: Crypto; - new (): Crypto; - }; - - var crypto: Crypto; - - /** - * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All - * instances of `TextEncoder` only support UTF-8 encoding. - * - * ```js - * const encoder = new TextEncoder(); - * const uint8array = encoder.encode('this is some data'); - * ``` - */ - interface TextEncoder extends Bun.TextEncoder {} - var TextEncoder: typeof TextEncoder; - - interface TextDecoder extends Bun.TextDecoder {} - var TextDecoder: typeof TextDecoder; - - type _Performance = import("perf_hooks").Performance; - interface Performance extends _Performance {} - var performance: Performance; - - interface Event extends _Event {} - var Event: { - prototype: Event; - new (type: string, eventInitDict?: Bun.EventInit): Event; - }; - - interface EventTarget extends _EventTarget {} - var EventTarget: { - prototype: EventTarget; - new (): EventTarget; - }; - - interface File extends Blob { - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; - readonly lastModified: number; - readonly name: string; - } - - var File: typeof File; - - type _RequestInit = import("undici-types").RequestInit; - interface RequestInit extends _RequestInit { - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: import("bun").S3Options; - } - - /** - * ShadowRealms are a distinct global environment, with its own global object - * containing its own intrinsics and built-ins (standard objects that are not - * bound to global variables, like the initial value of Object.prototype). - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - interface ShadowRealm { - /** - * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; - } - - var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; - }; - - function queueMicrotask(callback: (...args: any[]) => void): void; - /** - * Log an error using the default exception handler - * @param error Error or string - */ - function reportError(error: any): void; - - interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; - - [Symbol.toPrimitive](): number; - } - - /** - * Cancel a repeating timer by its timer ID. - * @param id timer id - */ - function clearInterval(id?: number | Timer): void; - /** - * Cancel a delayed function call by its timer ID. - * @param id timer id - */ - function clearTimeout(id?: number | Timer): void; - /** - * Cancel an immediate function call by its immediate ID. - * @param id immediate id - */ - function clearImmediate(id?: number | Timer): void; - /** - * Run a function immediately after main event loop is vacant - * @param handler function to call - */ - function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; - /** - * Run a function every `interval` milliseconds - * @param handler function to call - * @param interval milliseconds to wait between calls - */ - function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; - /** - * Run a function after `timeout` (milliseconds) - * @param handler function to call - * @param timeout milliseconds to wait between calls - */ - function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; - - function addEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - function addEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - function removeEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | Bun.EventListenerOptions, - ): void; - function removeEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | Bun.EventListenerOptions, - ): void; - - /** - * Events providing information related to errors in scripts or in files. - */ - interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; - } - - var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; - }; - - /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ - interface CloseEvent extends Event { - /** Returns the WebSocket connection close code provided by the server. */ - readonly code: number; - /** Returns the WebSocket connection close reason provided by the server. */ - readonly reason: string; - /** Returns true if the connection closed cleanly; false otherwise. */ - readonly wasClean: boolean; - } - - var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; - }; - - interface MessageEvent extends Bun.MessageEvent {} - var MessageEvent: { - prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; - }; - - interface CustomEvent extends Event { - /** Returns any custom data event was created with. Typically used for synthetic events. */ - readonly detail: T; - } - - var CustomEvent: { - prototype: CustomEvent; - new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; - }; - - // /** - // * The URL interface represents an object providing static methods used for - // * creating object URLs. - // */ - // interface URL extends _URL { - // new (url: string | URL, base?: string | URL): URL; - // /** Not implemented yet */ - // createObjectURL(obj: Blob): string; - // /** Not implemented yet */ - // revokeObjectURL(url: string): void; - - // /** - // * Check if `url` is a valid URL string - // * - // * @param url URL string to parse - // * @param base URL to resolve against - // */ - // canParse(url: string, base?: string): boolean; - // } - - interface EventListener { - (evt: Event): void; - } - - interface EventListenerObject { - handleEvent(object: Event): void; - } - - interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; - - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; - } - - interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; - // exit: Event; - } - - interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; - } - - /** - * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) - * - * Before using this, be aware of a few things: - * - * **Using this incorrectly will crash your application**. - * - * This API may change any time JavaScriptCore is updated. - * - * Bun may rewrite ESM import specifiers to point to bundled code. This will - * be confusing when using this API, as it will return a string like - * "/node_modules.server.bun". - * - * Bun may inject additional imports into your code. This usually has a `bun:` prefix. - */ - var Loader: { - /** - * ESM module registry - * - * This lets you implement live reload in Bun. If you - * delete a module specifier from this map, the next time it's imported, it - * will be re-transpiled and loaded again. - * - * The keys are the module specifiers and the - * values are metadata about the module. - * - * The keys are an implementation detail for Bun that will change between - * versions. - * - * - Userland modules are an absolute file path - * - Virtual modules have a `bun:` prefix or `node:` prefix - * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill - * - If you have a `node_modules.bun` file, many modules will point to that file - * - * Virtual modules and JS polyfills are embedded in bun's binary. They don't - * point to anywhere in your local filesystem. - */ - registry: Map< - string, - { - key: string; - /** - * This refers to the state the ESM module is in - * - * TODO: make an enum for this number - */ - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; - /** - * Your application will probably crash if you mess with this. - */ - module: { - dependenciesMap: (typeof Loader)["registry"]; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - /** - * For an already-evaluated module, return the dependencies as module specifiers - * - * This list is already sorted and uniqued. - * - * @example - * - * For this code: - * ```js - * // /foo.js - * import classNames from 'classnames'; - * import React from 'react'; - * import {createElement} from 'react'; - * ``` - * - * This would return: - * ```js - * Loader.dependencyKeysIfEvaluated("/foo.js") - * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] - * ``` - * - * @param specifier - module specifier as it appears in transpiled source code - */ - dependencyKeysIfEvaluated: (specifier: string) => string[]; - /** - * The function JavaScriptCore internally calls when you use an import statement. - * - * This may return a path to `node_modules.server.bun`, which will be confusing. - * - * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} - * instead. - * - * @param specifier - module specifier as it appears in transpiled source code - * @param referrer - module specifier that is resolving this specifier - */ - resolve: (specifier: string, referrer: string) => string; - }; - - interface QueuingStrategy { - highWaterMark?: number; - size?: QueuingStrategySize; - } - - interface QueuingStrategyInit { - /** - * Creates a new ByteLengthQueuingStrategy with the provided high water mark. - * - * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. - */ - highWaterMark: number; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface ByteLengthQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - // changed from QueuingStrategySize - // to avoid conflict with lib.dom.d.ts - readonly size: QueuingStrategySize; - } - - var ByteLengthQueuingStrategy: { - prototype: ByteLengthQueuingStrategy; - new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; - }; - - interface ReadableStreamDefaultController { - readonly desiredSize: number | null; - close(): void; - enqueue(chunk?: R): void; - error(e?: any): void; - } - - interface ReadableStreamDirectController { - close(error?: Error): void; - write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; - end(): number | Promise; - flush(): number | Promise; - start(): void; - } - - var ReadableStreamDefaultController: { - prototype: ReadableStreamDefaultController; - new (): ReadableStreamDefaultController; - }; - - interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { - read(): Promise>; - /** - * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. - * Will only return a promise if the data is not immediately available. - */ - readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; - releaseLock(): void; - } - - var ReadableStreamDefaultReader: { - prototype: ReadableStreamDefaultReader; - new (stream: ReadableStream): ReadableStreamDefaultReader; - }; - - interface ReadableStreamGenericReader { - readonly closed: Promise; - cancel(reason?: any): Promise; - } - - interface ReadableStreamDefaultReadDoneResult { - done: true; - value?: undefined; - } - - interface ReadableStreamDefaultReadValueResult { - done: false; - value: T; - } - - interface ReadableWritablePair { - readable: ReadableStream; - /** - * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - */ - writable: WritableStream; - } - - interface WritableStreamDefaultController { - error(e?: any): void; - } - - var WritableStreamDefaultController: { - prototype: WritableStreamDefaultController; - new (): WritableStreamDefaultController; - }; - - /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ - interface WritableStreamDefaultWriter { - readonly closed: Promise; - readonly desiredSize: number | null; - readonly ready: Promise; - abort(reason?: any): Promise; - close(): Promise; - releaseLock(): void; - write(chunk?: W): Promise; - } - - var WritableStreamDefaultWriter: { - prototype: WritableStreamDefaultWriter; - new (stream: WritableStream): WritableStreamDefaultWriter; - }; - - interface TransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; - } - - var TransformStream: { - prototype: TransformStream; - new ( - transformer?: Transformer, - writableStrategy?: QueuingStrategy, - readableStrategy?: QueuingStrategy, - ): TransformStream; - }; - - interface TransformStreamDefaultController { - readonly desiredSize: number | null; - enqueue(chunk?: O): void; - error(reason?: any): void; - terminate(): void; - } - - var TransformStreamDefaultController: { - prototype: TransformStreamDefaultController; - new (): TransformStreamDefaultController; - }; - - interface StreamPipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - /** - * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - * - * Errors and closures of the source and destination streams propagate as follows: - * - * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. - * - * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. - * - * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. - * - * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. - * - * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. - */ - preventClose?: boolean; - signal?: AbortSignal; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface CountQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - readonly size: QueuingStrategySize; - } - - var CountQueuingStrategy: { - prototype: CountQueuingStrategy; - new (init: QueuingStrategyInit): CountQueuingStrategy; - }; - - interface QueuingStrategySize { - (chunk?: T): number; - } - - interface Transformer { - flush?: Bun.TransformerFlushCallback; - readableType?: undefined; - start?: Bun.TransformerStartCallback; - transform?: Bun.TransformerTransformCallback; - writableType?: undefined; - } - - interface Dict { - [key: string]: T | undefined; - } - - interface ReadOnlyDict { - readonly [key: string]: T | undefined; - } - - interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; - } - - /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ - interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; - } - - var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; - }; - - function alert(message?: string): void; - function confirm(message?: string): boolean; - function prompt(message?: string, _default?: string): string | null; - - type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; - var SubtleCrypto: { - prototype: _SubtleCrypto; - new (): _SubtleCrypto; - }; - - type _CryptoKey = import("crypto").webcrypto.CryptoKey; - interface CryptoKey extends _CryptoKey {} - var CryptoKey: { - prototype: CryptoKey; - new (): CryptoKey; - }; - - interface Position { - lineText: string; - file: string; - namespace: string; - line: number; - column: number; - length: number; - offset: number; - } - - class ResolveMessage { - readonly name: "ResolveMessage"; - readonly position: Position | null; - readonly code: string; - readonly message: string; - readonly referrer: string; - readonly specifier: string; - readonly importKind: - | "entry_point" - | "stmt" - | "require" - | "import" - | "dynamic" - | "require_resolve" - | "at" - | "at_conditional" - | "url" - | "internal"; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - - toString(): string; - } - - class BuildMessage { - readonly name: "BuildMessage"; - readonly position: Position | null; - readonly message: string; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - } - - // Declare "static" methods in Error - interface ErrorConstructor { - /** Create .stack property on a target object */ - // eslint-disable-next-line @typescript-eslint/ban-types - captureStackTrace(targetObject: object, constructorOpt?: Function): void; - - /** - * Optional override for formatting stack traces - * - * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces - */ - prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; - - stackTraceLimit: number; - } - - interface ArrayBufferConstructor { - new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; - } - - interface ArrayBuffer { - /** - * Read-only. The length of the ArrayBuffer (in bytes). - */ - readonly byteLength: number; - /** - * Resize an ArrayBuffer in-place. - */ - resize(byteLength: number): ArrayBuffer; - - /** - * Returns a section of an ArrayBuffer. - */ - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; - } - - interface SharedArrayBuffer { - /** - * Grow the SharedArrayBuffer in-place. - */ - grow(size: number): SharedArrayBuffer; - } - - interface ArrayConstructor { - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; - - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. Results of the map function are also awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * await Array.fromAsync([1], (n) => n + 1); // [2] - * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. - * @param thisArg - The `this` to which `mapFn` is bound. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; - } - - interface ConsoleOptions { - stdout: import("stream").Writable; - stderr?: import("stream").Writable; - ignoreErrors?: boolean; - colorMode?: boolean | "auto"; - inspectOptions?: import("util").InspectOptions; - groupIndentation?: number; - } - - interface Console { - /** - * Asynchronously read lines from standard input (fd 0) - * - * ```ts - * for await (const line of console) { - * console.log(line); - * } - * ``` - */ - [Symbol.asyncIterator](): AsyncIterableIterator; - - /** - * Write text or bytes to stdout - * - * Unlike {@link console.log}, this does no formatting and doesn't add a - * newline or spaces between arguments. You can pass it strings or bytes or - * any combination of the two. - * - * ```ts - * console.write("hello world!", "\n"); // "hello world\n" - * ``` - * - * @param data - The data to write - * @returns The number of bytes written - * - * This function is not available in the browser. - */ - write(...data: Array): number; - - /** - * Clear the console - */ - clear(): void; - - assert(condition?: boolean, ...data: any[]): void; - - /** - * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) - * @param label label counter - */ - count(label?: string): void; - countReset(label?: string): void; - debug(...data: any[]): void; - dir(item?: any, options?: any): void; - dirxml(...data: any[]): void; - /** - * Log to stderr in your terminal - * - * Appears in red - * - * @param data something to display - */ - error(...data: any[]): void; - /** Does nothing currently */ - group(...data: any[]): void; - /** Does nothing currently */ - groupCollapsed(...data: any[]): void; - /** Does nothing currently */ - groupEnd(): void; - info(...data: any[]): void; - log(...data: any[]): void; - /** - * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just - * logging the argument if it can't be parsed as tabular. - * - * ```js - * // These can't be parsed as tabular data - * console.table(Symbol()); - * // Symbol() - * - * console.table(undefined); - * // undefined - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ b โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * ``` - * @param properties Alternate properties for constructing the table. - */ - table(tabularData?: any, properties?: string[]): void; - /** - * Begin a timer to log with {@link console.timeEnd} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - time(label?: string): void; - /** - * End a timer to log with {@link console.time} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - timeEnd(label?: string): void; - timeLog(label?: string, ...data: any[]): void; - timeStamp(label?: string): void; - trace(...data: any[]): void; - warn(...data: any[]): void; - - /** - * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. - */ - // Console: { - // new (options: ConsoleOptions): Console; - // new ( - // stdout: import("stream").Writable, - // stderr?: import("stream").Writable, - // ignoreErrors?: boolean, - // ): Console; - // }; - } - - var console: Console; - - interface ImportMeta { - /** - * `file://` url string for the current module. - * - * @example - * ```ts - * console.log(import.meta.url); - * "file:///Users/me/projects/my-app/src/my-app.ts" - * ``` - */ - url: string; - /** - * Absolute path to the source file - */ - readonly path: string; - /** - * Absolute path to the directory containing the source file. - * - * Does not have a trailing slash - */ - readonly dir: string; - /** - * Filename of the source file - */ - readonly file: string; - /** - * The environment variables of the process - * - * ```ts - * import.meta.env === process.env - * ``` - */ - readonly env: NodeJS.ProcessEnv; - - /** - * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead - * - * Resolve a module ID the same as if you imported it - * - * The `parent` argument is optional, and defaults to the current module's path. - */ - resolveSync(moduleId: string, parent?: string): string; - - /** - * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all - * calls to `require` with `import.meta.require` when transpiling ES Modules - * for the runtime. - * - * Warning: **This API is not stable** and may change or be removed in the - * future. Use at your own risk. - */ - require: NodeJS.Require; - - /** - * Did the current file start the process? - * - * @example - * ```ts - * if (import.meta.main) { - * console.log("I started the process!"); - * } - * ``` - * - * @example - * ```ts - * console.log( - * import.meta.main === (import.meta.path === Bun.main) - * ) - * ``` - */ - readonly main: boolean; - - /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ - dirname: string; - - /** Alias of `import.meta.path`. Exists for Node.js compatibility */ - filename: string; - } - - /** - * NodeJS-style `require` function - * - * @param moduleId - The module ID to resolve - */ - var require: NodeJS.Require; - - /** Same as module.exports */ - var exports: any; - - interface NodeModule { - exports: any; - } - - var module: NodeModule; - - /** - * Creates a deep clone of an object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) - */ - function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; - - /** - * Post a message to the parent thread. - * - * Only useful in a worker thread; calling this from the main thread does nothing. - */ - function postMessage(message: any, transfer?: Bun.Transferable[]): void; - - interface EventSourceInit { - withCredentials?: boolean; - } - - interface PromiseConstructor { - /** - * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called - * separately. - * - * This is useful when you want to return a Promise and have code outside the Promise - * resolve or reject it. - * - * ## Example - * ```ts - * const { promise, resolve, reject } = Promise.withResolvers(); - * - * setTimeout(() => { - * resolve("Hello world!"); - * }, 1000); - * - * await promise; // "Hello world!" - * ``` - * - * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). - */ - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; - } - - interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; - } - - var navigator: Navigator; - - interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; - } - - interface Blob { - /** - * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - */ - new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; - /** - * Read the data from the blob as a JSON object. - * - * This first decodes the data from UTF-8, then parses it as JSON. - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - json(): Promise; - - /** - * Read the data from the blob as a {@link FormData} object. - * - * This first decodes the data from UTF-8, then parses it as a - * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. - * - * The `type` property of the blob is used to determine the format of the - * body. - * - * This is a non-standard addition to the `Blob` API, to make it conform more - * closely to the `BodyMixin` API. - */ - formData(): Promise; - - arrayBuffer(): Promise; - - /** - * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` - */ - bytes(): Promise; - } - - var Blob: typeof Blob; + var Bun: typeof import("bun"); + + namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; + + /** Whether you are using Bun */ + isBun: true; + /** The current git sha of Bun **/ + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + } + + namespace Bun { + type ArrayBufferView = NodeJS.TypedArray | DataView; + type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; + type PathLike = import("bun").PathLike; + type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; + type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; + type ReadableStreamController = ReadableStreamDefaultController; + type ReadableStreamDefaultReadResult = + | ReadableStreamDefaultReadValueResult + | ReadableStreamDefaultReadDoneResult; + type ReadableStreamReader = ReadableStreamDefaultReader; + type Transferable = ArrayBuffer | import("worker_threads").MessagePort; + type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; + type DOMHighResTimeStamp = number; + type EventListenerOrEventListenerObject = + | EventListener + | EventListenerObject; + + type BlobOrStringOrBuffer = + | string + | NodeJS.TypedArray + | ArrayBufferLike + | Blob; + + type Platform = + | "aix" + | "android" + | "darwin" + | "freebsd" + | "haiku" + | "linux" + | "openbsd" + | "sunos" + | "win32" + | "cygwin" + | "netbsd"; + type Architecture = + | "arm" + | "arm64" + | "ia32" + | "mips" + | "mipsel" + | "ppc" + | "ppc64" + | "s390" + | "s390x" + | "x64"; + + 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. + */ + type UnhandledRejectionListener = ( + reason: unknown, + promise: Promise, + ) => void; + + type MultipleResolveListener = ( + type: MultipleResolveType, + promise: Promise, + value: unknown, + ) => void; + + type HeadersInit = + | Headers + | Record + | Array<[string, string]> + | IterableIterator<[string, string]>; + + type ResponseType = + | "basic" + | "cors" + | "default" + | "error" + | "opaque" + | "opaqueredirect"; + + type _TextEncoder = import("util").TextEncoder; + interface TextEncoder extends _TextEncoder { + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): TextEncoder; + /** + * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object + * containing the read Unicode code units and written UTF-8 bytes. + * + * ```js + * const encoder = new TextEncoder(); + * const src = 'this is some data'; + * const dest = new Uint8Array(10); + * const { read, written } = encoder.encodeInto(src, dest); + * ``` + * @param src The text to encode. + * @param dest The array to hold the encode result. + */ + encodeInto( + src?: string, + dest?: Bun.BufferSource, + ): import("util").EncodeIntoResult; + } + + type _TextDecoder = import("util").TextDecoder; + interface TextDecoder extends _TextDecoder { + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): TextDecoder; + } + + 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 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 extends Bun.EventInit { + detail?: T; + } + + /** A message received by a target object. */ + interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; + readonly source: Bun.MessageEventSource | null; + } + + interface ReadableStreamDefaultReadManyResult { + done: boolean; + /** Number of bytes */ + size: number; + value: T[]; + } + + interface ResponseInit { + headers?: HeadersInit; + /** @default 200 */ + status?: number; + + /** @default "OK" */ + statusText?: string; + } + + interface EventSourceEventMap { + error: Event; + message: MessageEvent; + open: Event; + } + + interface EventInit { + bubbles?: boolean; + cancelable?: boolean; + composed?: boolean; + } + + interface EventListenerOptions { + /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ + capture?: boolean; + } + + 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): void; + respondWith(response: Response | Promise): 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( + 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( + 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 { + ( + controller: TransformStreamDefaultController, + ): void | PromiseLike; + } + + interface TransformerStartCallback { + (controller: TransformStreamDefaultController): any; + } + + interface TransformerTransformCallback { + ( + chunk: I, + controller: TransformStreamDefaultController, + ): void | PromiseLike; + } + + interface UnderlyingSinkAbortCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSinkCloseCallback { + (): void | PromiseLike; + } + + interface UnderlyingSinkStartCallback { + (controller: WritableStreamDefaultController): any; + } + + interface UnderlyingSinkWriteCallback { + ( + chunk: W, + controller: WritableStreamDefaultController, + ): void | PromiseLike; + } + + interface UnderlyingSourceCancelCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSink { + abort?: UnderlyingSinkAbortCallback; + close?: UnderlyingSinkCloseCallback; + start?: UnderlyingSinkStartCallback; + type?: undefined | "default" | "bytes"; + write?: UnderlyingSinkWriteCallback; + } + + interface UnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull?: UnderlyingSourcePullCallback; + start?: UnderlyingSourceStartCallback; + /** + * Mode "bytes" is not currently supported. + */ + type?: undefined; + } + + interface DirectUnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull: ( + controller: ReadableStreamDirectController, + ) => void | PromiseLike; + type: "direct"; + } + + interface UnderlyingSourcePullCallback { + (controller: ReadableStreamController): void | PromiseLike; + } + + interface UnderlyingSourceStartCallback { + (controller: ReadableStreamController): 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( + type: K, + listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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 + | 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( + type: K, + listener: (this: Worker, ev: WorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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; + } + } + + type _ReadableStream = import("stream/web").ReadableStream; + interface ReadableStream extends _ReadableStream {} + var ReadableStream: { + prototype: ReadableStream; + new ( + underlyingSource?: Bun.UnderlyingSource, + strategy?: QueuingStrategy, + ): ReadableStream; + new ( + underlyingSource?: Bun.DirectUnderlyingSource, + strategy?: QueuingStrategy, + ): ReadableStream; + }; + + type _WritableStream = import("stream/web").WritableStream; + interface WritableStream extends _WritableStream {} + var WritableStream: { + prototype: WritableStream; + new ( + underlyingSink?: Bun.UnderlyingSink, + strategy?: QueuingStrategy, + ): WritableStream; + }; + + type _Worker = import("worker_threads").Worker; + interface Worker extends _Worker {} + var Worker: { + prototype: Worker; + new ( + scriptURL: string | URL, + options?: Bun.WorkerOptions | undefined, + ): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; + }; + + var WebSocket: typeof import("ws").WebSocket; + + type _Crypto = import("crypto").webcrypto.Crypto; + interface Crypto extends _Crypto {} + var Crypto: { + prototype: Crypto; + new (): Crypto; + }; + + var crypto: Crypto; + + /** + * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All + * instances of `TextEncoder` only support UTF-8 encoding. + * + * ```js + * const encoder = new TextEncoder(); + * const uint8array = encoder.encode('this is some data'); + * ``` + */ + interface TextEncoder extends Bun.TextEncoder {} + var TextEncoder: typeof TextEncoder; + + interface TextDecoder extends Bun.TextDecoder {} + var TextDecoder: typeof TextDecoder; + + type _Performance = import("perf_hooks").Performance; + interface Performance extends _Performance {} + var performance: Performance; + + interface Event extends _Event {} + var Event: { + prototype: Event; + new (type: string, eventInitDict?: Bun.EventInit): Event; + }; + + interface EventTarget extends _EventTarget {} + var EventTarget: { + prototype: EventTarget; + new (): EventTarget; + }; + + interface File extends Blob { + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new ( + parts: Bun.BlobPart[], + name: string, + options?: BlobPropertyBag & { lastModified?: Date | number }, + ): File; + readonly lastModified: number; + readonly name: string; + } + + var File: typeof File; + + type _RequestInit = import("undici-types").RequestInit; + interface RequestInit extends _RequestInit { + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: import("bun").S3Options; + } + + /** + * ShadowRealms are a distinct global environment, with its own global object + * containing its own intrinsics and built-ins (standard objects that are not + * bound to global variables, like the initial value of Object.prototype). + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + interface ShadowRealm { + /** + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; + } + + var ShadowRealm: { + prototype: ShadowRealm; + new (): ShadowRealm; + }; + + function queueMicrotask(callback: (...args: any[]) => void): void; + /** + * Log an error using the default exception handler + * @param error Error or string + */ + function reportError(error: any): void; + + interface Timer { + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; + + [Symbol.toPrimitive](): number; + } + + /** + * Cancel a repeating timer by its timer ID. + * @param id timer id + */ + function clearInterval(id?: number | Timer): void; + /** + * Cancel a delayed function call by its timer ID. + * @param id timer id + */ + function clearTimeout(id?: number | Timer): void; + /** + * Cancel an immediate function call by its immediate ID. + * @param id immediate id + */ + function clearImmediate(id?: number | Timer): void; + /** + * Run a function immediately after main event loop is vacant + * @param handler function to call + */ + function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; + /** + * Run a function every `interval` milliseconds + * @param handler function to call + * @param interval milliseconds to wait between calls + */ + function setInterval( + handler: Bun.TimerHandler, + interval?: number, + ...arguments: any[] + ): Timer; + /** + * Run a function after `timeout` (milliseconds) + * @param handler function to call + * @param timeout milliseconds to wait between calls + */ + function setTimeout( + handler: Bun.TimerHandler, + timeout?: number, + ...arguments: any[] + ): Timer; + + function addEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + function addEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + function removeEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | Bun.EventListenerOptions, + ): void; + function removeEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | Bun.EventListenerOptions, + ): void; + + /** + * Events providing information related to errors in scripts or in files. + */ + interface ErrorEvent extends Event { + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; + } + + var ErrorEvent: { + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; + }; + + /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ + interface CloseEvent extends Event { + /** Returns the WebSocket connection close code provided by the server. */ + readonly code: number; + /** Returns the WebSocket connection close reason provided by the server. */ + readonly reason: string; + /** Returns true if the connection closed cleanly; false otherwise. */ + readonly wasClean: boolean; + } + + var CloseEvent: { + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; + }; + + interface MessageEvent extends Bun.MessageEvent {} + var MessageEvent: { + prototype: MessageEvent; + new ( + type: string, + eventInitDict?: Bun.MessageEventInit, + ): MessageEvent; + }; + + interface CustomEvent extends Event { + /** Returns any custom data event was created with. Typically used for synthetic events. */ + readonly detail: T; + } + + var CustomEvent: { + prototype: CustomEvent; + new ( + type: string, + eventInitDict?: Bun.CustomEventInit, + ): CustomEvent; + }; + + // /** + // * The URL interface represents an object providing static methods used for + // * creating object URLs. + // */ + // interface URL extends _URL { + // new (url: string | URL, base?: string | URL): URL; + // /** Not implemented yet */ + // createObjectURL(obj: Blob): string; + // /** Not implemented yet */ + // revokeObjectURL(url: string): void; + + // /** + // * Check if `url` is a valid URL string + // * + // * @param url URL string to parse + // * @param base URL to resolve against + // */ + // canParse(url: string, base?: string): boolean; + // } + + interface EventListener { + (evt: Event): void; + } + + interface EventListenerObject { + handleEvent(object: Event): void; + } + + interface FetchEvent extends Event { + readonly request: Request; + readonly url: string; + + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; + } + + interface EventMap { + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; + // exit: Event; + } + + interface AddEventListenerOptions extends Bun.EventListenerOptions { + once?: boolean; + passive?: boolean; + signal?: AbortSignal; + } + + /** + * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) + * + * Before using this, be aware of a few things: + * + * **Using this incorrectly will crash your application**. + * + * This API may change any time JavaScriptCore is updated. + * + * Bun may rewrite ESM import specifiers to point to bundled code. This will + * be confusing when using this API, as it will return a string like + * "/node_modules.server.bun". + * + * Bun may inject additional imports into your code. This usually has a `bun:` prefix. + */ + var Loader: { + /** + * ESM module registry + * + * This lets you implement live reload in Bun. If you + * delete a module specifier from this map, the next time it's imported, it + * will be re-transpiled and loaded again. + * + * The keys are the module specifiers and the + * values are metadata about the module. + * + * The keys are an implementation detail for Bun that will change between + * versions. + * + * - Userland modules are an absolute file path + * - Virtual modules have a `bun:` prefix or `node:` prefix + * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill + * - If you have a `node_modules.bun` file, many modules will point to that file + * + * Virtual modules and JS polyfills are embedded in bun's binary. They don't + * point to anywhere in your local filesystem. + */ + registry: Map< + string, + { + key: string; + /** + * This refers to the state the ESM module is in + * + * TODO: make an enum for this number + */ + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array< + (typeof Loader)["registry"] extends Map ? V : any + >; + /** + * Your application will probably crash if you mess with this. + */ + module: { + dependenciesMap: (typeof Loader)["registry"]; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; + /** + * For an already-evaluated module, return the dependencies as module specifiers + * + * This list is already sorted and uniqued. + * + * @example + * + * For this code: + * ```js + * // /foo.js + * import classNames from 'classnames'; + * import React from 'react'; + * import {createElement} from 'react'; + * ``` + * + * This would return: + * ```js + * Loader.dependencyKeysIfEvaluated("/foo.js") + * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] + * ``` + * + * @param specifier - module specifier as it appears in transpiled source code + */ + dependencyKeysIfEvaluated: (specifier: string) => string[]; + /** + * The function JavaScriptCore internally calls when you use an import statement. + * + * This may return a path to `node_modules.server.bun`, which will be confusing. + * + * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} + * instead. + * + * @param specifier - module specifier as it appears in transpiled source code + * @param referrer - module specifier that is resolving this specifier + */ + resolve: (specifier: string, referrer: string) => string; + }; + + interface QueuingStrategy { + highWaterMark?: number; + size?: QueuingStrategySize; + } + + interface QueuingStrategyInit { + /** + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. + */ + highWaterMark: number; + } + + /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ + interface ByteLengthQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + // changed from QueuingStrategySize + // to avoid conflict with lib.dom.d.ts + readonly size: QueuingStrategySize; + } + + var ByteLengthQueuingStrategy: { + prototype: ByteLengthQueuingStrategy; + new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; + }; + + interface ReadableStreamDefaultController { + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; + } + + interface ReadableStreamDirectController { + close(error?: Error): void; + write( + data: Bun.BufferSource | ArrayBuffer | string, + ): number | Promise; + end(): number | Promise; + flush(): number | Promise; + start(): void; + } + + var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; + }; + + interface ReadableStreamDefaultReader + extends ReadableStreamGenericReader { + read(): Promise>; + /** + * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. + * Will only return a promise if the data is not immediately available. + */ + readMany(): + | Promise> + | Bun.ReadableStreamDefaultReadManyResult; + releaseLock(): void; + } + + var ReadableStreamDefaultReader: { + prototype: ReadableStreamDefaultReader; + new (stream: ReadableStream): ReadableStreamDefaultReader; + }; + + interface ReadableStreamGenericReader { + readonly closed: Promise; + cancel(reason?: any): Promise; + } + + interface ReadableStreamDefaultReadDoneResult { + done: true; + value?: undefined; + } + + interface ReadableStreamDefaultReadValueResult { + done: false; + value: T; + } + + interface ReadableWritablePair { + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; + } + + interface WritableStreamDefaultController { + error(e?: any): void; + } + + var WritableStreamDefaultController: { + prototype: WritableStreamDefaultController; + new (): WritableStreamDefaultController; + }; + + /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ + interface WritableStreamDefaultWriter { + readonly closed: Promise; + readonly desiredSize: number | null; + readonly ready: Promise; + abort(reason?: any): Promise; + close(): Promise; + releaseLock(): void; + write(chunk?: W): Promise; + } + + var WritableStreamDefaultWriter: { + prototype: WritableStreamDefaultWriter; + new (stream: WritableStream): WritableStreamDefaultWriter; + }; + + interface TransformStream { + readonly readable: ReadableStream; + readonly writable: WritableStream; + } + + var TransformStream: { + prototype: TransformStream; + new ( + transformer?: Transformer, + writableStrategy?: QueuingStrategy, + readableStrategy?: QueuingStrategy, + ): TransformStream; + }; + + interface TransformStreamDefaultController { + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; + } + + var TransformStreamDefaultController: { + prototype: TransformStreamDefaultController; + new (): TransformStreamDefaultController; + }; + + interface StreamPipeOptions { + preventAbort?: boolean; + preventCancel?: boolean; + /** + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + * + * Errors and closures of the source and destination streams propagate as follows: + * + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. + * + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. + * + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. + * + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. + */ + preventClose?: boolean; + signal?: AbortSignal; + } + + /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ + interface CountQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + readonly size: QueuingStrategySize; + } + + var CountQueuingStrategy: { + prototype: CountQueuingStrategy; + new (init: QueuingStrategyInit): CountQueuingStrategy; + }; + + interface QueuingStrategySize { + (chunk?: T): number; + } + + interface Transformer { + flush?: Bun.TransformerFlushCallback; + readableType?: undefined; + start?: Bun.TransformerStartCallback; + transform?: Bun.TransformerTransformCallback; + writableType?: undefined; + } + + interface Dict { + [key: string]: T | undefined; + } + + interface ReadOnlyDict { + readonly [key: string]: T | undefined; + } + + interface ErrnoException extends Error { + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; + } + + /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ + interface DOMException extends Error { + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; + } + + var DOMException: { + prototype: DOMException; + new (message?: string, name?: string): DOMException; + }; + + function alert(message?: string): void; + function confirm(message?: string): boolean; + function prompt(message?: string, _default?: string): string | null; + + type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; + var SubtleCrypto: { + prototype: _SubtleCrypto; + new (): _SubtleCrypto; + }; + + type _CryptoKey = import("crypto").webcrypto.CryptoKey; + interface CryptoKey extends _CryptoKey {} + var CryptoKey: { + prototype: CryptoKey; + new (): CryptoKey; + }; + + interface Position { + lineText: string; + file: string; + namespace: string; + line: number; + column: number; + length: number; + offset: number; + } + + class ResolveMessage { + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; + } + + class BuildMessage { + readonly name: "BuildMessage"; + readonly position: Position | null; + readonly message: string; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + } + + // Declare "static" methods in Error + interface ErrorConstructor { + /** Create .stack property on a target object */ + // eslint-disable-next-line @typescript-eslint/ban-types + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: + | ((err: Error, stackTraces: NodeJS.CallSite[]) => any) + | undefined; + + stackTraceLimit: number; + } + + interface ArrayBufferConstructor { + new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; + } + + interface ArrayBuffer { + /** + * Read-only. The length of the ArrayBuffer (in bytes). + */ + readonly byteLength: number; + /** + * Resize an ArrayBuffer in-place. + */ + resize(byteLength: number): ArrayBuffer; + + /** + * Returns a section of an ArrayBuffer. + */ + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; + } + + interface SharedArrayBuffer { + /** + * Grow the SharedArrayBuffer in-place. + */ + grow(size: number): SharedArrayBuffer; + } + + interface ArrayConstructor { + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + ): Promise[]>; + + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. Results of the map function are also awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * await Array.fromAsync([1], (n) => n + 1); // [2] + * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. + * @param thisArg - The `this` to which `mapFn` is bound. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; + } + + interface ConsoleOptions { + stdout: import("stream").Writable; + stderr?: import("stream").Writable; + ignoreErrors?: boolean; + colorMode?: boolean | "auto"; + inspectOptions?: import("util").InspectOptions; + groupIndentation?: number; + } + + interface Console { + /** + * Asynchronously read lines from standard input (fd 0) + * + * ```ts + * for await (const line of console) { + * console.log(line); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterableIterator; + + /** + * Write text or bytes to stdout + * + * Unlike {@link console.log}, this does no formatting and doesn't add a + * newline or spaces between arguments. You can pass it strings or bytes or + * any combination of the two. + * + * ```ts + * console.write("hello world!", "\n"); // "hello world\n" + * ``` + * + * @param data - The data to write + * @returns The number of bytes written + * + * This function is not available in the browser. + */ + write(...data: Array): number; + + /** + * Clear the console + */ + clear(): void; + + assert(condition?: boolean, ...data: any[]): void; + + /** + * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) + * @param label label counter + */ + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: any): void; + dirxml(...data: any[]): void; + /** + * Log to stderr in your terminal + * + * Appears in red + * + * @param data something to display + */ + error(...data: any[]): void; + /** Does nothing currently */ + group(...data: any[]): void; + /** Does nothing currently */ + groupCollapsed(...data: any[]): void; + /** Does nothing currently */ + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + /** + * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just + * logging the argument if it can't be parsed as tabular. + * + * ```js + * // These can't be parsed as tabular data + * console.table(Symbol()); + * // Symbol() + * + * console.table(undefined); + * // undefined + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ b โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * ``` + * @param properties Alternate properties for constructing the table. + */ + table(tabularData?: any, properties?: string[]): void; + /** + * Begin a timer to log with {@link console.timeEnd} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + time(label?: string): void; + /** + * End a timer to log with {@link console.time} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + timeStamp(label?: string): void; + trace(...data: any[]): void; + warn(...data: any[]): void; + + /** + * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. + */ + // Console: { + // new (options: ConsoleOptions): Console; + // new ( + // stdout: import("stream").Writable, + // stderr?: import("stream").Writable, + // ignoreErrors?: boolean, + // ): Console; + // }; + } + + var console: Console; + + interface ImportMeta { + /** + * `file://` url string for the current module. + * + * @example + * ```ts + * console.log(import.meta.url); + * "file:///Users/me/projects/my-app/src/my-app.ts" + * ``` + */ + url: string; + /** + * Absolute path to the source file + */ + readonly path: string; + /** + * Absolute path to the directory containing the source file. + * + * Does not have a trailing slash + */ + readonly dir: string; + /** + * Filename of the source file + */ + readonly file: string; + /** + * The environment variables of the process + * + * ```ts + * import.meta.env === process.env + * ``` + */ + readonly env: NodeJS.ProcessEnv; + + /** + * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead + * + * Resolve a module ID the same as if you imported it + * + * The `parent` argument is optional, and defaults to the current module's path. + */ + resolveSync(moduleId: string, parent?: string): string; + + /** + * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all + * calls to `require` with `import.meta.require` when transpiling ES Modules + * for the runtime. + * + * Warning: **This API is not stable** and may change or be removed in the + * future. Use at your own risk. + */ + require: NodeJS.Require; + + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; + + /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ + dirname: string; + + /** Alias of `import.meta.path`. Exists for Node.js compatibility */ + filename: string; + } + + /** + * NodeJS-style `require` function + * + * @param moduleId - The module ID to resolve + */ + var require: NodeJS.Require; + + /** Same as module.exports */ + var exports: any; + + interface NodeModule { + exports: any; + } + + var module: NodeModule; + + /** + * Creates a deep clone of an object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) + */ + function structuredClone( + value: T, + options?: Bun.StructuredSerializeOptions, + ): T; + + /** + * Post a message to the parent thread. + * + * Only useful in a worker thread; calling this from the main thread does nothing. + */ + function postMessage(message: any, transfer?: Bun.Transferable[]): void; + + interface EventSourceInit { + withCredentials?: boolean; + } + + interface PromiseConstructor { + /** + * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called + * separately. + * + * This is useful when you want to return a Promise and have code outside the Promise + * resolve or reject it. + * + * ## Example + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); + * + * setTimeout(() => { + * resolve("Hello world!"); + * }, 1000); + * + * await promise; // "Hello world!" + * ``` + * + * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). + */ + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; + } + + interface Navigator { + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; + } + + var navigator: Navigator; + + interface BlobPropertyBag { + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; + } + + interface Blob { + /** + * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + */ + new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; + /** + * Read the data from the blob as a JSON object. + * + * This first decodes the data from UTF-8, then parses it as JSON. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + json(): Promise; + + /** + * Read the data from the blob as a {@link FormData} object. + * + * This first decodes the data from UTF-8, then parses it as a + * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. + * + * The `type` property of the blob is used to determine the format of the + * body. + * + * This is a non-standard addition to the `Blob` API, to make it conform more + * closely to the `BodyMixin` API. + */ + formData(): Promise; + + arrayBuffer(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + */ + bytes(): Promise; + } + + var Blob: typeof Blob; } diff --git a/packages/bun-types/html-rewriter.d.ts b/packages/bun-types/html-rewriter.d.ts index 4b2b2954cff397..6bec7fea979ab2 100644 --- a/packages/bun-types/html-rewriter.d.ts +++ b/packages/bun-types/html-rewriter.d.ts @@ -1,129 +1,129 @@ declare namespace HTMLRewriterTypes { - interface HTMLRewriterElementContentHandlers { - element?(element: Element): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - } + interface HTMLRewriterElementContentHandlers { + element?(element: Element): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + } - interface HTMLRewriterDocumentContentHandlers { - doctype?(doctype: Doctype): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - end?(end: DocumentEnd): void | Promise; - } + interface HTMLRewriterDocumentContentHandlers { + doctype?(doctype: Doctype): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + end?(end: DocumentEnd): void | Promise; + } - interface Text { - /** The text content */ - readonly text: string; - /** Whether this chunk is the last piece of text in a text node */ - readonly lastInTextNode: boolean; - /** Whether this chunk was removed */ - readonly removed: boolean; - /** Insert content before this chunk */ - before(content: Content, options?: ContentOptions): Text; - /** Insert content after this chunk */ - after(content: Content, options?: ContentOptions): Text; - /** Replace this chunk with new content */ - replace(content: Content, options?: ContentOptions): Text; - /** Remove this chunk */ - remove(): Text; - } + interface Text { + /** The text content */ + readonly text: string; + /** Whether this chunk is the last piece of text in a text node */ + readonly lastInTextNode: boolean; + /** Whether this chunk was removed */ + readonly removed: boolean; + /** Insert content before this chunk */ + before(content: Content, options?: ContentOptions): Text; + /** Insert content after this chunk */ + after(content: Content, options?: ContentOptions): Text; + /** Replace this chunk with new content */ + replace(content: Content, options?: ContentOptions): Text; + /** Remove this chunk */ + remove(): Text; + } - interface Doctype { - /** The doctype name (e.g. "html" for ) */ - readonly name: string | null; - /** The doctype public identifier */ - readonly publicId: string | null; - /** The doctype system identifier */ - readonly systemId: string | null; - /** Whether this doctype was removed */ - readonly removed: boolean; - /** Remove this doctype */ - remove(): Doctype; - } + interface Doctype { + /** The doctype name (e.g. "html" for ) */ + readonly name: string | null; + /** The doctype public identifier */ + readonly publicId: string | null; + /** The doctype system identifier */ + readonly systemId: string | null; + /** Whether this doctype was removed */ + readonly removed: boolean; + /** Remove this doctype */ + remove(): Doctype; + } - interface DocumentEnd { - /** Append content at the end of the document */ - append(content: Content, options?: ContentOptions): DocumentEnd; - } + interface DocumentEnd { + /** Append content at the end of the document */ + append(content: Content, options?: ContentOptions): DocumentEnd; + } - interface ContentOptions { - /** Whether to parse the content as HTML */ - html?: boolean; - } + interface ContentOptions { + /** Whether to parse the content as HTML */ + html?: boolean; + } - type Content = string; + type Content = string; - interface Comment { - /** The comment text */ - text: string; - /** Whether this comment was removed */ - readonly removed: boolean; - /** Insert content before this comment */ - before(content: Content, options?: ContentOptions): Comment; - /** Insert content after this comment */ - after(content: Content, options?: ContentOptions): Comment; - /** Replace this comment with new content */ - replace(content: Content, options?: ContentOptions): Comment; - /** Remove this comment */ - remove(): Comment; - } + interface Comment { + /** The comment text */ + text: string; + /** Whether this comment was removed */ + readonly removed: boolean; + /** Insert content before this comment */ + before(content: Content, options?: ContentOptions): Comment; + /** Insert content after this comment */ + after(content: Content, options?: ContentOptions): Comment; + /** Replace this comment with new content */ + replace(content: Content, options?: ContentOptions): Comment; + /** Remove this comment */ + remove(): Comment; + } - interface Element { - /** The tag name in lowercase (e.g. "div", "span") */ - tagName: string; - /** Iterator for the element's attributes */ - readonly attributes: IterableIterator<[string, string]>; - /** Whether this element was removed */ - readonly removed: boolean; - /** Whether the element is explicitly self-closing, e.g. */ - readonly selfClosing: boolean; - /** - * Whether the element can have inner content. Returns `true` unless - * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) - * - or it's self-closing in a foreign context (eg. in SVG, MathML). - */ - readonly canHaveContent: boolean; - /** The element's namespace URI */ - readonly namespaceURI: string; - /** Get an attribute value by name */ - getAttribute(name: string): string | null; - /** Check if an attribute exists */ - hasAttribute(name: string): boolean; - /** Set an attribute value */ - setAttribute(name: string, value: string): Element; - /** Remove an attribute */ - removeAttribute(name: string): Element; - /** Insert content before this element */ - before(content: Content, options?: ContentOptions): Element; - /** Insert content after this element */ - after(content: Content, options?: ContentOptions): Element; - /** Insert content at the start of this element */ - prepend(content: Content, options?: ContentOptions): Element; - /** Insert content at the end of this element */ - append(content: Content, options?: ContentOptions): Element; - /** Replace this element with new content */ - replace(content: Content, options?: ContentOptions): Element; - /** Remove this element and its contents */ - remove(): Element; - /** Remove this element but keep its contents */ - removeAndKeepContent(): Element; - /** Set the inner content of this element */ - setInnerContent(content: Content, options?: ContentOptions): Element; - /** Add a handler for the end tag of this element */ - onEndTag(handler: (tag: EndTag) => void | Promise): void; - } + interface Element { + /** The tag name in lowercase (e.g. "div", "span") */ + tagName: string; + /** Iterator for the element's attributes */ + readonly attributes: IterableIterator<[string, string]>; + /** Whether this element was removed */ + readonly removed: boolean; + /** Whether the element is explicitly self-closing, e.g. */ + readonly selfClosing: boolean; + /** + * Whether the element can have inner content. Returns `true` unless + * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) + * - or it's self-closing in a foreign context (eg. in SVG, MathML). + */ + readonly canHaveContent: boolean; + /** The element's namespace URI */ + readonly namespaceURI: string; + /** Get an attribute value by name */ + getAttribute(name: string): string | null; + /** Check if an attribute exists */ + hasAttribute(name: string): boolean; + /** Set an attribute value */ + setAttribute(name: string, value: string): Element; + /** Remove an attribute */ + removeAttribute(name: string): Element; + /** Insert content before this element */ + before(content: Content, options?: ContentOptions): Element; + /** Insert content after this element */ + after(content: Content, options?: ContentOptions): Element; + /** Insert content at the start of this element */ + prepend(content: Content, options?: ContentOptions): Element; + /** Insert content at the end of this element */ + append(content: Content, options?: ContentOptions): Element; + /** Replace this element with new content */ + replace(content: Content, options?: ContentOptions): Element; + /** Remove this element and its contents */ + remove(): Element; + /** Remove this element but keep its contents */ + removeAndKeepContent(): Element; + /** Set the inner content of this element */ + setInnerContent(content: Content, options?: ContentOptions): Element; + /** Add a handler for the end tag of this element */ + onEndTag(handler: (tag: EndTag) => void | Promise): void; + } - interface EndTag { - /** The tag name in lowercase */ - name: string; - /** Insert content before this end tag */ - before(content: Content, options?: ContentOptions): EndTag; - /** Insert content after this end tag */ - after(content: Content, options?: ContentOptions): EndTag; - /** Remove this end tag */ - remove(): EndTag; - } + interface EndTag { + /** The tag name in lowercase */ + name: string; + /** Insert content before this end tag */ + before(content: Content, options?: ContentOptions): EndTag; + /** Insert content after this end tag */ + after(content: Content, options?: ContentOptions): EndTag; + /** Remove this end tag */ + remove(): EndTag; + } } /** @@ -149,36 +149,41 @@ declare namespace HTMLRewriterTypes { * ``` */ declare class HTMLRewriter { - constructor(); - /** - * Add handlers for elements matching a CSS selector - * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") - * @param handlers - Object containing handler functions for elements, comments, and text nodes - */ - on(selector: string, handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers): HTMLRewriter; + constructor(); + /** + * Add handlers for elements matching a CSS selector + * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") + * @param handlers - Object containing handler functions for elements, comments, and text nodes + */ + on( + selector: string, + handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers, + ): HTMLRewriter; - /** - * Add handlers for document-level events - * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end - */ - onDocument(handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers): HTMLRewriter; + /** + * Add handlers for document-level events + * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end + */ + onDocument( + handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers, + ): HTMLRewriter; - /** - * Transform HTML content - * @param input - The HTML to transform - * @returns A new {@link Response} with the transformed HTML - */ - transform(input: Response | Blob | Bun.BufferSource): Response; - /** - * Transform HTML content - * @param input - The HTML string to transform - * @returns A new {@link String} containing the transformed HTML - */ - transform(input: string): string; - /** - * Transform HTML content - * @param input - The HTML to transform as a {@link ArrayBuffer} - * @returns A new {@link ArrayBuffer} with the transformed HTML - */ - transform(input: ArrayBuffer): ArrayBuffer; + /** + * Transform HTML content + * @param input - The HTML to transform + * @returns A new {@link Response} with the transformed HTML + */ + transform(input: Response | Blob | Bun.BufferSource): Response; + /** + * Transform HTML content + * @param input - The HTML string to transform + * @returns A new {@link String} containing the transformed HTML + */ + transform(input: string): string; + /** + * Transform HTML content + * @param input - The HTML to transform as a {@link ArrayBuffer} + * @returns A new {@link ArrayBuffer} with the transformed HTML + */ + transform(input: ArrayBuffer): ArrayBuffer; } diff --git a/packages/bun-types/jsc.d.ts b/packages/bun-types/jsc.d.ts index 2a07534586516c..c5942da2813fb5 100644 --- a/packages/bun-types/jsc.d.ts +++ b/packages/bun-types/jsc.d.ts @@ -1,229 +1,243 @@ declare module "bun:jsc" { - /** - * This used to be called "describe" but it could be confused with the test runner. - */ - function jscDescribe(value: any): string; - function jscDescribeArray(args: any[]): string; - function gcAndSweep(): number; - function fullGC(): number; - function edenGC(): number; - function heapSize(): number; - function heapStats(): { - heapSize: number; - heapCapacity: number; - extraMemorySize: number; - objectCount: number; - protectedObjectCount: number; - globalObjectCount: number; - protectedGlobalObjectCount: number; - objectTypeCounts: Record; - protectedObjectTypeCounts: Record; - }; - function memoryUsage(): { - current: number; - peak: number; - currentCommit: number; - peakCommit: number; - pageFaults: number; - }; - function getRandomSeed(): number; - function setRandomSeed(value: number): void; - function isRope(input: string): boolean; - function callerSourceOrigin(): string; - function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; - function noOSRExitFuzzing(func: (...args: any[]) => any): (...args: any[]) => any; - function optimizeNextInvocation(func: (...args: any[]) => any): void; - function numberOfDFGCompiles(func: (...args: any[]) => any): number; - function releaseWeakRefs(): void; - function totalCompileTime(func: (...args: any[]) => any): number; - function reoptimizationRetryCount(func: (...args: any[]) => any): number; - function drainMicrotasks(): void; + /** + * This used to be called "describe" but it could be confused with the test runner. + */ + function jscDescribe(value: any): string; + function jscDescribeArray(args: any[]): string; + function gcAndSweep(): number; + function fullGC(): number; + function edenGC(): number; + function heapSize(): number; + function heapStats(): { + heapSize: number; + heapCapacity: number; + extraMemorySize: number; + objectCount: number; + protectedObjectCount: number; + globalObjectCount: number; + protectedGlobalObjectCount: number; + objectTypeCounts: Record; + protectedObjectTypeCounts: Record; + }; + function memoryUsage(): { + current: number; + peak: number; + currentCommit: number; + peakCommit: number; + pageFaults: number; + }; + function getRandomSeed(): number; + function setRandomSeed(value: number): void; + function isRope(input: string): boolean; + function callerSourceOrigin(): string; + function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; + function noOSRExitFuzzing( + func: (...args: any[]) => any, + ): (...args: any[]) => any; + function optimizeNextInvocation(func: (...args: any[]) => any): void; + function numberOfDFGCompiles(func: (...args: any[]) => any): number; + function releaseWeakRefs(): void; + function totalCompileTime(func: (...args: any[]) => any): number; + function reoptimizationRetryCount(func: (...args: any[]) => any): number; + function drainMicrotasks(): void; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A SharedArrayBuffer that can be sent to another Bun instance. - */ - function serialize(value: any, options?: { binaryType?: "arraybuffer" }): SharedArrayBuffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A SharedArrayBuffer that can be sent to another Bun instance. + */ + function serialize( + value: any, + options?: { binaryType?: "arraybuffer" }, + ): SharedArrayBuffer; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A Buffer that can be sent to another Bun instance. - */ - function serialize(value: any, options?: { binaryType: "nodebuffer" }): Buffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A Buffer that can be sent to another Bun instance. + */ + function serialize( + value: any, + options?: { binaryType: "nodebuffer" }, + ): Buffer; - /** - * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. - * - * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. - */ - function deserialize(value: ArrayBufferLike | NodeJS.TypedArray | Buffer): any; + /** + * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. + * + * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. + */ + function deserialize( + value: ArrayBufferLike | NodeJS.TypedArray | Buffer, + ): any; - /** - * Set the timezone used by Intl, Date, etc. - * - * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" - * - * @returns The normalized time zone string - * - * You can also set process.env.TZ to the time zone you want to use. - * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` - */ - function setTimeZone(timeZone: string): string; + /** + * Set the timezone used by Intl, Date, etc. + * + * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" + * + * @returns The normalized time zone string + * + * You can also set process.env.TZ to the time zone you want to use. + * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` + */ + function setTimeZone(timeZone: string): string; - interface SamplingProfile { - /** - * A formatted summary of the top functions - * - * Example output: - * ```js - * - * Sampling rate: 100.000000 microseconds. Total samples: 6858 - * Top functions as - * 2948 '#:8' - * 393 'visit#:8' - * 263 'push#:8' - * 164 'scan_ref_scoped#:8' - * 164 'walk#:8' - * 144 'pop#:8' - * 107 'extract_candidates#:8' - * 94 'get#:8' - * 82 'Function#:4294967295' - * 79 'set#:8' - * 67 'forEach#:5' - * 58 'collapse#:8' - * ``` - */ - functions: string; - /** - * A formatted summary of the top bytecodes - * - * Example output: - * ```js - * Tier breakdown: - * ----------------------------------- - * LLInt: 106 (1.545640%) - * Baseline: 2355 (34.339458%) - * DFG: 3290 (47.973170%) - * FTL: 833 (12.146398%) - * js builtin: 132 (1.924759%) - * Wasm: 0 (0.000000%) - * Host: 111 (1.618548%) - * RegExp: 15 (0.218723%) - * C/C++: 0 (0.000000%) - * Unknown Executable: 148 (2.158064%) - * - * Hottest bytecodes as - * 273 'visit#:DFG:bc#63' - * 121 'walk#:DFG:bc#7' - * 119 '#:Baseline:bc#1' - * 82 'Function#:None:' - * 66 '#:DFG:bc#11' - * 65 '#:DFG:bc#33' - * 58 '#:Baseline:bc#7' - * 53 '#:Baseline:bc#23' - * 50 'forEach#:DFG:bc#83' - * 49 'pop#:FTL:bc#65' - * 47 '#:DFG:bc#99' - * 45 '#:DFG:bc#16' - * 44 '#:DFG:bc#7' - * 44 '#:Baseline:bc#30' - * 44 'push#:FTL:bc#214' - * 41 '#:DFG:bc#50' - * 39 'get#:DFG:bc#27' - * 39 '#:Baseline:bc#0' - * 36 '#:DFG:bc#27' - * 36 'Dictionary#:DFG:bc#41' - * 36 'visit#:DFG:bc#81' - * 36 'get#:FTL:bc#11' - * 32 'push#:FTL:bc#49' - * 31 '#:DFG:bc#76' - * 31 '#:DFG:bc#10' - * 31 '#:DFG:bc#73' - * 29 'set#:DFG:bc#28' - * 28 'in_boolean_context#:DFG:bc#104' - * 28 '#:Baseline:' - * 28 'regExpSplitFast#:None:' - * 26 'visit#:DFG:bc#95' - * 26 'pop#:FTL:bc#120' - * 25 '#:DFG:bc#23' - * 25 'push#:FTL:bc#152' - * 24 'push#:FTL:bc#262' - * 24 '#:FTL:bc#10' - * 23 'is_identifier_char#:DFG:bc#22' - * 23 'visit#:DFG:bc#22' - * 22 '#:FTL:bc#27' - * 22 'indexOf#:None:' - * ``` - */ - bytecodes: string; + interface SamplingProfile { + /** + * A formatted summary of the top functions + * + * Example output: + * ```js + * + * Sampling rate: 100.000000 microseconds. Total samples: 6858 + * Top functions as + * 2948 '#:8' + * 393 'visit#:8' + * 263 'push#:8' + * 164 'scan_ref_scoped#:8' + * 164 'walk#:8' + * 144 'pop#:8' + * 107 'extract_candidates#:8' + * 94 'get#:8' + * 82 'Function#:4294967295' + * 79 'set#:8' + * 67 'forEach#:5' + * 58 'collapse#:8' + * ``` + */ + functions: string; + /** + * A formatted summary of the top bytecodes + * + * Example output: + * ```js + * Tier breakdown: + * ----------------------------------- + * LLInt: 106 (1.545640%) + * Baseline: 2355 (34.339458%) + * DFG: 3290 (47.973170%) + * FTL: 833 (12.146398%) + * js builtin: 132 (1.924759%) + * Wasm: 0 (0.000000%) + * Host: 111 (1.618548%) + * RegExp: 15 (0.218723%) + * C/C++: 0 (0.000000%) + * Unknown Executable: 148 (2.158064%) + * + * Hottest bytecodes as + * 273 'visit#:DFG:bc#63' + * 121 'walk#:DFG:bc#7' + * 119 '#:Baseline:bc#1' + * 82 'Function#:None:' + * 66 '#:DFG:bc#11' + * 65 '#:DFG:bc#33' + * 58 '#:Baseline:bc#7' + * 53 '#:Baseline:bc#23' + * 50 'forEach#:DFG:bc#83' + * 49 'pop#:FTL:bc#65' + * 47 '#:DFG:bc#99' + * 45 '#:DFG:bc#16' + * 44 '#:DFG:bc#7' + * 44 '#:Baseline:bc#30' + * 44 'push#:FTL:bc#214' + * 41 '#:DFG:bc#50' + * 39 'get#:DFG:bc#27' + * 39 '#:Baseline:bc#0' + * 36 '#:DFG:bc#27' + * 36 'Dictionary#:DFG:bc#41' + * 36 'visit#:DFG:bc#81' + * 36 'get#:FTL:bc#11' + * 32 'push#:FTL:bc#49' + * 31 '#:DFG:bc#76' + * 31 '#:DFG:bc#10' + * 31 '#:DFG:bc#73' + * 29 'set#:DFG:bc#28' + * 28 'in_boolean_context#:DFG:bc#104' + * 28 '#:Baseline:' + * 28 'regExpSplitFast#:None:' + * 26 'visit#:DFG:bc#95' + * 26 'pop#:FTL:bc#120' + * 25 '#:DFG:bc#23' + * 25 'push#:FTL:bc#152' + * 24 'push#:FTL:bc#262' + * 24 '#:FTL:bc#10' + * 23 'is_identifier_char#:DFG:bc#22' + * 23 'visit#:DFG:bc#22' + * 22 '#:FTL:bc#27' + * 22 'indexOf#:None:' + * ``` + */ + bytecodes: string; - /** - * Stack traces of the top functions - */ - stackTraces: string[]; - } + /** + * Stack traces of the top functions + */ + stackTraces: string[]; + } - /** - * Run JavaScriptCore's sampling profiler for a particular function - * - * This is pretty low-level. - * - * Things to know: - * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation - * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile - * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile - * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile - */ - function profile any>( - callback: T, - sampleInterval?: number, - ...args: Parameters - ): ReturnType extends Promise ? Promise : SamplingProfile; + /** + * Run JavaScriptCore's sampling profiler for a particular function + * + * This is pretty low-level. + * + * Things to know: + * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation + * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile + * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile + * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile + */ + function profile any>( + callback: T, + sampleInterval?: number, + ...args: Parameters + ): ReturnType extends Promise + ? Promise + : SamplingProfile; - /** - * This returns objects which native code has explicitly protected from being - * garbage collected - * - * By calling this function you create another reference to the object, which - * will further prevent it from being garbage collected - * - * This function is mostly a debugging tool for bun itself. - * - * Warning: not all objects returned are supposed to be observable from JavaScript - */ - function getProtectedObjects(): any[]; + /** + * This returns objects which native code has explicitly protected from being + * garbage collected + * + * By calling this function you create another reference to the object, which + * will further prevent it from being garbage collected + * + * This function is mostly a debugging tool for bun itself. + * + * Warning: not all objects returned are supposed to be observable from JavaScript + */ + function getProtectedObjects(): any[]; - /** - * Start a remote debugging socket server on the given port. - * - * This exposes JavaScriptCore's built-in debugging server. - * - * This is untested. May not be supported yet on macOS - */ - function startRemoteDebugger(host?: string, port?: number): void; + /** + * Start a remote debugging socket server on the given port. + * + * This exposes JavaScriptCore's built-in debugging server. + * + * This is untested. May not be supported yet on macOS + */ + function startRemoteDebugger(host?: string, port?: number): void; - /** - * Run JavaScriptCore's sampling profiler - */ - function startSamplingProfiler(optionalDirectory?: string): void; + /** + * Run JavaScriptCore's sampling profiler + */ + function startSamplingProfiler(optionalDirectory?: string): void; - /** - * Non-recursively estimate the memory usage of an object, excluding the memory usage of - * properties or other objects it references. For more accurate per-object - * memory usage, use {@link Bun.generateHeapSnapshot}. - * - * This is a best-effort estimate. It may not be 100% accurate. When it's - * wrong, it may mean the memory is non-contiguous (such as a large array). - * - * Passing a primitive type that isn't heap allocated returns 0. - */ - function estimateShallowMemoryUsageOf(value: object | CallableFunction | bigint | symbol | string): number; + /** + * Non-recursively estimate the memory usage of an object, excluding the memory usage of + * properties or other objects it references. For more accurate per-object + * memory usage, use {@link Bun.generateHeapSnapshot}. + * + * This is a best-effort estimate. It may not be 100% accurate. When it's + * wrong, it may mean the memory is non-contiguous (such as a large array). + * + * Passing a primitive type that isn't heap allocated returns 0. + */ + function estimateShallowMemoryUsageOf( + value: object | CallableFunction | bigint | symbol | string, + ): number; } diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts new file mode 100644 index 00000000000000..56b6e74a791b6c --- /dev/null +++ b/packages/bun-types/new/index.d.ts @@ -0,0 +1,449 @@ +export {}; +declare var onmessage: never; + +declare var Bun: typeof import("bun"); +declare var TextEncoder: typeof TextEncoder; +declare var TextDecoder: typeof TextDecoder; +declare var crypto: Crypto; +declare var performance: Performance; +declare var Event: { + prototype: Event; + new (type: string, eventInitDict?: Bun.EventInit): Event; +}; +declare var EventTarget: { + prototype: EventTarget; + new (): EventTarget; +}; +declare var File: typeof File; +declare var ShadowRealm: { + prototype: ShadowRealm; + new (): ShadowRealm; +}; +declare var queueMicrotask: (callback: (...args: any[]) => void) => void; +declare var reportError: (error: any) => void; +declare var clearInterval: (id?: number | Timer) => void; +declare var clearTimeout: (id?: number | Timer) => void; +declare var clearImmediate: (id?: number | Timer) => void; +declare var setImmediate: (handler: Bun.TimerHandler, ...arguments: any[]) => Timer; +declare var setInterval: (handler: Bun.TimerHandler, interval?: number, ...arguments: any[]) => Timer; +declare var setTimeout: (handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]) => Timer; +declare var addEventListener: typeof addEventListener; +declare var removeEventListener: typeof removeEventListener; +declare var ErrorEvent: { + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; +}; +declare var CloseEvent: { + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; +}; +declare var MessageEvent: { + prototype: MessageEvent; + new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; +}; +declare var CustomEvent: { + prototype: CustomEvent; + new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; +}; +declare var Loader: { + registry: Map< + string, + { + key: string; + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array; + module: { + dependenciesMap: Map; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; + dependencyKeysIfEvaluated: (specifier: string) => string[]; + resolve: (specifier: string, referrer: string) => string; +}; +declare var Blob: typeof Blob; +declare var WebSocket: typeof import("ws").WebSocket; +declare var navigator: Navigator; +declare var console: Console; +declare var require: NodeJS.Require; +declare var exports: any; +declare var module: NodeModule; +declare function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; +declare function postMessage(message: any, transfer?: Bun.Transferable[]): void; +declare function alert(message?: string): void; +declare function confirm(message?: string): boolean; +declare function prompt(message?: string, _default?: string): string | null; + +declare interface Timer { + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; + [Symbol.toPrimitive](): number; +} + +declare interface ReadableStream extends import("stream/web").ReadableStream {} +declare interface WritableStream extends import("stream/web").WritableStream {} +declare interface Worker extends import("worker_threads").Worker {} + +declare interface ShadowRealm { + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; +} + +declare interface Event { + readonly bubbles: boolean; + cancelBubble: () => void; + readonly cancelable: boolean; + readonly composed: boolean; + composedPath(): [EventTarget?]; + readonly currentTarget: EventTarget | null; + readonly defaultPrevented: boolean; + readonly eventPhase: 0 | 2; + readonly isTrusted: boolean; + preventDefault(): void; + returnValue: boolean; + readonly srcElement: EventTarget | null; + stopImmediatePropagation(): void; + stopPropagation(): void; + readonly target: EventTarget | null; + readonly timeStamp: number; + readonly type: string; +} + +declare module "bun" { + export function fetch(request: Request, init?: RequestInit): Promise; + export function fetch(url: string | URL | Request, init?: RequestInit): Promise; + export function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise; +} + +declare namespace Bun { + export * from "bun"; +} + +declare interface EventTarget { + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + dispatchEvent(event: Event): boolean; + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; +} + +declare interface File extends Blob { + readonly lastModified: number; + readonly name: string; +} + +declare interface RequestInit extends import("undici-types").RequestInit { + verbose?: boolean; + proxy?: string; + s3?: import("bun").S3Options; +} + +declare interface ErrorEvent extends Event { + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; +} + +declare interface CloseEvent extends Event { + readonly code: number; + readonly reason: string; + readonly wasClean: boolean; +} + +declare interface MessageEvent extends Event { + readonly data: T; + readonly lastEventId: string; + readonly origin: string; + readonly ports: readonly (typeof MessagePort)[]; + readonly source: Bun.MessageEventSource | null; +} + +declare interface CustomEvent extends Event { + readonly detail: T; +} + +declare interface EventListener { + (evt: Event): void; +} + +declare interface EventListenerObject { + handleEvent(object: Event): void; +} + +declare interface FetchEvent extends Event { + readonly request: Request; + readonly url: string; + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; +} + +declare interface EventMap { + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; +} + +declare interface AddEventListenerOptions extends Bun.EventListenerOptions { + once?: boolean; + passive?: boolean; + signal?: AbortSignal; +} + +declare interface Navigator { + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; +} + +declare interface Blob { + json(): Promise; + formData(): Promise; + arrayBuffer(): Promise; + bytes(): Promise; +} + +declare interface ArrayBuffer { + readonly byteLength: number; + resize(byteLength: number): ArrayBuffer; + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; +} + +declare interface SharedArrayBuffer { + grow(size: number): SharedArrayBuffer; +} + +declare interface ImportMeta { + url: string; + readonly path: string; + readonly dir: string; + readonly file: string; + readonly env: NodeJS.ProcessEnv; + resolveSync(moduleId: string, parent?: string): string; + require: NodeJS.Require; + readonly main: boolean; + dirname: string; + filename: string; + hot?: { + data: any; + }; +} + +declare function fetch(request: Request, init?: RequestInit): Promise; +declare function fetch(url: string | URL | Request, init?: RequestInit): Promise; +declare function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise; + +declare namespace Bun { + interface Env { + [key: string]: string | undefined; + } + + interface ProcessEnv extends Env {} + + export const env: Env; + export const fetch: typeof globalThis.fetch; +} + +declare interface NodeModule { + exports: any; +} + +declare namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; + isBun: true; + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + + interface ProcessVersions extends Dict { + bun: string; + } + + interface ProcessEnv extends Env {} +} + +declare namespace WebAssembly { + interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} + interface GlobalDescriptor + extends Bun.WebAssembly.GlobalDescriptor {} + interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} + interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} + interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} + interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} + interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} + + interface LinkError extends Error {} + var LinkError: { + prototype: LinkError; + new (message?: string): LinkError; + (message?: string): LinkError; + }; + + interface CompileError extends Error {} + var CompileError: { + prototype: CompileError; + new (message?: string): CompileError; + (message?: string): CompileError; + }; + + interface RuntimeError extends Error {} + var RuntimeError: { + prototype: RuntimeError; + new (message?: string): RuntimeError; + (message?: string): RuntimeError; + }; + + interface Global { + value: ValueTypeMap[T]; + valueOf(): ValueTypeMap[T]; + } + var Global: { + prototype: Global; + new ( + descriptor: GlobalDescriptor, + v?: ValueTypeMap[T], + ): Global; + }; + + interface Instance { + readonly exports: Bun.WebAssembly.Exports; + } + var Instance: { + prototype: Instance; + new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; + }; + + interface Memory { + readonly buffer: ArrayBuffer; + grow(delta: number): number; + } + var Memory: { + prototype: Memory; + new (descriptor: MemoryDescriptor): Memory; + }; + + interface Module {} + var Module: { + prototype: Module; + new (bytes: Bun.BufferSource): Module; + customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; + exports(moduleObject: Module): ModuleExportDescriptor[]; + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + + interface Table { + readonly length: number; + get(index: number): any; + grow(delta: number, value?: any): number; + set(index: number, value?: any): void; + } + var Table: { + prototype: Table; + new (descriptor: TableDescriptor, value?: any): Table; + }; + + function compile(bytes: Bun.BufferSource): Promise; + function compileStreaming(source: Response | PromiseLike): Promise; + function instantiate( + bytes: Bun.BufferSource, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; + function instantiateStreaming( + source: Response | PromiseLike, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + function validate(bytes: Bun.BufferSource): boolean; +} + +declare interface Dict { + [key: string]: T | undefined; +} + +declare interface ReadOnlyDict { + readonly [key: string]: T | undefined; +} + +declare interface ErrnoException extends Error { + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; +} + +declare interface DOMException extends Error { + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; +} + +declare var DOMException: { + prototype: DOMException; + new (message?: string, name?: string): DOMException; +}; + +declare interface PromiseConstructor { + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; +} + +declare interface ArrayConstructor { + fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; +} + +declare module "*.svg" { + const content: string; + export = content; +} diff --git a/packages/bun-types/overrides.d.ts b/packages/bun-types/overrides.d.ts index 2c9563224342e2..e679e20ae30824 100644 --- a/packages/bun-types/overrides.d.ts +++ b/packages/bun-types/overrides.d.ts @@ -3,62 +3,72 @@ export {}; import type { BunFile, Env, PathLike } from "bun"; declare global { - namespace NodeJS { - interface ProcessVersions extends Dict { - bun: string; - } - interface ProcessEnv extends Env {} - } + namespace NodeJS { + interface ProcessVersions extends Dict { + bun: string; + } + interface ProcessEnv extends Env {} + } } declare module "fs/promises" { - function exists(path: PathLike): Promise; + function exists(path: PathLike): Promise; } declare module "tls" { - interface BunConnectionOptions extends Omit { - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: string | Buffer | NodeJS.TypedArray | BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: - | string - | Buffer - | NodeJS.TypedArray - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: - | string - | Buffer - | BunFile - | NodeJS.TypedArray - | Array - | undefined; - } + interface BunConnectionOptions + extends Omit { + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: + | string + | Buffer + | NodeJS.TypedArray + | BunFile + | Array + | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: + | string + | Buffer + | NodeJS.TypedArray + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: + | string + | Buffer + | BunFile + | NodeJS.TypedArray + | Array + | undefined; + } - function connect(options: BunConnectionOptions, secureConnectListener?: () => void): TLSSocket; + function connect( + options: BunConnectionOptions, + secureConnectListener?: () => void, + ): TLSSocket; } diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index 1f7ffd8665fe8b..f07e563727bd7e 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -1,7 +1,7 @@ { "name": "bun-types", "license": "MIT", - "types": "./index.d.ts", + "types": "./new/index.d.ts", "description": "Type definitions and documentation for Bun, an incredibly fast JavaScript runtime", "repository": { "type": "git", @@ -9,7 +9,7 @@ "directory": "packages/bun-types" }, "files": [ - "*.d.ts", + "new/**/*.d.ts", "docs/**/*.md", "docs/*.md" ], diff --git a/packages/bun-types/sqlite.d.ts b/packages/bun-types/sqlite.d.ts index dd370d3f46bcc2..303469772cb98c 100644 --- a/packages/bun-types/sqlite.d.ts +++ b/packages/bun-types/sqlite.d.ts @@ -24,1118 +24,1143 @@ * | `null` | `NULL` | */ declare module "bun:sqlite" { - export class Database implements Disposable { - /** - * Open or create a SQLite3 database - * - * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. - * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. - * - * @example - * - * ```ts - * const db = new Database("mydb.sqlite"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open an in-memory database - * - * ```ts - * const db = new Database(":memory:"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open read-only - * - * ```ts - * const db = new Database("mydb.sqlite", {readonly: true}); - * ``` - */ - constructor( - filename?: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; + export class Database implements Disposable { + /** + * Open or create a SQLite3 database + * + * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. + * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. + * + * @example + * + * ```ts + * const db = new Database("mydb.sqlite"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open an in-memory database + * + * ```ts + * const db = new Database(":memory:"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open read-only + * + * ```ts + * const db = new Database("mydb.sqlite", {readonly: true}); + * ``` + */ + constructor( + filename?: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; - /** - * When set to `true`, integers are returned as `bigint` types. - * - * When set to `false`, integers are returned as `number` types and truncated to 52 bits. - * - * @default false - * @since v1.1.14 - */ - safeIntegers?: boolean; + /** + * When set to `true`, integers are returned as `bigint` types. + * + * When set to `false`, integers are returned as `number` types and truncated to 52 bits. + * + * @default false + * @since v1.1.14 + */ + safeIntegers?: boolean; - /** - * When set to `false` or `undefined`: - * - Queries missing bound parameters will NOT throw an error - * - Bound named parameters in JavaScript need to exactly match the SQL query. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: false }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); - * ``` - * - * When set to `true`: - * - Queries missing bound parameters will throw an error - * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: true }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); - * ``` - * @since v1.1.14 - */ - strict?: boolean; - }, - ); + /** + * When set to `false` or `undefined`: + * - Queries missing bound parameters will NOT throw an error + * - Bound named parameters in JavaScript need to exactly match the SQL query. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: false }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); + * ``` + * + * When set to `true`: + * - Queries missing bound parameters will throw an error + * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: true }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); + * ``` + * @since v1.1.14 + */ + strict?: boolean; + }, + ); - /** - * This is an alias of `new Database()` - * - * See {@link Database} - */ - static open( - filename: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; - }, - ): Database; + /** + * This is an alias of `new Database()` + * + * See {@link Database} + */ + static open( + filename: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; + }, + ): Database; - /** - * Execute a SQL query **without returning any results**. - * - * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * ``` - * - * Useful for queries like: - * - `CREATE TABLE` - * - `INSERT INTO` - * - `UPDATE` - * - `DELETE FROM` - * - `DROP TABLE` - * - `PRAGMA` - * - `ATTACH DATABASE` - * - `DETACH DATABASE` - * - `REINDEX` - * - `VACUUM` - * - `EXPLAIN ANALYZE` - * - `CREATE INDEX` - * - `CREATE TRIGGER` - * - `CREATE VIEW` - * - `CREATE VIRTUAL TABLE` - * - `CREATE TEMPORARY TABLE` - * - * @param sql The SQL query to run - * - * @param bindings Optional bindings for the query - * - * @returns `Database` instance - * - * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. - * - * * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(sqlQuery: string, ...bindings: ParamsType[]): Changes; - /** + /** + * Execute a SQL query **without returning any results**. + * + * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * ``` + * + * Useful for queries like: + * - `CREATE TABLE` + * - `INSERT INTO` + * - `UPDATE` + * - `DELETE FROM` + * - `DROP TABLE` + * - `PRAGMA` + * - `ATTACH DATABASE` + * - `DETACH DATABASE` + * - `REINDEX` + * - `VACUUM` + * - `EXPLAIN ANALYZE` + * - `CREATE INDEX` + * - `CREATE TRIGGER` + * - `CREATE VIEW` + * - `CREATE VIRTUAL TABLE` + * - `CREATE TEMPORARY TABLE` + * + * @param sql The SQL query to run + * + * @param bindings Optional bindings for the query + * + * @returns `Database` instance + * + * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. + * + * * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run( + sqlQuery: string, + ...bindings: ParamsType[] + ): Changes; + /** This is an alias of {@link Database.prototype.run} */ - exec(sqlQuery: string, ...bindings: ParamsType[]): Changes; + exec( + sqlQuery: string, + ...bindings: ParamsType[] + ): Changes; - /** - * Compile a SQL query and return a {@link Statement} object. This is the - * same as {@link prepare} except that it caches the compiled query. - * - * This **does not execute** the query, but instead prepares it for later - * execution and caches the compiled query if possible. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * - * // run the query again - * stmt.all(); - * ``` - * - * @param sql The SQL query to compile - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - query( - sqlQuery: string, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. This is the + * same as {@link prepare} except that it caches the compiled query. + * + * This **does not execute** the query, but instead prepares it for later + * execution and caches the compiled query if possible. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * + * // run the query again + * stmt.all(); + * ``` + * + * @param sql The SQL query to compile + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + query( + sqlQuery: string, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Compile a SQL query and return a {@link Statement} object. - * - * This does not cache the compiled query and does not execute the query. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * ``` - * - * @param sql The SQL query to compile - * @param params Optional bindings for the query - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - prepare( - sqlQuery: string, - params?: ParamsType, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. + * + * This does not cache the compiled query and does not execute the query. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * ``` + * + * @param sql The SQL query to compile + * @param params Optional bindings for the query + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + prepare< + ReturnType, + ParamsType extends SQLQueryBindings | SQLQueryBindings[], + >( + sqlQuery: string, + params?: ParamsType, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Is the database in a transaction? - * - * @returns `true` if the database is in a transaction, `false` otherwise - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * db.run("BEGIN"); - * db.run("INSERT INTO foo VALUES (?)", ["qux"]); - * console.log(db.inTransaction()); - * ``` - */ - get inTransaction(): boolean; + /** + * Is the database in a transaction? + * + * @returns `true` if the database is in a transaction, `false` otherwise + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * db.run("BEGIN"); + * db.run("INSERT INTO foo VALUES (?)", ["qux"]); + * console.log(db.inTransaction()); + * ``` + */ + get inTransaction(): boolean; - /** - * Close the database connection. - * - * It is safe to call this method multiple times. If the database is already - * closed, this is a no-op. Running queries after the database has been - * closed will throw an error. - * - * @example - * ```ts - * db.close(); - * ``` - * This is called automatically when the database instance is garbage collected. - * - * Internally, this calls `sqlite3_close_v2`. - */ - close( - /** - * If `true`, then the database will throw an error if it is in use - * @default false - * - * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. - * - * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). - * - * Bun will automatically call close by default when the database instance is garbage collected. - * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. - */ - throwOnError?: boolean, - ): void; + /** + * Close the database connection. + * + * It is safe to call this method multiple times. If the database is already + * closed, this is a no-op. Running queries after the database has been + * closed will throw an error. + * + * @example + * ```ts + * db.close(); + * ``` + * This is called automatically when the database instance is garbage collected. + * + * Internally, this calls `sqlite3_close_v2`. + */ + close( + /** + * If `true`, then the database will throw an error if it is in use + * @default false + * + * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. + * + * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). + * + * Bun will automatically call close by default when the database instance is garbage collected. + * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. + */ + throwOnError?: boolean, + ): void; - /** - * The filename passed when `new Database()` was called - * @example - * ```ts - * const db = new Database("mydb.sqlite"); - * console.log(db.filename); - * // => "mydb.sqlite" - * ``` - */ - readonly filename: string; + /** + * The filename passed when `new Database()` was called + * @example + * ```ts + * const db = new Database("mydb.sqlite"); + * console.log(db.filename); + * // => "mydb.sqlite" + * ``` + */ + readonly filename: string; - /** - * The underlying `sqlite3` database handle - * - * In native code, this is not a file descriptor, but an index into an array of database handles - */ - readonly handle: number; + /** + * The underlying `sqlite3` database handle + * + * In native code, this is not a file descriptor, but an index into an array of database handles + */ + readonly handle: number; - /** - * Load a SQLite3 extension - * - * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} - * - * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. - * - * @param extension name/path of the extension to load - * @param entryPoint optional entry point of the extension - */ - loadExtension(extension: string, entryPoint?: string): void; + /** + * Load a SQLite3 extension + * + * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} + * + * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. + * + * @param extension name/path of the extension to load + * @param entryPoint optional entry point of the extension + */ + loadExtension(extension: string, entryPoint?: string): void; - /** - * Change the dynamic library path to SQLite - * - * @note macOS-only - * - * This only works before SQLite is loaded, so - * that's before you call `new Database()`. - * - * It can only be run once because this will load - * the SQLite library into the process. - * - * @param path The path to the SQLite library - */ - static setCustomSQLite(path: string): boolean; + /** + * Change the dynamic library path to SQLite + * + * @note macOS-only + * + * This only works before SQLite is loaded, so + * that's before you call `new Database()`. + * + * It can only be run once because this will load + * the SQLite library into the process. + * + * @param path The path to the SQLite library + */ + static setCustomSQLite(path: string): boolean; - [Symbol.dispose](): void; + [Symbol.dispose](): void; - /** - * Creates a function that always runs inside a transaction. When the - * function is invoked, it will begin a new transaction. When the function - * returns, the transaction will be committed. If an exception is thrown, - * the transaction will be rolled back (and the exception will propagate as - * usual). - * - * @param insideTransaction The callback which runs inside a transaction - * - * @example - * ```ts - * // setup - * import { Database } from "bun:sqlite"; - * const db = Database.open(":memory:"); - * db.exec( - * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" - * ); - * - * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); - * const insertMany = db.transaction((cats) => { - * for (const cat of cats) insert.run(cat); - * }); - * - * insertMany([ - * { $name: "Joey", $age: 2 }, - * { $name: "Sally", $age: 4 }, - * { $name: "Junior", $age: 1 }, - * ]); - * ``` - */ - transaction(insideTransaction: (...args: any) => void): CallableFunction & { - /** - * uses "BEGIN DEFERRED" - */ - deferred: (...args: any) => void; - /** - * uses "BEGIN IMMEDIATE" - */ - immediate: (...args: any) => void; - /** - * uses "BEGIN EXCLUSIVE" - */ - exclusive: (...args: any) => void; - }; + /** + * Creates a function that always runs inside a transaction. When the + * function is invoked, it will begin a new transaction. When the function + * returns, the transaction will be committed. If an exception is thrown, + * the transaction will be rolled back (and the exception will propagate as + * usual). + * + * @param insideTransaction The callback which runs inside a transaction + * + * @example + * ```ts + * // setup + * import { Database } from "bun:sqlite"; + * const db = Database.open(":memory:"); + * db.exec( + * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" + * ); + * + * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); + * const insertMany = db.transaction((cats) => { + * for (const cat of cats) insert.run(cat); + * }); + * + * insertMany([ + * { $name: "Joey", $age: 2 }, + * { $name: "Sally", $age: 4 }, + * { $name: "Junior", $age: 1 }, + * ]); + * ``` + */ + transaction(insideTransaction: (...args: any) => void): CallableFunction & { + /** + * uses "BEGIN DEFERRED" + */ + deferred: (...args: any) => void; + /** + * uses "BEGIN IMMEDIATE" + */ + immediate: (...args: any) => void; + /** + * uses "BEGIN EXCLUSIVE" + */ + exclusive: (...args: any) => void; + }; - /** - * Save the database to an in-memory {@link Buffer} object. - * - * Internally, this calls `sqlite3_serialize`. - * - * @param name Name to save the database as @default "main" - * @returns Buffer containing the serialized database - */ - serialize(name?: string): Buffer; + /** + * Save the database to an in-memory {@link Buffer} object. + * + * Internally, this calls `sqlite3_serialize`. + * + * @param name Name to save the database as @default "main" + * @returns Buffer containing the serialized database + */ + serialize(name?: string): Buffer; - /** - * Load a serialized SQLite3 database - * - * Internally, this calls `sqlite3_deserialize`. - * - * @param serialized Data to load - * @returns `Database` instance - * - * @example - * ```ts - * test("supports serialize/deserialize", () => { - * const db = Database.open(":memory:"); - * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); - * db.exec('INSERT INTO test (name) VALUES ("Hello")'); - * db.exec('INSERT INTO test (name) VALUES ("World")'); - * - * const input = db.serialize(); - * const db2 = new Database(input); - * - * const stmt = db2.prepare("SELECT * FROM test"); - * expect(JSON.stringify(stmt.get())).toBe( - * JSON.stringify({ - * id: 1, - * name: "Hello", - * }), - * ); - * - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * ]), - * ); - * db2.exec("insert into test (name) values ('foo')"); - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * { - * id: 3, - * name: "foo", - * }, - * ]), - * ); - * - * const db3 = Database.deserialize(input, true); - * try { - * db3.exec("insert into test (name) values ('foo')"); - * throw new Error("Expected error"); - * } catch (e) { - * expect(e.message).toBe("attempt to write a readonly database"); - * } - * }); - * ``` - */ - static deserialize(serialized: NodeJS.TypedArray | ArrayBufferLike, isReadOnly?: boolean): Database; + /** + * Load a serialized SQLite3 database + * + * Internally, this calls `sqlite3_deserialize`. + * + * @param serialized Data to load + * @returns `Database` instance + * + * @example + * ```ts + * test("supports serialize/deserialize", () => { + * const db = Database.open(":memory:"); + * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); + * db.exec('INSERT INTO test (name) VALUES ("Hello")'); + * db.exec('INSERT INTO test (name) VALUES ("World")'); + * + * const input = db.serialize(); + * const db2 = new Database(input); + * + * const stmt = db2.prepare("SELECT * FROM test"); + * expect(JSON.stringify(stmt.get())).toBe( + * JSON.stringify({ + * id: 1, + * name: "Hello", + * }), + * ); + * + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * ]), + * ); + * db2.exec("insert into test (name) values ('foo')"); + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * { + * id: 3, + * name: "foo", + * }, + * ]), + * ); + * + * const db3 = Database.deserialize(input, true); + * try { + * db3.exec("insert into test (name) values ('foo')"); + * throw new Error("Expected error"); + * } catch (e) { + * expect(e.message).toBe("attempt to write a readonly database"); + * } + * }); + * ``` + */ + static deserialize( + serialized: NodeJS.TypedArray | ArrayBufferLike, + isReadOnly?: boolean, + ): Database; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(op: number, arg?: ArrayBufferView | number): number; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(zDbName: string, op: number, arg?: ArrayBufferView | number): number; - } + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(op: number, arg?: ArrayBufferView | number): number; + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl( + zDbName: string, + op: number, + arg?: ArrayBufferView | number, + ): number; + } - /** - * A prepared statement. - * - * This is returned by {@link Database.prepare} and {@link Database.query}. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.all("baz"); - * // => [{bar: "baz"}] - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.get("baz"); - * // => {bar: "baz"} - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.run("baz"); - * // => undefined - * ``` - */ - export class Statement implements Disposable { - /** - * Creates a new prepared statement from native code. - * - * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. - */ - constructor(nativeHandle: any); + /** + * A prepared statement. + * + * This is returned by {@link Database.prepare} and {@link Database.query}. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.all("baz"); + * // => [{bar: "baz"}] + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.get("baz"); + * // => {bar: "baz"} + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.run("baz"); + * // => undefined + * ``` + */ + export class Statement< + ReturnType = unknown, + ParamsType extends SQLQueryBindings[] = any[], + > implements Disposable + { + /** + * Creates a new prepared statement from native code. + * + * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. + */ + constructor(nativeHandle: any); - /** - * Execute the prepared statement and return all results as objects. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.all("baz"); - * // => [{bar: "baz"}] - * - * stmt.all(); - * // => [] - * - * stmt.all("foo"); - * // => [{bar: "foo"}] - * ``` - */ - all(...params: ParamsType): ReturnType[]; + /** + * Execute the prepared statement and return all results as objects. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.all("baz"); + * // => [{bar: "baz"}] + * + * stmt.all(); + * // => [] + * + * stmt.all("foo"); + * // => [{bar: "foo"}] + * ``` + */ + all(...params: ParamsType): ReturnType[]; - /** - * Execute the prepared statement and return **the first** result. - * - * If no result is returned, this returns `null`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.get("baz"); - * // => {bar: "baz"} - * - * stmt.get(); - * // => null - * - * stmt.get("foo"); - * // => {bar: "foo"} - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - get(...params: ParamsType): ReturnType | null; + /** + * Execute the prepared statement and return **the first** result. + * + * If no result is returned, this returns `null`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.get("baz"); + * // => {bar: "baz"} + * + * stmt.get(); + * // => null + * + * stmt.get("foo"); + * // => {bar: "foo"} + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + get(...params: ParamsType): ReturnType | null; - /** - * Execute the prepared statement and return an - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - */ - iterate(...params: ParamsType): IterableIterator; - [Symbol.iterator](): IterableIterator; + /** + * Execute the prepared statement and return an + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + */ + iterate(...params: ParamsType): IterableIterator; + [Symbol.iterator](): IterableIterator; - /** - * Execute the prepared statement. This returns `undefined`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("UPDATE foo SET bar = ?"); - * stmt.run("baz"); - * // => undefined - * - * stmt.run(); - * // => undefined - * - * stmt.run("foo"); - * // => undefined - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(...params: ParamsType): Changes; + /** + * Execute the prepared statement. This returns `undefined`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("UPDATE foo SET bar = ?"); + * stmt.run("baz"); + * // => undefined + * + * stmt.run(); + * // => undefined + * + * stmt.run("foo"); + * // => undefined + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(...params: ParamsType): Changes; - /** - * Execute the prepared statement and return the results as an array of arrays. - * - * In Bun v0.6.7 and earlier, this method returned `null` if there were no - * results instead of `[]`. This was changed in v0.6.8 to align - * more with what people expect. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.values("baz"); - * // => [['baz']] - * - * stmt.values(); - * // => [['baz']] - * - * stmt.values("foo"); - * // => [['foo']] - * - * stmt.values("not-found"); - * // => [] - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | ---------------|-------------| - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - values(...params: ParamsType): Array>; + /** + * Execute the prepared statement and return the results as an array of arrays. + * + * In Bun v0.6.7 and earlier, this method returned `null` if there were no + * results instead of `[]`. This was changed in v0.6.8 to align + * more with what people expect. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.values("baz"); + * // => [['baz']] + * + * stmt.values(); + * // => [['baz']] + * + * stmt.values("foo"); + * // => [['foo']] + * + * stmt.values("not-found"); + * // => [] + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | ---------------|-------------| + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + values( + ...params: ParamsType + ): Array>; - /** - * The names of the columns returned by the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); - * - * console.log(stmt.columnNames); - * // => ["bar"] - * ``` - */ - readonly columnNames: string[]; + /** + * The names of the columns returned by the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); + * + * console.log(stmt.columnNames); + * // => ["bar"] + * ``` + */ + readonly columnNames: string[]; - /** - * The number of parameters expected in the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * console.log(stmt.paramsCount); - * // => 1 - * ``` - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); - * console.log(stmt.paramsCount); - * // => 2 - * ``` - */ - readonly paramsCount: number; + /** + * The number of parameters expected in the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * console.log(stmt.paramsCount); + * // => 1 + * ``` + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); + * console.log(stmt.paramsCount); + * // => 2 + * ``` + */ + readonly paramsCount: number; - /** - * Finalize the prepared statement, freeing the resources used by the - * statement and preventing it from being executed again. - * - * This is called automatically when the prepared statement is garbage collected. - * - * It is safe to call this multiple times. Calling this on a finalized - * statement has no effect. - * - * Internally, this calls `sqlite3_finalize`. - */ - finalize(): void; + /** + * Finalize the prepared statement, freeing the resources used by the + * statement and preventing it from being executed again. + * + * This is called automatically when the prepared statement is garbage collected. + * + * It is safe to call this multiple times. Calling this on a finalized + * statement has no effect. + * + * Internally, this calls `sqlite3_finalize`. + */ + finalize(): void; - /** - * Calls {@link finalize} if it wasn't already called. - */ - [Symbol.dispose](): void; + /** + * Calls {@link finalize} if it wasn't already called. + */ + [Symbol.dispose](): void; - /** - * Return the expanded SQL string for the prepared statement. - * - * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); - * console.log(stmt.toString()); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * console.log(stmt); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * ``` - */ - toString(): string; + /** + * Return the expanded SQL string for the prepared statement. + * + * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); + * console.log(stmt.toString()); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * console.log(stmt); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * ``` + */ + toString(): string; - /** - * - * Make {@link get} and {@link all} return an instance of the provided - * `Class` instead of the default `Object`. - * - * @param Class A class to use - * @returns The same statement instance, modified to return an instance of `Class` - * - * This lets you attach methods, getters, and setters to the returned - * objects. - * - * For performance reasons, constructors for classes are not called, which means - * initializers will not be called and private fields will not be - * accessible. - * - * @example - * - * ## Custom class - * ```ts - * class User { - * rawBirthdate: string; - * get birthdate() { - * return new Date(this.rawBirthdate); - * } - * } - * - * const db = new Database(":memory:"); - * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); - * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); - * const query = db.query("SELECT * FROM users"); - * query.as(User); - * const user = query.get(); - * console.log(user.birthdate); - * // => Date(1995, 12, 19) - * ``` - */ - as(Class: new (...args: any[]) => T): Statement; + /** + * + * Make {@link get} and {@link all} return an instance of the provided + * `Class` instead of the default `Object`. + * + * @param Class A class to use + * @returns The same statement instance, modified to return an instance of `Class` + * + * This lets you attach methods, getters, and setters to the returned + * objects. + * + * For performance reasons, constructors for classes are not called, which means + * initializers will not be called and private fields will not be + * accessible. + * + * @example + * + * ## Custom class + * ```ts + * class User { + * rawBirthdate: string; + * get birthdate() { + * return new Date(this.rawBirthdate); + * } + * } + * + * const db = new Database(":memory:"); + * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); + * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); + * const query = db.query("SELECT * FROM users"); + * query.as(User); + * const user = query.get(); + * console.log(user.birthdate); + * // => Date(1995, 12, 19) + * ``` + */ + as(Class: new (...args: any[]) => T): Statement; - /** - * Native object representing the underlying `sqlite3_stmt` - * - * This is left untyped because the ABI of the native bindings may change at any time. - */ - readonly native: any; - } + /** + * Native object representing the underlying `sqlite3_stmt` + * + * This is left untyped because the ABI of the native bindings may change at any time. + */ + readonly native: any; + } - /** - * Constants from `sqlite3.h` - * - * This list isn't exhaustive, but some of the ones which are relevant - */ - export const constants: { - /** - * Open the database as read-only (no write operations, no create). - * @constant 0x00000001 - */ - SQLITE_OPEN_READONLY: number; - /** - * Open the database for reading and writing - * @constant 0x00000002 - */ - SQLITE_OPEN_READWRITE: number; - /** - * Allow creating a new database - * @constant 0x00000004 - */ - SQLITE_OPEN_CREATE: number; - /** - * @constant 0x00000008 - */ - SQLITE_OPEN_DELETEONCLOSE: number; - /** - * @constant 0x00000010 - */ - SQLITE_OPEN_EXCLUSIVE: number; - /** - * @constant 0x00000020 - */ - SQLITE_OPEN_AUTOPROXY: number; - /** - * @constant 0x00000040 - */ - SQLITE_OPEN_URI: number; - /** - * @constant 0x00000080 - */ - SQLITE_OPEN_MEMORY: number; - /** - * @constant 0x00000100 - */ - SQLITE_OPEN_MAIN_DB: number; - /** - * @constant 0x00000200 - */ - SQLITE_OPEN_TEMP_DB: number; - /** - * @constant 0x00000400 - */ - SQLITE_OPEN_TRANSIENT_DB: number; - /** - * @constant 0x00000800 - */ - SQLITE_OPEN_MAIN_JOURNAL: number; - /** - * @constant 0x00001000 - */ - SQLITE_OPEN_TEMP_JOURNAL: number; - /** - * @constant 0x00002000 - */ - SQLITE_OPEN_SUBJOURNAL: number; - /** - * @constant 0x00004000 - */ - SQLITE_OPEN_SUPER_JOURNAL: number; - /** - * @constant 0x00008000 - */ - SQLITE_OPEN_NOMUTEX: number; - /** - * @constant 0x00010000 - */ - SQLITE_OPEN_FULLMUTEX: number; - /** - * @constant 0x00020000 - */ - SQLITE_OPEN_SHAREDCACHE: number; - /** - * @constant 0x00040000 - */ - SQLITE_OPEN_PRIVATECACHE: number; - /** - * @constant 0x00080000 - */ - SQLITE_OPEN_WAL: number; - /** - * @constant 0x01000000 - */ - SQLITE_OPEN_NOFOLLOW: number; - /** - * @constant 0x02000000 - */ - SQLITE_OPEN_EXRESCODE: number; - /** - * @constant 0x01 - */ - SQLITE_PREPARE_PERSISTENT: number; - /** - * @constant 0x02 - */ - SQLITE_PREPARE_NORMALIZE: number; - /** - * @constant 0x04 - */ - SQLITE_PREPARE_NO_VTAB: number; + /** + * Constants from `sqlite3.h` + * + * This list isn't exhaustive, but some of the ones which are relevant + */ + export const constants: { + /** + * Open the database as read-only (no write operations, no create). + * @constant 0x00000001 + */ + SQLITE_OPEN_READONLY: number; + /** + * Open the database for reading and writing + * @constant 0x00000002 + */ + SQLITE_OPEN_READWRITE: number; + /** + * Allow creating a new database + * @constant 0x00000004 + */ + SQLITE_OPEN_CREATE: number; + /** + * @constant 0x00000008 + */ + SQLITE_OPEN_DELETEONCLOSE: number; + /** + * @constant 0x00000010 + */ + SQLITE_OPEN_EXCLUSIVE: number; + /** + * @constant 0x00000020 + */ + SQLITE_OPEN_AUTOPROXY: number; + /** + * @constant 0x00000040 + */ + SQLITE_OPEN_URI: number; + /** + * @constant 0x00000080 + */ + SQLITE_OPEN_MEMORY: number; + /** + * @constant 0x00000100 + */ + SQLITE_OPEN_MAIN_DB: number; + /** + * @constant 0x00000200 + */ + SQLITE_OPEN_TEMP_DB: number; + /** + * @constant 0x00000400 + */ + SQLITE_OPEN_TRANSIENT_DB: number; + /** + * @constant 0x00000800 + */ + SQLITE_OPEN_MAIN_JOURNAL: number; + /** + * @constant 0x00001000 + */ + SQLITE_OPEN_TEMP_JOURNAL: number; + /** + * @constant 0x00002000 + */ + SQLITE_OPEN_SUBJOURNAL: number; + /** + * @constant 0x00004000 + */ + SQLITE_OPEN_SUPER_JOURNAL: number; + /** + * @constant 0x00008000 + */ + SQLITE_OPEN_NOMUTEX: number; + /** + * @constant 0x00010000 + */ + SQLITE_OPEN_FULLMUTEX: number; + /** + * @constant 0x00020000 + */ + SQLITE_OPEN_SHAREDCACHE: number; + /** + * @constant 0x00040000 + */ + SQLITE_OPEN_PRIVATECACHE: number; + /** + * @constant 0x00080000 + */ + SQLITE_OPEN_WAL: number; + /** + * @constant 0x01000000 + */ + SQLITE_OPEN_NOFOLLOW: number; + /** + * @constant 0x02000000 + */ + SQLITE_OPEN_EXRESCODE: number; + /** + * @constant 0x01 + */ + SQLITE_PREPARE_PERSISTENT: number; + /** + * @constant 0x02 + */ + SQLITE_PREPARE_NORMALIZE: number; + /** + * @constant 0x04 + */ + SQLITE_PREPARE_NO_VTAB: number; - /** - * @constant 1 - */ - SQLITE_FCNTL_LOCKSTATE: number; - /** - * @constant 2 - */ - SQLITE_FCNTL_GET_LOCKPROXYFILE: number; - /** - * @constant 3 - */ - SQLITE_FCNTL_SET_LOCKPROXYFILE: number; - /** - * @constant 4 - */ - SQLITE_FCNTL_LAST_ERRNO: number; - /** - * @constant 5 - */ - SQLITE_FCNTL_SIZE_HINT: number; - /** - * @constant 6 - */ - SQLITE_FCNTL_CHUNK_SIZE: number; - /** - * @constant 7 - */ - SQLITE_FCNTL_FILE_POINTER: number; - /** - * @constant 8 - */ - SQLITE_FCNTL_SYNC_OMITTED: number; - /** - * @constant 9 - */ - SQLITE_FCNTL_WIN32_AV_RETRY: number; - /** - * @constant 10 - * - * Control whether or not the WAL is persisted - * Some versions of macOS configure WAL to be persistent by default. - * - * You can change this with code like the below: - * ```ts - * import { Database } from "bun:sqlite"; - * - * const db = Database.open("mydb.sqlite"); - * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); - * // enable WAL - * db.exec("PRAGMA journal_mode = WAL"); - * // .. do some work - * db.close(); - * ``` - * - */ - SQLITE_FCNTL_PERSIST_WAL: number; - /** - * @constant 11 - */ - SQLITE_FCNTL_OVERWRITE: number; - /** - * @constant 12 - */ - SQLITE_FCNTL_VFSNAME: number; - /** - * @constant 13 - */ - SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; - /** - * @constant 14 - */ - SQLITE_FCNTL_PRAGMA: number; - /** - * @constant 15 - */ - SQLITE_FCNTL_BUSYHANDLER: number; - /** - * @constant 16 - */ - SQLITE_FCNTL_TEMPFILENAME: number; - /** - * @constant 18 - */ - SQLITE_FCNTL_MMAP_SIZE: number; - /** - * @constant 19 - */ - SQLITE_FCNTL_TRACE: number; - /** - * @constant 20 - */ - SQLITE_FCNTL_HAS_MOVED: number; - /** - * @constant 21 - */ - SQLITE_FCNTL_SYNC: number; - /** - * @constant 22 - */ - SQLITE_FCNTL_COMMIT_PHASETWO: number; - /** - * @constant 23 - */ - SQLITE_FCNTL_WIN32_SET_HANDLE: number; - /** - * @constant 24 - */ - SQLITE_FCNTL_WAL_BLOCK: number; - /** - * @constant 25 - */ - SQLITE_FCNTL_ZIPVFS: number; - /** - * @constant 26 - */ - SQLITE_FCNTL_RBU: number; - /** - * @constant 27 - */ - SQLITE_FCNTL_VFS_POINTER: number; - /** - * @constant 28 - */ - SQLITE_FCNTL_JOURNAL_POINTER: number; - /** - * @constant 29 - */ - SQLITE_FCNTL_WIN32_GET_HANDLE: number; - /** - * @constant 30 - */ - SQLITE_FCNTL_PDB: number; - /** - * @constant 31 - */ - SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; - /** - * @constant 32 - */ - SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; - /** - * @constant 33 - */ - SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; - /** - * @constant 34 - */ - SQLITE_FCNTL_LOCK_TIMEOUT: number; - /** - * @constant 35 - */ - SQLITE_FCNTL_DATA_VERSION: number; - /** - * @constant 36 - */ - SQLITE_FCNTL_SIZE_LIMIT: number; - /** - * @constant 37 - */ - SQLITE_FCNTL_CKPT_DONE: number; - /** - * @constant 38 - */ - SQLITE_FCNTL_RESERVE_BYTES: number; - /** - * @constant 39 - */ - SQLITE_FCNTL_CKPT_START: number; - /** - * @constant 40 - */ - SQLITE_FCNTL_EXTERNAL_READER: number; - /** - * @constant 41 - */ - SQLITE_FCNTL_CKSM_FILE: number; - /** - * @constant 42 - */ - SQLITE_FCNTL_RESET_CACHE: number; - }; + /** + * @constant 1 + */ + SQLITE_FCNTL_LOCKSTATE: number; + /** + * @constant 2 + */ + SQLITE_FCNTL_GET_LOCKPROXYFILE: number; + /** + * @constant 3 + */ + SQLITE_FCNTL_SET_LOCKPROXYFILE: number; + /** + * @constant 4 + */ + SQLITE_FCNTL_LAST_ERRNO: number; + /** + * @constant 5 + */ + SQLITE_FCNTL_SIZE_HINT: number; + /** + * @constant 6 + */ + SQLITE_FCNTL_CHUNK_SIZE: number; + /** + * @constant 7 + */ + SQLITE_FCNTL_FILE_POINTER: number; + /** + * @constant 8 + */ + SQLITE_FCNTL_SYNC_OMITTED: number; + /** + * @constant 9 + */ + SQLITE_FCNTL_WIN32_AV_RETRY: number; + /** + * @constant 10 + * + * Control whether or not the WAL is persisted + * Some versions of macOS configure WAL to be persistent by default. + * + * You can change this with code like the below: + * ```ts + * import { Database } from "bun:sqlite"; + * + * const db = Database.open("mydb.sqlite"); + * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); + * // enable WAL + * db.exec("PRAGMA journal_mode = WAL"); + * // .. do some work + * db.close(); + * ``` + * + */ + SQLITE_FCNTL_PERSIST_WAL: number; + /** + * @constant 11 + */ + SQLITE_FCNTL_OVERWRITE: number; + /** + * @constant 12 + */ + SQLITE_FCNTL_VFSNAME: number; + /** + * @constant 13 + */ + SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; + /** + * @constant 14 + */ + SQLITE_FCNTL_PRAGMA: number; + /** + * @constant 15 + */ + SQLITE_FCNTL_BUSYHANDLER: number; + /** + * @constant 16 + */ + SQLITE_FCNTL_TEMPFILENAME: number; + /** + * @constant 18 + */ + SQLITE_FCNTL_MMAP_SIZE: number; + /** + * @constant 19 + */ + SQLITE_FCNTL_TRACE: number; + /** + * @constant 20 + */ + SQLITE_FCNTL_HAS_MOVED: number; + /** + * @constant 21 + */ + SQLITE_FCNTL_SYNC: number; + /** + * @constant 22 + */ + SQLITE_FCNTL_COMMIT_PHASETWO: number; + /** + * @constant 23 + */ + SQLITE_FCNTL_WIN32_SET_HANDLE: number; + /** + * @constant 24 + */ + SQLITE_FCNTL_WAL_BLOCK: number; + /** + * @constant 25 + */ + SQLITE_FCNTL_ZIPVFS: number; + /** + * @constant 26 + */ + SQLITE_FCNTL_RBU: number; + /** + * @constant 27 + */ + SQLITE_FCNTL_VFS_POINTER: number; + /** + * @constant 28 + */ + SQLITE_FCNTL_JOURNAL_POINTER: number; + /** + * @constant 29 + */ + SQLITE_FCNTL_WIN32_GET_HANDLE: number; + /** + * @constant 30 + */ + SQLITE_FCNTL_PDB: number; + /** + * @constant 31 + */ + SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; + /** + * @constant 32 + */ + SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; + /** + * @constant 33 + */ + SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; + /** + * @constant 34 + */ + SQLITE_FCNTL_LOCK_TIMEOUT: number; + /** + * @constant 35 + */ + SQLITE_FCNTL_DATA_VERSION: number; + /** + * @constant 36 + */ + SQLITE_FCNTL_SIZE_LIMIT: number; + /** + * @constant 37 + */ + SQLITE_FCNTL_CKPT_DONE: number; + /** + * @constant 38 + */ + SQLITE_FCNTL_RESERVE_BYTES: number; + /** + * @constant 39 + */ + SQLITE_FCNTL_CKPT_START: number; + /** + * @constant 40 + */ + SQLITE_FCNTL_EXTERNAL_READER: number; + /** + * @constant 41 + */ + SQLITE_FCNTL_CKSM_FILE: number; + /** + * @constant 42 + */ + SQLITE_FCNTL_RESET_CACHE: number; + }; - /** - * The native module implementing the sqlite3 C bindings - * - * It is lazily-initialized, so this will return `undefined` until the first - * call to new Database(). - * - * The native module makes no gurantees about ABI stability, so it is left - * untyped - * - * If you need to use it directly for some reason, please let us know because - * that probably points to a deficiency in this API. - */ - export var native: any; + /** + * The native module implementing the sqlite3 C bindings + * + * It is lazily-initialized, so this will return `undefined` until the first + * call to new Database(). + * + * The native module makes no gurantees about ABI stability, so it is left + * untyped + * + * If you need to use it directly for some reason, please let us know because + * that probably points to a deficiency in this API. + */ + export var native: any; - export type SQLQueryBindings = - | string - | bigint - | NodeJS.TypedArray - | number - | boolean - | null - | Record; + export type SQLQueryBindings = + | string + | bigint + | NodeJS.TypedArray + | number + | boolean + | null + | Record< + string, + string | bigint | NodeJS.TypedArray | number | boolean | null + >; - export default Database; + export default Database; - /** - * Errors from SQLite have a name `SQLiteError`. - * - */ - export class SQLiteError extends Error { - readonly name: "SQLiteError"; + /** + * Errors from SQLite have a name `SQLiteError`. + * + */ + export class SQLiteError extends Error { + readonly name: "SQLiteError"; - /** - * The SQLite3 extended error code - * - * This corresponds to `sqlite3_extended_errcode`. - * - * @since v1.0.21 - */ - errno: number; + /** + * The SQLite3 extended error code + * + * This corresponds to `sqlite3_extended_errcode`. + * + * @since v1.0.21 + */ + errno: number; - /** - * The name of the SQLite3 error code - * - * @example - * "SQLITE_CONSTRAINT_UNIQUE" - * - * @since v1.0.21 - */ - code?: string; + /** + * The name of the SQLite3 error code + * + * @example + * "SQLITE_CONSTRAINT_UNIQUE" + * + * @since v1.0.21 + */ + code?: string; - /** - * The UTF-8 byte offset of the sqlite3 query that failed, if known - * - * This corresponds to `sqlite3_error_offset`. - * - * @since v1.0.21 - */ - readonly byteOffset: number; - } + /** + * The UTF-8 byte offset of the sqlite3 query that failed, if known + * + * This corresponds to `sqlite3_error_offset`. + * + * @since v1.0.21 + */ + readonly byteOffset: number; + } - /** - * An object representing the changes made to the database since the last `run` or `exec` call. - * - * @since Bun v1.1.14 - */ - export interface Changes { - /** - * The number of rows changed by the last `run` or `exec` call. - */ - changes: number; + /** + * An object representing the changes made to the database since the last `run` or `exec` call. + * + * @since Bun v1.1.14 + */ + export interface Changes { + /** + * The number of rows changed by the last `run` or `exec` call. + */ + changes: number; - /** - * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. - */ - lastInsertRowid: number | bigint; - } + /** + * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. + */ + lastInsertRowid: number | bigint; + } } diff --git a/packages/bun-types/test.d.ts b/packages/bun-types/test.d.ts index 9c5ef1a2da6670..e2d4a01871c381 100644 --- a/packages/bun-types/test.d.ts +++ b/packages/bun-types/test.d.ts @@ -14,995 +14,1060 @@ * ``` */ declare module "bun:test" { - /** - * -- Mocks -- - */ - export type Mock any> = JestMock.Mock; - - export const mock: { - any>(Function?: T): Mock; - - /** - * Replace the module `id` with the return value of `factory`. - * - * This is useful for mocking modules. - * - * @param id module ID to mock - * @param factory a function returning an object that will be used as the exports of the mocked module - * - * @example - * ## Example - * ```ts - * import { mock } from "bun:test"; - * - * mock.module("fs/promises", () => { - * return { - * readFile: () => Promise.resolve("hello world"), - * }; - * }); - * - * import { readFile } from "fs/promises"; - * - * console.log(await readFile("hello.txt", "utf8")); // hello world - * ``` - * - * ## More notes - * - * If the module is already loaded, exports are overwritten with the return - * value of `factory`. If the export didn't exist before, it will not be - * added to existing import statements. This is due to how ESM works. - */ - module(id: string, factory: () => any): void | Promise; - /** - * Restore the previous value of mocks. - */ - restore(): void; - }; - - /** - * Control the system time used by: - * - `Date.now()` - * - `new Date()` - * - `Intl.DateTimeFormat().format()` - * - * In the future, we may add support for more functions, but we haven't done that yet. - * - * @param now The time to set the system time to. If not provided, the system time will be reset. - * @returns `this` - * @since v0.6.13 - * - * ## Set Date to a specific time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); - * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z - * ``` - * ## Reset Date to the current time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(); - * ``` - */ - export function setSystemTime(now?: Date | number): ThisType; - - interface Jest { - restoreAllMocks(): void; - clearAllMocks(): void; - fn any>(func?: T): Mock; - setSystemTime(now?: number | Date): void; - setTimeout(milliseconds: number): void; - } - export const jest: Jest; - export namespace jest { - /** - * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. - */ - type Mock any = (...args: any[]) => any> = JestMock.Mock; - /** - * Wraps a class, function or object type with Jest mock type definitions. - */ - // type Mocked = JestMock.Mocked; - /** - * Wraps a class type with Jest mock type definitions. - */ - // type MockedClass = JestMock.MockedClass; - /** - * Wraps a function type with Jest mock type definitions. - */ - // type MockedFunction any> = JestMock.MockedFunction; - /** - * Wraps an object type with Jest mock type definitions. - */ - // type MockedObject = JestMock.MockedObject; - /** - * Constructs the type of a replaced property. - */ - type Replaced = JestMock.Replaced; - /** - * Constructs the type of a spied class or function. - */ - type Spied any)> = JestMock.Spied; - /** - * Constructs the type of a spied class. - */ - type SpiedClass = JestMock.SpiedClass; - /** - * Constructs the type of a spied function. - */ - type SpiedFunction any> = JestMock.SpiedFunction; - /** - * Constructs the type of a spied getter. - */ - type SpiedGetter = JestMock.SpiedGetter; - /** - * Constructs the type of a spied setter. - */ - type SpiedSetter = JestMock.SpiedSetter; - } - - export function spyOn( - obj: T, - methodOrPropertyValue: K, - ): Mock any ? T[K] : never>; - - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export interface Describe { - (label: string, fn: () => void): void; - /** - * Skips all other tests, except this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - only(label: string, fn: () => void): void; - /** - * Skips this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - skip(label: string, fn: () => void): void; - /** - * Marks this group of tests as to be written or to be fixed. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - todo(label: string, fn?: () => void): void; - /** - * Runs this group of tests, only if `condition` is true. - * - * This is the opposite of `describe.skipIf()`. - * - * @param condition if these tests should run - */ - if(condition: boolean): (label: string, fn: () => void) => void; - /** - * Skips this group of tests, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - skipIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Marks this group of tests as to be written or to be fixed, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - todoIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; - each( - table: readonly T[], - ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; - each( - table: T[], - ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; - } - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export const describe: Describe; - /** - * Runs a function, once, before all the tests. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, tests will not run in this file. - * - * @example - * let database; - * beforeAll(async () => { - * database = await connect("localhost"); - * }); - * - * @param fn the function to run - */ - export function beforeAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function before each test. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, the test will not run. - * - * @param fn the function to run - */ - export function beforeEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function, once, after all the tests. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @example - * let database; - * afterAll(async () => { - * if (database) { - * await database.close(); - * } - * }); - * - * @param fn the function to run - */ - export function afterAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function after each test. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @param fn the function to run - */ - export function afterEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will - * override this value. The default timeout is 5000ms (5 seconds). - * - * @param milliseconds the number of milliseconds for the default timeout - */ - export function setDefaultTimeout(milliseconds: number): void; - export interface TestOptions { - /** - * Sets the timeout for the test in milliseconds. - * - * If the test does not complete within this time, the test will fail with: - * ```ts - * 'Timeout: test {name} timed out after 5000ms' - * ``` - * - * @default 5000 // 5 seconds - */ - timeout?: number; - /** - * Sets the number of times to retry the test if it fails. - * - * @default 0 - */ - retry?: number; - /** - * Sets the number of times to repeat the test, regardless of whether it passed or failed. - * - * @default 0 - */ - repeats?: number; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * test("can set a timeout", async () => { - * await Bun.sleep(100); - * }, 50); // or { timeout: 50 } - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - export interface Test { - ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - /** - * - If a `number`, sets the timeout for the test in milliseconds. - * - If an `object`, sets the options for the test. - * - `timeout` sets the timeout for the test in milliseconds. - * - `retry` sets the number of times to retry the test if it fails. - * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. - */ - options?: number | TestOptions, - ): void; - /** - * Skips all other tests, except this test when run with the `--only` option. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - only( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Skips this test. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - skip( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as to be written or to be fixed. - * - * These tests will not be executed unless the `--todo` flag is passed. With the flag, - * if the test passes, the test will be marked as `fail` in the results; you will have to - * remove the `.todo` or check that your test - * is implemented correctly. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - todo( - label: string, - fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as failing. - * - * Use `test.failing` when you are writing a test and expecting it to fail. - * These tests will behave the other way normal tests do. If failing test - * will throw any errors then it will pass. If it does not throw it will - * fail. - * - * `test.failing` is very similar to {@link test.todo} except that it always - * runs, regardless of the `--todo` flag. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - failing(label: string, fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs this test, if `condition` is true. - * - * This is the opposite of `test.skipIf()`. - * - * @param condition if the test should run - */ - if( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Skips this test, if `condition` is true. - * - * @param condition if the test should be skipped - */ - skipIf( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Marks this test as to be written or to be fixed, if `condition` is true. - * - * @param condition if the test should be marked TODO - */ - todoIf( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; - each( - table: readonly T[], - ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; - each( - table: T[], - ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * @param label the label for the test - * @param fn the test function - */ - export const test: Test; - export { test as it }; - - /** - * Asserts that a value matches some criteria. - * - * @link https://jestjs.io/docs/expect#reference - * @example - * expect(1 + 1).toBe(2); - * expect([1,2,3]).toContain(2); - * expect(null).toBeNull(); - * - * @param actual The actual (received) value - */ - export const expect: Expect; - - type ExpectNot = Omit & AsymmetricMatchersBuiltinNegated; - - export interface Expect extends AsymmetricMatchers { - // the `expect()` callable signature - /** - * @param actual the actual value - * @param customFailMessage an optional custom message to display if the test fails. - * */ - - (actual?: T, customFailMessage?: string): Matchers; - - /** - * Access to negated asymmetric matchers. - * - * @example - * expect("abc").toEqual(expect.stringContaining("abc")); // will pass - * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail - */ - not: ExpectNot; - - /** - * Create an asymmetric matcher for a promise resolved value. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass - * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail - * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail - */ - resolvesTo: AsymmetricMatchers; - - /** - * Create an asymmetric matcher for a promise rejected value. - * - * @example - * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass - * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail - * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail - */ - rejectsTo: AsymmetricMatchers; - - /** - * Register new custom matchers. - * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. - * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` - * - * @example - * expect.extend({ - * toBeWithinRange(actual, min, max) { - * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') - * throw new Error('Invalid usage'); - * const pass = actual >= min && actual <= max; - * return { - * pass: pass, - * message: () => `expected ${this.utils.printReceived(actual)} ` + - * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, - * }; - * }, - * }); - * - * test('some test', () => { - * expect(50).toBeWithinRange(0, 100); // will pass - * expect(50).toBeWithinRange(100, 200); // will fail - * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass - * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass - * }); - */ - extend(matchers: ExpectExtendMatchers): void; - - /** - * Throw an error if this function is called. - * - * @param msg Optional message to display if the test fails - * @returns never - * - * @example - * ## Example - * - * ```ts - * import { expect, test } from "bun:test"; - * - * test("!!abc!! is not a module", () => { - * try { - * require("!!abc!!"); - * expect.unreachable(); - * } catch(e) { - * expect(e.name).not.toBe("UnreachableError"); - * } - * }); - * ``` - */ - unreachable(msg?: string | Error): never; - - /** - * Ensures that an assertion is made - */ - hasAssertions(): void; - - /** - * Ensures that a specific number of assertions are made - */ - assertions(neededAssertions: number): void; - } - - /** - * You can extend this interface with declaration merging, in order to add type support for custom matchers. - * @template T Type of the actual value - * - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface Matchers extends MatchersBuiltin {} - - /** - * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} - - export interface AsymmetricMatchersBuiltin { - /** - * Matches anything that was created with the given constructor. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * @example - * - * function randocall(fn) { - * return fn(Math.floor(Math.random() * 6 + 1)); - * } - * - * test('randocall calls its callback with a number', () => { - * const mock = jest.fn(); - * randocall(mock); - * expect(mock).toBeCalledWith(expect.any(Number)); - * }); - */ - any(constructor: ((...args: any[]) => any) | { new (...args: any[]): any }): AsymmetricMatcher; - /** - * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead - * of a literal value. For example, if you want to check that a mock function is called with a - * non-null argument: - * - * @example - * - * test('map calls its argument with a non-null argument', () => { - * const mock = jest.fn(); - * [1].map(x => mock(x)); - * expect(mock).toBeCalledWith(expect.anything()); - * }); - */ - anything(): AsymmetricMatcher; - /** - * Matches any array made up entirely of elements in the provided array. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - /** - * Matches any object that recursively matches the provided keys. - * This is often handy in conjunction with other asymmetric matchers. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - /** - * Matches any received string that contains the exact expected string - */ - stringContaining(str: string | String): AsymmetricMatcher; - /** - * Matches any string that contains the exact provided string - */ - stringMatching(regex: string | String | RegExp): AsymmetricMatcher; - /** - * Useful when comparing floating point numbers in object properties or array item. - * If you need to compare a number, use `.toBeCloseTo` instead. - * - * The optional `numDigits` argument limits the number of digits to check after the decimal point. - * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - interface AsymmetricMatchersBuiltinNegated { - /** - * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail - * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - */ - resolvesTo: ExpectNot; - - /** - * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. - * - * @example - * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail - * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - */ - rejectsTo: ExpectNot; - - /** - * `expect.not.arrayContaining(array)` matches a received array which - * does not contain all of the elements in the expected array. That is, - * the expected array is not a subset of the received array. It is the - * inverse of `expect.arrayContaining`. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - - /** - * `expect.not.objectContaining(object)` matches any received object - * that does not recursively match the expected properties. That is, the - * expected object is not a subset of the received object. Therefore, - * it matches a received object which contains properties that are not - * in the expected object. It is the inverse of `expect.objectContaining`. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - - /** - * `expect.not.stringContaining(string)` matches the received string - * that does not contain the exact expected string. It is the inverse of - * `expect.stringContaining`. - */ - stringContaining(str: string | String): AsymmetricMatcher; - - /** - * `expect.not.stringMatching(string | regexp)` matches the received - * string that does not match the expected regexp. It is the inverse of - * `expect.stringMatching`. - */ - stringMatching(str: string | String | RegExp): AsymmetricMatcher; - - /** - * `expect.not.closeTo` matches a number not close to the provided value. - * Useful when comparing floating point numbers in object properties or array item. - * It is the inverse of `expect.closeTo`. - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - export interface MatchersBuiltin { - /** - * Negates the result of a subsequent assertion. - * If you know how to test something, `.not` lets you test its opposite. - * - * @example - * expect(1).not.toBe(0); - * expect(null).not.toBeNull(); - * - * @example - * expect(42).toEqual(42); // will pass - * expect(42).not.toEqual(42); // will fail - */ - not: Matchers; - - /** - * Expects the value to be a promise that resolves. - * - * @example - * expect(Promise.resolve(1)).resolves.toBe(1); - */ - resolves: Matchers>; - - /** - * Expects the value to be a promise that rejects. - * - * @example - * expect(Promise.reject("error")).rejects.toBe("error"); - */ - rejects: Matchers; - - /** - * Assertion which passes. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass - * @example - * expect().pass(); - * expect().pass("message is optional"); - * expect().not.pass(); - * expect().not.pass("hi"); - * - * @param message the message to display if the test fails (optional) - */ - pass: (message?: string) => void; - /** - * Assertion which fails. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail - * @example - * expect().fail(); - * expect().fail("message is optional"); - * expect().not.fail(); - * expect().not.fail("hi"); - */ - fail: (message?: string) => void; - /** - * Asserts that a value equals what is expected. - * - * - For non-primitive values, like objects and arrays, - * use `toEqual()` instead. - * - For floating-point numbers, use `toBeCloseTo()` instead. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([123]).toBe([123]); // fail, use toEqual() - * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() - * - * @param expected the expected value - */ - toBe(expected: T): void; - /** - * Asserts that a number is odd. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd - * @example - * expect(1).toBeOdd(); - * expect(2).not.toBeOdd(); - */ - toBeOdd(): void; - /** - * Asserts that a number is even. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven - * @example - * expect(2).toBeEven(); - * expect(1).not.toBeEven(); - */ - toBeEven(): void; - /** - * Asserts that value is close to the expected by floating point precision. - * - * For example, the following fails because arithmetic on decimal (base 10) - * values often have rounding errors in limited precision binary (base 2) representation. - * - * @example - * expect(0.2 + 0.1).toBe(0.3); // fails - * - * Use `toBeCloseTo` to compare floating point numbers for approximate equality. - * - * @example - * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes - * - * @param expected the expected value - * @param numDigits the number of digits to check after the decimal point. Default is `2` - */ - toBeCloseTo(expected: number, numDigits?: number): void; - /** - * Asserts that a value is deeply equal to what is expected. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([456]).toEqual([456]); - * expect({ value: 1 }).toEqual({ value: 1 }); - * - * @param expected the expected value - */ - toEqual(expected: T): void; - /** - * Asserts that a value is deeply and strictly equal to - * what is expected. - * - * There are two key differences from `toEqual()`: - * 1. It checks that the class is the same. - * 2. It checks that `undefined` values match as well. - * - * @example - * class Dog { - * type = "dog"; - * } - * const actual = new Dog(); - * expect(actual).toStrictEqual(new Dog()); - * expect(actual).toStrictEqual({ type: "dog" }); // fail - * - * @example - * const actual = { value: 1, name: undefined }; - * expect(actual).toEqual({ value: 1 }); - * expect(actual).toStrictEqual({ value: 1 }); // fail - * - * @param expected the expected value - */ - toStrictEqual(expected: T): void; - /** - * Asserts that the value is deep equal to an element in the expected array. - * - * The value must be an array or iterable, which includes strings. - * - * @example - * expect(1).toBeOneOf([1,2,3]); - * expect("foo").toBeOneOf(["foo", "bar"]); - * expect(true).toBeOneOf(new Set([true])); - * - * @param expected the expected value - */ - toBeOneOf(expected: Array | Iterable): void; - /** - * Asserts that a value contains what is expected. - * - * The value must be an array or iterable, which - * includes strings. - * - * @example - * expect([1, 2, 3]).toContain(1); - * expect(new Set([true])).toContain(true); - * expect("hello").toContain("o"); - * - * @param expected the expected value - */ - toContain(expected: unknown): void; - /** - * Asserts that an `object` contains a key. - * - * The value must be an object - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); - * - * @param expected the expected value - */ - toContainKey(expected: unknown): void; - /** - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); - * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); - * - * @param expected the expected value - */ - toContainAllKeys(expected: unknown): void; - /** - * Asserts that an `object` contains at least one of the provided keys. - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); - * - * @param expected the expected value - */ - toContainAnyKeys(expected: unknown): void; - - /** + /** + * -- Mocks -- + */ + export type Mock any> = JestMock.Mock; + + export const mock: { + any>(Function?: T): Mock; + + /** + * Replace the module `id` with the return value of `factory`. + * + * This is useful for mocking modules. + * + * @param id module ID to mock + * @param factory a function returning an object that will be used as the exports of the mocked module + * + * @example + * ## Example + * ```ts + * import { mock } from "bun:test"; + * + * mock.module("fs/promises", () => { + * return { + * readFile: () => Promise.resolve("hello world"), + * }; + * }); + * + * import { readFile } from "fs/promises"; + * + * console.log(await readFile("hello.txt", "utf8")); // hello world + * ``` + * + * ## More notes + * + * If the module is already loaded, exports are overwritten with the return + * value of `factory`. If the export didn't exist before, it will not be + * added to existing import statements. This is due to how ESM works. + */ + module(id: string, factory: () => any): void | Promise; + /** + * Restore the previous value of mocks. + */ + restore(): void; + }; + + /** + * Control the system time used by: + * - `Date.now()` + * - `new Date()` + * - `Intl.DateTimeFormat().format()` + * + * In the future, we may add support for more functions, but we haven't done that yet. + * + * @param now The time to set the system time to. If not provided, the system time will be reset. + * @returns `this` + * @since v0.6.13 + * + * ## Set Date to a specific time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); + * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z + * ``` + * ## Reset Date to the current time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(); + * ``` + */ + export function setSystemTime(now?: Date | number): ThisType; + + interface Jest { + restoreAllMocks(): void; + clearAllMocks(): void; + fn any>(func?: T): Mock; + setSystemTime(now?: number | Date): void; + setTimeout(milliseconds: number): void; + } + export const jest: Jest; + export namespace jest { + /** + * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. + */ + type Mock any = (...args: any[]) => any> = + JestMock.Mock; + /** + * Wraps a class, function or object type with Jest mock type definitions. + */ + // type Mocked = JestMock.Mocked; + /** + * Wraps a class type with Jest mock type definitions. + */ + // type MockedClass = JestMock.MockedClass; + /** + * Wraps a function type with Jest mock type definitions. + */ + // type MockedFunction any> = JestMock.MockedFunction; + /** + * Wraps an object type with Jest mock type definitions. + */ + // type MockedObject = JestMock.MockedObject; + /** + * Constructs the type of a replaced property. + */ + type Replaced = JestMock.Replaced; + /** + * Constructs the type of a spied class or function. + */ + type Spied any)> = + JestMock.Spied; + /** + * Constructs the type of a spied class. + */ + type SpiedClass = JestMock.SpiedClass; + /** + * Constructs the type of a spied function. + */ + type SpiedFunction any> = + JestMock.SpiedFunction; + /** + * Constructs the type of a spied getter. + */ + type SpiedGetter = JestMock.SpiedGetter; + /** + * Constructs the type of a spied setter. + */ + type SpiedSetter = JestMock.SpiedSetter; + } + + export function spyOn( + obj: T, + methodOrPropertyValue: K, + ): Mock any ? T[K] : never>; + + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export interface Describe { + (label: string, fn: () => void): void; + /** + * Skips all other tests, except this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + only(label: string, fn: () => void): void; + /** + * Skips this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + skip(label: string, fn: () => void): void; + /** + * Marks this group of tests as to be written or to be fixed. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + todo(label: string, fn?: () => void): void; + /** + * Runs this group of tests, only if `condition` is true. + * + * This is the opposite of `describe.skipIf()`. + * + * @param condition if these tests should run + */ + if(condition: boolean): (label: string, fn: () => void) => void; + /** + * Skips this group of tests, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + skipIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Marks this group of tests as to be written or to be fixed, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + todoIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): ( + label: string, + fn: (...args: [...T]) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: readonly T[], + ): ( + label: string, + fn: (...args: Readonly) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: T[], + ): ( + label: string, + fn: (...args: T[]) => void | Promise, + options?: number | TestOptions, + ) => void; + } + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export const describe: Describe; + /** + * Runs a function, once, before all the tests. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, tests will not run in this file. + * + * @example + * let database; + * beforeAll(async () => { + * database = await connect("localhost"); + * }); + * + * @param fn the function to run + */ + export function beforeAll( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function before each test. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, the test will not run. + * + * @param fn the function to run + */ + export function beforeEach( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function, once, after all the tests. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @example + * let database; + * afterAll(async () => { + * if (database) { + * await database.close(); + * } + * }); + * + * @param fn the function to run + */ + export function afterAll( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function after each test. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @param fn the function to run + */ + export function afterEach( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will + * override this value. The default timeout is 5000ms (5 seconds). + * + * @param milliseconds the number of milliseconds for the default timeout + */ + export function setDefaultTimeout(milliseconds: number): void; + export interface TestOptions { + /** + * Sets the timeout for the test in milliseconds. + * + * If the test does not complete within this time, the test will fail with: + * ```ts + * 'Timeout: test {name} timed out after 5000ms' + * ``` + * + * @default 5000 // 5 seconds + */ + timeout?: number; + /** + * Sets the number of times to retry the test if it fails. + * + * @default 0 + */ + retry?: number; + /** + * Sets the number of times to repeat the test, regardless of whether it passed or failed. + * + * @default 0 + */ + repeats?: number; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * test("can set a timeout", async () => { + * await Bun.sleep(100); + * }, 50); // or { timeout: 50 } + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + export interface Test { + ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + /** + * - If a `number`, sets the timeout for the test in milliseconds. + * - If an `object`, sets the options for the test. + * - `timeout` sets the timeout for the test in milliseconds. + * - `retry` sets the number of times to retry the test if it fails. + * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. + */ + options?: number | TestOptions, + ): void; + /** + * Skips all other tests, except this test when run with the `--only` option. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + only( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Skips this test. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + skip( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as to be written or to be fixed. + * + * These tests will not be executed unless the `--todo` flag is passed. With the flag, + * if the test passes, the test will be marked as `fail` in the results; you will have to + * remove the `.todo` or check that your test + * is implemented correctly. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + todo( + label: string, + fn?: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as failing. + * + * Use `test.failing` when you are writing a test and expecting it to fail. + * These tests will behave the other way normal tests do. If failing test + * will throw any errors then it will pass. If it does not throw it will + * fail. + * + * `test.failing` is very similar to {@link test.todo} except that it always + * runs, regardless of the `--todo` flag. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + failing( + label: string, + fn?: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs this test, if `condition` is true. + * + * This is the opposite of `test.skipIf()`. + * + * @param condition if the test should run + */ + if( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Skips this test, if `condition` is true. + * + * @param condition if the test should be skipped + */ + skipIf( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Marks this test as to be written or to be fixed, if `condition` is true. + * + * @param condition if the test should be marked TODO + */ + todoIf( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): ( + label: string, + fn: (...args: [...T]) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: readonly T[], + ): ( + label: string, + fn: (...args: Readonly) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: T[], + ): ( + label: string, + fn: (...args: T[]) => void | Promise, + options?: number | TestOptions, + ) => void; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * @param label the label for the test + * @param fn the test function + */ + export const test: Test; + export { test as it }; + + /** + * Asserts that a value matches some criteria. + * + * @link https://jestjs.io/docs/expect#reference + * @example + * expect(1 + 1).toBe(2); + * expect([1,2,3]).toContain(2); + * expect(null).toBeNull(); + * + * @param actual The actual (received) value + */ + export const expect: Expect; + + type ExpectNot = Omit & + AsymmetricMatchersBuiltinNegated; + + export interface Expect extends AsymmetricMatchers { + // the `expect()` callable signature + /** + * @param actual the actual value + * @param customFailMessage an optional custom message to display if the test fails. + * */ + + (actual?: T, customFailMessage?: string): Matchers; + + /** + * Access to negated asymmetric matchers. + * + * @example + * expect("abc").toEqual(expect.stringContaining("abc")); // will pass + * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail + */ + not: ExpectNot; + + /** + * Create an asymmetric matcher for a promise resolved value. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass + * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail + * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail + */ + resolvesTo: AsymmetricMatchers; + + /** + * Create an asymmetric matcher for a promise rejected value. + * + * @example + * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass + * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail + * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail + */ + rejectsTo: AsymmetricMatchers; + + /** + * Register new custom matchers. + * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. + * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` + * + * @example + * expect.extend({ + * toBeWithinRange(actual, min, max) { + * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') + * throw new Error('Invalid usage'); + * const pass = actual >= min && actual <= max; + * return { + * pass: pass, + * message: () => `expected ${this.utils.printReceived(actual)} ` + + * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, + * }; + * }, + * }); + * + * test('some test', () => { + * expect(50).toBeWithinRange(0, 100); // will pass + * expect(50).toBeWithinRange(100, 200); // will fail + * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass + * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass + * }); + */ + extend(matchers: ExpectExtendMatchers): void; + + /** + * Throw an error if this function is called. + * + * @param msg Optional message to display if the test fails + * @returns never + * + * @example + * ## Example + * + * ```ts + * import { expect, test } from "bun:test"; + * + * test("!!abc!! is not a module", () => { + * try { + * require("!!abc!!"); + * expect.unreachable(); + * } catch(e) { + * expect(e.name).not.toBe("UnreachableError"); + * } + * }); + * ``` + */ + unreachable(msg?: string | Error): never; + + /** + * Ensures that an assertion is made + */ + hasAssertions(): void; + + /** + * Ensures that a specific number of assertions are made + */ + assertions(neededAssertions: number): void; + } + + /** + * You can extend this interface with declaration merging, in order to add type support for custom matchers. + * @template T Type of the actual value + * + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface Matchers extends MatchersBuiltin {} + + /** + * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} + + export interface AsymmetricMatchersBuiltin { + /** + * Matches anything that was created with the given constructor. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * @example + * + * function randocall(fn) { + * return fn(Math.floor(Math.random() * 6 + 1)); + * } + * + * test('randocall calls its callback with a number', () => { + * const mock = jest.fn(); + * randocall(mock); + * expect(mock).toBeCalledWith(expect.any(Number)); + * }); + */ + any( + constructor: ((...args: any[]) => any) | { new (...args: any[]): any }, + ): AsymmetricMatcher; + /** + * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead + * of a literal value. For example, if you want to check that a mock function is called with a + * non-null argument: + * + * @example + * + * test('map calls its argument with a non-null argument', () => { + * const mock = jest.fn(); + * [1].map(x => mock(x)); + * expect(mock).toBeCalledWith(expect.anything()); + * }); + */ + anything(): AsymmetricMatcher; + /** + * Matches any array made up entirely of elements in the provided array. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + /** + * Matches any object that recursively matches the provided keys. + * This is often handy in conjunction with other asymmetric matchers. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + /** + * Matches any received string that contains the exact expected string + */ + stringContaining(str: string | String): AsymmetricMatcher; + /** + * Matches any string that contains the exact provided string + */ + stringMatching(regex: string | String | RegExp): AsymmetricMatcher; + /** + * Useful when comparing floating point numbers in object properties or array item. + * If you need to compare a number, use `.toBeCloseTo` instead. + * + * The optional `numDigits` argument limits the number of digits to check after the decimal point. + * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + interface AsymmetricMatchersBuiltinNegated { + /** + * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail + * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + */ + resolvesTo: ExpectNot; + + /** + * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. + * + * @example + * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail + * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + */ + rejectsTo: ExpectNot; + + /** + * `expect.not.arrayContaining(array)` matches a received array which + * does not contain all of the elements in the expected array. That is, + * the expected array is not a subset of the received array. It is the + * inverse of `expect.arrayContaining`. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + + /** + * `expect.not.objectContaining(object)` matches any received object + * that does not recursively match the expected properties. That is, the + * expected object is not a subset of the received object. Therefore, + * it matches a received object which contains properties that are not + * in the expected object. It is the inverse of `expect.objectContaining`. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + + /** + * `expect.not.stringContaining(string)` matches the received string + * that does not contain the exact expected string. It is the inverse of + * `expect.stringContaining`. + */ + stringContaining(str: string | String): AsymmetricMatcher; + + /** + * `expect.not.stringMatching(string | regexp)` matches the received + * string that does not match the expected regexp. It is the inverse of + * `expect.stringMatching`. + */ + stringMatching(str: string | String | RegExp): AsymmetricMatcher; + + /** + * `expect.not.closeTo` matches a number not close to the provided value. + * Useful when comparing floating point numbers in object properties or array item. + * It is the inverse of `expect.closeTo`. + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + export interface MatchersBuiltin { + /** + * Negates the result of a subsequent assertion. + * If you know how to test something, `.not` lets you test its opposite. + * + * @example + * expect(1).not.toBe(0); + * expect(null).not.toBeNull(); + * + * @example + * expect(42).toEqual(42); // will pass + * expect(42).not.toEqual(42); // will fail + */ + not: Matchers; + + /** + * Expects the value to be a promise that resolves. + * + * @example + * expect(Promise.resolve(1)).resolves.toBe(1); + */ + resolves: Matchers>; + + /** + * Expects the value to be a promise that rejects. + * + * @example + * expect(Promise.reject("error")).rejects.toBe("error"); + */ + rejects: Matchers; + + /** + * Assertion which passes. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass + * @example + * expect().pass(); + * expect().pass("message is optional"); + * expect().not.pass(); + * expect().not.pass("hi"); + * + * @param message the message to display if the test fails (optional) + */ + pass: (message?: string) => void; + /** + * Assertion which fails. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail + * @example + * expect().fail(); + * expect().fail("message is optional"); + * expect().not.fail(); + * expect().not.fail("hi"); + */ + fail: (message?: string) => void; + /** + * Asserts that a value equals what is expected. + * + * - For non-primitive values, like objects and arrays, + * use `toEqual()` instead. + * - For floating-point numbers, use `toBeCloseTo()` instead. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([123]).toBe([123]); // fail, use toEqual() + * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() + * + * @param expected the expected value + */ + toBe(expected: T): void; + /** + * Asserts that a number is odd. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd + * @example + * expect(1).toBeOdd(); + * expect(2).not.toBeOdd(); + */ + toBeOdd(): void; + /** + * Asserts that a number is even. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven + * @example + * expect(2).toBeEven(); + * expect(1).not.toBeEven(); + */ + toBeEven(): void; + /** + * Asserts that value is close to the expected by floating point precision. + * + * For example, the following fails because arithmetic on decimal (base 10) + * values often have rounding errors in limited precision binary (base 2) representation. + * + * @example + * expect(0.2 + 0.1).toBe(0.3); // fails + * + * Use `toBeCloseTo` to compare floating point numbers for approximate equality. + * + * @example + * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes + * + * @param expected the expected value + * @param numDigits the number of digits to check after the decimal point. Default is `2` + */ + toBeCloseTo(expected: number, numDigits?: number): void; + /** + * Asserts that a value is deeply equal to what is expected. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([456]).toEqual([456]); + * expect({ value: 1 }).toEqual({ value: 1 }); + * + * @param expected the expected value + */ + toEqual(expected: T): void; + /** + * Asserts that a value is deeply and strictly equal to + * what is expected. + * + * There are two key differences from `toEqual()`: + * 1. It checks that the class is the same. + * 2. It checks that `undefined` values match as well. + * + * @example + * class Dog { + * type = "dog"; + * } + * const actual = new Dog(); + * expect(actual).toStrictEqual(new Dog()); + * expect(actual).toStrictEqual({ type: "dog" }); // fail + * + * @example + * const actual = { value: 1, name: undefined }; + * expect(actual).toEqual({ value: 1 }); + * expect(actual).toStrictEqual({ value: 1 }); // fail + * + * @param expected the expected value + */ + toStrictEqual(expected: T): void; + /** + * Asserts that the value is deep equal to an element in the expected array. + * + * The value must be an array or iterable, which includes strings. + * + * @example + * expect(1).toBeOneOf([1,2,3]); + * expect("foo").toBeOneOf(["foo", "bar"]); + * expect(true).toBeOneOf(new Set([true])); + * + * @param expected the expected value + */ + toBeOneOf(expected: Array | Iterable): void; + /** + * Asserts that a value contains what is expected. + * + * The value must be an array or iterable, which + * includes strings. + * + * @example + * expect([1, 2, 3]).toContain(1); + * expect(new Set([true])).toContain(true); + * expect("hello").toContain("o"); + * + * @param expected the expected value + */ + toContain(expected: unknown): void; + /** + * Asserts that an `object` contains a key. + * + * The value must be an object + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); + * + * @param expected the expected value + */ + toContainKey(expected: unknown): void; + /** + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); + * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); + * + * @param expected the expected value + */ + toContainAllKeys(expected: unknown): void; + /** + * Asserts that an `object` contains at least one of the provided keys. + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); + * + * @param expected the expected value + */ + toContainAnyKeys(expected: unknown): void; + + /** * Asserts that an `object` contain the provided value. * * The value must be an object @@ -1029,1148 +1094,1189 @@ declare module "bun:test" { * * @param expected the expected value */ - toContainValue(expected: unknown): void; - - /** - * Asserts that an `object` contain the provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainValues(['foo']); - * expect(o).toContainValues(['baz', 'bar']); - * expect(o).not.toContainValues(['qux', 'foo']); - * @param expected the expected value - */ - toContainValues(expected: unknown): void; - - /** - * Asserts that an `object` contain all the provided values. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAllValues(['foo', 'bar', 'baz']); - * expect(o).toContainAllValues(['baz', 'bar', 'foo']); - * expect(o).not.toContainAllValues(['bar', 'foo']); - * @param expected the expected value - */ - toContainAllValues(expected: unknown): void; - - /** - * Asserts that an `object` contain any provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAnyValues(['qux', 'foo']); - * expect(o).toContainAnyValues(['qux', 'bar']); - * expect(o).toContainAnyValues(['qux', 'baz']); - * expect(o).not.toContainAnyValues(['qux']); - * @param expected the expected value - */ - toContainAnyValues(expected: unknown): void; - - /** - * Asserts that an `object` contains all the provided keys. - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); - * - * @param expected the expected value - */ - toContainKeys(expected: unknown): void; - /** - * Asserts that a value contains and equals what is expected. - * - * This matcher will perform a deep equality check for members - * of arrays, rather than checking for object identity. - * - * @example - * expect([{ a: 1 }]).toContainEqual({ a: 1 }); - * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); - * - * @param expected the expected value - */ - toContainEqual(expected: unknown): void; - /** - * Asserts that a value has a `.length` property - * that is equal to the expected length. - * - * @example - * expect([]).toHaveLength(0); - * expect("hello").toHaveLength(4); - * - * @param length the expected length - */ - toHaveLength(length: number): void; - /** - * Asserts that a value has a property with the - * expected name, and value if provided. - * - * @example - * expect(new Set()).toHaveProperty("size"); - * expect(new Uint8Array()).toHaveProperty("byteLength", 0); - * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); - * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); - * - * @param keyPath the expected property name or path, or an index - * @param value the expected property value, if provided - */ - toHaveProperty(keyPath: string | number | Array, value?: unknown): void; - /** - * Asserts that a value is "truthy". - * - * To assert that a value equals `true`, use `toBe(true)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeTruthy(): void; - /** - * Asserts that a value is "falsy". - * - * To assert that a value equals `false`, use `toBe(false)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeFalsy(): void; - /** - * Asserts that a value is defined. (e.g. is not `undefined`) - * - * @example - * expect(true).toBeDefined(); - * expect(undefined).toBeDefined(); // fail - */ - toBeDefined(): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that a value is `undefined`. - * - * @example - * expect(undefined).toBeUndefined(); - * expect(null).toBeUndefined(); // fail - */ - toBeUndefined(): void; - /** - * Asserts that a value is `null`. - * - * @example - * expect(null).toBeNull(); - * expect(undefined).toBeNull(); // fail - */ - toBeNull(): void; - /** - * Asserts that a value is `NaN`. - * - * Same as using `Number.isNaN()`. - * - * @example - * expect(NaN).toBeNaN(); - * expect(Infinity).toBeNaN(); // fail - * expect("notanumber").toBeNaN(); // fail - */ - toBeNaN(): void; - /** - * Asserts that a value is a `number` and is greater than the expected value. - * - * @example - * expect(1).toBeGreaterThan(0); - * expect(3.14).toBeGreaterThan(3); - * expect(9).toBeGreaterThan(9); // fail - * - * @param expected the expected number - */ - toBeGreaterThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is greater than or equal to the expected value. - * - * @example - * expect(1).toBeGreaterThanOrEqual(0); - * expect(3.14).toBeGreaterThanOrEqual(3); - * expect(9).toBeGreaterThanOrEqual(9); - * - * @param expected the expected number - */ - toBeGreaterThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than the expected value. - * - * @example - * expect(-1).toBeLessThan(0); - * expect(3).toBeLessThan(3.14); - * expect(9).toBeLessThan(9); // fail - * - * @param expected the expected number - */ - toBeLessThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than or equal to the expected value. - * - * @example - * expect(-1).toBeLessThanOrEqual(0); - * expect(3).toBeLessThanOrEqual(3.14); - * expect(9).toBeLessThanOrEqual(9); - * - * @param expected the expected number - */ - toBeLessThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrow("Oops!"); - * expect(fail).toThrow(/oops/i); - * expect(fail).toThrow(Error); - * expect(fail).toThrow(); - * - * @param expected the expected error, error message, or error pattern - */ - toThrow(expected?: unknown): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowError("Oops!"); - * expect(fail).toThrowError(/oops/i); - * expect(fail).toThrowError(Error); - * expect(fail).toThrowError(); - * - * @param expected the expected error, error message, or error pattern - * @alias toThrow - */ - toThrowError(expected?: unknown): void; - /** - * Asserts that a value matches a regular expression or includes a substring. - * - * @example - * expect("dog").toMatch(/dog/); - * expect("dog").toMatch("og"); - * - * @param expected the expected substring or pattern. - */ - toMatch(expected: string | RegExp): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot('hint message'); - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(hint?: string): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot(); - * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); - * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(propertyMatchers?: object, hint?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect("Hello").toMatchInlineSnapshot(); - * expect("Hello").toMatchInlineSnapshot(`"Hello"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(value?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` - * { - * "v": Any, - * } - * `); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingSnapshot(); - * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingSnapshot(hint?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingInlineSnapshot(); - * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingInlineSnapshot(value?: string): void; - /** - * Asserts that an object matches a subset of properties. - * - * @example - * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); - * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); - * - * @param subset Subset of properties to match with. - */ - toMatchObject(subset: object): void; - /** - * Asserts that a value is empty. - * - * @example - * expect("").toBeEmpty(); - * expect([]).toBeEmpty(); - * expect({}).toBeEmpty(); - * expect(new Set()).toBeEmpty(); - */ - toBeEmpty(): void; - /** - * Asserts that a value is an empty `object`. - * - * @example - * expect({}).toBeEmptyObject(); - * expect({ a: 'hello' }).not.toBeEmptyObject(); - */ - toBeEmptyObject(): void; - /** - * Asserts that a value is `null` or `undefined`. - * - * @example - * expect(null).toBeNil(); - * expect(undefined).toBeNil(); - */ - toBeNil(): void; - /** - * Asserts that a value is a `array`. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray - * @example - * expect([1]).toBeArray(); - * expect(new Array(1)).toBeArray(); - * expect({}).not.toBeArray(); - */ - toBeArray(): void; - /** - * Asserts that a value is a `array` of a certain length. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize - * @example - * expect([]).toBeArrayOfSize(0); - * expect([1]).toBeArrayOfSize(1); - * expect(new Array(1)).toBeArrayOfSize(1); - * expect({}).not.toBeArrayOfSize(0); - */ - toBeArrayOfSize(size: number): void; - /** - * Asserts that a value is a `boolean`. - * - * @example - * expect(true).toBeBoolean(); - * expect(false).toBeBoolean(); - * expect(null).not.toBeBoolean(); - * expect(0).not.toBeBoolean(); - */ - toBeBoolean(): void; - /** - * Asserts that a value is `true`. - * - * @example - * expect(true).toBeTrue(); - * expect(false).not.toBeTrue(); - * expect(1).not.toBeTrue(); - */ - toBeTrue(): void; - /** - * Asserts that a value matches a specific type. - * - * @link https://vitest.dev/api/expect.html#tobetypeof - * @example - * expect(1).toBeTypeOf("number"); - * expect("hello").toBeTypeOf("string"); - * expect([]).not.toBeTypeOf("boolean"); - */ - toBeTypeOf(type: "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"): void; - /** - * Asserts that a value is `false`. - * - * @example - * expect(false).toBeFalse(); - * expect(true).not.toBeFalse(); - * expect(0).not.toBeFalse(); - */ - toBeFalse(): void; - /** - * Asserts that a value is a `number`. - * - * @example - * expect(1).toBeNumber(); - * expect(3.14).toBeNumber(); - * expect(NaN).toBeNumber(); - * expect(BigInt(1)).not.toBeNumber(); - */ - toBeNumber(): void; - /** - * Asserts that a value is a `number`, and is an integer. - * - * @example - * expect(1).toBeInteger(); - * expect(3.14).not.toBeInteger(); - * expect(NaN).not.toBeInteger(); - */ - toBeInteger(): void; - /** - * Asserts that a value is an `object`. - * - * @example - * expect({}).toBeObject(); - * expect("notAnObject").not.toBeObject(); - * expect(NaN).not.toBeObject(); - */ - toBeObject(): void; - /** - * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. - * - * @example - * expect(1).toBeFinite(); - * expect(3.14).toBeFinite(); - * expect(NaN).not.toBeFinite(); - * expect(Infinity).not.toBeFinite(); - */ - toBeFinite(): void; - /** - * Asserts that a value is a positive `number`. - * - * @example - * expect(1).toBePositive(); - * expect(-3.14).not.toBePositive(); - * expect(NaN).not.toBePositive(); - */ - toBePositive(): void; - /** - * Asserts that a value is a negative `number`. - * - * @example - * expect(-3.14).toBeNegative(); - * expect(1).not.toBeNegative(); - * expect(NaN).not.toBeNegative(); - */ - toBeNegative(): void; - /** - * Asserts that a value is a number between a start and end value. - * - * @param start the start number (inclusive) - * @param end the end number (exclusive) - */ - toBeWithin(start: number, end: number): void; - /** - * Asserts that a value is equal to the expected string, ignoring any whitespace. - * - * @example - * expect(" foo ").toEqualIgnoringWhitespace("foo"); - * expect("bar").toEqualIgnoringWhitespace(" bar "); - * - * @param expected the expected string - */ - toEqualIgnoringWhitespace(expected: string): void; - /** - * Asserts that a value is a `symbol`. - * - * @example - * expect(Symbol("foo")).toBeSymbol(); - * expect("foo").not.toBeSymbol(); - */ - toBeSymbol(): void; - /** - * Asserts that a value is a `function`. - * - * @example - * expect(() => {}).toBeFunction(); - */ - toBeFunction(): void; - /** - * Asserts that a value is a `Date` object. - * - * To check if a date is valid, use `toBeValidDate()` instead. - * - * @example - * expect(new Date()).toBeDate(); - * expect(new Date(null)).toBeDate(); - * expect("2020-03-01").not.toBeDate(); - */ - toBeDate(): void; - /** - * Asserts that a value is a valid `Date` object. - * - * @example - * expect(new Date()).toBeValidDate(); - * expect(new Date(null)).not.toBeValidDate(); - * expect("2020-03-01").not.toBeValidDate(); - */ - toBeValidDate(): void; - /** - * Asserts that a value is a `string`. - * - * @example - * expect("foo").toBeString(); - * expect(new String("bar")).toBeString(); - * expect(123).not.toBeString(); - */ - toBeString(): void; - /** - * Asserts that a value includes a `string`. - * - * For non-string values, use `toContain()` instead. - * - * @param expected the expected substring - */ - toInclude(expected: string): void; - /** - * Asserts that a value includes a `string` {times} times. - * @param expected the expected substring - * @param times the number of times the substring should occur - */ - toIncludeRepeated(expected: string, times: number): void; - /** - * Checks whether a value satisfies a custom condition. - * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. - * @example - * expect(1).toSatisfy((val) => val > 0); - * expect("foo").toSatisfy((val) => val === "foo"); - * expect("bar").not.toSatisfy((val) => val === "bun"); - * @link https://vitest.dev/api/expect.html#tosatisfy - * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy - */ - toSatisfy(predicate: (value: T) => boolean): void; - /** - * Asserts that a value starts with a `string`. - * - * @param expected the string to start with - */ - toStartWith(expected: string): void; - /** - * Asserts that a value ends with a `string`. - * - * @param expected the string to end with - */ - toEndWith(expected: string): void; - /** - * Ensures that a mock function has returned successfully at least once. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturned(): void; - - /** - * Ensures that a mock function has returned successfully at `times` times. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturnedTimes(times: number): void; - - /** - * Ensures that a mock function is called. - */ - toHaveBeenCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - * @alias toHaveBeenCalled - */ - toBeCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - */ - toHaveBeenCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledTimes - */ - toBeCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - */ - toHaveBeenCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledWith - */ - toBeCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the last call. - */ - toHaveBeenLastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - lastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - */ - toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - nthCalledWith(n: number, ...expected: unknown[]): void; - } - - /** - * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. - */ - // Defined as an alias of `any` so that it does not trigger any type mismatch - export type AsymmetricMatcher = any; - - export interface MatcherResult { - pass: boolean; - message?: string | (() => string); - } - - export type CustomMatcher = ( - this: MatcherContext, - expected: E, - ...matcherArguments: P - ) => MatcherResult | Promise; - - /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ - export type CustomMatchersDetected = Omit, keyof MatchersBuiltin> & - Omit; - - /** - * If the types has been defined through declaration merging, enforce it. - * Otherwise enforce the generic custom matcher signature. - */ - export type ExpectExtendMatchers = { - [k in keyof M]: k extends keyof CustomMatchersDetected - ? CustomMatcher> - : CustomMatcher; - }; - - /** Custom equality tester */ - export type Tester = (this: TesterContext, a: any, b: any, customTesters: Tester[]) => boolean | undefined; - - export type EqualsFunction = ( - a: unknown, - b: unknown, - //customTesters?: Array, - //strictCheck?: boolean, - ) => boolean; - - export interface TesterContext { - equals: EqualsFunction; - } - - interface MatcherState { - //assertionCalls: number; - //currentConcurrentTestName?: () => string | undefined; - //currentTestName?: string; - //error?: Error; - //expand: boolean; - //expectedAssertionsNumber: number | null; - //expectedAssertionsNumberError?: Error; - //isExpectingAssertions: boolean; - //isExpectingAssertionsError?: Error; - isNot: boolean; - //numPassingAsserts: number; - promise: string; - //suppressedErrors: Array; - //testPath?: string; - } - - type MatcherHintColor = (arg: string) => string; // subset of Chalk type - - interface MatcherUtils { - //customTesters: Array; - //dontThrow(): void; // (internally used by jest snapshot) - equals: EqualsFunction; - utils: Readonly<{ - stringify(value: unknown): string; - printReceived(value: unknown): string; - printExpected(value: unknown): string; - matcherHint( - matcherName: string, - received?: unknown, - expected?: unknown, - options?: { - isNot?: boolean; - promise?: string; - isDirectExpectCall?: boolean; // (internal) - comment?: string; - expectedColor?: MatcherHintColor; - receivedColor?: MatcherHintColor; - secondArgument?: string; - secondArgumentColor?: MatcherHintColor; - }, - ): string; - //iterableEquality: Tester; - //subsetEquality: Tester; - // ... - }>; - } - - type MatcherContext = MatcherUtils & MatcherState; + toContainValue(expected: unknown): void; + + /** + * Asserts that an `object` contain the provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainValues(['foo']); + * expect(o).toContainValues(['baz', 'bar']); + * expect(o).not.toContainValues(['qux', 'foo']); + * @param expected the expected value + */ + toContainValues(expected: unknown): void; + + /** + * Asserts that an `object` contain all the provided values. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAllValues(['foo', 'bar', 'baz']); + * expect(o).toContainAllValues(['baz', 'bar', 'foo']); + * expect(o).not.toContainAllValues(['bar', 'foo']); + * @param expected the expected value + */ + toContainAllValues(expected: unknown): void; + + /** + * Asserts that an `object` contain any provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAnyValues(['qux', 'foo']); + * expect(o).toContainAnyValues(['qux', 'bar']); + * expect(o).toContainAnyValues(['qux', 'baz']); + * expect(o).not.toContainAnyValues(['qux']); + * @param expected the expected value + */ + toContainAnyValues(expected: unknown): void; + + /** + * Asserts that an `object` contains all the provided keys. + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); + * + * @param expected the expected value + */ + toContainKeys(expected: unknown): void; + /** + * Asserts that a value contains and equals what is expected. + * + * This matcher will perform a deep equality check for members + * of arrays, rather than checking for object identity. + * + * @example + * expect([{ a: 1 }]).toContainEqual({ a: 1 }); + * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); + * + * @param expected the expected value + */ + toContainEqual(expected: unknown): void; + /** + * Asserts that a value has a `.length` property + * that is equal to the expected length. + * + * @example + * expect([]).toHaveLength(0); + * expect("hello").toHaveLength(4); + * + * @param length the expected length + */ + toHaveLength(length: number): void; + /** + * Asserts that a value has a property with the + * expected name, and value if provided. + * + * @example + * expect(new Set()).toHaveProperty("size"); + * expect(new Uint8Array()).toHaveProperty("byteLength", 0); + * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); + * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); + * + * @param keyPath the expected property name or path, or an index + * @param value the expected property value, if provided + */ + toHaveProperty( + keyPath: string | number | Array, + value?: unknown, + ): void; + /** + * Asserts that a value is "truthy". + * + * To assert that a value equals `true`, use `toBe(true)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeTruthy(): void; + /** + * Asserts that a value is "falsy". + * + * To assert that a value equals `false`, use `toBe(false)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeFalsy(): void; + /** + * Asserts that a value is defined. (e.g. is not `undefined`) + * + * @example + * expect(true).toBeDefined(); + * expect(undefined).toBeDefined(); // fail + */ + toBeDefined(): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that a value is `undefined`. + * + * @example + * expect(undefined).toBeUndefined(); + * expect(null).toBeUndefined(); // fail + */ + toBeUndefined(): void; + /** + * Asserts that a value is `null`. + * + * @example + * expect(null).toBeNull(); + * expect(undefined).toBeNull(); // fail + */ + toBeNull(): void; + /** + * Asserts that a value is `NaN`. + * + * Same as using `Number.isNaN()`. + * + * @example + * expect(NaN).toBeNaN(); + * expect(Infinity).toBeNaN(); // fail + * expect("notanumber").toBeNaN(); // fail + */ + toBeNaN(): void; + /** + * Asserts that a value is a `number` and is greater than the expected value. + * + * @example + * expect(1).toBeGreaterThan(0); + * expect(3.14).toBeGreaterThan(3); + * expect(9).toBeGreaterThan(9); // fail + * + * @param expected the expected number + */ + toBeGreaterThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is greater than or equal to the expected value. + * + * @example + * expect(1).toBeGreaterThanOrEqual(0); + * expect(3.14).toBeGreaterThanOrEqual(3); + * expect(9).toBeGreaterThanOrEqual(9); + * + * @param expected the expected number + */ + toBeGreaterThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than the expected value. + * + * @example + * expect(-1).toBeLessThan(0); + * expect(3).toBeLessThan(3.14); + * expect(9).toBeLessThan(9); // fail + * + * @param expected the expected number + */ + toBeLessThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than or equal to the expected value. + * + * @example + * expect(-1).toBeLessThanOrEqual(0); + * expect(3).toBeLessThanOrEqual(3.14); + * expect(9).toBeLessThanOrEqual(9); + * + * @param expected the expected number + */ + toBeLessThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrow("Oops!"); + * expect(fail).toThrow(/oops/i); + * expect(fail).toThrow(Error); + * expect(fail).toThrow(); + * + * @param expected the expected error, error message, or error pattern + */ + toThrow(expected?: unknown): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowError("Oops!"); + * expect(fail).toThrowError(/oops/i); + * expect(fail).toThrowError(Error); + * expect(fail).toThrowError(); + * + * @param expected the expected error, error message, or error pattern + * @alias toThrow + */ + toThrowError(expected?: unknown): void; + /** + * Asserts that a value matches a regular expression or includes a substring. + * + * @example + * expect("dog").toMatch(/dog/); + * expect("dog").toMatch("og"); + * + * @param expected the expected substring or pattern. + */ + toMatch(expected: string | RegExp): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot('hint message'); + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(hint?: string): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot(); + * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); + * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(propertyMatchers?: object, hint?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect("Hello").toMatchInlineSnapshot(); + * expect("Hello").toMatchInlineSnapshot(`"Hello"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(value?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` + * { + * "v": Any, + * } + * `); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingSnapshot(); + * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingSnapshot(hint?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingInlineSnapshot(); + * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingInlineSnapshot(value?: string): void; + /** + * Asserts that an object matches a subset of properties. + * + * @example + * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); + * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); + * + * @param subset Subset of properties to match with. + */ + toMatchObject(subset: object): void; + /** + * Asserts that a value is empty. + * + * @example + * expect("").toBeEmpty(); + * expect([]).toBeEmpty(); + * expect({}).toBeEmpty(); + * expect(new Set()).toBeEmpty(); + */ + toBeEmpty(): void; + /** + * Asserts that a value is an empty `object`. + * + * @example + * expect({}).toBeEmptyObject(); + * expect({ a: 'hello' }).not.toBeEmptyObject(); + */ + toBeEmptyObject(): void; + /** + * Asserts that a value is `null` or `undefined`. + * + * @example + * expect(null).toBeNil(); + * expect(undefined).toBeNil(); + */ + toBeNil(): void; + /** + * Asserts that a value is a `array`. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray + * @example + * expect([1]).toBeArray(); + * expect(new Array(1)).toBeArray(); + * expect({}).not.toBeArray(); + */ + toBeArray(): void; + /** + * Asserts that a value is a `array` of a certain length. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize + * @example + * expect([]).toBeArrayOfSize(0); + * expect([1]).toBeArrayOfSize(1); + * expect(new Array(1)).toBeArrayOfSize(1); + * expect({}).not.toBeArrayOfSize(0); + */ + toBeArrayOfSize(size: number): void; + /** + * Asserts that a value is a `boolean`. + * + * @example + * expect(true).toBeBoolean(); + * expect(false).toBeBoolean(); + * expect(null).not.toBeBoolean(); + * expect(0).not.toBeBoolean(); + */ + toBeBoolean(): void; + /** + * Asserts that a value is `true`. + * + * @example + * expect(true).toBeTrue(); + * expect(false).not.toBeTrue(); + * expect(1).not.toBeTrue(); + */ + toBeTrue(): void; + /** + * Asserts that a value matches a specific type. + * + * @link https://vitest.dev/api/expect.html#tobetypeof + * @example + * expect(1).toBeTypeOf("number"); + * expect("hello").toBeTypeOf("string"); + * expect([]).not.toBeTypeOf("boolean"); + */ + toBeTypeOf( + type: + | "bigint" + | "boolean" + | "function" + | "number" + | "object" + | "string" + | "symbol" + | "undefined", + ): void; + /** + * Asserts that a value is `false`. + * + * @example + * expect(false).toBeFalse(); + * expect(true).not.toBeFalse(); + * expect(0).not.toBeFalse(); + */ + toBeFalse(): void; + /** + * Asserts that a value is a `number`. + * + * @example + * expect(1).toBeNumber(); + * expect(3.14).toBeNumber(); + * expect(NaN).toBeNumber(); + * expect(BigInt(1)).not.toBeNumber(); + */ + toBeNumber(): void; + /** + * Asserts that a value is a `number`, and is an integer. + * + * @example + * expect(1).toBeInteger(); + * expect(3.14).not.toBeInteger(); + * expect(NaN).not.toBeInteger(); + */ + toBeInteger(): void; + /** + * Asserts that a value is an `object`. + * + * @example + * expect({}).toBeObject(); + * expect("notAnObject").not.toBeObject(); + * expect(NaN).not.toBeObject(); + */ + toBeObject(): void; + /** + * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. + * + * @example + * expect(1).toBeFinite(); + * expect(3.14).toBeFinite(); + * expect(NaN).not.toBeFinite(); + * expect(Infinity).not.toBeFinite(); + */ + toBeFinite(): void; + /** + * Asserts that a value is a positive `number`. + * + * @example + * expect(1).toBePositive(); + * expect(-3.14).not.toBePositive(); + * expect(NaN).not.toBePositive(); + */ + toBePositive(): void; + /** + * Asserts that a value is a negative `number`. + * + * @example + * expect(-3.14).toBeNegative(); + * expect(1).not.toBeNegative(); + * expect(NaN).not.toBeNegative(); + */ + toBeNegative(): void; + /** + * Asserts that a value is a number between a start and end value. + * + * @param start the start number (inclusive) + * @param end the end number (exclusive) + */ + toBeWithin(start: number, end: number): void; + /** + * Asserts that a value is equal to the expected string, ignoring any whitespace. + * + * @example + * expect(" foo ").toEqualIgnoringWhitespace("foo"); + * expect("bar").toEqualIgnoringWhitespace(" bar "); + * + * @param expected the expected string + */ + toEqualIgnoringWhitespace(expected: string): void; + /** + * Asserts that a value is a `symbol`. + * + * @example + * expect(Symbol("foo")).toBeSymbol(); + * expect("foo").not.toBeSymbol(); + */ + toBeSymbol(): void; + /** + * Asserts that a value is a `function`. + * + * @example + * expect(() => {}).toBeFunction(); + */ + toBeFunction(): void; + /** + * Asserts that a value is a `Date` object. + * + * To check if a date is valid, use `toBeValidDate()` instead. + * + * @example + * expect(new Date()).toBeDate(); + * expect(new Date(null)).toBeDate(); + * expect("2020-03-01").not.toBeDate(); + */ + toBeDate(): void; + /** + * Asserts that a value is a valid `Date` object. + * + * @example + * expect(new Date()).toBeValidDate(); + * expect(new Date(null)).not.toBeValidDate(); + * expect("2020-03-01").not.toBeValidDate(); + */ + toBeValidDate(): void; + /** + * Asserts that a value is a `string`. + * + * @example + * expect("foo").toBeString(); + * expect(new String("bar")).toBeString(); + * expect(123).not.toBeString(); + */ + toBeString(): void; + /** + * Asserts that a value includes a `string`. + * + * For non-string values, use `toContain()` instead. + * + * @param expected the expected substring + */ + toInclude(expected: string): void; + /** + * Asserts that a value includes a `string` {times} times. + * @param expected the expected substring + * @param times the number of times the substring should occur + */ + toIncludeRepeated(expected: string, times: number): void; + /** + * Checks whether a value satisfies a custom condition. + * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. + * @example + * expect(1).toSatisfy((val) => val > 0); + * expect("foo").toSatisfy((val) => val === "foo"); + * expect("bar").not.toSatisfy((val) => val === "bun"); + * @link https://vitest.dev/api/expect.html#tosatisfy + * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy + */ + toSatisfy(predicate: (value: T) => boolean): void; + /** + * Asserts that a value starts with a `string`. + * + * @param expected the string to start with + */ + toStartWith(expected: string): void; + /** + * Asserts that a value ends with a `string`. + * + * @param expected the string to end with + */ + toEndWith(expected: string): void; + /** + * Ensures that a mock function has returned successfully at least once. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturned(): void; + + /** + * Ensures that a mock function has returned successfully at `times` times. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturnedTimes(times: number): void; + + /** + * Ensures that a mock function is called. + */ + toHaveBeenCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + * @alias toHaveBeenCalled + */ + toBeCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + */ + toHaveBeenCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledTimes + */ + toBeCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + */ + toHaveBeenCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledWith + */ + toBeCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the last call. + */ + toHaveBeenLastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + lastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + */ + toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + nthCalledWith(n: number, ...expected: unknown[]): void; + } + + /** + * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. + */ + // Defined as an alias of `any` so that it does not trigger any type mismatch + export type AsymmetricMatcher = any; + + export interface MatcherResult { + pass: boolean; + message?: string | (() => string); + } + + export type CustomMatcher = ( + this: MatcherContext, + expected: E, + ...matcherArguments: P + ) => MatcherResult | Promise; + + /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ + export type CustomMatchersDetected = Omit< + Matchers, + keyof MatchersBuiltin + > & + Omit; + + /** + * If the types has been defined through declaration merging, enforce it. + * Otherwise enforce the generic custom matcher signature. + */ + export type ExpectExtendMatchers = { + [k in keyof M]: k extends keyof CustomMatchersDetected + ? CustomMatcher> + : CustomMatcher; + }; + + /** Custom equality tester */ + export type Tester = ( + this: TesterContext, + a: any, + b: any, + customTesters: Tester[], + ) => boolean | undefined; + + export type EqualsFunction = ( + a: unknown, + b: unknown, + //customTesters?: Array, + //strictCheck?: boolean, + ) => boolean; + + export interface TesterContext { + equals: EqualsFunction; + } + + interface MatcherState { + //assertionCalls: number; + //currentConcurrentTestName?: () => string | undefined; + //currentTestName?: string; + //error?: Error; + //expand: boolean; + //expectedAssertionsNumber: number | null; + //expectedAssertionsNumberError?: Error; + //isExpectingAssertions: boolean; + //isExpectingAssertionsError?: Error; + isNot: boolean; + //numPassingAsserts: number; + promise: string; + //suppressedErrors: Array; + //testPath?: string; + } + + type MatcherHintColor = (arg: string) => string; // subset of Chalk type + + interface MatcherUtils { + //customTesters: Array; + //dontThrow(): void; // (internally used by jest snapshot) + equals: EqualsFunction; + utils: Readonly<{ + stringify(value: unknown): string; + printReceived(value: unknown): string; + printExpected(value: unknown): string; + matcherHint( + matcherName: string, + received?: unknown, + expected?: unknown, + options?: { + isNot?: boolean; + promise?: string; + isDirectExpectCall?: boolean; // (internal) + comment?: string; + expectedColor?: MatcherHintColor; + receivedColor?: MatcherHintColor; + secondArgument?: string; + secondArgumentColor?: MatcherHintColor; + }, + ): string; + //iterableEquality: Tester; + //subsetEquality: Tester; + // ... + }>; + } + + type MatcherContext = MatcherUtils & MatcherState; } declare module "test" { - export type * from "bun:test"; + export type * from "bun:test"; } declare namespace JestMock { - /** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - export interface ClassLike { - new (...args: any): any; - } - - export type ConstructorLikeKeys = keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - }; - - // export const fn: ( - // implementation?: T | undefined, - // ) => Mock; - - export type FunctionLike = (...args: any) => any; - - export type MethodLikeKeys = keyof { - [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; - }; - - export interface Mock any> extends MockInstance { - (...args: Parameters): ReturnType; - } - - /** - * All what the internal typings need is to be sure that we have any-function. - * `FunctionLike` type ensures that and helps to constrain the type as well. - * The default of `UnknownFunction` makes sure that `any`s do not leak to the - * user side. For instance, calling `fn()` without implementation will return - * a mock of `(...args: Array) => unknown` type. If implementation - * is provided, its typings are inferred correctly. - */ - // export interface Mock - // extends Function, - // MockInstance { - // new (...args: Parameters): ReturnType; - // (...args: Parameters): ReturnType; - // } - - // export type Mocked = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunction - // : T extends object - // ? MockedObject - // : T; - - // export const mocked: { - // ( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // ( - // source: T_1, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // }; - - // export type MockedClass = MockInstance< - // (...args: ConstructorParameters) => Mocked> - // > & - // MockedObject; - - // export type MockedFunction = MockInstance & - // MockedObject; - - // type MockedFunctionShallow = MockInstance & T; - - // export type MockedObject = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunction - // : T[K] extends object - // ? MockedObject - // : T[K]; - // } & T; - - // type MockedObjectShallow = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunctionShallow - // : T[K]; - // } & T; - - // export type MockedShallow = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunctionShallow - // : T extends object - // ? MockedObjectShallow - // : T; - - // export type MockFunctionMetadata< - // T = unknown, - // MetadataType = MockMetadataType, - // > = MockMetadata; - - // export type MockFunctionMetadataType = MockMetadataType; - - type MockFunctionResult = - | MockFunctionResultIncomplete - | MockFunctionResultReturn - | MockFunctionResultThrow; - - interface MockFunctionResultIncomplete { - type: "incomplete"; - /** - * Result of a single call to a mock function that has not yet completed. - * This occurs if you test the result from within the mock function itself, - * or from within a function that was called by the mock. - */ - value: undefined; - } - - interface MockFunctionResultReturn { - type: "return"; - /** - * Result of a single call to a mock function that returned. - */ - value: ReturnType; - } - - interface MockFunctionResultThrow { - type: "throw"; - /** - * Result of a single call to a mock function that threw. - */ - value: unknown; - } - - interface MockFunctionState { - /** - * List of the call arguments of all calls that have been made to the mock. - */ - calls: Array>; - /** - * List of all the object instances that have been instantiated from the mock. - */ - instances: Array>; - /** - * List of all the function contexts that have been applied to calls to the mock. - */ - contexts: Array>; - /** - * List of the call order indexes of the mock. Jest is indexing the order of - * invocations of all mocks in a test file. The index is starting with `1`. - */ - invocationCallOrder: number[]; - /** - * List of the call arguments of the last call that was made to the mock. - * If the function was not called, it will return `undefined`. - */ - lastCall?: Parameters; - /** - * List of the results of all calls that have been made to the mock. - */ - results: Array>; - } - - export interface MockInstance { - _isMockFunction: true; - _protoImpl: Function; - getMockImplementation(): T | undefined; - getMockName(): string; - mock: MockFunctionState; - mockClear(): this; - mockReset(): this; - mockRestore(): void; - mockImplementation(fn: T): this; - mockImplementationOnce(fn: T): this; - withImplementation(fn: T, callback: () => Promise): Promise; - withImplementation(fn: T, callback: () => void): void; - mockName(name: string): this; - mockReturnThis(): this; - mockReturnValue(value: ReturnType): this; - mockReturnValueOnce(value: ReturnType): this; - mockResolvedValue(value: ResolveType): this; - mockResolvedValueOnce(value: ResolveType): this; - mockRejectedValue(value: RejectType): this; - mockRejectedValueOnce(value: RejectType): this; - } - - // export type MockMetadata = { - // ref?: number; - // members?: Record>; - // mockImpl?: T; - // name?: string; - // refID?: number; - // type?: MetadataType; - // value?: T; - // length?: number; - // }; - - // export type MockMetadataType = - // | "object" - // | "array" - // | "regexp" - // | "function" - // | "constant" - // | "collection" - // | "null" - // | "undefined"; - - // export class ModuleMocker { - // private readonly _environmentGlobal; - // private _mockState; - // private _mockConfigRegistry; - // private _spyState; - // private _invocationCallCounter; - // /** - // * @see README.md - // * @param global Global object of the test environment, used to create - // * mocks - // */ - // constructor(global: typeof globalThis); - // private _getSlots; - // private _ensureMockConfig; - // private _ensureMockState; - // private _defaultMockConfig; - // private _defaultMockState; - // private _makeComponent; - // private _createMockFunction; - // private _generateMock; - // /** - // * Check whether the given property of an object has been already replaced. - // */ - // private _findReplacedProperty; - // /** - // * @see README.md - // * @param metadata Metadata for the mock in the schema returned by the - // * getMetadata method of this module. - // */ - // generateFromMetadata(metadata: MockMetadata): Mocked; - // /** - // * @see README.md - // * @param component The component for which to retrieve metadata. - // */ - // getMetadata( - // component: T, - // _refs?: Map, - // ): MockMetadata | null; - // isMockFunction( - // fn: MockInstance, - // ): fn is MockInstance; - // isMockFunction

, R>( - // fn: (...args: P) => R, - // ): fn is Mock<(...args: P) => R>; - // isMockFunction(fn: unknown): fn is Mock; - // fn(implementation?: T): Mock; - // private _attachMockImplementation; - // spyOn< - // T extends object, - // K extends PropertyLikeKeys, - // A extends "get" | "set", - // >( - // object: T, - // methodKey: K, - // accessType: A, - // ): A extends "get" - // ? SpiedGetter - // : A extends "set" - // ? SpiedSetter - // : never; - // spyOn< - // T extends object, - // K extends ConstructorLikeKeys | MethodLikeKeys, - // V extends Required[K], - // >( - // object: T, - // methodKey: K, - // ): V extends ClassLike | FunctionLike ? Spied : never; - // private _spyOnProperty; - // replaceProperty< - // T extends object, - // K extends PropertyLikeKeys, - // V extends T[K], - // >(object: T, propertyKey: K, value: V): Replaced; - // clearAllMocks(): void; - // resetAllMocks(): void; - // restoreAllMocks(): void; - // private _typeOf; - // mocked( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // mocked( - // source: T, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // } - - export type PropertyLikeKeys = Exclude | MethodLikeKeys>; - - export type RejectType = ReturnType extends PromiseLike ? unknown : never; - - export interface Replaced { - /** - * Restore property to its original value known at the time of mocking. - */ - restore(): void; - /** - * Change the value of the property. - */ - replaceValue(value: T): this; - } - - export function replaceProperty< - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; - } - >, - V extends T[K_2], - >(object: T, propertyKey: K_2, value: V): Replaced; - - export type ResolveType = ReturnType extends PromiseLike ? U : never; - - export type Spied = T extends ClassLike - ? SpiedClass - : T extends FunctionLike - ? SpiedFunction - : never; - - export type SpiedClass = MockInstance< - (...args: ConstructorParameters) => InstanceType - >; - - export type SpiedFunction = MockInstance< - (...args: Parameters) => ReturnType - >; - - export type SpiedGetter = MockInstance<() => T>; - - export type SpiedSetter = MockInstance<(arg: T) => void>; - - export interface SpyInstance extends MockInstance {} - - export const spyOn: { - < - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; - } - >, - V extends Required[K_2], - A extends "set" | "get", - >( - object: T, - methodKey: K_2, - accessType: A, - ): A extends "get" ? SpiedGetter : A extends "set" ? SpiedSetter : never; - < - T_1 extends object, - K_5 extends - | keyof { - [K_3 in keyof T_1 as Required[K_3] extends ClassLike ? K_3 : never]: T_1[K_3]; - } - | keyof { - [K_4 in keyof T_1 as Required[K_4] extends FunctionLike ? K_4 : never]: T_1[K_4]; - }, - V_1 extends Required[K_5], - >( - object: T_1, - methodKey: K_5, - ): V_1 extends ClassLike | FunctionLike ? Spied : never; - }; - - export interface UnknownClass { - new (...args: unknown[]): unknown; - } - - export type UnknownFunction = (...args: unknown[]) => unknown; + /** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + export interface ClassLike { + new (...args: any): any; + } + + export type ConstructorLikeKeys = keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + }; + + // export const fn: ( + // implementation?: T | undefined, + // ) => Mock; + + export type FunctionLike = (...args: any) => any; + + export type MethodLikeKeys = keyof { + [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; + }; + + export interface Mock any> + extends MockInstance { + (...args: Parameters): ReturnType; + } + + /** + * All what the internal typings need is to be sure that we have any-function. + * `FunctionLike` type ensures that and helps to constrain the type as well. + * The default of `UnknownFunction` makes sure that `any`s do not leak to the + * user side. For instance, calling `fn()` without implementation will return + * a mock of `(...args: Array) => unknown` type. If implementation + * is provided, its typings are inferred correctly. + */ + // export interface Mock + // extends Function, + // MockInstance { + // new (...args: Parameters): ReturnType; + // (...args: Parameters): ReturnType; + // } + + // export type Mocked = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunction + // : T extends object + // ? MockedObject + // : T; + + // export const mocked: { + // ( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // ( + // source: T_1, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // }; + + // export type MockedClass = MockInstance< + // (...args: ConstructorParameters) => Mocked> + // > & + // MockedObject; + + // export type MockedFunction = MockInstance & + // MockedObject; + + // type MockedFunctionShallow = MockInstance & T; + + // export type MockedObject = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunction + // : T[K] extends object + // ? MockedObject + // : T[K]; + // } & T; + + // type MockedObjectShallow = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunctionShallow + // : T[K]; + // } & T; + + // export type MockedShallow = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunctionShallow + // : T extends object + // ? MockedObjectShallow + // : T; + + // export type MockFunctionMetadata< + // T = unknown, + // MetadataType = MockMetadataType, + // > = MockMetadata; + + // export type MockFunctionMetadataType = MockMetadataType; + + type MockFunctionResult = + | MockFunctionResultIncomplete + | MockFunctionResultReturn + | MockFunctionResultThrow; + + interface MockFunctionResultIncomplete { + type: "incomplete"; + /** + * Result of a single call to a mock function that has not yet completed. + * This occurs if you test the result from within the mock function itself, + * or from within a function that was called by the mock. + */ + value: undefined; + } + + interface MockFunctionResultReturn { + type: "return"; + /** + * Result of a single call to a mock function that returned. + */ + value: ReturnType; + } + + interface MockFunctionResultThrow { + type: "throw"; + /** + * Result of a single call to a mock function that threw. + */ + value: unknown; + } + + interface MockFunctionState { + /** + * List of the call arguments of all calls that have been made to the mock. + */ + calls: Array>; + /** + * List of all the object instances that have been instantiated from the mock. + */ + instances: Array>; + /** + * List of all the function contexts that have been applied to calls to the mock. + */ + contexts: Array>; + /** + * List of the call order indexes of the mock. Jest is indexing the order of + * invocations of all mocks in a test file. The index is starting with `1`. + */ + invocationCallOrder: number[]; + /** + * List of the call arguments of the last call that was made to the mock. + * If the function was not called, it will return `undefined`. + */ + lastCall?: Parameters; + /** + * List of the results of all calls that have been made to the mock. + */ + results: Array>; + } + + export interface MockInstance { + _isMockFunction: true; + _protoImpl: Function; + getMockImplementation(): T | undefined; + getMockName(): string; + mock: MockFunctionState; + mockClear(): this; + mockReset(): this; + mockRestore(): void; + mockImplementation(fn: T): this; + mockImplementationOnce(fn: T): this; + withImplementation(fn: T, callback: () => Promise): Promise; + withImplementation(fn: T, callback: () => void): void; + mockName(name: string): this; + mockReturnThis(): this; + mockReturnValue(value: ReturnType): this; + mockReturnValueOnce(value: ReturnType): this; + mockResolvedValue(value: ResolveType): this; + mockResolvedValueOnce(value: ResolveType): this; + mockRejectedValue(value: RejectType): this; + mockRejectedValueOnce(value: RejectType): this; + } + + // export type MockMetadata = { + // ref?: number; + // members?: Record>; + // mockImpl?: T; + // name?: string; + // refID?: number; + // type?: MetadataType; + // value?: T; + // length?: number; + // }; + + // export type MockMetadataType = + // | "object" + // | "array" + // | "regexp" + // | "function" + // | "constant" + // | "collection" + // | "null" + // | "undefined"; + + // export class ModuleMocker { + // private readonly _environmentGlobal; + // private _mockState; + // private _mockConfigRegistry; + // private _spyState; + // private _invocationCallCounter; + // /** + // * @see README.md + // * @param global Global object of the test environment, used to create + // * mocks + // */ + // constructor(global: typeof globalThis); + // private _getSlots; + // private _ensureMockConfig; + // private _ensureMockState; + // private _defaultMockConfig; + // private _defaultMockState; + // private _makeComponent; + // private _createMockFunction; + // private _generateMock; + // /** + // * Check whether the given property of an object has been already replaced. + // */ + // private _findReplacedProperty; + // /** + // * @see README.md + // * @param metadata Metadata for the mock in the schema returned by the + // * getMetadata method of this module. + // */ + // generateFromMetadata(metadata: MockMetadata): Mocked; + // /** + // * @see README.md + // * @param component The component for which to retrieve metadata. + // */ + // getMetadata( + // component: T, + // _refs?: Map, + // ): MockMetadata | null; + // isMockFunction( + // fn: MockInstance, + // ): fn is MockInstance; + // isMockFunction

, R>( + // fn: (...args: P) => R, + // ): fn is Mock<(...args: P) => R>; + // isMockFunction(fn: unknown): fn is Mock; + // fn(implementation?: T): Mock; + // private _attachMockImplementation; + // spyOn< + // T extends object, + // K extends PropertyLikeKeys, + // A extends "get" | "set", + // >( + // object: T, + // methodKey: K, + // accessType: A, + // ): A extends "get" + // ? SpiedGetter + // : A extends "set" + // ? SpiedSetter + // : never; + // spyOn< + // T extends object, + // K extends ConstructorLikeKeys | MethodLikeKeys, + // V extends Required[K], + // >( + // object: T, + // methodKey: K, + // ): V extends ClassLike | FunctionLike ? Spied : never; + // private _spyOnProperty; + // replaceProperty< + // T extends object, + // K extends PropertyLikeKeys, + // V extends T[K], + // >(object: T, propertyKey: K, value: V): Replaced; + // clearAllMocks(): void; + // resetAllMocks(): void; + // restoreAllMocks(): void; + // private _typeOf; + // mocked( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // mocked( + // source: T, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // } + + export type PropertyLikeKeys = Exclude< + keyof T, + ConstructorLikeKeys | MethodLikeKeys + >; + + export type RejectType = + ReturnType extends PromiseLike ? unknown : never; + + export interface Replaced { + /** + * Restore property to its original value known at the time of mocking. + */ + restore(): void; + /** + * Change the value of the property. + */ + replaceValue(value: T): this; + } + + export function replaceProperty< + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike + ? K_1 + : never]: T[K_1]; + } + >, + V extends T[K_2], + >(object: T, propertyKey: K_2, value: V): Replaced; + + export type ResolveType = + ReturnType extends PromiseLike ? U : never; + + export type Spied = T extends ClassLike + ? SpiedClass + : T extends FunctionLike + ? SpiedFunction + : never; + + export type SpiedClass = MockInstance< + (...args: ConstructorParameters) => InstanceType + >; + + export type SpiedFunction = + MockInstance<(...args: Parameters) => ReturnType>; + + export type SpiedGetter = MockInstance<() => T>; + + export type SpiedSetter = MockInstance<(arg: T) => void>; + + export interface SpyInstance + extends MockInstance {} + + export const spyOn: { + < + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike + ? K + : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike + ? K_1 + : never]: T[K_1]; + } + >, + V extends Required[K_2], + A extends "set" | "get", + >( + object: T, + methodKey: K_2, + accessType: A, + ): A extends "get" + ? SpiedGetter + : A extends "set" + ? SpiedSetter + : never; + < + T_1 extends object, + K_5 extends + | keyof { + [K_3 in keyof T_1 as Required[K_3] extends ClassLike + ? K_3 + : never]: T_1[K_3]; + } + | keyof { + [K_4 in keyof T_1 as Required[K_4] extends FunctionLike + ? K_4 + : never]: T_1[K_4]; + }, + V_1 extends Required[K_5], + >( + object: T_1, + methodKey: K_5, + ): V_1 extends ClassLike | FunctionLike ? Spied : never; + }; + + export interface UnknownClass { + new (...args: unknown[]): unknown; + } + + export type UnknownFunction = (...args: unknown[]) => unknown; } diff --git a/packages/bun-types/test/array-buffer.test.ts b/packages/bun-types/test/array-buffer.test.ts index a3253138e308c2..9fd63d35108368 100644 --- a/packages/bun-types/test/array-buffer.test.ts +++ b/packages/bun-types/test/array-buffer.test.ts @@ -1,5 +1,5 @@ const buffer = new ArrayBuffer(1024, { - maxByteLength: 2048, + maxByteLength: 2048, }); console.log(buffer.byteLength); // 1024 diff --git a/packages/bun-types/test/array.test.ts b/packages/bun-types/test/array.test.ts index af57108192d40d..d9fce478c69188 100644 --- a/packages/bun-types/test/array.test.ts +++ b/packages/bun-types/test/array.test.ts @@ -1,16 +1,18 @@ import { expectType } from "./utilities.test"; async function* listReleases() { - for (let page = 1; ; page++) { - const response = await fetch(`https://api.github.com/repos/oven-sh/bun/releases?page=${page}`); - const releases = (await response.json()) as Array<{ data: string }>; - if (!releases.length) { - break; - } - for (const release of releases) { - yield release; - } - } + for (let page = 1; ; page++) { + const response = await fetch( + `https://api.github.com/repos/oven-sh/bun/releases?page=${page}`, + ); + const releases = (await response.json()) as Array<{ data: string }>; + if (!releases.length) { + break; + } + for (const release of releases) { + yield release; + } + } } await Array.fromAsync(listReleases()); @@ -18,12 +20,12 @@ await Array.fromAsync(listReleases()); // Tests from issue #8484 // https://github.com/oven-sh/bun/issues/8484 async function* naturals() { - for (let i = 0; i < 10; i++) { - yield i; - } + for (let i = 0; i < 10; i++) { + yield i; + } } -const test1 = await Array.fromAsync(naturals(), n => Promise.resolve(`${n}`)); +const test1 = await Array.fromAsync(naturals(), (n) => Promise.resolve(`${n}`)); expectType(test1); const test2 = await Array.fromAsync([Promise.resolve(1), Promise.resolve(2)]); diff --git a/packages/bun-types/test/broadcast.test.ts b/packages/bun-types/test/broadcast.test.ts index 1d853f7fec23dc..1458e0c0615365 100644 --- a/packages/bun-types/test/broadcast.test.ts +++ b/packages/bun-types/test/broadcast.test.ts @@ -1,9 +1,9 @@ const channel = new BroadcastChannel("my-channel"); const message = { hello: "world" }; -channel.onmessage = event => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - console.log((event as any).data); // { hello: "world" } +channel.onmessage = (event) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + console.log((event as any).data); // { hello: "world" } }; channel.postMessage(message); diff --git a/packages/bun-types/test/bun.test.ts b/packages/bun-types/test/bun.test.ts index ae642ff6f1e53c..b3cfb1bfeed41b 100644 --- a/packages/bun-types/test/bun.test.ts +++ b/packages/bun-types/test/bun.test.ts @@ -1,51 +1,51 @@ import { BunFile, BunPlugin, FileBlob } from "bun"; import * as tsd from "./utilities.test"; { - const _plugin: BunPlugin = { - name: "asdf", - setup() {}, - }; - _plugin; + const _plugin: BunPlugin = { + name: "asdf", + setup() {}, + }; + _plugin; } { - // tslint:disable-next-line:no-void-expression - const arg = Bun.plugin({ - name: "arg", - setup() {}, - }); + // tslint:disable-next-line:no-void-expression + const arg = Bun.plugin({ + name: "arg", + setup() {}, + }); - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - tsd.expectType(arg); + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + tsd.expectType(arg); } { - // tslint:disable-next-line:no-void-expression - const arg = Bun.plugin({ - name: "arg", - async setup() {}, - }); + // tslint:disable-next-line:no-void-expression + const arg = Bun.plugin({ + name: "arg", + async setup() {}, + }); - tsd.expectType>(arg); + tsd.expectType>(arg); } { - const f = Bun.file("asdf"); - tsd.expectType(f); - tsd.expectType(f); + const f = Bun.file("asdf"); + tsd.expectType(f); + tsd.expectType(f); } { - Bun.spawn(["anything"], { - env: process.env, - }); - Bun.spawn(["anything"], { - env: { ...process.env }, - }); - Bun.spawn(["anything"], { - env: { ...process.env, dummy: "" }, - }); + Bun.spawn(["anything"], { + env: process.env, + }); + Bun.spawn(["anything"], { + env: { ...process.env }, + }); + Bun.spawn(["anything"], { + env: { ...process.env, dummy: "" }, + }); } { - Bun.TOML.parse("asdf = asdf"); + Bun.TOML.parse("asdf = asdf"); } DOMException; diff --git a/packages/bun-types/test/console.test.ts b/packages/bun-types/test/console.test.ts index 779bbab1984711..b00be4b0c7e101 100644 --- a/packages/bun-types/test/console.test.ts +++ b/packages/bun-types/test/console.test.ts @@ -5,19 +5,19 @@ c1.log(); c2.log(); async () => { - // tslint:disable-next-line:await-promise - for await (const line of c1) { - console.log("Received:", line); - } + // tslint:disable-next-line:await-promise + for await (const line of c1) { + console.log("Received:", line); + } - // tslint:disable-next-line:await-promise - for await (const line of c2) { - console.log("Received:", line); - } - // tslint:disable-next-line:await-promise - for await (const line of console) { - console.log("Received:", line); - } + // tslint:disable-next-line:await-promise + for await (const line of c2) { + console.log("Received:", line); + } + // tslint:disable-next-line:await-promise + for await (const line of console) { + console.log("Received:", line); + } - return null; + return null; }; diff --git a/packages/bun-types/test/diag.test.ts b/packages/bun-types/test/diag.test.ts index 35f41ce050664d..df3aef7e3c6e82 100644 --- a/packages/bun-types/test/diag.test.ts +++ b/packages/bun-types/test/diag.test.ts @@ -5,7 +5,7 @@ const channel = diagnostics_channel.channel("my-channel"); // Subscribe to the channel channel.subscribe((message, name) => { - console.log("Received message:", message); + console.log("Received message:", message); }); // Publish a message to the channel diff --git a/packages/bun-types/test/dom.test.ts b/packages/bun-types/test/dom.test.ts index c3d8a4383640e5..804f5cead79e61 100644 --- a/packages/bun-types/test/dom.test.ts +++ b/packages/bun-types/test/dom.test.ts @@ -3,23 +3,23 @@ import { INSPECT_MAX_BYTES } from "buffer"; INSPECT_MAX_BYTES; { - new Blob([]); + new Blob([]); } { - new MessagePort(); + new MessagePort(); } { - new MessageChannel(); + new MessageChannel(); } { - new BroadcastChannel("zxgdfg"); + new BroadcastChannel("zxgdfg"); } { - new Response("asdf"); + new Response("asdf"); } { - Response.json({ asdf: "asdf" }).ok; - const r = Response.json({ hello: "world" }); - r.body; + Response.json({ asdf: "asdf" }).ok; + const r = Response.json({ hello: "world" }); + r.body; } diff --git a/packages/bun-types/test/env.test.ts b/packages/bun-types/test/env.test.ts index f9b1d53be648b4..aa26b9f002ee84 100644 --- a/packages/bun-types/test/env.test.ts +++ b/packages/bun-types/test/env.test.ts @@ -1,19 +1,19 @@ import { expectType } from "./utilities.test"; declare module "bun" { - interface Env { - FOO: "FOO"; - } + interface Env { + FOO: "FOO"; + } } expectType<"FOO">(process.env.FOO); declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace NodeJS { - interface ProcessEnv { - BAR: "BAR"; - } - } + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace NodeJS { + interface ProcessEnv { + BAR: "BAR"; + } + } } expectType<"BAR">(process.env.BAR); diff --git a/packages/bun-types/test/events.test.ts b/packages/bun-types/test/events.test.ts index d774a4b619d0dd..b3404096aa7185 100644 --- a/packages/bun-types/test/events.test.ts +++ b/packages/bun-types/test/events.test.ts @@ -13,8 +13,8 @@ import { expectType } from "./utilities.test"; const e2 = new EventEmitter(); e2.on("qwer", (_: any) => { - _; + _; }); -e2.on("asdf", arg => { - expectType(arg); +e2.on("asdf", (arg) => { + expectType(arg); }); diff --git a/packages/bun-types/test/ffi.test.ts b/packages/bun-types/test/ffi.test.ts index 277c45b5ec57a6..c7a74e0cdb5ff4 100644 --- a/packages/bun-types/test/ffi.test.ts +++ b/packages/bun-types/test/ffi.test.ts @@ -1,4 +1,12 @@ -import { CString, dlopen, FFIType, JSCallback, Pointer, read, suffix } from "bun:ffi"; +import { + CString, + dlopen, + FFIType, + JSCallback, + Pointer, + read, + suffix, +} from "bun:ffi"; import * as tsd from "./utilities.test"; // `suffix` is either "dylib", "so", or "dll" depending on the platform @@ -6,60 +14,60 @@ import * as tsd from "./utilities.test"; const path = `libsqlite3.${suffix}`; const lib = dlopen( - path, // a library name or file path - { - sqlite3_libversion: { - // no arguments, returns a string - args: [], - returns: FFIType.cstring, - }, - add: { - args: [FFIType.i32, FFIType.i32], - returns: FFIType.i32, - }, - ptr_type: { - args: [FFIType.pointer], - returns: FFIType.pointer, - }, - fn_type: { - args: [FFIType.function], - returns: FFIType.function, - }, - allArgs: { - args: [ - FFIType.char, // string - FFIType.int8_t, - FFIType.i8, - FFIType.uint8_t, - FFIType.u8, - FFIType.int16_t, - FFIType.i16, - FFIType.uint16_t, - FFIType.u16, - FFIType.int32_t, - FFIType.i32, - FFIType.int, - FFIType.uint32_t, - FFIType.u32, - FFIType.int64_t, - FFIType.i64, - FFIType.uint64_t, - FFIType.u64, - FFIType.double, - FFIType.f64, - FFIType.float, - FFIType.f32, - FFIType.bool, - FFIType.ptr, - FFIType.pointer, - FFIType.void, - FFIType.cstring, - FFIType.i64_fast, - FFIType.u64_fast, - ], - returns: FFIType.void, - }, - }, + path, // a library name or file path + { + sqlite3_libversion: { + // no arguments, returns a string + args: [], + returns: FFIType.cstring, + }, + add: { + args: [FFIType.i32, FFIType.i32], + returns: FFIType.i32, + }, + ptr_type: { + args: [FFIType.pointer], + returns: FFIType.pointer, + }, + fn_type: { + args: [FFIType.function], + returns: FFIType.function, + }, + allArgs: { + args: [ + FFIType.char, // string + FFIType.int8_t, + FFIType.i8, + FFIType.uint8_t, + FFIType.u8, + FFIType.int16_t, + FFIType.i16, + FFIType.uint16_t, + FFIType.u16, + FFIType.int32_t, + FFIType.i32, + FFIType.int, + FFIType.uint32_t, + FFIType.u32, + FFIType.int64_t, + FFIType.i64, + FFIType.uint64_t, + FFIType.u64, + FFIType.double, + FFIType.f64, + FFIType.float, + FFIType.f32, + FFIType.bool, + FFIType.ptr, + FFIType.pointer, + FFIType.void, + FFIType.cstring, + FFIType.i64_fast, + FFIType.u64_fast, + ], + returns: FFIType.void, + }, + }, ); declare const ptr: Pointer; @@ -69,44 +77,46 @@ tsd.expectType(lib.symbols.add(1, 2)); tsd.expectType(lib.symbols.ptr_type(ptr)); -tsd.expectType(lib.symbols.fn_type(new JSCallback(() => {}, {}))); +tsd.expectType( + lib.symbols.fn_type(new JSCallback(() => {}, {})), +); function _arg( - ...params: [ - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - boolean, - Pointer, - Pointer, - // tslint:disable-next-line: void-return - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - void, - CString, - number | bigint, - number | bigint, - ] + ...params: [ + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + boolean, + Pointer, + Pointer, + // tslint:disable-next-line: void-return + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + void, + CString, + number | bigint, + number | bigint, + ] ) { - console.log("asdf"); + console.log("asdf"); } _arg; @@ -143,20 +153,20 @@ tsd.expectTypeEquals(true); // tslint:disable-next-line:no-object-literal-type-assertion const as_const_test = { - sqlite3_libversion: { - args: [], - returns: FFIType.cstring, - }, - multi_args: { - args: [FFIType.i32, FFIType.f32], - returns: FFIType.void, - }, - no_returns: { - args: [FFIType.i32], - }, - no_args: { - returns: FFIType.i32, - }, + sqlite3_libversion: { + args: [], + returns: FFIType.cstring, + }, + multi_args: { + args: [FFIType.i32, FFIType.f32], + returns: FFIType.void, + }, + no_returns: { + args: [FFIType.i32], + }, + no_args: { + returns: FFIType.i32, + }, } as const; const lib2 = dlopen(path, as_const_test); @@ -165,7 +175,10 @@ tsd.expectType(lib2.symbols.sqlite3_libversion()); // tslint:disable-next-line:no-void-expression // eslint-disable-next-line @typescript-eslint/no-invalid-void-type tsd.expectType(lib2.symbols.multi_args(1, 2)); -tsd.expectTypeEquals, undefined>(true); +tsd.expectTypeEquals< + ReturnType<(typeof lib2)["symbols"]["no_returns"]>, + undefined +>(true); tsd.expectTypeEquals, []>(true); tsd.expectType(read.u8(ptr)); diff --git a/packages/bun-types/test/fs.test.ts b/packages/bun-types/test/fs.test.ts index 863c528d1ba72b..5fe2e4c920835c 100644 --- a/packages/bun-types/test/fs.test.ts +++ b/packages/bun-types/test/fs.test.ts @@ -11,10 +11,10 @@ tsd.expectType>(fs.promises.exists("/etc/passwd")); // file path watch(".", (eventType, filename) => { - console.log(`event type = ${eventType}`); - if (filename) { - console.log(`filename = ${filename}`); - } + console.log(`event type = ${eventType}`); + if (filename) { + console.log(`filename = ${filename}`); + } }); await Bun.file("sdf").exists(); diff --git a/packages/bun-types/test/fsrouter.test.ts b/packages/bun-types/test/fsrouter.test.ts index 1a1b9975560bff..2e26f90bb0e066 100644 --- a/packages/bun-types/test/fsrouter.test.ts +++ b/packages/bun-types/test/fsrouter.test.ts @@ -2,8 +2,8 @@ import { FileSystemRouter } from "bun"; import { expectType } from "./utilities.test"; const router = new FileSystemRouter({ - dir: "/pages", - style: "nextjs", + dir: "/pages", + style: "nextjs", }); const match = router.match("/"); diff --git a/packages/bun-types/test/globals.test.ts b/packages/bun-types/test/globals.test.ts index d2fb69e4c9eb89..3644f515ba4c0d 100644 --- a/packages/bun-types/test/globals.test.ts +++ b/packages/bun-types/test/globals.test.ts @@ -26,14 +26,16 @@ expectType(new Bun.SHA512_256().update("test").digest("hex")); expectType(Bun.deflateSync(new Uint8Array(128))); expectType(Bun.gzipSync(new Uint8Array(128))); expectType( - Bun.deflateSync(new Uint8Array(128), { - level: -1, - memLevel: 8, - strategy: 0, - windowBits: 15, - }), + Bun.deflateSync(new Uint8Array(128), { + level: -1, + memLevel: 8, + strategy: 0, + windowBits: 15, + }), +); +expectType( + Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 }), ); -expectType(Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 })); expectType(Bun.inflateSync(new Uint8Array(64))); // Pretend this is DEFLATE compressed data expectType(Bun.gunzipSync(new Uint8Array(64))); // Pretend this is GZIP compressed data expectAssignable({ windowBits: -11 }); @@ -45,7 +47,9 @@ expectType(Bun.pathToFileURL("/foo/bar.txt")); expectType(Bun.fileURLToPath(new URL("file:///foo/bar.txt"))); // Testing ../fs.d.ts -expectType(fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString()); +expectType( + fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString(), +); expectType(fs.existsSync("./index.d.ts")); // tslint:disable-next-line:no-void-expression // eslint-disable-next-line @typescript-eslint/no-invalid-void-type @@ -58,7 +62,9 @@ expectType(fs.appendFileSync("./index.d.ts", "test")); expectType(fs.mkdirSync("./index.d.ts")); // Testing ^promises.d.ts -expectType((await fsPromises.readFile("./index.d.ts", { encoding: "utf-8" })).toString()); +expectType( + (await fsPromises.readFile("./index.d.ts", { encoding: "utf-8" })).toString(), +); expectType>(fsPromises.access("./index.d.ts")); expectType>(fsPromises.appendFile("./index.d.ts", "test")); expectType>(fsPromises.mkdir("./index.d.ts")); @@ -136,7 +142,7 @@ function stuff(arg: ReadableStreamDefaultReader): any; function stuff(arg: ReadableStreamDefaultController): any; function stuff(arg: WritableStreamDefaultWriter): any; function stuff(arg: any) { - return "asfd"; + return "asfd"; } stuff("asdf" as any as Blob); @@ -157,145 +163,145 @@ const readableStream = new ReadableStream(); const writableStream = new WritableStream(); { - const a = new ByteLengthQueuingStrategy({ highWaterMark: 0 }); - a.highWaterMark; + const a = new ByteLengthQueuingStrategy({ highWaterMark: 0 }); + a.highWaterMark; } { - const a = new ReadableStreamDefaultController(); - a.close(); + const a = new ReadableStreamDefaultController(); + a.close(); } { - const a = new ReadableStreamDefaultReader(readableStream); - await a.cancel(); + const a = new ReadableStreamDefaultReader(readableStream); + await a.cancel(); } { - const a = new WritableStreamDefaultController(); - a.error(); + const a = new WritableStreamDefaultController(); + a.error(); } { - const a = new WritableStreamDefaultWriter(writableStream); - await a.close(); + const a = new WritableStreamDefaultWriter(writableStream); + await a.close(); } { - const a = new TransformStream(); - a.readable; + const a = new TransformStream(); + a.readable; } { - const a = new TransformStreamDefaultController(); - a.enqueue("asdf"); + const a = new TransformStreamDefaultController(); + a.enqueue("asdf"); } { - const a = new CountQueuingStrategy({ highWaterMark: 0 }); - a.highWaterMark; + const a = new CountQueuingStrategy({ highWaterMark: 0 }); + a.highWaterMark; } { - const a = new DOMException(); - a.DATA_CLONE_ERR; + const a = new DOMException(); + a.DATA_CLONE_ERR; } { - const a = new SubtleCrypto(); - await a.decrypt("asdf", new CryptoKey(), new Uint8Array()); + const a = new SubtleCrypto(); + await a.decrypt("asdf", new CryptoKey(), new Uint8Array()); } { - const a = new CryptoKey(); - a.algorithm; + const a = new CryptoKey(); + a.algorithm; } { - const a = new BuildError(); - a.level; + const a = new BuildError(); + a.level; } { - const a = new ResolveError(); - a.level; + const a = new ResolveError(); + a.level; } { - const a = new AbortController(); - a; + const a = new AbortController(); + a; } { - const a = new AbortSignal(); - a.aborted; + const a = new AbortSignal(); + a.aborted; } { - const a = new Request("asdf"); - await a.json(); - a.cache; + const a = new Request("asdf"); + await a.json(); + a.cache; } { - const a = new Response(); - await a.text(); - a.ok; + const a = new Response(); + await a.text(); + a.ok; } { - const a = new FormData(); - a.delete("asdf"); + const a = new FormData(); + a.delete("asdf"); } { - const a = new Headers(); - a.append("asdf", "asdf"); + const a = new Headers(); + a.append("asdf", "asdf"); } { - const a = new EventTarget(); - a.dispatchEvent(new Event("asdf")); + const a = new EventTarget(); + a.dispatchEvent(new Event("asdf")); } { - const a = new Event("asdf"); - a.bubbles; - a.composedPath()[0]; + const a = new Event("asdf"); + a.bubbles; + a.composedPath()[0]; } { - const a = new Blob(); - a.size; + const a = new Blob(); + a.size; } { - const a = new File(["asdf"], "stuff.txt "); - a.name; + const a = new File(["asdf"], "stuff.txt "); + a.name; } { - performance.now(); + performance.now(); } { - const a = new URL("asdf"); - a.host; - a.href; + const a = new URL("asdf"); + a.host; + a.href; } { - const a = new URLSearchParams(); - a; + const a = new URLSearchParams(); + a; } { - const a = new TextDecoder(); - a.decode(new Uint8Array()); + const a = new TextDecoder(); + a.decode(new Uint8Array()); } { - const a = new TextEncoder(); - a.encode("asdf"); + const a = new TextEncoder(); + a.encode("asdf"); } { - const a = new BroadcastChannel("stuff"); - a.close(); + const a = new BroadcastChannel("stuff"); + a.close(); } { - const a = new MessageChannel(); - a.port1; + const a = new MessageChannel(); + a.port1; } { - const a = new MessagePort(); - a.close(); + const a = new MessagePort(); + a.close(); } { - var a!: RequestInit; - a.mode; - a.credentials; + var a!: RequestInit; + a.mode; + a.credentials; } { - var b!: ResponseInit; - b.status; + var b!: ResponseInit; + b.status; } { - const ws = new WebSocket("ws://www.host.com/path"); - ws.send("asdf"); + const ws = new WebSocket("ws://www.host.com/path"); + ws.send("asdf"); } atob("asf"); diff --git a/packages/bun-types/test/http.test.ts b/packages/bun-types/test/http.test.ts index c78ab80c233ce8..49ee1e02c1b9f0 100644 --- a/packages/bun-types/test/http.test.ts +++ b/packages/bun-types/test/http.test.ts @@ -29,7 +29,7 @@ export {}; // URLSearchParams should be iterable const sp = new URLSearchParams("q=foo&bar=baz"); for (const q of sp) { - console.log(q); + console.log(q); } fetch; diff --git a/packages/bun-types/test/jsc.test.ts b/packages/bun-types/test/jsc.test.ts index c1a531f1153af3..181c5d84179a69 100644 --- a/packages/bun-types/test/jsc.test.ts +++ b/packages/bun-types/test/jsc.test.ts @@ -6,5 +6,5 @@ const buffer = serialize(obj); const clone = deserialize(buffer); if (deepEquals(obj, clone)) { - console.log("They are equal!"); + console.log("They are equal!"); } diff --git a/packages/bun-types/test/mocks.test.ts b/packages/bun-types/test/mocks.test.ts index 8c891743356fcc..87eb74dcea59db 100644 --- a/packages/bun-types/test/mocks.test.ts +++ b/packages/bun-types/test/mocks.test.ts @@ -2,7 +2,7 @@ import { jest, mock } from "bun:test"; import { expectType } from "./utilities.test"; const mock1 = mock((arg: string) => { - return arg.length; + return arg.length; }); const arg1 = mock1("1"); diff --git a/packages/bun-types/test/net.test.ts b/packages/bun-types/test/net.test.ts index 76ad4b01516fe9..2756dd4d1dd7d4 100644 --- a/packages/bun-types/test/net.test.ts +++ b/packages/bun-types/test/net.test.ts @@ -1,11 +1,11 @@ import * as net from "node:net"; const socket = net.connect({ - port: 80, - host: "localhost", + port: 80, + host: "localhost", }); socket.connect({ - port: 80, - host: "localhost", + port: 80, + host: "localhost", }); diff --git a/packages/bun-types/test/process.test.ts b/packages/bun-types/test/process.test.ts index 6ea7cf043d902c..04c8d17b249856 100644 --- a/packages/bun-types/test/process.test.ts +++ b/packages/bun-types/test/process.test.ts @@ -2,15 +2,15 @@ process.memoryUsage(); process.cpuUsage().system; process.cpuUsage().user; process.on("SIGINT", () => { - console.log("Interrupt from keyboard"); + console.log("Interrupt from keyboard"); }); -process.on("beforeExit", code => { - console.log("Event loop is empty and no work is left to schedule.", code); +process.on("beforeExit", (code) => { + console.log("Event loop is empty and no work is left to schedule.", code); }); -process.on("exit", code => { - console.log("Exiting with code:", code); +process.on("exit", (code) => { + console.log("Exiting with code:", code); }); process.kill(123, "SIGTERM"); @@ -21,7 +21,7 @@ process.getgroups!(); process.getuid!(); process.once("SIGINT", () => { - console.log("Interrupt from keyboard"); + console.log("Interrupt from keyboard"); }); // commented methods are not yet implemented diff --git a/packages/bun-types/test/readline.test.ts b/packages/bun-types/test/readline.test.ts index 967d9b06d5db79..7b4be00a01a201 100644 --- a/packages/bun-types/test/readline.test.ts +++ b/packages/bun-types/test/readline.test.ts @@ -1,10 +1,10 @@ import * as readline from "node:readline/promises"; const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: true, + input: process.stdin, + output: process.stdout, + terminal: true, }); -await rl.question("What is your age?\n").then(answer => { - console.log("Your age is: " + answer); +await rl.question("What is your age?\n").then((answer) => { + console.log("Your age is: " + answer); }); diff --git a/packages/bun-types/test/serve.test.ts b/packages/bun-types/test/serve.test.ts index 1ddd23a0c6dff3..60903bf71fc7fc 100644 --- a/packages/bun-types/test/serve.test.ts +++ b/packages/bun-types/test/serve.test.ts @@ -1,160 +1,160 @@ Bun.serve({ - fetch(req) { - console.log(req.url); // => http://localhost:3000/ - return new Response("Hello World"); - }, + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, }); Bun.serve({ - fetch(req) { - console.log(req.url); // => http://localhost:3000/ - return new Response("Hello World"); - }, - keyFile: "ca.pem", - certFile: "cert.pem", + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, + keyFile: "ca.pem", + certFile: "cert.pem", }); Bun.serve({ - websocket: { - message(ws, message) { - ws.send(message); - }, - }, - - fetch(req, server) { - // Upgrade to a ServerWebSocket if we can - // This automatically checks for the `Sec-WebSocket-Key` header - // meaning you don't have to check headers, you can just call `upgrade()` - if (server.upgrade(req)) { - // When upgrading, we return undefined since we don't want to send a Response - return; - } - - return new Response("Regular HTTP response"); - }, + websocket: { + message(ws, message) { + ws.send(message); + }, + }, + + fetch(req, server) { + // Upgrade to a ServerWebSocket if we can + // This automatically checks for the `Sec-WebSocket-Key` header + // meaning you don't have to check headers, you can just call `upgrade()` + if (server.upgrade(req)) { + // When upgrading, we return undefined since we don't want to send a Response + return; + } + + return new Response("Regular HTTP response"); + }, }); Bun.serve<{ - name: string; + name: string; }>({ - fetch(req, server) { - const url = new URL(req.url); - if (url.pathname === "/chat") { - if ( - server.upgrade(req, { - data: { - name: new URL(req.url).searchParams.get("name") || "Friend", - }, - headers: { - "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), - }, - }) - ) { - return; - } - } - - return new Response("Expected a websocket connection", { status: 400 }); - }, - - websocket: { - open(ws) { - console.log("WebSocket opened"); - ws.subscribe("the-group-chat"); - }, - - message(ws, message) { - ws.publish("the-group-chat", `${ws.data.name}: ${message.toString()}`); - }, - - close(ws, code, reason) { - ws.publish("the-group-chat", `${ws.data.name} left the chat`); - }, - - drain(ws) { - console.log("Please send me data. I am ready to receive it."); - }, - - perMessageDeflate: true, - }, + fetch(req, server) { + const url = new URL(req.url); + if (url.pathname === "/chat") { + if ( + server.upgrade(req, { + data: { + name: new URL(req.url).searchParams.get("name") || "Friend", + }, + headers: { + "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), + }, + }) + ) { + return; + } + } + + return new Response("Expected a websocket connection", { status: 400 }); + }, + + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("the-group-chat"); + }, + + message(ws, message) { + ws.publish("the-group-chat", `${ws.data.name}: ${message.toString()}`); + }, + + close(ws, code, reason) { + ws.publish("the-group-chat", `${ws.data.name} left the chat`); + }, + + drain(ws) { + console.log("Please send me data. I am ready to receive it."); + }, + + perMessageDeflate: true, + }, }); Bun.serve({ - fetch(req) { - throw new Error("woops!"); - }, - error(error) { - return new Response(`

${error.message}\n${error.stack}
`, { - headers: { - "Content-Type": "text/html", - }, - }); - }, + fetch(req) { + throw new Error("woops!"); + }, + error(error) { + return new Response(`
${error.message}\n${error.stack}
`, { + headers: { + "Content-Type": "text/html", + }, + }); + }, }); export {}; Bun.serve({ - port: 1234, - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, + port: 1234, + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch() { - return new Response(); - }, + unix: "/tmp/bun.sock", + fetch() { + return new Response(); + }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, + unix: "/tmp/bun.sock", + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch() { - return new Response(); - }, - tls: {}, + unix: "/tmp/bun.sock", + fetch() { + return new Response(); + }, + tls: {}, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, - tls: {}, + unix: "/tmp/bun.sock", + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, + tls: {}, }); Bun.serve({ - fetch(req, server) { - server.upgrade(req); - }, - websocket: { - open(ws) { - console.log("WebSocket opened"); - ws.subscribe("test-channel"); - }, - - message(ws, message) { - ws.publish("test-channel", `${message.toString()}`); - }, - perMessageDeflate: true, - }, + fetch(req, server) { + server.upgrade(req); + }, + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("test-channel"); + }, + + message(ws, message) { + ws.publish("test-channel", `${message.toString()}`); + }, + perMessageDeflate: true, + }, }); // Bun.serve({ // unix: "/tmp/bun.sock", diff --git a/packages/bun-types/test/spawn.test.ts b/packages/bun-types/test/spawn.test.ts index a6c8fddff15b5d..9dbfef61bf9264 100644 --- a/packages/bun-types/test/spawn.test.ts +++ b/packages/bun-types/test/spawn.test.ts @@ -1,145 +1,176 @@ -import { FileSink, NullSubprocess, PipedSubprocess, ReadableSubprocess, SyncSubprocess, WritableSubprocess } from "bun"; +import { + FileSink, + NullSubprocess, + PipedSubprocess, + ReadableSubprocess, + SyncSubprocess, + WritableSubprocess, +} from "bun"; import * as tsd from "./utilities.test"; Bun.spawn(["echo", "hello"]); function depromise(_promise: Promise): T { - return "asdf" as any as T; + return "asdf" as any as T; } { - const proc = Bun.spawn(["echo", "hello"], { - cwd: "./path/to/subdir", // specify a working direcory - env: { ...process.env, FOO: "bar" }, // specify environment variables - onExit(proc, exitCode, signalCode, error) { - // exit handler - }, - }); - - proc.pid; // process ID of subprocess - - tsd.expectType>(proc.stdout); - tsd.expectType(proc.stderr); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + cwd: "./path/to/subdir", // specify a working direcory + env: { ...process.env, FOO: "bar" }, // specify environment variables + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + proc.pid; // process ID of subprocess + + tsd.expectType>(proc.stdout); + tsd.expectType(proc.stderr); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["cat"], { - stdin: depromise(fetch("https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js")), - }); - - const text = depromise(new Response(proc.stdout).text()); - console.log(text); // "const input = "hello world".repeat(400); ..." + const proc = Bun.spawn(["cat"], { + stdin: depromise( + fetch( + "https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js", + ), + ), + }); + + const text = depromise(new Response(proc.stdout).text()); + console.log(text); // "const input = "hello world".repeat(400); ..." } { - const proc = Bun.spawn(["cat"], { - stdin: "pipe", // return a FileSink for writing - }); - - // enqueue string data - proc.stdin.write("hello"); - - // enqueue binary data - const enc = new TextEncoder(); - proc.stdin.write(enc.encode(" world!")); - enc.encodeInto(" world!", {} as any as Uint8Array); - // Bun-specific overloads - // these fail when lib.dom.d.ts is present - enc.encodeInto(" world!", new Uint32Array(124)); - enc.encodeInto(" world!", {} as any as DataView); - - // send buffered data - await proc.stdin.flush(); - - // close the input stream - await proc.stdin.end(); + const proc = Bun.spawn(["cat"], { + stdin: "pipe", // return a FileSink for writing + }); + + // enqueue string data + proc.stdin.write("hello"); + + // enqueue binary data + const enc = new TextEncoder(); + proc.stdin.write(enc.encode(" world!")); + enc.encodeInto(" world!", {} as any as Uint8Array); + // Bun-specific overloads + // these fail when lib.dom.d.ts is present + enc.encodeInto(" world!", new Uint32Array(124)); + enc.encodeInto(" world!", {} as any as DataView); + + // send buffered data + await proc.stdin.flush(); + + // close the input stream + await proc.stdin.end(); } { - const proc = Bun.spawn(["echo", "hello"]); - const text = depromise(new Response(proc.stdout).text()); - console.log(text); // => "hello" + const proc = Bun.spawn(["echo", "hello"]); + const text = depromise(new Response(proc.stdout).text()); + console.log(text); // => "hello" } { - const proc = Bun.spawn(["echo", "hello"], { - onExit(proc, exitCode, signalCode, error) { - // exit handler - }, - }); - - await proc.exited; // resolves when process exit - proc.killed; // boolean โ€” was the process killed? - proc.exitCode; // null | number - proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... - proc.kill(); - proc.killed; // true - - proc.kill(); // specify an exit code - proc.unref(); + const proc = Bun.spawn(["echo", "hello"], { + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + await proc.exited; // resolves when process exit + proc.killed; // boolean โ€” was the process killed? + proc.exitCode; // null | number + proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... + proc.kill(); + proc.killed; // true + + proc.kill(); // specify an exit code + proc.unref(); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["pipe", "pipe", "pipe"], - }); - tsd.expectType(proc.stdin); - tsd.expectType>(proc.stdout); - tsd.expectType>(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["pipe", "pipe", "pipe"], + }); + tsd.expectType(proc.stdin); + tsd.expectType>(proc.stdout); + tsd.expectType>(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["inherit", "inherit", "inherit"], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["inherit", "inherit", "inherit"], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["ignore", "ignore", "ignore"], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["ignore", "ignore", "ignore"], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [null, null, null], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [null, null, null], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Request("1"), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Request("1"), null, null], + }); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Response("1"), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Response("1"), null, null], + }); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Uint8Array([]), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Uint8Array([]), null, null], + }); + tsd.expectType(proc.stdin); } -tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); -tsd.expectNotAssignable(Bun.spawn([], { stdio: ["inherit", "inherit", "inherit"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); -tsd.expectNotAssignable(Bun.spawn([], { stdio: ["pipe", "ignore", "pipe"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "ignore", "inherit"] })); -tsd.expectNotAssignable(Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["ignore", "inherit", "ignore"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: [null, null, null] })); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), +); +tsd.expectNotAssignable( + Bun.spawn([], { stdio: ["inherit", "inherit", "inherit"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), +); +tsd.expectNotAssignable( + Bun.spawn([], { stdio: ["pipe", "ignore", "pipe"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["pipe", "ignore", "inherit"] }), +); +tsd.expectNotAssignable( + Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["ignore", "inherit", "ignore"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: [null, null, null] }), +); tsd.expectNotAssignable(Bun.spawn([], {})); tsd.expectNotAssignable(Bun.spawn([], {})); diff --git a/packages/bun-types/test/sqlite.test.ts b/packages/bun-types/test/sqlite.test.ts index 32cd98057e3d7a..7cb261f571f397 100644 --- a/packages/bun-types/test/sqlite.test.ts +++ b/packages/bun-types/test/sqlite.test.ts @@ -3,14 +3,14 @@ import { expectType } from "./utilities.test"; const db = new Database(":memory:"); const query1 = db.query< - { name: string; dob: number }, // return type first - { $id: string } + { name: string; dob: number }, // return type first + { $id: string } >("select name, dob from users where id = $id"); query1.all({ $id: "asdf" }); // => {name: string; dob:string}[] const query2 = db.query< - { name: string; dob: number }, - [string, number] // pass tuple for positional params + { name: string; dob: number }, + [string, number] // pass tuple for positional params >("select ?1 as name, ?2 as dob"); const allResults = query2.all("Shaq", 50); // => {name: string; dob:string}[] const getResults = query2.get("Shaq", 50); // => {name: string; dob:string}[] @@ -25,9 +25,9 @@ expectType<{ name: string; dob: number } | null>(getResults); expectType(runResults); const query3 = db.prepare< - { name: string; dob: number }, // return type first - // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [{ $id: string }] + { name: string; dob: number }, // return type first + // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [{ $id: string }] >("select name, dob from users where id = $id"); const allResults3 = query3.all({ $id: "asdf" }); expectType>(allResults3); diff --git a/packages/bun-types/test/streams.test.ts b/packages/bun-types/test/streams.test.ts index 50c6fdeb65dd6f..3a303a618b8bc9 100644 --- a/packages/bun-types/test/streams.test.ts +++ b/packages/bun-types/test/streams.test.ts @@ -1,23 +1,23 @@ new ReadableStream({ - start(controller) { - controller.enqueue("hello"); - controller.enqueue("world"); - controller.close(); - }, + start(controller) { + controller.enqueue("hello"); + controller.enqueue("world"); + controller.close(); + }, }); // this will have type errors when lib.dom.d.ts is present // afaik this isn't fixable new ReadableStream({ - type: "direct", - pull(controller) { - // eslint-disable-next-line - controller.write("hello"); - // eslint-disable-next-line - controller.write("world"); - controller.close(); - }, - cancel() { - // called if stream.cancel() is called - }, + type: "direct", + pull(controller) { + // eslint-disable-next-line + controller.write("hello"); + // eslint-disable-next-line + controller.write("world"); + controller.close(); + }, + cancel() { + // called if stream.cancel() is called + }, }); diff --git a/packages/bun-types/test/tcp.test.ts b/packages/bun-types/test/tcp.test.ts index fe1b66a64880c5..f9f1038f2fbb43 100644 --- a/packages/bun-types/test/tcp.test.ts +++ b/packages/bun-types/test/tcp.test.ts @@ -1,134 +1,134 @@ import * as Bun from "bun"; await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLocaleLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLocaleLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, - tls: { - certFile: "asdf", - keyFile: "adsf", - }, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, + tls: { + certFile: "asdf", + keyFile: "adsf", + }, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, - tls: { - cert: "asdf", - key: Bun.file("adsf"), - ca: Buffer.from("asdf"), - }, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, + tls: { + cert: "asdf", + key: Bun.file("adsf"), + ca: Buffer.from("asdf"), + }, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); const listener = Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); listener.data.arg = "asdf"; @@ -140,8 +140,8 @@ listener.data.arg = 234; // }); listener.reload({ - socket: { - open() {}, - // ...listener. - }, + socket: { + open() {}, + // ...listener. + }, }); diff --git a/packages/bun-types/test/test.test.ts b/packages/bun-types/test/test.test.ts index 31a580aba2cfd5..6f7d1a4951dab3 100644 --- a/packages/bun-types/test/test.test.ts +++ b/packages/bun-types/test/test.test.ts @@ -1,4 +1,13 @@ -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, spyOn, test } from "bun:test"; +import { + afterAll, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + spyOn, + test, +} from "bun:test"; import { expectType } from "./utilities.test"; const spy = spyOn(console, "log"); @@ -7,119 +16,119 @@ expectType(spy.mock.calls); const hooks = [beforeAll, beforeEach, afterAll, afterEach]; for (const hook of hooks) { - hook(() => { - // ... - }); - // eslint-disable-next-line - hook(async () => { - // ... - return; - }); - hook((done: (err?: unknown) => void) => { - done(); - done(new Error()); - done("Error"); - }); + hook(() => { + // ... + }); + // eslint-disable-next-line + hook(async () => { + // ... + return; + }); + hook((done: (err?: unknown) => void) => { + done(); + done(new Error()); + done("Error"); + }); } describe("bun:test", () => { - describe("expect()", () => { - test("toThrow()", () => { - function fail() { - throw new Error("Bad"); - } - expect(fail).toThrow(); - expect(fail).toThrow("Bad"); - expect(fail).toThrow(/bad/i); - expect(fail).toThrow(Error); - expect(fail).toThrow(new Error("Bad")); - }); - }); - test("expect()", () => { - expect(1).toBe(1); - expect(1).not.toBe(2); - // @ts-expect-error - expect({ a: 1 }).toEqual({ a: 1, b: undefined }); - expect({ a: 1 }).toStrictEqual({ a: 1 }); - expect(new Set()).toHaveProperty("size"); - expect(new Uint8Array()).toHaveProperty("byteLength", 0); - expect([]).toHaveLength(0); - expect(["bun"]).toContain("bun"); - expect(true).toBeTruthy(); - expect(false).toBeFalsy(); - expect(Math.PI).toBeGreaterThan(3.14); - expect(Math.PI).toBeGreaterThan(3n); - expect(Math.PI).toBeGreaterThanOrEqual(3.14); - expect(Math.PI).toBeGreaterThanOrEqual(3n); - expect(NaN).toBeNaN(); - expect(null).toBeNull(); - expect(undefined).toBeUndefined(); - expect(undefined).not.toBeDefined(); - }); + describe("expect()", () => { + test("toThrow()", () => { + function fail() { + throw new Error("Bad"); + } + expect(fail).toThrow(); + expect(fail).toThrow("Bad"); + expect(fail).toThrow(/bad/i); + expect(fail).toThrow(Error); + expect(fail).toThrow(new Error("Bad")); + }); + }); + test("expect()", () => { + expect(1).toBe(1); + expect(1).not.toBe(2); + // @ts-expect-error + expect({ a: 1 }).toEqual({ a: 1, b: undefined }); + expect({ a: 1 }).toStrictEqual({ a: 1 }); + expect(new Set()).toHaveProperty("size"); + expect(new Uint8Array()).toHaveProperty("byteLength", 0); + expect([]).toHaveLength(0); + expect(["bun"]).toContain("bun"); + expect(true).toBeTruthy(); + expect(false).toBeFalsy(); + expect(Math.PI).toBeGreaterThan(3.14); + expect(Math.PI).toBeGreaterThan(3n); + expect(Math.PI).toBeGreaterThanOrEqual(3.14); + expect(Math.PI).toBeGreaterThanOrEqual(3n); + expect(NaN).toBeNaN(); + expect(null).toBeNull(); + expect(undefined).toBeUndefined(); + expect(undefined).not.toBeDefined(); + }); }); // inference should work when data is passed directly in test.each([ - ["a", true, 5], - ["b", false, 1234], + ["a", true, 5], + ["b", false, 1234], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([ - ["a", true, 5], - ["b", false, 5], + ["a", true, 5], + ["b", false, 5], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([{ asdf: "asdf" }, { asdf: "asdf" }])("test.each", (a, b, c) => { - expectType<{ asdf: string }>(a); - expectType<{ asdf: string }>(c); + expectType<{ asdf: string }>(a); + expectType<{ asdf: string }>(c); }); // no inference on data const data = [ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ]; test.each(data)("test.each", (...args) => { - expectType(args[0]); + expectType(args[0]); }); describe.each(data)("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); // as const const dataAsConst = [ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ] as const; test.each(dataAsConst)("test.each", (...args) => { - expectType(args[0]); - expectType(args[1]); - expectType(args[2]); + expectType(args[0]); + expectType(args[1]); + expectType(args[2]); }); describe.each(dataAsConst)("test.each", (...args) => { - expectType(args[0]); - expectType(args[1]); - expectType(args[2]); + expectType(args[0]); + expectType(args[1]); + expectType(args[2]); }); describe.each(dataAsConst)("test.each", (a, b, c) => { - expectType<"a" | "b">(a); - expectType(b); - expectType<5 | "asdf">(c); + expectType<"a" | "b">(a); + expectType(b); + expectType<5 | "asdf">(c); }); diff --git a/packages/bun-types/test/tls.test.ts b/packages/bun-types/test/tls.test.ts index fb2aa7d9b885a1..df6f1979c53b95 100644 --- a/packages/bun-types/test/tls.test.ts +++ b/packages/bun-types/test/tls.test.ts @@ -3,30 +3,30 @@ import tls from "node:tls"; tls.getCiphers()[0]; tls.connect({ - host: "localhost", - port: 80, - ca: "asdf", - cert: "path to cert", + host: "localhost", + port: 80, + ca: "asdf", + cert: "path to cert", }); tls.connect({ - host: "localhost", - port: 80, - ca: Bun.file("asdf"), - cert: Bun.file("path to cert"), - ciphers: "adsf", + host: "localhost", + port: 80, + ca: Bun.file("asdf"), + cert: Bun.file("path to cert"), + ciphers: "adsf", }); tls.connect({ - host: "localhost", - port: 80, - ca: Buffer.from("asdf"), - cert: Buffer.from("asdf"), + host: "localhost", + port: 80, + ca: Buffer.from("asdf"), + cert: Buffer.from("asdf"), }); tls.connect({ - host: "localhost", - port: 80, - ca: new Uint8Array([1, 2, 3]), - cert: new Uint8Array([1, 2, 3]), + host: "localhost", + port: 80, + ca: new Uint8Array([1, 2, 3]), + cert: new Uint8Array([1, 2, 3]), }); diff --git a/packages/bun-types/test/tty.test.ts b/packages/bun-types/test/tty.test.ts index 7e9f45115c731f..f6aff4b61e7e52 100644 --- a/packages/bun-types/test/tty.test.ts +++ b/packages/bun-types/test/tty.test.ts @@ -1,10 +1,10 @@ import * as tty from "tty"; const rs = new tty.ReadStream(234, { - allowHalfOpen: true, - readable: true, - signal: new AbortSignal(), - writable: true, + allowHalfOpen: true, + readable: true, + signal: new AbortSignal(), + writable: true, }); const ws = new tty.WriteStream(234); diff --git a/packages/bun-types/test/utilities.test.ts b/packages/bun-types/test/utilities.test.ts index 9fb6f411160b93..ef198a27614e3d 100644 --- a/packages/bun-types/test/utilities.test.ts +++ b/packages/bun-types/test/utilities.test.ts @@ -5,4 +5,6 @@ export declare const expectAssignable: (expression: T) => void; // eslint-disable-next-line @definitelytyped/no-unnecessary-generics export declare const expectNotAssignable: (expression: any) => void; // eslint-disable-next-line @definitelytyped/no-unnecessary-generics -export declare const expectTypeEquals: (expression: T extends S ? (S extends T ? true : false) : false) => void; +export declare const expectTypeEquals: ( + expression: T extends S ? (S extends T ? true : false) : false, +) => void; diff --git a/packages/bun-types/test/wasm.test.ts b/packages/bun-types/test/wasm.test.ts index 3b8785ec732709..f745fbe84e94ec 100644 --- a/packages/bun-types/test/wasm.test.ts +++ b/packages/bun-types/test/wasm.test.ts @@ -1,42 +1,42 @@ async () => { - // Fetch and compile a WebAssembly module - const response = await fetch("module.wasm"); - const buffer = await response.arrayBuffer(); - const module = await WebAssembly.compile(buffer); - - // Create a WebAssembly Memory object - const memory = new WebAssembly.Memory({ initial: 1 }); - - // Create a WebAssembly Table object - const table = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); - - // Instantiate the WebAssembly module - const instance = await WebAssembly.instantiate(module, { - js: { - log: (arg: any) => console.log("Logging from WASM:", arg), - tableFunc: () => console.log("Table function called"), - }, - env: { - memory: memory, - table: table, - }, - }); - - // Exported WebAssembly functions - const { exportedFunction } = instance.exports; - exportedFunction; - - // Call an exported WebAssembly function - // exportedFunction(); - - // Interact with WebAssembly memory - const uint8Array = new Uint8Array(memory.buffer); - uint8Array[0] = 1; // Modify memory - - // Use the WebAssembly Table - table.set(0, instance.exports.exportedTableFunction); - // eslint-disable-next-line - table.get(0)(); // Call a function stored in the table - - // Additional operations with instance, memory, and table can be performed here + // Fetch and compile a WebAssembly module + const response = await fetch("module.wasm"); + const buffer = await response.arrayBuffer(); + const module = await WebAssembly.compile(buffer); + + // Create a WebAssembly Memory object + const memory = new WebAssembly.Memory({ initial: 1 }); + + // Create a WebAssembly Table object + const table = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); + + // Instantiate the WebAssembly module + const instance = await WebAssembly.instantiate(module, { + js: { + log: (arg: any) => console.log("Logging from WASM:", arg), + tableFunc: () => console.log("Table function called"), + }, + env: { + memory: memory, + table: table, + }, + }); + + // Exported WebAssembly functions + const { exportedFunction } = instance.exports; + exportedFunction; + + // Call an exported WebAssembly function + // exportedFunction(); + + // Interact with WebAssembly memory + const uint8Array = new Uint8Array(memory.buffer); + uint8Array[0] = 1; // Modify memory + + // Use the WebAssembly Table + table.set(0, instance.exports.exportedTableFunction); + // eslint-disable-next-line + table.get(0)(); // Call a function stored in the table + + // Additional operations with instance, memory, and table can be performed here }; diff --git a/packages/bun-types/test/worker.test.ts b/packages/bun-types/test/worker.test.ts index 335f2652a9fe23..a6a32787b4a99e 100644 --- a/packages/bun-types/test/worker.test.ts +++ b/packages/bun-types/test/worker.test.ts @@ -3,17 +3,17 @@ import * as tsd from "./utilities.test"; const webWorker = new Worker("./worker.js"); -webWorker.addEventListener("message", event => { - tsd.expectType(event); +webWorker.addEventListener("message", (event) => { + tsd.expectType(event); }); -webWorker.addEventListener("error", event => { - tsd.expectType(event); +webWorker.addEventListener("error", (event) => { + tsd.expectType(event); }); -webWorker.addEventListener("messageerror", event => { - tsd.expectType(event); +webWorker.addEventListener("messageerror", (event) => { + tsd.expectType(event); }); -webWorker.onmessage = ev => "asdf"; -webWorker.onmessageerror = ev => "asdf"; +webWorker.onmessage = (ev) => "asdf"; +webWorker.onmessageerror = (ev) => "asdf"; webWorker.postMessage("asdf", []); webWorker.terminate(); webWorker.addEventListener("close", () => {}); @@ -24,8 +24,8 @@ webWorker.unref(); webWorker.threadId; const nodeWorker = new NodeWorker("./worker.ts"); -nodeWorker.on("message", event => { - console.log("Message from worker:", event); +nodeWorker.on("message", (event) => { + console.log("Message from worker:", event); }); nodeWorker.postMessage("Hello from main thread!"); @@ -33,8 +33,8 @@ const workerURL = new URL("worker.ts", "/path/to/").href; const _worker2 = new Worker(workerURL); nodeWorker.postMessage("hello"); -webWorker.onmessage = event => { - console.log(event.data); +webWorker.onmessage = (event) => { + console.log(event.data); }; // On the worker thread, `postMessage` is automatically "routed" to the parent thread. @@ -49,13 +49,13 @@ await nodeWorker.terminate(); // Bun.pathToFileURL const _worker3 = new Worker(new URL("worker.ts", "/path/to/").href, { - ref: true, - smol: true, - credentials: "same-origin", - name: "a name", - env: { - envValue: "hello", - }, + ref: true, + smol: true, + credentials: "same-origin", + name: "a name", + env: { + envValue: "hello", + }, }); export { _worker2, _worker3, nodeWorker as worker }; diff --git a/packages/bun-types/test/ws.test.ts b/packages/bun-types/test/ws.test.ts index fdc4072af2403f..83bfd0e4723b43 100644 --- a/packages/bun-types/test/ws.test.ts +++ b/packages/bun-types/test/ws.test.ts @@ -5,7 +5,7 @@ const ws = new WebSocket("ws://www.host.com/path"); ws.send("asdf"); const wss = new WebSocketServer({ - port: 8080, - perMessageDeflate: false, + port: 8080, + perMessageDeflate: false, }); wss; diff --git a/packages/bun-types/wasm.d.ts b/packages/bun-types/wasm.d.ts index b4975f140a94e2..ccbc0d1ef97d21 100644 --- a/packages/bun-types/wasm.d.ts +++ b/packages/bun-types/wasm.d.ts @@ -1,270 +1,291 @@ export {}; -type _Global = typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; -} - ? T - : Bun.WebAssembly.Global; +type _Global = + typeof globalThis extends { + onerror: any; + WebAssembly: { Global: infer T }; + } + ? T + : Bun.WebAssembly.Global; type _CompileError = typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; + onerror: any; + WebAssembly: { CompileError: infer T }; } - ? T - : Bun.WebAssembly.CompileError; + ? T + : Bun.WebAssembly.CompileError; type _LinkError = typeof globalThis extends { - onerror: any; - WebAssembly: { LinkError: infer T }; + onerror: any; + WebAssembly: { LinkError: infer T }; } - ? T - : Bun.WebAssembly.LinkError; + ? T + : Bun.WebAssembly.LinkError; type _RuntimeError = typeof globalThis extends { - onerror: any; - WebAssembly: { RuntimeError: infer T }; + onerror: any; + WebAssembly: { RuntimeError: infer T }; } - ? T - : Bun.WebAssembly.RuntimeError; + ? T + : Bun.WebAssembly.RuntimeError; type _Memory = typeof globalThis extends { - onerror: any; - WebAssembly: { Memory: infer T }; + onerror: any; + WebAssembly: { Memory: infer T }; } - ? T - : Bun.WebAssembly.Memory; + ? T + : Bun.WebAssembly.Memory; type _Instance = typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; + onerror: any; + WebAssembly: { Instance: infer T }; } - ? T - : Bun.WebAssembly.Instance; + ? T + : Bun.WebAssembly.Instance; type _Module = typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; + onerror: any; + WebAssembly: { Module: infer T }; } - ? T - : Bun.WebAssembly.Module; + ? T + : Bun.WebAssembly.Module; type _Table = typeof globalThis extends { - onerror: any; - WebAssembly: { Table: infer T }; + onerror: any; + WebAssembly: { Table: infer T }; } - ? T - : Bun.WebAssembly.Table; + ? T + : Bun.WebAssembly.Table; declare global { - namespace Bun { - namespace WebAssembly { - type ImportExportKind = "function" | "global" | "memory" | "table"; - type TableKind = "anyfunc" | "externref"; - // eslint-disable-next-line @typescript-eslint/ban-types - type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table; - type Exports = Record; - type ImportValue = ExportValue | number; - type Imports = Record; - type ModuleImports = Record; - - interface ValueTypeMap { - // eslint-disable-next-line @typescript-eslint/ban-types - anyfunc: Function; - externref: any; - f32: number; - f64: number; - i32: number; - i64: bigint; - v128: never; - } - - type ValueType = keyof ValueTypeMap; - - interface GlobalDescriptor { - mutable?: boolean; - value: T; - } - - interface Global { - // { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ - value: ValueTypeMap[T]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ - valueOf(): ValueTypeMap[T]; - } - - interface CompileError extends Error {} - - interface LinkError extends Error {} - - interface RuntimeError extends Error {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ - interface Instance { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ - readonly exports: Exports; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ - interface Memory { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ - readonly buffer: ArrayBuffer; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ - grow(delta: number): number; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ - interface Module {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ - interface Table { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ - readonly length: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ - get(index: number): any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ - grow(delta: number, value?: any): number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ - set(index: number, value?: any): void; - } - - interface MemoryDescriptor { - initial: number; - maximum?: number; - shared?: boolean; - } - - interface ModuleExportDescriptor { - kind: ImportExportKind; - name: string; - } - - interface ModuleImportDescriptor { - kind: ImportExportKind; - module: string; - name: string; - } - - interface TableDescriptor { - element: TableKind; - initial: number; - maximum?: number; - } - - interface WebAssemblyInstantiatedSource { - instance: Instance; - module: Module; - } - } - } - - namespace WebAssembly { - interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} - interface GlobalDescriptor - extends Bun.WebAssembly.GlobalDescriptor {} - interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} - interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} - interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} - interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} - interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} - - interface LinkError extends _LinkError {} - var LinkError: { - prototype: LinkError; - new (message?: string): LinkError; - (message?: string): LinkError; - }; - - interface CompileError extends _CompileError {} - var CompileError: typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; - } - ? T - : { - prototype: CompileError; - new (message?: string): CompileError; - (message?: string): CompileError; - }; - - interface RuntimeError extends _RuntimeError {} - var RuntimeError: { - prototype: RuntimeError; - new (message?: string): RuntimeError; - (message?: string): RuntimeError; - }; - - interface Global extends _Global {} - var Global: typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; - } - ? T - : { - prototype: Global; - new ( - descriptor: GlobalDescriptor, - v?: ValueTypeMap[T], - ): Global; - }; - - interface Instance extends _Instance {} - var Instance: typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; - } - ? T - : { - prototype: Instance; - new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; - }; - - interface Memory extends _Memory {} - var Memory: { - prototype: Memory; - new (descriptor: MemoryDescriptor): Memory; - }; - - interface Module extends _Module {} - var Module: typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; - } - ? T - : { - prototype: Module; - new (bytes: Bun.BufferSource): Module; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ - customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ - exports(moduleObject: Module): ModuleExportDescriptor[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ - imports(moduleObject: Module): ModuleImportDescriptor[]; - }; - - interface Table extends _Table {} - var Table: { - prototype: Table; - new (descriptor: TableDescriptor, value?: any): Table; - }; - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ - function compile(bytes: Bun.BufferSource): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ - function compileStreaming(source: Response | PromiseLike): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ - function instantiate( - bytes: Bun.BufferSource, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ - function instantiateStreaming( - source: Response | PromiseLike, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ - function validate(bytes: Bun.BufferSource): boolean; - } + namespace Bun { + namespace WebAssembly { + type ImportExportKind = "function" | "global" | "memory" | "table"; + type TableKind = "anyfunc" | "externref"; + // eslint-disable-next-line @typescript-eslint/ban-types + type ExportValue = + | Function + | Global + | WebAssembly.Memory + | WebAssembly.Table; + type Exports = Record; + type ImportValue = ExportValue | number; + type Imports = Record; + type ModuleImports = Record; + + interface ValueTypeMap { + // eslint-disable-next-line @typescript-eslint/ban-types + anyfunc: Function; + externref: any; + f32: number; + f64: number; + i32: number; + i64: bigint; + v128: never; + } + + type ValueType = keyof ValueTypeMap; + + interface GlobalDescriptor { + mutable?: boolean; + value: T; + } + + interface Global { + // { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ + value: ValueTypeMap[T]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ + valueOf(): ValueTypeMap[T]; + } + + interface CompileError extends Error {} + + interface LinkError extends Error {} + + interface RuntimeError extends Error {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ + interface Instance { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ + readonly exports: Exports; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ + interface Memory { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ + readonly buffer: ArrayBuffer; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ + grow(delta: number): number; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ + interface Module {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ + interface Table { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ + readonly length: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ + get(index: number): any; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ + grow(delta: number, value?: any): number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ + set(index: number, value?: any): void; + } + + interface MemoryDescriptor { + initial: number; + maximum?: number; + shared?: boolean; + } + + interface ModuleExportDescriptor { + kind: ImportExportKind; + name: string; + } + + interface ModuleImportDescriptor { + kind: ImportExportKind; + module: string; + name: string; + } + + interface TableDescriptor { + element: TableKind; + initial: number; + maximum?: number; + } + + interface WebAssemblyInstantiatedSource { + instance: Instance; + module: Module; + } + } + } + + namespace WebAssembly { + interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} + interface GlobalDescriptor< + T extends keyof ValueTypeMap = keyof ValueTypeMap, + > extends Bun.WebAssembly.GlobalDescriptor {} + interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} + interface ModuleExportDescriptor + extends Bun.WebAssembly.ModuleExportDescriptor {} + interface ModuleImportDescriptor + extends Bun.WebAssembly.ModuleImportDescriptor {} + interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} + interface WebAssemblyInstantiatedSource + extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} + + interface LinkError extends _LinkError {} + var LinkError: { + prototype: LinkError; + new (message?: string): LinkError; + (message?: string): LinkError; + }; + + interface CompileError extends _CompileError {} + var CompileError: typeof globalThis extends { + onerror: any; + WebAssembly: { CompileError: infer T }; + } + ? T + : { + prototype: CompileError; + new (message?: string): CompileError; + (message?: string): CompileError; + }; + + interface RuntimeError extends _RuntimeError {} + var RuntimeError: { + prototype: RuntimeError; + new (message?: string): RuntimeError; + (message?: string): RuntimeError; + }; + + interface Global + extends _Global {} + var Global: typeof globalThis extends { + onerror: any; + WebAssembly: { Global: infer T }; + } + ? T + : { + prototype: Global; + new ( + descriptor: GlobalDescriptor, + v?: ValueTypeMap[T], + ): Global; + }; + + interface Instance extends _Instance {} + var Instance: typeof globalThis extends { + onerror: any; + WebAssembly: { Instance: infer T }; + } + ? T + : { + prototype: Instance; + new ( + module: Module, + importObject?: Bun.WebAssembly.Imports, + ): Instance; + }; + + interface Memory extends _Memory {} + var Memory: { + prototype: Memory; + new (descriptor: MemoryDescriptor): Memory; + }; + + interface Module extends _Module {} + var Module: typeof globalThis extends { + onerror: any; + WebAssembly: { Module: infer T }; + } + ? T + : { + prototype: Module; + new (bytes: Bun.BufferSource): Module; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ + customSections( + moduleObject: Module, + sectionName: string, + ): ArrayBuffer[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ + exports(moduleObject: Module): ModuleExportDescriptor[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + + interface Table extends _Table {} + var Table: { + prototype: Table; + new (descriptor: TableDescriptor, value?: any): Table; + }; + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ + function compile(bytes: Bun.BufferSource): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ + function compileStreaming( + source: Response | PromiseLike, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ + function instantiate( + bytes: Bun.BufferSource, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + function instantiate( + moduleObject: Module, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ + function instantiateStreaming( + source: Response | PromiseLike, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ + function validate(bytes: Bun.BufferSource): boolean; + } } diff --git a/src/cli/init/tsconfig.default.json b/src/cli/init/tsconfig.default.json index ab0f0b0964d4e6..df0868aa329314 100644 --- a/src/cli/init/tsconfig.default.json +++ b/src/cli/init/tsconfig.default.json @@ -16,7 +16,7 @@ // Best practices "strict": true, - "skipLibCheck": true, + "skipLibCheck": false, "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true, diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index f71f6912cf566f..64b81e21ad8248 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -14,7 +14,7 @@ "packages": { "@types/bun": ["@types/bun@types-bun-1.2.3.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }], - "@types/node": ["@types/node@22.13.5", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg=="], + "@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index b679f9f9d7496b..02ad2d0156a5e1 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -1,6 +1,8 @@ import svgpath from "cool.svg"; svgpath satisfies `${string}.svg`; +fetch; + // just some APIs new Request("url"); new Response(); @@ -15,7 +17,9 @@ new TransformStream(); new AbortSignal(); new AbortController(); -fetch("url"); +fetch("url", { + proxy: "", +}); new Bun.$.ShellError(); From c0b883019f642fa33930c5453a70cb3e6d1a1136 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Wed, 5 Mar 2025 21:10:36 +0000 Subject: [PATCH 02/72] . --- packages/bun-types/ambient.d.ts | 28 +- packages/bun-types/bun.d.ts | 14938 ++++++++--------- packages/bun-types/deprecated.d.ts | 105 +- packages/bun-types/devserver.d.ts | 40 +- packages/bun-types/fetch.d.ts | 256 +- packages/bun-types/ffi.d.ts | 2196 ++- packages/bun-types/globals.d.ts | 3625 ++-- packages/bun-types/html-rewriter.d.ts | 297 +- packages/bun-types/jsc.d.ts | 446 +- packages/bun-types/overrides.d.ts | 112 +- packages/bun-types/sqlite.d.ts | 2167 ++- packages/bun-types/test.d.ts | 4360 +++-- packages/bun-types/test/array-buffer.test.ts | 2 +- packages/bun-types/test/array.test.ts | 30 +- packages/bun-types/test/broadcast.test.ts | 6 +- packages/bun-types/test/bun.test.ts | 62 +- packages/bun-types/test/console.test.ts | 26 +- packages/bun-types/test/diag.test.ts | 2 +- packages/bun-types/test/dom.test.ts | 16 +- packages/bun-types/test/env.test.ts | 18 +- packages/bun-types/test/events.test.ts | 6 +- packages/bun-types/test/ffi.test.ts | 223 +- packages/bun-types/test/fs.test.ts | 8 +- packages/bun-types/test/fsrouter.test.ts | 4 +- packages/bun-types/test/globals.test.ts | 170 +- packages/bun-types/test/http.test.ts | 2 +- packages/bun-types/test/jsc.test.ts | 2 +- packages/bun-types/test/mocks.test.ts | 2 +- packages/bun-types/test/net.test.ts | 8 +- packages/bun-types/test/process.test.ts | 12 +- packages/bun-types/test/readline.test.ts | 10 +- packages/bun-types/test/serve.test.ts | 246 +- packages/bun-types/test/spawn.test.ts | 243 +- packages/bun-types/test/sqlite.test.ts | 14 +- packages/bun-types/test/streams.test.ts | 32 +- packages/bun-types/test/tcp.test.ts | 216 +- packages/bun-types/test/test.test.ts | 171 +- packages/bun-types/test/tls.test.ts | 34 +- packages/bun-types/test/tty.test.ts | 8 +- packages/bun-types/test/utilities.test.ts | 4 +- packages/bun-types/test/wasm.test.ts | 80 +- packages/bun-types/test/worker.test.ts | 38 +- packages/bun-types/test/ws.test.ts | 4 +- packages/bun-types/wasm.d.ts | 509 +- 44 files changed, 15038 insertions(+), 15740 deletions(-) diff --git a/packages/bun-types/ambient.d.ts b/packages/bun-types/ambient.d.ts index db712274c46e99..05d908557716b6 100644 --- a/packages/bun-types/ambient.d.ts +++ b/packages/bun-types/ambient.d.ts @@ -1,31 +1,31 @@ declare module "*.txt" { - var text: string; - export = text; + var text: string; + export = text; } declare module "*.toml" { - var contents: any; - export = contents; + var contents: any; + export = contents; } declare module "*.jsonc" { - var contents: any; - export = contents; + var contents: any; + export = contents; } declare module "*/bun.lock" { - var contents: import("bun").BunLockFile; - export = contents; + var contents: import("bun").BunLockFile; + export = contents; } declare module "*.html" { - // In Bun v1.2, we might change this to Bun.HTMLBundle - var contents: any; - export = contents; + // In Bun v1.2, we might change this to Bun.HTMLBundle + var contents: any; + export = contents; } declare module "*.svg" { - // Bun 1.2.3 added support for frontend dev server - var contents: `${string}.svg`; - export = contents; + // Bun 1.2.3 added support for frontend dev server + var contents: `${string}.svg`; + export = contents; } diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 53da987d07911c..bc50aefc82b134 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -1,72 +1,72 @@ declare 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; - - bytes(): Uint8Array; + 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; + + bytes(): Uint8Array; } /** @@ -85,7636 +85,7314 @@ declare class _ShellError extends Error implements ShellOutput { * This module aliases `globalThis.Bun`. */ declare module "bun" { - import type { FFIFunctionCallableSymbol } from "bun:ffi"; - import type { Encoding as CryptoEncoding } from "crypto"; - import type { X509Certificate } from "node:crypto"; - import type { Stats } from "node:fs"; - import type { - CipherNameAndProtocol, - EphemeralKeyInfo, - PeerCertificate, - } from "tls"; - - type DistributedOmit = T extends T ? Omit : never; - type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; - - 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 - | string - | { raw: string } - | Subprocess - | SpawnOptions.Readable - | SpawnOptions.Writable - | ReadableStream; - - class ShellPromise extends Promise { - 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 | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - } - - type ShellError = _ShellError; - - export interface Shell { - ( - strings: TemplateStringsArray, - ...expressions: ShellExpression[] - ): ShellPromise; - - readonly ShellError: typeof _ShellError; - - /** - * 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): 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; - - /** - * 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; - - /** - * 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 | S3File | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - 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, - maxLength?: number, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - maxLength: number, - asUint8Array: false, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - 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, - ): Promise | 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, - ): Promise | 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; - - /** - * 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, - multipartBoundaryExcludingDashes?: - | string - | NodeJS.TypedArray - | ArrayBufferView, - ): Promise; - - /** - * 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; - - /** - * 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; - - /** - * 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( - stream: ReadableStream, - ): Promise | T[]; - - /** - * Escape the following characters in a string: - * - * - `"` 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. - * - * @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 { - (promise: T | Promise): Promise | T; - status( - promise: T | Promise, - ): "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; - - /** - * - * **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; - }; - - ADDRCONFIG: number; - ALL: number; - 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; - } - - /** - * 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; - /** - * Close the file descriptor. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; - - 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; - - /** - * 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; - - /** - * Deletes the file. - */ - unlink(): Promise; - - /** - * Deletes the file. ( same as unlink ) - */ - delete(): Promise; - - /** - * Provides useful information about the file. - */ - stat(): Promise; - } - interface NetworkSink extends FileSink { - /** - * Write a chunk of data to the network. - * - * If the network is not writable yet, the data is buffered. - */ - write( - chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - ): number; - /** - * Flush the internal buffer, committing the data to the network. - */ - flush(): number | Promise; - /** - * Finish the upload. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; - - /** - * Get the stat of the file. - */ - stat(): Promise; - } - - var S3Client: S3Client; - var s3: S3Client; - - /** - * Configuration options for S3 operations - */ - interface S3Options extends BlobPropertyBag { - /** - * The Access Control List (ACL) policy for the file. - * Controls who can access the file and what permissions they have. - * - * @example - * // Setting public read access - * const file = s3("public-file.txt", { - * acl: "public-read", - * bucket: "my-bucket" - * }); - * - * @example - * // Using with presigned URLs - * const url = file.presign({ - * acl: "public-read", - * expiresIn: 3600 - * }); - */ - acl?: - | "private" - | "public-read" - | "public-read-write" - | "aws-exec-read" - | "authenticated-read" - | "bucket-owner-read" - | "bucket-owner-full-control" - | "log-delivery-write"; - - /** - * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. - * - * @example - * // Using explicit bucket - * const file = s3("my-file.txt", { bucket: "my-bucket" }); - * - * @example - * // Using environment variables - * // With S3_BUCKET=my-bucket in .env - * const file = s3("my-file.txt"); - */ - bucket?: string; - - /** - * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. - * - * @example - * const file = s3("my-file.txt", { - * bucket: "my-bucket", - * region: "us-west-2" - * }); - */ - region?: string; - - /** - * The access key ID for authentication. - * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. - */ - accessKeyId?: string; - - /** - * The secret access key for authentication. - * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. - */ - secretAccessKey?: string; - - /** - * Optional session token for temporary credentials. - * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. - * - * @example - * // Using temporary credentials - * const file = s3("my-file.txt", { - * accessKeyId: tempAccessKey, - * secretAccessKey: tempSecretKey, - * sessionToken: tempSessionToken - * }); - */ - sessionToken?: string; - - /** - * The S3-compatible service endpoint URL. - * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. - * - * @example - * // AWS S3 - * const file = s3("my-file.txt", { - * endpoint: "https://s3.us-east-1.amazonaws.com" - * }); - * - * @example - * // Cloudflare R2 - * const file = s3("my-file.txt", { - * endpoint: "https://.r2.cloudflarestorage.com" - * }); - * - * @example - * // DigitalOcean Spaces - * const file = s3("my-file.txt", { - * endpoint: "https://.digitaloceanspaces.com" - * }); - * - * @example - * // MinIO (local development) - * const file = s3("my-file.txt", { - * endpoint: "http://localhost:9000" - * }); - */ - endpoint?: string; - - /** - * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` - * - * @example - * // Using virtual hosted style - * const file = s3("my-file.txt", { - * virtualHostedStyle: true, - * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" - * }); - */ - virtualHostedStyle?: boolean; - - /** - * The size of each part in multipart uploads (in bytes). - * - Minimum: 5 MiB - * - Maximum: 5120 MiB - * - Default: 5 MiB - * - * @example - * // Configuring multipart uploads - * const file = s3("large-file.dat", { - * partSize: 10 * 1024 * 1024, // 10 MiB parts - * queueSize: 4 // Upload 4 parts in parallel - * }); - * - * const writer = file.writer(); - * // ... write large file in chunks - */ - partSize?: number; - - /** - * Number of parts to upload in parallel for multipart uploads. - * - Default: 5 - * - Maximum: 255 - * - * Increasing this value can improve upload speeds for large files - * but will use more memory. - */ - queueSize?: number; - - /** - * Number of retry attempts for failed uploads. - * - Default: 3 - * - Maximum: 255 - * - * @example - * // Setting retry attempts - * const file = s3("my-file.txt", { - * retry: 5 // Retry failed uploads up to 5 times - * }); - */ - retry?: number; - - /** - * The Content-Type of the file. - * Automatically set based on file extension when possible. - * - * @example - * // Setting explicit content type - * const file = s3("data.bin", { - * type: "application/octet-stream" - * }); - */ - type?: string; - - /** - * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. - * - * @example - * // Setting explicit Storage class - * const file = s3("my-file.json", { - * storageClass: "STANDARD_IA" - * }); - */ - storageClass?: - | "STANDARD" - | "DEEP_ARCHIVE" - | "EXPRESS_ONEZONE" - | "GLACIER" - | "GLACIER_IR" - | "INTELLIGENT_TIERING" - | "ONEZONE_IA" - | "OUTPOSTS" - | "REDUCED_REDUNDANCY" - | "SNOW" - | "STANDARD_IA"; - - /** - * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. - */ - highWaterMark?: number; - } - - /** - * Options for generating presigned URLs - */ - interface S3FilePresignOptions extends S3Options { - /** - * Number of seconds until the presigned URL expires. - * - Default: 86400 (1 day) - * - * @example - * // Short-lived URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Long-lived public URL - * const url = file.presign({ - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - expiresIn?: number; - - /** - * The HTTP method allowed for the presigned URL. - * - * @example - * // GET URL for downloads - * const downloadUrl = file.presign({ - * method: "GET", - * expiresIn: 3600 - * }); - * - * @example - * // PUT URL for uploads - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "application/json" - * }); - */ - method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; - } - - interface S3Stats { - size: number; - lastModified: Date; - etag: string; - type: string; - } - - /** - * Represents a file in an S3-compatible storage service. - * Extends the Blob interface for compatibility with web APIs. - */ - interface S3File extends Blob { - /** - * The size of the file in bytes. - * This is a Promise because it requires a network request to determine the size. - * - * @example - * // Getting file size - * const size = await file.size; - * console.log(`File size: ${size} bytes`); - * - * @example - * // Check if file is larger than 1MB - * if (await file.size > 1024 * 1024) { - * console.log("Large file detected"); - * } - */ - /** - * TODO: figure out how to get the typescript types to not error for this property. - */ - // size: Promise; - - /** - * Creates a new S3File representing a slice of the original file. - * Uses HTTP Range headers for efficient partial downloads. - * - * @param begin - Starting byte offset - * @param end - Ending byte offset (exclusive) - * @param contentType - Optional MIME type for the slice - * @returns A new S3File representing the specified range - * - * @example - * // Reading file header - * const header = file.slice(0, 1024); - * const headerText = await header.text(); - * - * @example - * // Reading with content type - * const jsonSlice = file.slice(1024, 2048, "application/json"); - * const data = await jsonSlice.json(); - * - * @example - * // Reading from offset to end - * const remainder = file.slice(1024); - * const content = await remainder.text(); - */ - slice(begin?: number, end?: number, contentType?: string): S3File; - slice(begin?: number, contentType?: string): S3File; - slice(contentType?: string): S3File; - - /** - * Creates a writable stream for uploading data. - * Suitable for large files as it uses multipart upload. - * - * @param options - Configuration for the upload - * @returns A NetworkSink for writing data - * - * @example - * // Basic streaming write - * const writer = file.writer({ - * type: "application/json" - * }); - * writer.write('{"hello": '); - * writer.write('"world"}'); - * await writer.end(); - * - * @example - * // Optimized large file upload - * const writer = file.writer({ - * partSize: 10 * 1024 * 1024, // 10MB parts - * queueSize: 4, // Upload 4 parts in parallel - * retry: 3 // Retry failed parts - * }); - * - * // Write large chunks of data efficiently - * for (const chunk of largeDataChunks) { - * writer.write(chunk); - * } - * await writer.end(); - * - * @example - * // Error handling - * const writer = file.writer(); - * try { - * writer.write(data); - * await writer.end(); - * } catch (err) { - * console.error('Upload failed:', err); - * // Writer will automatically abort multipart upload on error - * } - */ - writer(options?: S3Options): NetworkSink; - - /** - * Gets a readable stream of the file's content. - * Useful for processing large files without loading them entirely into memory. - * - * @returns A ReadableStream for the file content - * - * @example - * // Basic streaming read - * const stream = file.stream(); - * for await (const chunk of stream) { - * console.log('Received chunk:', chunk); - * } - * - * @example - * // Piping to response - * const stream = file.stream(); - * return new Response(stream, { - * headers: { 'Content-Type': file.type } - * }); - * - * @example - * // Processing large files - * const stream = file.stream(); - * const textDecoder = new TextDecoder(); - * for await (const chunk of stream) { - * const text = textDecoder.decode(chunk); - * // Process text chunk by chunk - * } - */ - readonly readable: ReadableStream; - stream(): ReadableStream; - - /** - * The name or path of the file in the bucket. - * - * @example - * const file = s3("folder/image.jpg"); - * console.log(file.name); // "folder/image.jpg" - */ - readonly name?: string; - - /** - * The bucket name containing the file. - * - * @example - * const file = s3("s3://my-bucket/file.txt"); - * console.log(file.bucket); // "my-bucket" - */ - readonly bucket?: string; - - /** - * Checks if the file exists in S3. - * Uses HTTP HEAD request to efficiently check existence without downloading. - * - * @returns Promise resolving to true if file exists, false otherwise - * - * @example - * // Basic existence check - * if (await file.exists()) { - * console.log("File exists in S3"); - * } - * - * @example - * // With error handling - * try { - * const exists = await file.exists(); - * if (!exists) { - * console.log("File not found"); - * } - * } catch (err) { - * console.error("Error checking file:", err); - * } - */ - exists(): Promise; - - /** - * Uploads data to S3. - * Supports various input types and automatically handles large files. - * - * @param data - The data to upload - * @param options - Upload configuration options - * @returns Promise resolving to number of bytes written - * - * @example - * // Writing string data - * await file.write("Hello World", { - * type: "text/plain" - * }); - * - * @example - * // Writing JSON - * const data = { hello: "world" }; - * await file.write(JSON.stringify(data), { - * type: "application/json" - * }); - * - * @example - * // Writing from Response - * const response = await fetch("https://example.com/data"); - * await file.write(response); - * - * @example - * // Writing with ACL - * await file.write(data, { - * acl: "public-read", - * type: "application/octet-stream" - * }); - */ - write( - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob, - options?: S3Options, - ): Promise; - - /** - * Generates a presigned URL for the file. - * Allows temporary access to the file without exposing credentials. - * - * @param options - Configuration for the presigned URL - * @returns Presigned URL string - * - * @example - * // Basic download URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Upload URL with specific content type - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * @example - * // URL with custom permissions - * const url = file.presign({ - * method: "GET", - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(options?: S3FilePresignOptions): string; - - /** - * Deletes the file from S3. - * - * @returns Promise that resolves when deletion is complete - * - * @example - * // Basic deletion - * await file.delete(); - * - * @example - * // With error handling - * try { - * await file.delete(); - * console.log("File deleted successfully"); - * } catch (err) { - * console.error("Failed to delete file:", err); - * } - */ - delete(): Promise; - - /** - * Alias for delete() method. - * Provided for compatibility with Node.js fs API naming. - * - * @example - * await file.unlink(); - */ - unlink: S3File["delete"]; - - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @returns Promise resolving to S3Stat - */ - stat(): Promise; - } - - /** - * A configured S3 bucket instance for managing files. - * The instance is callable to create S3File instances and provides methods - * for common operations. - * - * @example - * // Basic bucket setup - * const bucket = new S3Client({ - * bucket: "my-bucket", - * accessKeyId: "key", - * secretAccessKey: "secret" - * }); - * - * // Get file instance - * const file = bucket("image.jpg"); - * - * // Common operations - * await bucket.write("data.json", JSON.stringify({hello: "world"})); - * const url = bucket.presign("file.pdf"); - * await bucket.unlink("old.txt"); - */ - type S3Client = { - /** - * Create a new instance of an S3 bucket so that credentials can be managed - * from a single instance instead of being passed to every method. - * - * @param options The default options to use for the S3 client. Can be - * overriden by passing options to the methods. - * - * ## Keep S3 credentials in a single instance - * - * @example - * const bucket = new Bun.S3Client({ - * accessKeyId: "your-access-key", - * secretAccessKey: "your-secret-key", - * bucket: "my-bucket", - * endpoint: "https://s3.us-east-1.amazonaws.com", - * sessionToken: "your-session-token", - * }); - * - * // S3Client is callable, so you can do this: - * const file = bucket.file("my-file.txt"); - * - * // or this: - * await file.write("Hello Bun!"); - * await file.text(); - * - * // To delete the file: - * await bucket.delete("my-file.txt"); - * - * // To write a file without returning the instance: - * await bucket.write("my-file.txt", "Hello Bun!"); - * - */ - new (options?: S3Options): S3Client; - - /** - * Creates an S3File instance for the given path. - * - * @example - * const file = bucket.file("image.jpg"); - * await file.write(imageData); - * const configFile = bucket("config.json", { - * type: "application/json", - * acl: "private" - * }); - */ - file(path: string, options?: S3Options): S3File; - - /** - * Writes data directly to a path in the bucket. - * Supports strings, buffers, streams, and web API types. - * - * @example - * // Write string - * await bucket.write("hello.txt", "Hello World"); - * - * // Write JSON with type - * await bucket.write( - * "data.json", - * JSON.stringify({hello: "world"}), - * {type: "application/json"} - * ); - * - * // Write from fetch - * const res = await fetch("https://example.com/data"); - * await bucket.write("data.bin", res); - * - * // Write with ACL - * await bucket.write("public.html", html, { - * acl: "public-read", - * type: "text/html" - * }); - */ - write( - path: string, - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob - | File, - options?: S3Options, - ): Promise; - - /** - * Generate a presigned URL for temporary access to a file. - * Useful for generating upload/download URLs without exposing credentials. - * - * @example - * // Download URL - * const downloadUrl = bucket.presign("file.pdf", { - * expiresIn: 3600 // 1 hour - * }); - * - * // Upload URL - * const uploadUrl = bucket.presign("uploads/image.jpg", { - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * // Long-lived public URL - * const publicUrl = bucket.presign("public/doc.pdf", { - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(path: string, options?: S3FilePresignOptions): string; - - /** - * Delete a file from the bucket. - * - * @example - * // Simple delete - * await bucket.unlink("old-file.txt"); - * - * // With error handling - * try { - * await bucket.unlink("file.dat"); - * console.log("File deleted"); - * } catch (err) { - * console.error("Delete failed:", err); - * } - */ - unlink(path: string, options?: S3Options): Promise; - delete: S3Client["unlink"]; - - /** - * Get the size of a file in bytes. - * Uses HEAD request to efficiently get size. - * - * @example - * // Get size - * const bytes = await bucket.size("video.mp4"); - * console.log(`Size: ${bytes} bytes`); - * - * // Check if file is large - * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { - * console.log("File is larger than 100MB"); - * } - */ - size(path: string, options?: S3Options): Promise; - - /** - * Check if a file exists in the bucket. - * Uses HEAD request to check existence. - * - * @example - * // Check existence - * if (await bucket.exists("config.json")) { - * const file = bucket("config.json"); - * const config = await file.json(); - * } - * - * // With error handling - * try { - * if (!await bucket.exists("required.txt")) { - * throw new Error("Required file missing"); - * } - * } catch (err) { - * console.error("Check failed:", err); - * } - */ - exists(path: string, options?: S3Options): Promise; - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @param path The path to the file. - * @param options The options to use for the S3 client. - */ - stat(path: string, options?: S3Options): Promise; - }; - /** - * Configuration options for SQL client connection and behavior - * @example - * const config: SQLOptions = { - * host: 'localhost', - * port: 5432, - * user: 'dbuser', - * password: 'secretpass', - * database: 'myapp', - * idleTimeout: 30000, - * max: 20, - * onconnect: (client) => { - * console.log('Connected to database'); - * } - * }; - */ - type 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); - /** Database password for authentication (alias for password) */ - pass?: string | (() => Promise); - /** 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 extends Promise { - /** Indicates if the query is currently executing */ - active: boolean; - /** Indicates if the query has been cancelled */ - cancelled: boolean; - /** Cancels the executing query */ - cancel(): SQLQuery; - /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ - simple(): SQLQuery; - /** Executes the query */ - execute(): SQLQuery; - /** Returns the raw query result */ - raw(): SQLQuery; - /** Returns only the values from the query result */ - values(): SQLQuery; - } - - /** - * Callback function type for transaction contexts - * @param sql Function to execute SQL queries within the transaction - */ - type SQLTransactionContextCallback = ( - sql: TransactionSQL, - ) => Promise | Array; - /** - * Callback function type for savepoint contexts - * @param sql Function to execute SQL queries within the savepoint - */ - type SQLSavepointContextCallback = ( - sql: SavepointSQL, - ) => Promise | Array; - - /** - * Main SQL client interface providing connection and transaction management - */ - interface SQL { - /** Creates a new SQL client instance - * @example - * const sql = new SQL("postgres://localhost:5432/mydb"); - * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); - */ - new (connectionString: string | URL): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); - */ - new (connectionString: string | URL, options: SQLOptions): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); - */ - new (options?: SQLOptions): SQL; - /** Executes a SQL query using template literals - * @example - * const [user] = await sql`select * from users where id = ${1}`; - */ - (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; - /** - * Helper function to allow easy use to insert values into a query - * @example - * const result = await sql`insert into users ${sql(users)} RETURNING *`; - */ - (obj: any): SQLQuery; - /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.commitDistributed("my_distributed_transaction"); - */ - commitDistributed(name: string): Promise; - /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.rollbackDistributed("my_distributed_transaction"); - */ - rollbackDistributed(name: string): Promise; - /** Waits for the database connection to be established - * @example - * await sql.connect(); - */ - connect(): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @example - * await sql.close({ timeout: 1 }); - */ - close(options?: { timeout?: number }): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @alias close - * @example - * await sql.end({ timeout: 1 }); - */ - end(options?: { timeout?: number }): Promise; - /** Flushes any pending operations */ - flush(): void; - /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. - * This can be used for running queries on an isolated connection. - * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). - * @example - * const reserved = await sql.reserve(); - * await reserved`select * from users`; - * await reserved.release(); - * // with in a production scenario would be something more like - * const reserved = await sql.reserve(); - * try { - * // ... queries - * } finally { - * await reserved.release(); - * } - * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose - * { - * // always release after context (safer) - * using reserved = await sql.reserve() - * await reserved`select * from users` - * } - */ - reserve(): Promise; - /** Begins a new transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(fn: SQLTransactionContextCallback): Promise; - /** Begins a new transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(options: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction( - options: string, - fn: SQLTransactionContextCallback, - ): Promise; - /** Begins a distributed transaction - * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. - * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. - * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. - * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. - * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. - * @example - * await sql.beginDistributed("numbers", async sql => { - * await sql`create table if not exists numbers (a int)`; - * await sql`insert into numbers values(1)`; - * }); - * // later you can call - * await sql.commitDistributed("numbers"); - * // or await sql.rollbackDistributed("numbers"); - */ - beginDistributed( - name: string, - fn: SQLTransactionContextCallback, - ): Promise; - /** Alternative method to begin a distributed transaction - * @alias beginDistributed - */ - distributed(name: string, fn: SQLTransactionContextCallback): Promise; - /**If you know what you're doing, you can use unsafe to pass any string you'd like. - * Please note that this can lead to SQL injection if you're not careful. - * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. - * @example - * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) - */ - unsafe(string: string, values?: any[]): SQLQuery; - /** - * Reads a file and uses the contents as a query. - * Optional parameters can be used if the file includes $1, $2, etc - * @example - * const result = await sql.file("query.sql", [1, 2, 3]); - */ - file(filename: string, values?: any[]): SQLQuery; - - /** Current client options */ - options: SQLOptions; - - [Symbol.asyncDispose](): Promise; - } - - /** - * Represents a reserved connection from the connection pool - * Extends SQL with additional release functionality - */ - interface ReservedSQL extends SQL { - /** Releases the client back to the connection pool */ - release(): void; - [Symbol.dispose](): void; - } - - /** - * Represents a client within a transaction context - * Extends SQL with savepoint functionality - */ - interface TransactionSQL extends SQL { - /** Creates a savepoint within the current transaction */ - savepoint(name: string, fn: SQLSavepointContextCallback): Promise; - savepoint(fn: SQLSavepointContextCallback): Promise; - } - /** - * Represents a savepoint within a transaction - */ - interface SavepointSQL extends SQL {} - - var sql: SQL; - var postgres: SQL; - var SQL: SQL; - - /** - * This lets you use macros as regular imports - * @example - * ``` - * { - * "react-relay": { - * "graphql": "bun-macro-relay/bun-macro-relay.tsx" - * } - * } - * ``` - */ - type MacroMap = Record>; - - /** - * 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; - } - - 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; - 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; - - /** 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; - }; - 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 = () =>
Hello World
; - * 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; - /** - * 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-run" - | "entry-point-build"; - - 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?: /** + import type { FFIFunctionCallableSymbol } from "bun:ffi"; + import type { Encoding as CryptoEncoding } from "crypto"; + import type { X509Certificate } from "node:crypto"; + import type { Stats } from "node:fs"; + import type { CipherNameAndProtocol, EphemeralKeyInfo, PeerCertificate } from "tls"; + + type DistributedOmit = T extends T ? Omit : never; + type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; + + interface Env { + NODE_ENV?: string; + /** + * Can be used to change the default timezone at runtime + */ + TZ?: string; + } - * ECMAScript Module format + /** + * 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 */ - | "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; - // origin?: string; // e.g. http://mydomain.com - loader?: { [k in string]: Loader }; - sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; // 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; - - /** - * Controls how environment variables are handled during bundling. - * - * Can be one of: - * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` - * references to string literals containing the actual environment variable values - * - `"disable"`: Disables environment variable injection entirely - * - A string ending in `*`: Inlines environment variables that match the given prefix. - * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" - * - * @example - * ```ts - * Bun.build({ - * env: "MY_PUBLIC_*", - * entrypoints: ["src/index.ts"], - * }) - * ``` - */ - env?: "inline" | "disable" | `${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; - - /** - * Drop function calls to matching property accesses. - */ - drop?: string[]; - - /** - * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. - * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. - * This defaults to `true`. - */ - throw?: boolean; - } - - 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 password. - * If empty, always returns false - */ - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - * - * If specified and the algorithm does not match the hash, this function - * throws an error. - */ - algorithm?: Password.AlgorithmLabel, - ): Promise; - /** - * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. - * - * @returns A promise that resolves to the hashed password - * - * ## Example with argon2 - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world"); - * console.log(hash); // $argon2id$v=1... - * const verify = await password.verify("hello world", hash); - * ``` - * ## Example with bcrypt - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world", "bcrypt"); - * console.log(hash); // $2b$10$... - * const verify = await password.verify("hello world", hash); - * ``` - */ - hash( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before - */ - algorithm?: - | Password.AlgorithmLabel - | Password.Argon2Algorithm - | Password.BCryptAlgorithm, - ): Promise; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.verify} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - verifySync( - password: Bun.StringOrBuffer, - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - */ - algorithm?: Password.AlgorithmLabel, - ): boolean; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.hash} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - hashSync( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before - */ - algorithm?: - | Password.AlgorithmLabel - | Password.Argon2Algorithm - | Password.BCryptAlgorithm, - ): string; - }; - - interface BuildArtifact extends Blob { - path: string; - loader: Loader; - hash: string | null; - kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; - sourcemap: BuildArtifact | null; - } - - interface BuildOutput { - outputs: BuildArtifact[]; - success: boolean; - logs: Array; - } - - /** - * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. + 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 + | string + | { raw: string } + | Subprocess + | SpawnOptions.Readable + | SpawnOptions.Writable + | ReadableStream; + + class ShellPromise extends Promise { + 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 | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + } + + type ShellError = _ShellError; + + export interface Shell { + (strings: TemplateStringsArray, ...expressions: ShellExpression[]): ShellPromise; + + readonly ShellError: typeof _ShellError; + + /** + * 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): 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; + + /** + * Synchronously resolve a `moduleId` as though it were imported from `parent` * - * @param {Object} config - Build configuration options - * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status - * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) + * 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` * - * @example Basic usage - Bundle a single entrypoint and check results - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist' - }); + * 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; - if (!result.success) { - console.error('Build failed:', result.logs); - process.exit(1); - } - ``` - * - * @example Set up multiple entrypoints with code splitting enabled - ```ts - await Bun.build({ - entrypoints: ['./src/app.tsx', './src/admin.tsx'], - outdir: './dist', - splitting: true, - sourcemap: "external" - }); - ``` - * - * @example Configure minification and optimization settings - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - minify: { - whitespace: true, - identifiers: true, - syntax: true - }, - drop: ['console', 'debugger'] - }); - ``` - * - * @example Set up custom loaders and mark packages as external - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - loader: { - '.png': 'dataurl', - '.svg': 'file', - '.txt': 'text', - '.json': 'json' + /** + * 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 | S3File | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + 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, maxLength?: number): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + maxLength: number, + asUint8Array: false, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + 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, + ): Promise | 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, + ): Promise | 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; + + /** + * 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, + multipartBoundaryExcludingDashes?: string | NodeJS.TypedArray | ArrayBufferView, + ): Promise; + + /** + * 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; + + /** + * 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; + + /** + * 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(stream: ReadableStream): Promise | T[]; + + /** + * Escape the following characters in a string: + * + * - `"` 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. + * + * @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 { + (promise: T | Promise): Promise | T; + status(promise: T | Promise): "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"; }, - external: ['react', 'react-dom'] - }); - ``` - * - * @example Configure environment variable handling with different modes - ```ts - // Inline all environment variables - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'inline' - }); + ): Promise; + + /** + * + * **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; - // Only include specific env vars - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'PUBLIC_*' - }); - ``` - * - * @example Set up custom naming patterns for all output types - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - naming: { - entry: '[dir]/[name]-[hash].[ext]', - chunk: 'chunks/[name]-[hash].[ext]', - asset: 'assets/[name]-[hash].[ext]' - } - }); - ``` - @example Work with build artifacts in different formats - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'] - }); + /** + * **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; + }; - for (const artifact of result.outputs) { - const text = await artifact.text(); - const buffer = await artifact.arrayBuffer(); - const bytes = await artifact.bytes(); + ADDRCONFIG: number; + ALL: number; + 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; + } - new Response(artifact); - await Bun.write(artifact.path, artifact); - } - ``` - @example Implement comprehensive error handling with position info - ```ts - try { - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'], - }); - } catch (e) { - const error = e as AggregateError; - console.error('Build failed:'); - for (const msg of error.errors) { - if ('position' in msg) { - console.error( - `${msg.message} at ${msg.position?.file}:${msg.position?.line}:${msg.position?.column}` - ); - } else { - console.error(msg.message); - } - } - } - ``` - @example Set up Node.js target with specific configurations - ```ts - await Bun.build({ - entrypoints: ['./src/server.ts'], - outdir: './dist', - target: 'node', - format: 'cjs', - sourcemap: 'external', - minify: false, - packages: 'external' - }); - ``` - * - * @example Configure experimental CSS bundling with multiple themes - ```ts - await Bun.build({ - entrypoints: [ - './src/styles.css', - './src/themes/dark.css', - './src/themes/light.css' - ], - outdir: './dist/css', - }); - ``` - @example Define compile-time constants and version information + /** + * 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; + /** + * Close the file descriptor. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; + + 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; + + /** + * 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; + + /** + * Deletes the file. + */ + unlink(): Promise; + + /** + * Deletes the file. ( same as unlink ) + */ + delete(): Promise; + + /** + * Provides useful information about the file. + */ + stat(): Promise; + } + interface NetworkSink extends FileSink { + /** + * Write a chunk of data to the network. + * + * If the network is not writable yet, the data is buffered. + */ + write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number; + /** + * Flush the internal buffer, committing the data to the network. + */ + flush(): number | Promise; + /** + * Finish the upload. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; + + /** + * Get the stat of the file. + */ + stat(): Promise; + } + + var S3Client: S3Client; + var s3: S3Client; + + /** + * Configuration options for S3 operations + */ + interface S3Options extends BlobPropertyBag { + /** + * The Access Control List (ACL) policy for the file. + * Controls who can access the file and what permissions they have. + * + * @example + * // Setting public read access + * const file = s3("public-file.txt", { + * acl: "public-read", + * bucket: "my-bucket" + * }); + * + * @example + * // Using with presigned URLs + * const url = file.presign({ + * acl: "public-read", + * expiresIn: 3600 + * }); + */ + acl?: + | "private" + | "public-read" + | "public-read-write" + | "aws-exec-read" + | "authenticated-read" + | "bucket-owner-read" + | "bucket-owner-full-control" + | "log-delivery-write"; + + /** + * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. + * + * @example + * // Using explicit bucket + * const file = s3("my-file.txt", { bucket: "my-bucket" }); + * + * @example + * // Using environment variables + * // With S3_BUCKET=my-bucket in .env + * const file = s3("my-file.txt"); + */ + bucket?: string; + + /** + * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. + * + * @example + * const file = s3("my-file.txt", { + * bucket: "my-bucket", + * region: "us-west-2" + * }); + */ + region?: string; + + /** + * The access key ID for authentication. + * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. + */ + accessKeyId?: string; + + /** + * The secret access key for authentication. + * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. + */ + secretAccessKey?: string; + + /** + * Optional session token for temporary credentials. + * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. + * + * @example + * // Using temporary credentials + * const file = s3("my-file.txt", { + * accessKeyId: tempAccessKey, + * secretAccessKey: tempSecretKey, + * sessionToken: tempSessionToken + * }); + */ + sessionToken?: string; + + /** + * The S3-compatible service endpoint URL. + * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. + * + * @example + * // AWS S3 + * const file = s3("my-file.txt", { + * endpoint: "https://s3.us-east-1.amazonaws.com" + * }); + * + * @example + * // Cloudflare R2 + * const file = s3("my-file.txt", { + * endpoint: "https://.r2.cloudflarestorage.com" + * }); + * + * @example + * // DigitalOcean Spaces + * const file = s3("my-file.txt", { + * endpoint: "https://.digitaloceanspaces.com" + * }); + * + * @example + * // MinIO (local development) + * const file = s3("my-file.txt", { + * endpoint: "http://localhost:9000" + * }); + */ + endpoint?: string; + + /** + * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` + * + * @example + * // Using virtual hosted style + * const file = s3("my-file.txt", { + * virtualHostedStyle: true, + * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" + * }); + */ + virtualHostedStyle?: boolean; + + /** + * The size of each part in multipart uploads (in bytes). + * - Minimum: 5 MiB + * - Maximum: 5120 MiB + * - Default: 5 MiB + * + * @example + * // Configuring multipart uploads + * const file = s3("large-file.dat", { + * partSize: 10 * 1024 * 1024, // 10 MiB parts + * queueSize: 4 // Upload 4 parts in parallel + * }); + * + * const writer = file.writer(); + * // ... write large file in chunks + */ + partSize?: number; + + /** + * Number of parts to upload in parallel for multipart uploads. + * - Default: 5 + * - Maximum: 255 + * + * Increasing this value can improve upload speeds for large files + * but will use more memory. + */ + queueSize?: number; + + /** + * Number of retry attempts for failed uploads. + * - Default: 3 + * - Maximum: 255 + * + * @example + * // Setting retry attempts + * const file = s3("my-file.txt", { + * retry: 5 // Retry failed uploads up to 5 times + * }); + */ + retry?: number; + + /** + * The Content-Type of the file. + * Automatically set based on file extension when possible. + * + * @example + * // Setting explicit content type + * const file = s3("data.bin", { + * type: "application/octet-stream" + * }); + */ + type?: string; + + /** + * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. + * + * @example + * // Setting explicit Storage class + * const file = s3("my-file.json", { + * storageClass: "STANDARD_IA" + * }); + */ + storageClass?: + | "STANDARD" + | "DEEP_ARCHIVE" + | "EXPRESS_ONEZONE" + | "GLACIER" + | "GLACIER_IR" + | "INTELLIGENT_TIERING" + | "ONEZONE_IA" + | "OUTPOSTS" + | "REDUCED_REDUNDANCY" + | "SNOW" + | "STANDARD_IA"; + + /** + * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. + */ + highWaterMark?: number; + } + + /** + * Options for generating presigned URLs + */ + interface S3FilePresignOptions extends S3Options { + /** + * Number of seconds until the presigned URL expires. + * - Default: 86400 (1 day) + * + * @example + * // Short-lived URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Long-lived public URL + * const url = file.presign({ + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + expiresIn?: number; + + /** + * The HTTP method allowed for the presigned URL. + * + * @example + * // GET URL for downloads + * const downloadUrl = file.presign({ + * method: "GET", + * expiresIn: 3600 + * }); + * + * @example + * // PUT URL for uploads + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "application/json" + * }); + */ + method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; + } + + interface S3Stats { + size: number; + lastModified: Date; + etag: string; + type: string; + } + + /** + * Represents a file in an S3-compatible storage service. + * Extends the Blob interface for compatibility with web APIs. + */ + interface S3File extends Blob { + /** + * The size of the file in bytes. + * This is a Promise because it requires a network request to determine the size. + * + * @example + * // Getting file size + * const size = await file.size; + * console.log(`File size: ${size} bytes`); + * + * @example + * // Check if file is larger than 1MB + * if (await file.size > 1024 * 1024) { + * console.log("Large file detected"); + * } + */ + /** + * TODO: figure out how to get the typescript types to not error for this property. + */ + // size: Promise; + + /** + * Creates a new S3File representing a slice of the original file. + * Uses HTTP Range headers for efficient partial downloads. + * + * @param begin - Starting byte offset + * @param end - Ending byte offset (exclusive) + * @param contentType - Optional MIME type for the slice + * @returns A new S3File representing the specified range + * + * @example + * // Reading file header + * const header = file.slice(0, 1024); + * const headerText = await header.text(); + * + * @example + * // Reading with content type + * const jsonSlice = file.slice(1024, 2048, "application/json"); + * const data = await jsonSlice.json(); + * + * @example + * // Reading from offset to end + * const remainder = file.slice(1024); + * const content = await remainder.text(); + */ + slice(begin?: number, end?: number, contentType?: string): S3File; + slice(begin?: number, contentType?: string): S3File; + slice(contentType?: string): S3File; + + /** + * Creates a writable stream for uploading data. + * Suitable for large files as it uses multipart upload. + * + * @param options - Configuration for the upload + * @returns A NetworkSink for writing data + * + * @example + * // Basic streaming write + * const writer = file.writer({ + * type: "application/json" + * }); + * writer.write('{"hello": '); + * writer.write('"world"}'); + * await writer.end(); + * + * @example + * // Optimized large file upload + * const writer = file.writer({ + * partSize: 10 * 1024 * 1024, // 10MB parts + * queueSize: 4, // Upload 4 parts in parallel + * retry: 3 // Retry failed parts + * }); + * + * // Write large chunks of data efficiently + * for (const chunk of largeDataChunks) { + * writer.write(chunk); + * } + * await writer.end(); + * + * @example + * // Error handling + * const writer = file.writer(); + * try { + * writer.write(data); + * await writer.end(); + * } catch (err) { + * console.error('Upload failed:', err); + * // Writer will automatically abort multipart upload on error + * } + */ + writer(options?: S3Options): NetworkSink; + + /** + * Gets a readable stream of the file's content. + * Useful for processing large files without loading them entirely into memory. + * + * @returns A ReadableStream for the file content + * + * @example + * // Basic streaming read + * const stream = file.stream(); + * for await (const chunk of stream) { + * console.log('Received chunk:', chunk); + * } + * + * @example + * // Piping to response + * const stream = file.stream(); + * return new Response(stream, { + * headers: { 'Content-Type': file.type } + * }); + * + * @example + * // Processing large files + * const stream = file.stream(); + * const textDecoder = new TextDecoder(); + * for await (const chunk of stream) { + * const text = textDecoder.decode(chunk); + * // Process text chunk by chunk + * } + */ + readonly readable: ReadableStream; + stream(): ReadableStream; + + /** + * The name or path of the file in the bucket. + * + * @example + * const file = s3("folder/image.jpg"); + * console.log(file.name); // "folder/image.jpg" + */ + readonly name?: string; + + /** + * The bucket name containing the file. + * + * @example + * const file = s3("s3://my-bucket/file.txt"); + * console.log(file.bucket); // "my-bucket" + */ + readonly bucket?: string; + + /** + * Checks if the file exists in S3. + * Uses HTTP HEAD request to efficiently check existence without downloading. + * + * @returns Promise resolving to true if file exists, false otherwise + * + * @example + * // Basic existence check + * if (await file.exists()) { + * console.log("File exists in S3"); + * } + * + * @example + * // With error handling + * try { + * const exists = await file.exists(); + * if (!exists) { + * console.log("File not found"); + * } + * } catch (err) { + * console.error("Error checking file:", err); + * } + */ + exists(): Promise; + + /** + * Uploads data to S3. + * Supports various input types and automatically handles large files. + * + * @param data - The data to upload + * @param options - Upload configuration options + * @returns Promise resolving to number of bytes written + * + * @example + * // Writing string data + * await file.write("Hello World", { + * type: "text/plain" + * }); + * + * @example + * // Writing JSON + * const data = { hello: "world" }; + * await file.write(JSON.stringify(data), { + * type: "application/json" + * }); + * + * @example + * // Writing from Response + * const response = await fetch("https://example.com/data"); + * await file.write(response); + * + * @example + * // Writing with ACL + * await file.write(data, { + * acl: "public-read", + * type: "application/octet-stream" + * }); + */ + write( + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | Request | Response | BunFile | S3File | Blob, + options?: S3Options, + ): Promise; + + /** + * Generates a presigned URL for the file. + * Allows temporary access to the file without exposing credentials. + * + * @param options - Configuration for the presigned URL + * @returns Presigned URL string + * + * @example + * // Basic download URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Upload URL with specific content type + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * @example + * // URL with custom permissions + * const url = file.presign({ + * method: "GET", + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(options?: S3FilePresignOptions): string; + + /** + * Deletes the file from S3. + * + * @returns Promise that resolves when deletion is complete + * + * @example + * // Basic deletion + * await file.delete(); + * + * @example + * // With error handling + * try { + * await file.delete(); + * console.log("File deleted successfully"); + * } catch (err) { + * console.error("Failed to delete file:", err); + * } + */ + delete(): Promise; + + /** + * Alias for delete() method. + * Provided for compatibility with Node.js fs API naming. + * + * @example + * await file.unlink(); + */ + unlink: S3File["delete"]; + + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @returns Promise resolving to S3Stat + */ + stat(): Promise; + } + + /** + * A configured S3 bucket instance for managing files. + * The instance is callable to create S3File instances and provides methods + * for common operations. + * + * @example + * // Basic bucket setup + * const bucket = new S3Client({ + * bucket: "my-bucket", + * accessKeyId: "key", + * secretAccessKey: "secret" + * }); + * + * // Get file instance + * const file = bucket("image.jpg"); + * + * // Common operations + * await bucket.write("data.json", JSON.stringify({hello: "world"})); + * const url = bucket.presign("file.pdf"); + * await bucket.unlink("old.txt"); + */ + type S3Client = { + /** + * Create a new instance of an S3 bucket so that credentials can be managed + * from a single instance instead of being passed to every method. + * + * @param options The default options to use for the S3 client. Can be + * overriden by passing options to the methods. + * + * ## Keep S3 credentials in a single instance + * + * @example + * const bucket = new Bun.S3Client({ + * accessKeyId: "your-access-key", + * secretAccessKey: "your-secret-key", + * bucket: "my-bucket", + * endpoint: "https://s3.us-east-1.amazonaws.com", + * sessionToken: "your-session-token", + * }); + * + * // S3Client is callable, so you can do this: + * const file = bucket.file("my-file.txt"); + * + * // or this: + * await file.write("Hello Bun!"); + * await file.text(); + * + * // To delete the file: + * await bucket.delete("my-file.txt"); + * + * // To write a file without returning the instance: + * await bucket.write("my-file.txt", "Hello Bun!"); + * + */ + new (options?: S3Options): S3Client; + + /** + * Creates an S3File instance for the given path. + * + * @example + * const file = bucket.file("image.jpg"); + * await file.write(imageData); + * const configFile = bucket("config.json", { + * type: "application/json", + * acl: "private" + * }); + */ + file(path: string, options?: S3Options): S3File; + + /** + * Writes data directly to a path in the bucket. + * Supports strings, buffers, streams, and web API types. + * + * @example + * // Write string + * await bucket.write("hello.txt", "Hello World"); + * + * // Write JSON with type + * await bucket.write( + * "data.json", + * JSON.stringify({hello: "world"}), + * {type: "application/json"} + * ); + * + * // Write from fetch + * const res = await fetch("https://example.com/data"); + * await bucket.write("data.bin", res); + * + * // Write with ACL + * await bucket.write("public.html", html, { + * acl: "public-read", + * type: "text/html" + * }); + */ + write( + path: string, + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob + | File, + options?: S3Options, + ): Promise; + + /** + * Generate a presigned URL for temporary access to a file. + * Useful for generating upload/download URLs without exposing credentials. + * + * @example + * // Download URL + * const downloadUrl = bucket.presign("file.pdf", { + * expiresIn: 3600 // 1 hour + * }); + * + * // Upload URL + * const uploadUrl = bucket.presign("uploads/image.jpg", { + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * // Long-lived public URL + * const publicUrl = bucket.presign("public/doc.pdf", { + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(path: string, options?: S3FilePresignOptions): string; + + /** + * Delete a file from the bucket. + * + * @example + * // Simple delete + * await bucket.unlink("old-file.txt"); + * + * // With error handling + * try { + * await bucket.unlink("file.dat"); + * console.log("File deleted"); + * } catch (err) { + * console.error("Delete failed:", err); + * } + */ + unlink(path: string, options?: S3Options): Promise; + delete: S3Client["unlink"]; + + /** + * Get the size of a file in bytes. + * Uses HEAD request to efficiently get size. + * + * @example + * // Get size + * const bytes = await bucket.size("video.mp4"); + * console.log(`Size: ${bytes} bytes`); + * + * // Check if file is large + * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { + * console.log("File is larger than 100MB"); + * } + */ + size(path: string, options?: S3Options): Promise; + + /** + * Check if a file exists in the bucket. + * Uses HEAD request to check existence. + * + * @example + * // Check existence + * if (await bucket.exists("config.json")) { + * const file = bucket("config.json"); + * const config = await file.json(); + * } + * + * // With error handling + * try { + * if (!await bucket.exists("required.txt")) { + * throw new Error("Required file missing"); + * } + * } catch (err) { + * console.error("Check failed:", err); + * } + */ + exists(path: string, options?: S3Options): Promise; + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @param path The path to the file. + * @param options The options to use for the S3 client. + */ + stat(path: string, options?: S3Options): Promise; + }; + /** + * Configuration options for SQL client connection and behavior + * @example + * const config: SQLOptions = { + * host: 'localhost', + * port: 5432, + * user: 'dbuser', + * password: 'secretpass', + * database: 'myapp', + * idleTimeout: 30000, + * max: 20, + * onconnect: (client) => { + * console.log('Connected to database'); + * } + * }; + */ + type 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); + /** Database password for authentication (alias for password) */ + pass?: string | (() => Promise); + /** 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 extends Promise { + /** Indicates if the query is currently executing */ + active: boolean; + /** Indicates if the query has been cancelled */ + cancelled: boolean; + /** Cancels the executing query */ + cancel(): SQLQuery; + /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ + simple(): SQLQuery; + /** Executes the query */ + execute(): SQLQuery; + /** Returns the raw query result */ + raw(): SQLQuery; + /** Returns only the values from the query result */ + values(): SQLQuery; + } + + /** + * Callback function type for transaction contexts + * @param sql Function to execute SQL queries within the transaction + */ + type SQLTransactionContextCallback = (sql: TransactionSQL) => Promise | Array; + /** + * Callback function type for savepoint contexts + * @param sql Function to execute SQL queries within the savepoint + */ + type SQLSavepointContextCallback = (sql: SavepointSQL) => Promise | Array; + + /** + * Main SQL client interface providing connection and transaction management + */ + interface SQL { + /** Creates a new SQL client instance + * @example + * const sql = new SQL("postgres://localhost:5432/mydb"); + * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); + */ + new (connectionString: string | URL): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); + */ + new (connectionString: string | URL, options: SQLOptions): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); + */ + new (options?: SQLOptions): SQL; + /** Executes a SQL query using template literals + * @example + * const [user] = await sql`select * from users where id = ${1}`; + */ + (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; + /** + * Helper function to allow easy use to insert values into a query + * @example + * const result = await sql`insert into users ${sql(users)} RETURNING *`; + */ + (obj: any): SQLQuery; + /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.commitDistributed("my_distributed_transaction"); + */ + commitDistributed(name: string): Promise; + /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.rollbackDistributed("my_distributed_transaction"); + */ + rollbackDistributed(name: string): Promise; + /** Waits for the database connection to be established + * @example + * await sql.connect(); + */ + connect(): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @example + * await sql.close({ timeout: 1 }); + */ + close(options?: { timeout?: number }): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @alias close + * @example + * await sql.end({ timeout: 1 }); + */ + end(options?: { timeout?: number }): Promise; + /** Flushes any pending operations */ + flush(): void; + /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. + * This can be used for running queries on an isolated connection. + * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). + * @example + * const reserved = await sql.reserve(); + * await reserved`select * from users`; + * await reserved.release(); + * // with in a production scenario would be something more like + * const reserved = await sql.reserve(); + * try { + * // ... queries + * } finally { + * await reserved.release(); + * } + * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose + * { + * // always release after context (safer) + * using reserved = await sql.reserve() + * await reserved`select * from users` + * } + */ + reserve(): Promise; + /** Begins a new transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(fn: SQLTransactionContextCallback): Promise; + /** Begins a new transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(options: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(options: string, fn: SQLTransactionContextCallback): Promise; + /** Begins a distributed transaction + * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. + * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. + * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. + * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. + * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. + * @example + * await sql.beginDistributed("numbers", async sql => { + * await sql`create table if not exists numbers (a int)`; + * await sql`insert into numbers values(1)`; + * }); + * // later you can call + * await sql.commitDistributed("numbers"); + * // or await sql.rollbackDistributed("numbers"); + */ + beginDistributed(name: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a distributed transaction + * @alias beginDistributed + */ + distributed(name: string, fn: SQLTransactionContextCallback): Promise; + /**If you know what you're doing, you can use unsafe to pass any string you'd like. + * Please note that this can lead to SQL injection if you're not careful. + * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. + * @example + * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) + */ + unsafe(string: string, values?: any[]): SQLQuery; + /** + * Reads a file and uses the contents as a query. + * Optional parameters can be used if the file includes $1, $2, etc + * @example + * const result = await sql.file("query.sql", [1, 2, 3]); + */ + file(filename: string, values?: any[]): SQLQuery; + + /** Current client options */ + options: SQLOptions; + + [Symbol.asyncDispose](): Promise; + } + + /** + * Represents a reserved connection from the connection pool + * Extends SQL with additional release functionality + */ + interface ReservedSQL extends SQL { + /** Releases the client back to the connection pool */ + release(): void; + [Symbol.dispose](): void; + } + + /** + * Represents a client within a transaction context + * Extends SQL with savepoint functionality + */ + interface TransactionSQL extends SQL { + /** Creates a savepoint within the current transaction */ + savepoint(name: string, fn: SQLSavepointContextCallback): Promise; + savepoint(fn: SQLSavepointContextCallback): Promise; + } + /** + * Represents a savepoint within a transaction + */ + interface SavepointSQL extends SQL {} + + var sql: SQL; + var postgres: SQL; + var SQL: SQL; + + /** + * This lets you use macros as regular imports + * @example + * ``` + * { + * "react-relay": { + * "graphql": "bun-macro-relay/bun-macro-relay.tsx" + * } + * } + * ``` + */ + type MacroMap = Record>; + + /** + * 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; + } + + 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; + 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; + + /** 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; + }; + 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 = () =>
Hello World
; + * 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; + /** + * 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-run" + | "entry-point-build"; + + 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; + // origin?: string; // e.g. http://mydomain.com + loader?: { [k in string]: Loader }; + sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; // 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; + + /** + * Controls how environment variables are handled during bundling. + * + * Can be one of: + * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` + * references to string literals containing the actual environment variable values + * - `"disable"`: Disables environment variable injection entirely + * - A string ending in `*`: Inlines environment variables that match the given prefix. + * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" + * + * @example + * ```ts + * Bun.build({ + * env: "MY_PUBLIC_*", + * entrypoints: ["src/index.ts"], + * }) + * ``` + */ + env?: "inline" | "disable" | `${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; + + /** + * Drop function calls to matching property accesses. + */ + drop?: string[]; + + /** + * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. + * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. + * This defaults to `true`. + */ + throw?: boolean; + } + + 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 password. + * If empty, always returns false + */ + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + * + * If specified and the algorithm does not match the hash, this function + * throws an error. + */ + algorithm?: Password.AlgorithmLabel, + ): Promise; + /** + * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. + * + * @returns A promise that resolves to the hashed password + * + * ## Example with argon2 + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world"); + * console.log(hash); // $argon2id$v=1... + * const verify = await password.verify("hello world", hash); + * ``` + * ## Example with bcrypt + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world", "bcrypt"); + * console.log(hash); // $2b$10$... + * const verify = await password.verify("hello world", hash); + * ``` + */ + hash( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before + */ + algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, + ): Promise; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.verify} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + verifySync( + password: Bun.StringOrBuffer, + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + */ + algorithm?: Password.AlgorithmLabel, + ): boolean; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.hash} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + hashSync( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before + */ + algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, + ): string; + }; + + interface BuildArtifact extends Blob { + path: string; + loader: Loader; + hash: string | null; + kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; + sourcemap: BuildArtifact | null; + } + + interface BuildOutput { + outputs: BuildArtifact[]; + success: boolean; + logs: Array; + } + + /** + * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. + * + * @param {Object} config - Build configuration options + * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status + * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) + * + * @example Basic usage - Bundle a single entrypoint and check results + ```ts + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist' + }); + + if (!result.success) { + console.error('Build failed:', result.logs); + process.exit(1); + } + ``` + * + * @example Set up multiple entrypoints with code splitting enabled ```ts await Bun.build({ - entrypoints: ['./src/index.tsx'], + entrypoints: ['./src/app.tsx', './src/admin.tsx'], outdir: './dist', - define: { - 'process.env.NODE_ENV': JSON.stringify('production'), - 'CONSTANTS.VERSION': JSON.stringify('1.0.0'), - 'CONSTANTS.BUILD_TIME': JSON.stringify(new Date().toISOString()) - } + splitting: true, + sourcemap: "external" }); ``` - @example Create a custom plugin for handling special file types + * + * @example Configure minification and optimization settings ```ts await Bun.build({ entrypoints: ['./src/index.tsx'], outdir: './dist', - plugins: [ - { - name: 'my-plugin', - setup(build) { - build.onLoad({ filter: /\.custom$/ }, async (args) => { - const content = await Bun.file(args.path).text(); - return { - contents: `export default ${JSON.stringify(content)}`, - loader: 'js' - }; - }); - } - } - ] + minify: { + whitespace: true, + identifiers: true, + syntax: true + }, + drop: ['console', 'debugger'] }); ``` - @example Enable bytecode generation for faster startup + * + * @example Set up custom loaders and mark packages as external ```ts await Bun.build({ - entrypoints: ['./src/server.ts'], + entrypoints: ['./src/index.tsx'], outdir: './dist', - target: 'bun', - format: 'cjs', - bytecode: true + loader: { + '.png': 'dataurl', + '.svg': 'file', + '.txt': 'text', + '.json': 'json' + }, + external: ['react', 'react-dom'] }); ``` - @example Add custom banner and footer to output files + * + * @example Configure environment variable handling with different modes ```ts + // Inline all environment variables await Bun.build({ entrypoints: ['./src/index.tsx'], outdir: './dist', - banner: '"use client";\n// Built with Bun', - footer: '// Generated on ' + new Date().toISOString() + env: 'inline' }); - ``` - @example Configure CDN public path for asset loading - ```ts + + // Only include specific env vars await Bun.build({ entrypoints: ['./src/index.tsx'], outdir: './dist', - publicPath: 'https://cdn.example.com/assets/', - loader: { - '.png': 'file', - '.svg': 'file' - } + env: 'PUBLIC_*' }); ``` - @example Set up package export conditions for different environments + * + * @example Set up custom naming patterns for all output types ```ts await Bun.build({ entrypoints: ['./src/index.tsx'], outdir: './dist', - conditions: ['production', 'browser', 'module'], - packages: 'external' + naming: { + entry: '[dir]/[name]-[hash].[ext]', + chunk: 'chunks/[name]-[hash].[ext]', + asset: 'assets/[name]-[hash].[ext]' + } }); ``` - */ - function build(config: BuildConfig): Promise; - /** - * A status that represents the outcome of a sent message. - * - * - if **0**, the message was **dropped**. - * - if **-1**, there is **backpressure** of messages. - * - if **>0**, it represents the **number of bytes sent**. - * - * @example - * ```js - * const status = ws.send("Hello!"); - * if (status === 0) { - * console.log("Message was dropped"); - * } else if (status === -1) { - * console.log("Backpressure was applied"); - * } else { - * console.log(`Success! Sent ${status} bytes`); - * } - * ``` - */ - type ServerWebSocketSendStatus = number; - - /** - * A state that represents if a WebSocket is connected. - * - * - `WebSocket.CONNECTING` is `0`, the connection is pending. - * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. - * - `WebSocket.CLOSING` is `2`, the connection is closing. - * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState - */ - type WebSocketReadyState = 0 | 1 | 2 | 3; - - /** - * A fast WebSocket designed for servers. - * - * Features: - * - **Message compression** - Messages can be compressed - * - **Backpressure** - If the client is not ready to receive data, the server will tell you. - * - **Dropped messages** - If the client cannot receive data, the server will tell you. - * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics - * - * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. - * - * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). - * - * @example - * import { serve } from "bun"; - * - * serve({ - * websocket: { - * open(ws) { - * console.log("Connected", ws.remoteAddress); - * }, - * message(ws, data) { - * console.log("Received", data); - * ws.send(data); - * }, - * close(ws, code, reason) { - * console.log("Disconnected", code, reason); - * }, - * } - * }); - */ - interface ServerWebSocket { - /** - * Sends a message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - * ws.send(new Uint8Array([1, 2, 3, 4])); - */ - send( - data: string | Bun.BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a text message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - */ - sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send(new TextEncoder().encode("Hello!")); - * ws.send(new Uint8Array([1, 2, 3, 4]), true); - */ - sendBinary( - data: Bun.BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Closes the connection. - * - * Here is a list of close codes: - * - `1000` means "normal closure" **(default)** - * - `1009` means a message was too big and was rejected - * - `1011` means the server encountered an error - * - `1012` means the server is restarting - * - `1013` means the server is too busy or the client is rate-limited - * - `4000` through `4999` are reserved for applications (you can use it!) - * - * To close the connection abruptly, use `terminate()`. - * - * @param code The close code to send - * @param reason The close reason to send - */ - close(code?: number, reason?: string): void; - - /** - * Abruptly close the connection. - * - * To gracefully close the connection, use `close()`. - */ - terminate(): void; - - /** - * Sends a ping. - * - * @param data The data to send - */ - ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a pong. - * - * @param data The data to send - */ - pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); - */ - publish( - topic: string, - data: string | Bun.BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a text message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - */ - publishText( - topic: string, - data: string, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a binary message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", new TextEncoder().encode("Hello!")); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); - */ - publishBinary( - topic: string, - data: Bun.BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Subscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - */ - subscribe(topic: string): void; - - /** - * Unsubscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.unsubscribe("chat"); - */ - unsubscribe(topic: string): void; - - /** - * Is the client subscribed to a topic? - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - * console.log(ws.isSubscribed("chat")); // true - */ - isSubscribed(topic: string): boolean; - - /** - * Batches `send()` and `publish()` operations, which makes it faster to send data. - * - * The `message`, `open`, and `drain` callbacks are automatically corked, so - * you only need to call this if you are sending messages outside of those - * callbacks or in async functions. - * - * @param callback The callback to run. - * @example - * ws.cork((ctx) => { - * ctx.send("These messages"); - * ctx.sendText("are sent"); - * ctx.sendBinary(new TextEncoder().encode("together!")); - * }); - */ - cork(callback: (ws: ServerWebSocket) => T): T; - - /** - * The IP address of the client. - * - * @example - * console.log(socket.remoteAddress); // "127.0.0.1" - */ - readonly remoteAddress: string; - - /** - * The ready state of the client. - * - * - if `0`, the client is connecting. - * - if `1`, the client is connected. - * - if `2`, the client is closing. - * - if `3`, the client is closed. - * - * @example - * console.log(socket.readyState); // 1 - */ - readonly readyState: WebSocketReadyState; - - /** - * Sets how binary data is returned in events. - * - * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** - * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. - * - if `uint8array`, binary data is returned as `Uint8Array` objects. - * - * @example - * let ws: WebSocket; - * ws.binaryType = "uint8array"; - * ws.addEventListener("message", ({ data }) => { - * console.log(data instanceof Uint8Array); // true - * }); - */ - binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; - - /** - * Custom data that you can assign to a client, can be read and written at any time. - * - * @example - * import { serve } from "bun"; - * - * serve({ - * fetch(request, server) { - * const data = { - * accessToken: request.headers.get("Authorization"), - * }; - * if (server.upgrade(request, { data })) { - * return; - * } - * return new Response(); - * }, - * websocket: { - * open(ws) { - * console.log(ws.data.accessToken); - * } - * } - * }); - */ - data: T; - - getBufferedAmount(): number; - } - - /** - * Compression options for WebSocket messages. - */ - type WebSocketCompressor = - | "disable" - | "shared" - | "dedicated" - | "3KB" - | "4KB" - | "8KB" - | "16KB" - | "32KB" - | "64KB" - | "128KB" - | "256KB"; - - /** - * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} - * - * @example - * ```ts - * import { websocket, serve } from "bun"; - * - * serve<{name: string}>({ - * port: 3000, - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log(`${ws.data.name}: ${message}`); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req, { - * data: { - * name: new URL(req.url).searchParams.get("name"), - * }, - * }); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * return; - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - */ - interface WebSocketHandler { - /** - * Called when the server receives an incoming message. - * - * If the message is not a `string`, its type is based on the value of `binaryType`. - * - if `nodebuffer`, then the message is a `Buffer`. - * - if `arraybuffer`, then the message is an `ArrayBuffer`. - * - if `uint8array`, then the message is a `Uint8Array`. - * - * @param ws The websocket that sent the message - * @param message The message received - */ - message( - ws: ServerWebSocket, - message: string | Buffer, - ): void | Promise; - - /** - * Called when a connection is opened. - * - * @param ws The websocket that was opened - */ - open?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection was previously under backpressure, - * meaning it had too many queued messages, but is now ready to receive more data. - * - * @param ws The websocket that is ready for more data - */ - drain?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection is closed. - * - * @param ws The websocket that was closed - * @param code The close code - * @param message The close message - */ - close?( - ws: ServerWebSocket, - code: number, - reason: string, - ): void | Promise; - - /** - * Called when a ping is sent. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - ping?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Called when a pong is received. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - pong?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Sets the maximum size of messages in bytes. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - maxPayloadLength?: number; - - /** - * Sets the maximum number of bytes that can be buffered on a single connection. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - backpressureLimit?: number; - - /** - * Sets if the connection should be closed if `backpressureLimit` is reached. - * - * Default is `false`. - */ - closeOnBackpressureLimit?: boolean; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to no messages or pings. - * - * Default is 2 minutes, or `120` in seconds. - */ - idleTimeout?: number; - - /** - * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? - * - * Default is `false`. - */ - publishToSelf?: boolean; - - /** - * Should the server automatically send and respond to pings to clients? - * - * Default is `true`. - */ - sendPings?: boolean; - - /** - * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. - * - * Default is `false`. - */ - perMessageDeflate?: - | boolean - | { - /** - * Sets the compression level. - */ - compress?: WebSocketCompressor | boolean; - /** - * Sets the decompression level. - */ - decompress?: WebSocketCompressor | boolean; - }; - } - - namespace RouterTypes { - type ExtractRouteParams = - T extends `${string}:${infer Param}/${infer Rest}` - ? { [K in Param]: string } & ExtractRouteParams - : T extends `${string}:${infer Param}` - ? { [K in Param]: string } - : T extends `${string}*` - ? {} - : {}; - - type RouteHandler = ( - req: BunRequest, - server: Server, - ) => Response | Promise; - - type HTTPMethod = - | "GET" - | "POST" - | "PUT" - | "DELETE" - | "PATCH" - | "HEAD" - | "OPTIONS"; - - type RouteHandlerObject = { - [K in HTTPMethod]?: RouteHandler; - }; - - type RouteValue = - | Response - | false - | RouteHandler - | RouteHandlerObject; - } - - interface BunRequest extends Request { - params: RouterTypes.ExtractRouteParams; - } - - interface GenericServeOptions { - /** - * What URI should be used to make {@link Request.url} absolute? - * - * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one - * - * @example - * ```js - * "http://my-app.com" - * ``` - * - * @example - * ```js - * "https://wongmjane.com/" - * ``` - * - * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. - * - * @example - * "http://localhost:3000" - */ - // baseURI?: string; - - /** - * What is the maximum size of a request body? (in bytes) - * @default 1024 * 1024 * 128 // 128MB - */ - maxRequestBodySize?: number; - - /** - * Render contextual errors? This enables bun's error page - * @default process.env.NODE_ENV !== 'production' - */ - development?: - | boolean - | { - /** - * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) - * - * @default true if process.env.NODE_ENV !== 'production' - * - */ - hmr?: boolean; - }; - - error?: ( - this: Server, - error: ErrorLike, - ) => Response | Promise | undefined | Promise; - - /** - * Uniquely identify a server instance with an ID - * - * ### When bun is started with the `--hot` flag - * - * This string will be used to hot reload the server without interrupting - * pending requests or websockets. If not provided, a value will be - * generated. To disable hot reloading, set this value to `null`. - * - * ### When bun is not started with the `--hot` flag - * - * This string will currently do nothing. But in the future it could be useful for logs or metrics. - */ - id?: string | null; - } - - interface ServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * Whether the `SO_REUSEPORT` flag should be set. - * - * This allows multiple processes to bind to the same port, which is useful for load balancing. - * - * @default false - */ - reusePort?: boolean; - - /** - * Whether the `IPV6_V6ONLY` flag should be set. - * @default false - */ - ipv6Only?: boolean; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix?: never; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to inactivity. - * - * Default is `10` seconds. - */ - idleTimeout?: number; - - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | Promise; - } - - interface UnixServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | Promise; - } - - interface WebSocketServeOptions - extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | void | Promise; - } - - interface UnixWebSocketServeOptions - extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | Promise; - } - - interface TLSWebSocketServeOptions - extends WebSocketServeOptions, - TLSOptionsAsDeprecated { - unix?: never; - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSWebSocketServeOptions - extends UnixWebSocketServeOptions, - TLSOptionsAsDeprecated { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - tls?: TLSOptions | TLSOptions[]; - } - - interface ErrorLike extends Error { - code?: string; - errno?: number; - syscall?: string; - } - - interface TLSOptions { - /** - * Passphrase for the TLS key - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - // Note for contributors: TLSOptionsAsDeprecated should be considered immutable - // and new TLS option keys should only be supported on the `.tls` property (which comes - // from the TLSOptions interface above). - /** - * This exists because Bun.serve() extends the TLSOptions object, but - * they're now considered deprecated. You should be passing the - * options on `.tls` instead. - * - * @example - * ```ts - * //// OLD //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * passphrase: "secret", - * }); - * - * //// NEW //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * tls: { - * passphrase: "secret", - * }, - * }); - * ``` - */ - interface TLSOptionsAsDeprecated { - /** - * Passphrase for the TLS key - * - * @deprecated Use `.tls.passphrase` instead - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - * - * @deprecated Use `.tls.dhParamsFile` instead - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - * - * @deprecated Use `.tls.serverName` instead - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - * - * @deprecated Use `.tls.lowMemoryMode` instead - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - * - * @deprecated Use `.tls.rejectUnauthorized` instead - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - * - * @deprecated Use `.tls.requestCert` instead - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - * - * @deprecated Use `.tls.ca` instead - */ - ca?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - * - * @deprecated Use `.tls.cert` instead - */ - cert?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - * - * @deprecated Use `.tls.key` instead - */ - key?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - * - * @deprecated `Use .tls.secureOptions` instead - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSServeOptions - extends UnixServeOptions, - TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface SocketAddress { - /** - * The IP address of the client. - */ - address: string; - /** - * The port of the client. - */ - port: number; - /** - * The IP family ("IPv4" or "IPv6"). - */ - family: "IPv4" | "IPv6"; - } - - /** - * HTTP & HTTPS Server - * - * To start the server, see {@link serve} - * - * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. - * That means starting a new server allocates about 500 KB of memory. Try to - * avoid starting and stopping the server often (unless it's a new instance of bun). - * - * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. - */ - interface Server extends Disposable { - /** - * Stop listening to prevent new connections from being accepted. - * - * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. - * - * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. - * @default false - */ - stop(closeActiveConnections?: boolean): Promise; - - /** - * Update the `fetch` and `error` handlers without restarting the server. - * - * This is useful if you want to change the behavior of your server without - * restarting it or for hot reloading. - * - * @example - * - * ```js - * // create the server - * const server = Bun.serve({ - * fetch(request) { - * return new Response("Hello World v1") - * } - * }); - * - * // Update the server to return a different response - * server.reload({ - * fetch(request) { - * return new Response("Hello World v2") - * } - * }); - * ``` - * - * Passing other options such as `port` or `hostname` won't do anything. - */ - reload }>( - options: ( - | (Omit & { - routes: R; - fetch?: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | (Omit & { - routes?: never; - fetch: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. - */ - static?: R; - }, - ): Server; - - /** - * Mock the fetch handler for a running server. - * - * This feature is not fully implemented yet. It doesn't normalize URLs - * consistently in all cases and it doesn't yet call the `error` handler - * consistently. This needs to be fixed - */ - fetch(request: Request | string): Response | Promise; - - /** - * Upgrade a {@link Request} to a {@link ServerWebSocket} - * - * @param request The {@link Request} to upgrade - * @param options Pass headers or attach data to the {@link ServerWebSocket} - * - * @returns `true` if the upgrade was successful and `false` if it failed - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * What you pass to `data` is available on the {@link ServerWebSocket.data} property - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - upgrade( - request: Request, - options?: { - /** - * Send any additional headers while upgrading, like cookies - */ - headers?: Bun.HeadersInit; - /** - * This value is passed to the {@link ServerWebSocket.data} property - */ - data?: T; - }, - ): boolean; - - /** - * Send a message to all connected {@link ServerWebSocket} subscribed to a topic - * - * @param topic The topic to publish to - * @param data The data to send - * @param compress Should the data be compressed? Ignored if the client does not support compression. - * - * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. - * - * @example - * - * ```js - * server.publish("chat", "Hello World"); - * ``` - * - * @example - * ```js - * server.publish("chat", new Uint8Array([1, 2, 3, 4])); - * ``` - * - * @example - * ```js - * server.publish("chat", new ArrayBuffer(4), true); - * ``` - * - * @example - * ```js - * server.publish("chat", new DataView(new ArrayBuffer(4))); - * ``` - */ - publish( - topic: string, - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * A count of connections subscribed to a given topic - * - * This operation will loop through each topic internally to get the count. - * - * @param topic the websocket topic to check how many subscribers are connected to - * @returns the number of subscribers - */ - subscriberCount(topic: string): number; - - /** - * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * return new Response(server.requestIP(request)); - * } - * } - * ``` - */ - requestIP(request: Request): SocketAddress | null; - - /** - * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * server.timeout(request, 60); - * await Bun.sleep(30000); - * return new Response("30 seconds have passed"); - * } - * } - * ``` - */ - timeout(request: Request, seconds: number): void; - /** - * Undo a call to {@link Server.unref} - * - * If the Server has already been stopped, this does nothing. - * - * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. - */ - ref(): void; - - /** - * Don't keep the process alive if this server is the only thing left. - * Active connections may continue to keep the process alive. - * - * By default, the server is ref'd. - * - * To prevent new connections from being accepted, use {@link Server.stop} - */ - unref(): void; - - /** - * How many requests are in-flight right now? - */ - readonly pendingRequests: number; - - /** - * How many {@link ServerWebSocket}s are in-flight right now? - */ - readonly pendingWebSockets: number; - - readonly url: URL; - - readonly port: number; - /** - * The hostname the server is listening on. Does not include the port - * @example - * ```js - * "localhost" - * ``` - */ - readonly hostname: string; - /** - * Is the server running in development mode? - * - * In development mode, `Bun.serve()` returns rendered error messages with - * stack traces instead of a generic 500 error. This makes debugging easier, - * but development mode shouldn't be used in production or you will risk - * leaking sensitive information. - */ - readonly development: boolean; - - /** - * An identifier of the server instance - * - * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. - * - * When bun is not started with the `--hot` flag, this ID is currently unused. - */ - readonly id: string; - } - - type Serve = - | ServeOptions - | TLSServeOptions - | UnixServeOptions - | UnixTLSServeOptions - | WebSocketServeOptions - | TLSWebSocketServeOptions - | UnixWebSocketServeOptions - | UnixTLSWebSocketServeOptions; - - /** - Bun.serve provides a high-performance HTTP server with built-in routing support. - It enables both function-based and object-based route handlers with type-safe - parameters and method-specific handling. - - @example Basic Usage + @example Work with build artifacts in different formats ```ts - Bun.serve({ - port: 3000, - fetch(req) { - return new Response("Hello World"); - } + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'] }); - ``` - @example Route-based Handlers + for (const artifact of result.outputs) { + const text = await artifact.text(); + const buffer = await artifact.arrayBuffer(); + const bytes = await artifact.bytes(); + + new Response(artifact); + await Bun.write(artifact.path, artifact); + } + ``` + @example Implement comprehensive error handling with position info ```ts - Bun.serve({ - routes: { - // Static responses - "/": new Response("Home page"), - - // Function handlers with type-safe parameters - "/users/:id": (req) => { - // req.params.id is typed as string - return new Response(`User ${req.params.id}`); - }, - - // Method-specific handlers - "/api/posts": { - GET: () => new Response("Get posts"), - POST: async (req) => { - const body = await req.json(); - return new Response("Created post"); - }, - DELETE: (req) => new Response("Deleted post") - }, - - // Wildcard routes - "/static/*": (req) => { - // Handle any path under /static/ - return new Response("Static file"); - }, - - // Disable route (fall through to fetch handler) - "/api/legacy": false - }, - - // Fallback handler for unmatched routes - fetch(req) { - return new Response("Not Found", { status: 404 }); + try { + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'], + }); + } catch (e) { + const error = e as AggregateError; + console.error('Build failed:'); + for (const msg of error.errors) { + if ('position' in msg) { + console.error( + `${msg.message} at ${msg.position?.file}:${msg.position?.line}:${msg.position?.column}` + ); + } else { + console.error(msg.message); + } } + } + ``` + @example Set up Node.js target with specific configurations + ```ts + await Bun.build({ + entrypoints: ['./src/server.ts'], + outdir: './dist', + target: 'node', + format: 'cjs', + sourcemap: 'external', + minify: false, + packages: 'external' }); ``` - - @example Path Parameters + * + * @example Configure experimental CSS bundling with multiple themes ```ts - Bun.serve({ - routes: { - // Single parameter - "/users/:id": (req: BunRequest<"/users/:id">) => { - return new Response(`User ID: ${req.params.id}`); - }, - - // Multiple parameters - "/posts/:postId/comments/:commentId": ( - req: BunRequest<"/posts/:postId/comments/:commentId"> - ) => { - return new Response(JSON.stringify(req.params)); - // Output: {"postId": "123", "commentId": "456"} - } - } + await Bun.build({ + entrypoints: [ + './src/styles.css', + './src/themes/dark.css', + './src/themes/light.css' + ], + outdir: './dist/css', }); ``` - - @example Route Precedence + @example Define compile-time constants and version information ```ts - // Routes are matched in the following order: - // 1. Exact static routes ("/about") - // 2. Parameter routes ("/users/:id") - // 3. Wildcard routes ("/api/*") - - Bun.serve({ - routes: { - "/api/users": () => new Response("Users list"), - "/api/users/:id": (req) => new Response(`User ${req.params.id}`), - "/api/*": () => new Response("API catchall"), - "/*": () => new Response("Root catchall") + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + define: { + 'process.env.NODE_ENV': JSON.stringify('production'), + 'CONSTANTS.VERSION': JSON.stringify('1.0.0'), + 'CONSTANTS.BUILD_TIME': JSON.stringify(new Date().toISOString()) } }); ``` - - @example Error Handling + @example Create a custom plugin for handling special file types ```ts - Bun.serve({ - routes: { - "/error": () => { - throw new Error("Something went wrong"); + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + plugins: [ + { + name: 'my-plugin', + setup(build) { + build.onLoad({ filter: /\.custom$/ }, async (args) => { + const content = await Bun.file(args.path).text(); + return { + contents: `export default ${JSON.stringify(content)}`, + loader: 'js' + }; + }); + } } - }, - error(error) { - // Custom error handler - console.error(error); - return new Response(`Error: ${error.message}`, { - status: 500 - }); - } + ] }); ``` - - @example Server Lifecycle + @example Enable bytecode generation for faster startup ```ts - const server = Bun.serve({ - // Server config... + await Bun.build({ + entrypoints: ['./src/server.ts'], + outdir: './dist', + target: 'bun', + format: 'cjs', + bytecode: true }); - - // Update routes at runtime - server.reload({ - routes: { - "/": () => new Response("Updated route") - } + ``` + @example Add custom banner and footer to output files + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + banner: '"use client";\n// Built with Bun', + footer: '// Generated on ' + new Date().toISOString() }); - - // Stop the server - server.stop(); ``` - - @example Development Mode + @example Configure CDN public path for asset loading ```ts - Bun.serve({ - development: true, // Enable hot reloading - routes: { - // Routes will auto-reload on changes + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + publicPath: 'https://cdn.example.com/assets/', + loader: { + '.png': 'file', + '.svg': 'file' } }); ``` - - @example Type-Safe Request Handling + @example Set up package export conditions for different environments ```ts - type Post = { - id: string; - title: string; - }; - - Bun.serve({ - routes: { - "/api/posts/:id": async ( - req: BunRequest<"/api/posts/:id"> - ) => { - if (req.method === "POST") { - const body: Post = await req.json(); - return Response.json(body); - } - return new Response("Method not allowed", { - status: 405 - }); - } - } + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + conditions: ['production', 'browser', 'module'], + packages: 'external' }); ``` - @param options - Server configuration options - @param options.routes - Route definitions mapping paths to handlers - */ - function serve< - T, - R extends { [K in keyof R]: RouterTypes.RouteValue }, - >( - options: ( - | (DistributedOmit & { - routes: R; - fetch?: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | (DistributedOmit & { - routes?: never; - fetch: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for a while though. - */ - static?: R; - }, - ): Server; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - `type` is auto-set based on the file extension when possible - * - * @example - * ```js - * const file = Bun.file("./hello.json"); - * console.log(file.type); // "application/json" - * console.log(await file.json()); // { hello: "world" } - * ``` - * - * @example - * ```js - * await Bun.write( - * Bun.file("./hello.txt"), - * "Hello, world!" - * ); - * ``` - * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file(path: string | URL, options?: BlobPropertyBag): BunFile; - - /** - * A list of files embedded into the standalone executable. Lexigraphically sorted by name. - * - * If the process is not a standalone executable, this returns an empty array. - */ - const embeddedFiles: ReadonlyArray; - - /** - * `Blob` that leverages the fastest system calls available to operate on files. - * - * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. - * - * `Blob.size` will not be valid until the contents of the file are read at least once. - * `Blob.type` will have a default set based on the file extension - * - * @example - * ```js - * const file = Bun.file(new TextEncoder.encode("./hello.json")); - * console.log(file.type); // "application/json" - * ``` - * - * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file( - path: ArrayBufferLike | Uint8Array, - options?: BlobPropertyBag, - ): BunFile; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - * @example - * ```js - * const file = Bun.file(fd); - * ``` - * - * @param fileDescriptor The file descriptor of the file - */ - // tslint:disable-next-line:unified-signatures - function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; - - /** - * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. - * - * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. - */ - function allocUnsafe(size: number): Uint8Array; - - interface BunInspectOptions { - colors?: boolean; - depth?: number; - sorted?: boolean; - compact?: boolean; - } - - /** - * Pretty-print an object the same as {@link console.log} to a `string` - * - * Supports JSX - * - * @param args - */ - function inspect(arg: any, options?: BunInspectOptions): string; - namespace inspect { - /** - * That can be used to declare custom inspect functions. - */ - const custom: typeof import("util").inspect.custom; - - /** - * Pretty-print an object or array as a table - * - * Like {@link console.table}, except it returns a string - */ - function table( - tabularData: object | unknown[], - properties?: string[], - options?: { colors?: boolean }, - ): string; - function table( - tabularData: object | unknown[], - options?: { colors?: boolean }, - ): string; - } - - interface MMapOptions { - /** - * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. - */ - sync?: boolean; - /** - * Allow other processes to see results instantly? - * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. - * @default true - */ - shared?: boolean; - } - /** - * Open a file as a live-updating `Uint8Array` without copying memory - * - Writing to the array writes to the file. - * - Reading from the array reads from the file. - * - * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. - * - * --- - * - * This API inherently has some rough edges: - * - It does not support empty files. It will throw a `SystemError` with `EINVAL` - * - Usage on shared/networked filesystems is discouraged. It will be very slow. - * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. - * - * --- - * - * To close the file, set the array to `null` and it will be garbage collected eventually. - */ - function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; - - /** Write to stdout */ - const stdout: BunFile; - /** Write to stderr */ - const stderr: BunFile; - /** - * Read from stdin - * - * This is read-only - */ - const stdin: BunFile; - - type StringLike = string | { toString(): string }; - - type ColorInput = - | { r: number; g: number; b: number; a?: number } - | [number, number, number] - | [number, number, number, number] - | Uint8Array - | Uint8ClampedArray - | Float32Array - | Float64Array - | string - | number - | { toString(): string }; - - function color( - input: ColorInput, - outputFormat?: /** - * True color ANSI color string, for use in terminals - * @example \x1b[38;2;100;200;200m - */ - | "ansi" - | "ansi-16" - | "ansi-16m" - /** - * 256 color ANSI color string, for use in terminals which don't support true color - * - * Tries to match closest 24-bit color to 256 color palette - */ - | "ansi-256" - /** - * Picks the format that produces the shortest output - */ - | "css" - /** - * Lowercase hex color string without alpha - * @example #ff9800 - */ - | "hex" - /** - * Uppercase hex color string without alpha - * @example #FF9800 - */ - | "HEX" - /** - * @example hsl(35.764706, 1, 0.5) - */ - | "hsl" - /** - * @example lab(0.72732764, 33.938198, -25.311619) - */ - | "lab" - /** - * @example 16750592 - */ - | "number" - /** - * RGB color string without alpha - * @example rgb(255, 152, 0) - */ - | "rgb" - /** - * RGB color string with alpha - * @example rgba(255, 152, 0, 1) - */ - | "rgba", - ): string | null; - - function color( - input: ColorInput, - /** - * An array of numbers representing the RGB color - * @example [100, 200, 200] - */ - outputFormat: "[rgb]", - ): [number, number, number] | null; - function color( - input: ColorInput, - /** - * An array of numbers representing the RGBA color - * @example [100, 200, 200, 255] - */ - outputFormat: "[rgba]", - ): [number, number, number, number] | null; - function color( - input: ColorInput, - /** - * An object representing the RGB color - * @example { r: 100, g: 200, b: 200 } - */ - outputFormat: "{rgb}", - ): { r: number; g: number; b: number } | null; - function color( - input: ColorInput, - /** - * An object representing the RGBA color - * @example { r: 100, g: 200, b: 200, a: 0.5 } - */ - outputFormat: "{rgba}", - ): { r: number; g: number; b: number; a: number } | null; - function color(input: ColorInput, outputFormat: "number"): number | null; - - interface Semver { - /** - * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. - */ - satisfies(version: StringLike, range: StringLike): boolean; - - /** - * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. - * Throws an error if either version is invalid. - */ - order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; - } - var semver: Semver; - - interface Unsafe { - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. - * - * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; - - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` - * - * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - // tslint:disable-next-line:unified-signatures - arrayBufferToString(buffer: Uint16Array): string; - - /** Mock bun's segfault handler. You probably don't want to use this */ - segfault(): void; - - /** - * Force the garbage collector to run extremely often, - * especially inside `bun:test`. - * - * - `0`: default, disable - * - `1`: asynchronously call the garbage collector more often - * - `2`: synchronously call the garbage collector more often. - * - * This is a global setting. It's useful for debugging seemingly random crashes. - * - * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. - * - * @param level - * @returns The previous level - */ - gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; - } - const unsafe: Unsafe; - - type DigestEncoding = - | "utf8" - | "ucs2" - | "utf16le" - | "latin1" - | "ascii" - | "base64" - | "base64url" - | "hex"; - - /** - * Are ANSI colors enabled for stdin and stdout? - * - * Used for {@link console.log} - */ - const enableANSIColors: boolean; - - /** - * What script launched bun? - * - * Absolute file path - * - * @example "/never-gonna-give-you-up.js" - */ - const main: string; - - /** - * Manually trigger the garbage collector - * - * This does two things: - * 1. It tells JavaScriptCore to run the garbage collector - * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. - * - * @param force Synchronously run the garbage collector - */ - function gc(force: boolean): void; - - /** - * JavaScriptCore engine's internal heap snapshot - * - * I don't know how to make this something Chrome or Safari can read. - * - * If you have any ideas, please file an issue https://github.com/oven-sh/bun - */ - interface HeapSnapshot { - /** 2 */ - version: number; - - /** "Inspector" */ - type: string; - - nodes: number[]; - - nodeClassNames: string[]; - edges: number[]; - edgeTypes: string[]; - edgeNames: string[]; - } - - /** - * Returns the number of nanoseconds since the process was started. - * - * This function uses a high-resolution monotonic system timer to provide precise time measurements. - * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), - * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). - * - * Due to this limitation, while the internal counter may continue beyond this point, - * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond - * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but - * with reduced precision, which might affect time calculations and comparisons in long-running applications. - * - * @returns {number} The number of nanoseconds since the process was started, with precise values up to - * Number.MAX_SAFE_INTEGER. - */ - function nanoseconds(): number; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector - */ - function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code - * - * This is a JSON string that can be saved to a file. - * ```ts - * const snapshot = Bun.generateHeapSnapshot("v8"); - * await Bun.write("heap.heapsnapshot", snapshot); - * ``` - */ - function generateHeapSnapshot(format: "v8"): string; - - /** - * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. - */ - function shrink(): void; - - /** - * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` - * - * @param path path to open - */ - function openInEditor(path: string, options?: EditorOptions): void; - - var fetch: typeof globalThis.fetch & { - preconnect(url: string): void; - }; - - interface EditorOptions { - editor?: "vscode" | "subl"; - line?: number; - column?: number; - } - - /** - * This class only exists in types - */ - abstract class CryptoHashInterface { - /** - * Update the hash with data - * - * @param data - */ - update(data: Bun.BlobOrStringOrBuffer): T; - - /** - * Finalize the hash - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash( - input: Bun.BlobOrStringOrBuffer, - hashInto?: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - } - - type SupportedCryptoAlgorithms = - | "blake2b256" - | "blake2b512" - | "md4" - | "md5" - | "ripemd160" - | "sha1" - | "sha224" - | "sha256" - | "sha384" - | "sha512" - | "sha512-224" - | "sha512-256" - | "sha3-224" - | "sha3-256" - | "sha3-384" - | "sha3-512" - | "shake128" - | "shake256"; - - /** - * Hardware-accelerated cryptographic hash functions - * - * Used for `crypto.createHash()` - */ - class CryptoHasher { - /** - * The algorithm chosen to hash the data - */ - readonly algorithm: SupportedCryptoAlgorithms; - - /** - * The length of the output hash in bytes - */ - readonly byteLength: number; - - /** - * Create a new hasher - * - * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms - * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. - */ - constructor( - algorithm: SupportedCryptoAlgorithms, - hmacKey?: string | NodeJS.TypedArray, - ); - - /** - * Update the hash with data - * - * @param input - */ - update( - input: Bun.BlobOrStringOrBuffer, - inputEncoding?: CryptoEncoding, - ): CryptoHasher; - - /** - * Perform a deep copy of the hasher - */ - copy(): CryptoHasher; - - /** - * Finalize the hash. Resets the CryptoHasher so it can be reused. - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(): Buffer; - digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - ): Buffer; - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - hashInto: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - - /** - * List of supported hash algorithms - * - * These are hardware accelerated with BoringSSL - */ - static readonly algorithms: SupportedCryptoAlgorithms[]; - } - - /** - * Resolve a `Promise` after milliseconds. This is like - * {@link setTimeout} except it returns a `Promise`. - * - * @param ms milliseconds to delay resolving the promise. This is a minimum - * number. It may take longer. If a {@link Date} is passed, it will sleep until the - * {@link Date} is reached. - * - * @example - * ## Sleep for 1 second - * ```ts - * import { sleep } from "bun"; - * - * await sleep(1000); - * ``` - * ## Sleep for 10 milliseconds - * ```ts - * await Bun.sleep(10); - * ``` - * ## Sleep until `Date` - * - * ```ts - * const target = new Date(); - * target.setSeconds(target.getSeconds() + 1); - * await Bun.sleep(target); - * ``` - * Internally, `Bun.sleep` is the equivalent of - * ```ts - * await new Promise((resolve) => setTimeout(resolve, ms)); - * ``` - * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. - */ - function sleep(ms: number | Date): Promise; - - /** - * Sleep the thread for a given number of milliseconds - * - * This is a blocking function. - * - * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) - */ - function sleepSync(ms: number): void; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha( - input: Bun.StringOrBuffer, - hashInto?: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param encoding `DigestEncoding` to return the hash in - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; - - /** - * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} - * - * Consider using the ugly-named {@link SHA512_256} instead - */ - class SHA1 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 20; - } - class MD5 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class MD4 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class SHA224 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 28; - } - class SHA512 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 64; - } - class SHA384 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 48; - } - class SHA256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - /** - * See also {@link sha} - */ - class SHA512_256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - - /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ - interface ZlibCompressionOptions { - /** - * The compression level to use. Must be between `-1` and `9`. - * - A value of `-1` uses the default compression level (Currently `6`) - * - A value of `0` gives no compression - * - A value of `1` gives least compression, fastest speed - * - A value of `9` gives best compression, slowest speed - */ - level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * How much memory should be allocated for the internal compression state. - * - * A value of `1` uses minimum memory but is slow and reduces compression ratio. - * - * A value of `9` uses maximum memory for optimal speed. The default is `8`. - */ - memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * The base 2 logarithm of the window size (the size of the history buffer). - * - * Larger values of this parameter result in better compression at the expense of memory usage. - * - * The following value ranges are supported: - * - `9..15`: The output will have a zlib header and footer (Deflate) - * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) - * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) - * - * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. - */ - windowBits?: - | -9 - | -10 - | -11 - | -12 - | -13 - | -14 - | -15 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 25 - | 26 - | 27 - | 28 - | 29 - | 30 - | 31; - /** - * Tunes the compression algorithm. - * - * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** - * - `Z_FILTERED`: For data produced by a filter or predictor - * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) - * - `Z_RLE`: Limit match distances to one (run-length encoding) - * - `Z_FIXED` prevents the use of dynamic Huffman codes - * - * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. - * - * `Z_FILTERED` forces more Huffman coding and less string matching, it is - * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. - * Filtered data consists mostly of small values with a somewhat random distribution. - */ - strategy?: number; - - library?: "zlib"; - } - - interface LibdeflateCompressionOptions { - level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; - library?: "libdeflate"; - } - - /** - * Compresses a chunk of data with `zlib` DEFLATE algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function deflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Compresses a chunk of data with `zlib` GZIP algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function gzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` INFLATE algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function inflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` GUNZIP algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function gunzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - - type Target = - /** - * For generating bundles that are intended to be run by the Bun runtime. In many cases, - * it isn't necessary to bundle server-side code; you can directly execute the source code - * without modification. However, bundling your server code can reduce startup times and - * improve running performance. - * - * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which - * indicates to the Bun runtime that there's no need to re-transpile the file before execution. - */ - | "bun" - /** - * The plugin will be applied to Node.js builds - */ - | "node" - /** - * The plugin will be applied to browser builds - */ - | "browser"; - - /** https://bun.sh/docs/bundler/loaders */ - type Loader = - | "js" - | "jsx" - | "ts" - | "tsx" - | "json" - | "toml" - | "file" - | "napi" - | "wasm" - | "text" - | "css" - | "html"; - - interface PluginConstraints { - /** - * Only apply the plugin when the import specifier matches this regular expression - * - * @example - * ```ts - * // Only apply the plugin when the import specifier matches the regex - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { - * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; - * }); - * } - * }) - * ``` - */ - filter: RegExp; - - /** - * Only apply the plugin when the import specifier has a namespace matching - * this string - * - * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` - * has the namespace `"bun"`. - * - * The default namespace is `"file"` and it can be omitted from import - * specifiers. - */ - namespace?: string; - } - - interface OnLoadResultSourceCode { - /** - * The source code of the module - */ - contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; - /** - * The loader to use for this file - * - * "css" will be added in a future version of Bun. - */ - loader?: Loader; - } - - interface OnLoadResultObject { - /** - * The object to use as the module - * @example - * ```ts - * // In your loader - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * - * // In your script - * import {foo} from "hello:world"; - * console.log(foo); // "bar" - * ``` - */ - exports: Record; - /** - * The loader to use for this file - */ - loader: "object"; - } - - interface OnLoadArgs { - /** - * The resolved import specifier of the module being loaded - * @example - * ```ts - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * console.log(args.path); // "hello:world" - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * ``` - */ - path: string; - /** - * The namespace of the module being loaded - */ - namespace: string; - /** - * The default loader for this file extension - */ - loader: Loader; - /** - * Defer the execution of this callback until all other modules have been parsed. - * - * @returns Promise which will be resolved when all modules have been parsed - */ - defer: () => Promise; - } - - type OnLoadResult = - | OnLoadResultSourceCode - | OnLoadResultObject - | undefined - | void; - type OnLoadCallback = ( - args: OnLoadArgs, - ) => OnLoadResult | Promise; - type OnStartCallback = () => void | Promise; - - interface OnResolveArgs { - /** - * The import specifier of the module being loaded - */ - path: string; - /** - * The module that imported the module being resolved - */ - importer: string; - /** - * The namespace of the importer. - */ - namespace: string; - /** - * The directory to perform file-based resolutions in. - */ - resolveDir: string; - /** - * The kind of import this resolve is for. - */ - kind: ImportKind; - // resolveDir: string; - // pluginData: any; - } - - interface OnResolveResult { - /** - * The destination of the import - */ - path: string; - /** - * The namespace of the destination - * It will be concatenated with `path` to form the final import specifier - * @example - * ```ts - * "foo" // "foo:bar" - * ``` - */ - namespace?: string; - external?: boolean; - } - - type OnResolveCallback = ( - args: OnResolveArgs, - ) => - | OnResolveResult - | Promise - | undefined - | null; - - type FFIFunctionCallable = Function & { - // Making a nominally typed function so that the user must get it from dlopen - readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - - interface PluginBuilder { - /** - * Register a callback which will be invoked when bundling starts. When - * using hot module reloading, this is called at the start of each - * incremental rebuild. - * - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onStart(() => { - * console.log("bundle just started!!") - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onStart(callback: OnStartCallback): this; - onBeforeParse( - constraints: PluginConstraints, - callback: { - napiModule: unknown; - symbol: string; - external?: unknown | undefined; - }, - ): this; - /** - * Register a callback to load imports with a specific import specifier - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; - /** - * Register a callback to resolve imports matching a filter and/or namespace - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onResolve({ filter: /^wat$/ }, (args) => { - * return { path: "/tmp/woah.js" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onResolve( - constraints: PluginConstraints, - callback: OnResolveCallback, - ): this; - /** - * The config object passed to `Bun.build` as is. Can be mutated. - */ - config: BuildConfig & { plugins: BunPlugin[] }; - - /** - * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules - * - * @param specifier The module specifier to register the callback for - * @param callback The function to run when the module is imported or required - * - * ### Example - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.module("hello:world", () => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * - * // sometime later - * const { foo } = await import("hello:world"); - * console.log(foo); // "bar" - * - * // or - * const { foo } = require("hello:world"); - * console.log(foo); // "bar" - * ``` - * - * @returns `this` for method chaining - */ - module( - specifier: string, - callback: () => OnLoadResult | Promise, - ): this; - } - - interface BunPlugin { - /** - * Human-readable name of the plugin - * - * In a future version of Bun, this will be used in error messages. - */ - name: string; - - /** - * The target JavaScript environment the plugin should be applied to. - * - `bun`: The default environment when using `bun run` or `bun` to load a script - * - `browser`: The plugin will be applied to browser builds - * - `node`: The plugin will be applied to Node.js builds - * - * If unspecified, it is assumed that the plugin is compatible with all targets. - * - * This field is not read by Bun.plugin - */ - target?: Target; - /** - * A function that will be called when the plugin is loaded. - * - * This function may be called in the same tick that it is registered, or it may be called later. It could potentially be called multiple times for different targets. - */ - setup( - /** - * A builder object that can be used to register plugin hooks - * @example - * ```ts - * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), - * })); - * ``` - */ - build: PluginBuilder, - ): void | Promise; - } - - /** - * Extend Bun's module resolution and loading behavior - * - * Plugins are applied in the order they are defined. - * - * Today, there are two kinds of hooks: - * - `onLoad` lets you return source code or an object that will become the module's exports - * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. - * - * Plugin hooks must define a `filter` RegExp and will only be matched if the - * import specifier contains a "." or a ":". - * - * ES Module resolution semantics mean that plugins may be initialized _after_ - * a module is resolved. You might need to load plugins at the very beginning - * of the application and then use a dynamic import to load the rest of the - * application. A future version of Bun may also support specifying plugins - * via `bunfig.toml`. - * - * @example - * A YAML loader plugin - * - * ```js - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) - * })); - * }); - * - * // You can use require() - * const {foo} = require("./file.yaml"); - * - * // Or import - * await import("./file.yaml"); - * - * ``` - */ - interface BunRegisterPlugin { - (options: T): ReturnType; - - /** - * Deactivate all plugins - * - * This prevents registered plugins from being applied to future builds. - */ - clearAll(): void; - } - - const plugin: BunRegisterPlugin; - - /** - * Is the current global scope the main thread? - */ - const isMainThread: boolean; - - /** - * Used when importing an HTML file at runtime. - * - * @example - * - * ```ts - * import app from "./index.html"; - * ``` - * - * Bun.build support for this isn't imlpemented yet. - */ - interface HTMLBundle { - index: string; - } - - interface Socket extends Disposable { - /** - * Write `data` to the socket - * - * @param data The data to write to the socket - * @param byteOffset The offset in the buffer to start writing from (defaults to 0) - * @param byteLength The number of bytes to write (defaults to the length of the buffer) - * - * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. - * - * This is unbuffered as of Bun v0.2.2. That means individual write() calls - * will be slow. In the future, Bun will buffer writes and flush them at the - * end of the tick, when the event loop is idle, or sooner if the buffer is full. - */ - write( - data: string | Bun.BufferSource, - byteOffset?: number, - byteLength?: number, - ): number; - - /** - * The data context for the socket. - */ - data: Data; - - /** - * Like {@link Socket.write} except it includes a TCP FIN packet - * - * Use it to send your last message and close the connection. - */ - end( - data?: string | Bun.BufferSource, - byteOffset?: number, - byteLength?: number, - ): number; - - /** - * Close the socket immediately - */ - end(): void; - - /** - * Keep Bun's process alive at least until this socket is closed - * - * After the socket has closed, the socket is unref'd, the process may exit, - * and this becomes a no-op - */ - ref(): void; - - /** - * Set a timeout until the socket automatically closes. - * - * To reset the timeout, call this function again. - * - * When a timeout happens, the `timeout` callback is called and the socket is closed. - */ - timeout(seconds: number): void; - - /** - * Forcefully close the socket. The other end may not receive all data, and - * the socket will be closed immediately. - * - * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to - * `0` and then calls `close(2)`. - */ - terminate(): void; - - /** - * Shutdown writes to a socket - * - * This makes the socket a half-closed socket. It can still receive data. - * - * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally - */ - shutdown(halfClose?: boolean): void; - - readonly readyState: "open" | "closing" | "closed"; - - /** - * Allow Bun's process to exit even if this socket is still open - * - * After the socket has closed, this function does nothing. - */ - unref(): void; - - /** - * Flush any buffered data to the socket - */ - flush(): void; - - /** - * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. - * - * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. - */ - reload(handler: SocketHandler): void; - - /** - * Get the server that created this socket - * - * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. - */ - readonly listener?: SocketListener; - - /** - * Remote IP address connected to the socket - */ - readonly remoteAddress: string; - - /** - * local port connected to the socket - */ - readonly localPort: number; - - /** - * This property is `true` if the peer certificate was signed by one of the CAs - * specified when creating the `Socket` instance, otherwise `false`. - */ - readonly authorized: boolean; - - /** - * String containing the selected ALPN protocol. - * Before a handshake has completed, this value is always null. - * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. - */ - readonly alpnProtocol: string | false | null; - - /** - * Disables TLS renegotiation for this `Socket` instance. Once called, attempts - * to renegotiate will trigger an `error` handler on the `Socket`. - * - * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) - */ - disableRenegotiation(): void; - - /** - * Keying material is used for validations to prevent different kind of attacks in - * network protocols, for example in the specifications of IEEE 802.1X. - * - * Example - * - * ```js - * const keyingMaterial = socket.exportKeyingMaterial( - * 128, - * 'client finished'); - * - * /* - * Example return value of keyingMaterial: - * - * - * ``` - * - * @param length number of bytes to retrieve from keying material - * @param label an application specific label, typically this will be a value from the [IANA Exporter Label - * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). - * @param context Optionally provide a context. - * @return requested bytes of the keying material - */ - exportKeyingMaterial( - length: number, - label: string, - context: Buffer, - ): Buffer; - - /** - * Returns the reason why the peer's certificate was not been verified. This - * property is set only when `socket.authorized === false`. - */ - getAuthorizationError(): Error | null; - - /** - * Returns an object representing the local certificate. The returned object has - * some properties corresponding to the fields of the certificate. - * - * If there is no local certificate, an empty object will be returned. If the - * socket has been destroyed, `null` will be returned. - */ - getCertificate(): PeerCertificate | object | null; - getX509Certificate(): X509Certificate | undefined; - - /** - * Returns an object containing information on the negotiated cipher suite. - * - * For example, a TLSv1.2 protocol with AES256-SHA cipher: - * - * ```json - * { - * "name": "AES256-SHA", - * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", - * "version": "SSLv3" - * } - * ``` - * - */ - getCipher(): CipherNameAndProtocol; - - /** - * Returns an object representing the type, name, and size of parameter of - * an ephemeral key exchange in `perfect forward secrecy` on a client - * connection. It returns an empty object when the key exchange is not - * ephemeral. As this is only supported on a client socket; `null` is returned - * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. - * - * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. - */ - getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; - - /** - * Returns an object representing the peer's certificate. If the peer does not - * provide a certificate, an empty object will be returned. If the socket has been - * destroyed, `null` will be returned. - * - * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's - * certificate. - * @return A certificate object. - */ - getPeerCertificate(): PeerCertificate; - getPeerX509Certificate(): X509Certificate; - - /** - * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. - * @since v12.11.0 - * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. - */ - getSharedSigalgs(): string[]; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. - */ - getTLSFinishedMessage(): Buffer | undefined; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so - * far. - */ - getTLSPeerFinishedMessage(): Buffer | undefined; - - /** - * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. - * - * It may be useful for debugging. - * - * See `Session Resumption` for more information. - */ - getTLSTicket(): Buffer | undefined; - - /** - * Returns a string containing the negotiated SSL/TLS protocol version of the - * current connection. The value `'unknown'` will be returned for connected - * sockets that have not completed the handshaking process. The value `null` will - * be returned for server sockets or disconnected client sockets. - * - * Protocol versions are: - * - * * `'SSLv3'` - * * `'TLSv1'` - * * `'TLSv1.1'` - * * `'TLSv1.2'` - * * `'TLSv1.3'` - * - */ - getTLSVersion(): string; - - /** - * See `Session Resumption` for more information. - * @return `true` if the session was reused, `false` otherwise. - */ - isSessionReused(): boolean; - - /** - * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. - * Returns `true` if setting the limit succeeded; `false` otherwise. - * - * Smaller fragment sizes decrease the buffering latency on the client: larger - * fragments are buffered by the TLS layer until the entire fragment is received - * and its integrity is verified; large fragments can span multiple roundtrips - * and their processing can be delayed due to packet loss or reordering. However, - * smaller fragments add extra TLS framing bytes and CPU overhead, which may - * decrease overall server throughput. - * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. - */ - setMaxSendFragment(size: number): boolean; - - /** - * Enable/disable the use of Nagle's algorithm. - * Only available for already connected sockets, will return false otherwise - * @param noDelay Default: `true` - * @returns true if is able to setNoDelay and false if it fails. - */ - setNoDelay(noDelay?: boolean): boolean; - - /** - * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. - * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. - * Only available for already connected sockets, will return false otherwise. - * - * Enabling the keep-alive functionality will set the following socket options: - * SO_KEEPALIVE=1 - * TCP_KEEPIDLE=initialDelay - * TCP_KEEPCNT=10 - * TCP_KEEPINTVL=1 - * @param enable Default: `false` - * @param initialDelay Default: `0` - * @returns true if is able to setNoDelay and false if it fails. - */ - setKeepAlive(enable?: boolean, initialDelay?: number): boolean; - - /** - * The number of bytes written to the socket. - */ - readonly bytesWritten: number; - } - - interface SocketListener extends Disposable { - stop(closeActiveConnections?: boolean): void; - ref(): void; - unref(): void; - reload(options: Pick, "socket">): void; - data: Data; - } - interface TCPSocketListener extends SocketListener { - readonly port: number; - readonly hostname: string; - } - interface UnixSocketListener extends SocketListener { - readonly unix: string; - } - - interface TCPSocket extends Socket {} - interface TLSSocket extends Socket {} - - interface BinaryTypeList { - arraybuffer: ArrayBuffer; - buffer: Buffer; - uint8array: Uint8Array; - // TODO: DataView - // dataview: DataView; - } - type BinaryType = keyof BinaryTypeList; - - interface SocketHandler< - Data = unknown, - DataBinaryType extends BinaryType = "buffer", - > { - /** - * Is called when the socket connects, or in case of TLS if no handshake is provided - * this will be called only after handshake - * @param socket - */ - open?(socket: Socket): void | Promise; - close?(socket: Socket): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - ): void | Promise; - drain?(socket: Socket): void | Promise; - - /** - * When handshake is completed, this functions is called. - * @param socket - * @param success Indicates if the server authorized despite the authorizationError. - * @param authorizationError Certificate Authorization Error or null. - */ - handshake?( - socket: Socket, - success: boolean, - authorizationError: Error | null, - ): void; - - /** - * When the socket has been shutdown from the other end, this function is - * called. This is a TCP FIN packet. - */ - end?(socket: Socket): void | Promise; - - /** - * When the socket fails to be created, this function is called. - * - * The promise returned by `Bun.connect` rejects **after** this function is - * called. - * - * When `connectError` is specified, the rejected promise will not be - * added to the promise rejection queue (so it won't be reported as an - * unhandled promise rejection, since connectError handles it). - * - * When `connectError` is not specified, the rejected promise will be added - * to the promise rejection queue. - */ - connectError?(socket: Socket, error: Error): void | Promise; - - /** - * Called when a message times out. - */ - timeout?(socket: Socket): void | Promise; - /** - * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. - * - * @default "buffer" - * - * @remarks - * This lets you select the desired binary type for the `data` callback. - * It's a small performance optimization to let you avoid creating extra - * ArrayBufferView objects when possible. - * - * Bun originally defaulted to `Uint8Array` but when dealing with network - * data, it's more useful to be able to directly read from the bytes which - * `Buffer` allows. - */ - binaryType?: BinaryType; - } - - interface SocketOptions { - socket: SocketHandler; - data?: Data; - } - // interface TCPSocketOptions extends SocketOptions { - // hostname: string; - // port: number; - // } - - interface TCPSocketListenOptions - extends SocketOptions { - hostname: string; - port: number; - tls?: TLSOptions; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface TCPSocketConnectOptions - extends SocketOptions { - hostname: string; - port: number; - tls?: boolean; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface UnixSocketOptions extends SocketOptions { - tls?: TLSOptions; - unix: string; - } - - interface FdSocketOptions extends SocketOptions { - tls?: TLSOptions; - fd: number; - } - - /** - * Create a TCP client that connects to a server - * - * @param options The options to use when creating the client - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function connect( - options: TCPSocketConnectOptions, - ): Promise>; - function connect( - options: UnixSocketOptions, - ): Promise>; - - /** - * Create a TCP server that listens on a port - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function listen( - options: TCPSocketListenOptions, - ): TCPSocketListener; - function listen( - options: UnixSocketOptions, - ): UnixSocketListener; - - namespace udp { - type Data = string | ArrayBufferView | ArrayBufferLike; - - export interface SocketHandler { - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: Socket): void | Promise; - error?( - socket: Socket, - error: Error, - ): void | Promise; - } - - export interface ConnectedSocketHandler { - data?( - socket: ConnectedSocket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: ConnectedSocket): void | Promise; - error?( - socket: ConnectedSocket, - error: Error, - ): void | Promise; - } - - export interface SocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: SocketHandler; - } - - export interface ConnectSocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: ConnectedSocketHandler; - connect: { - hostname: string; - port: number; - }; - } - - export interface BaseUDPSocket { - readonly hostname: string; - readonly port: number; - readonly address: SocketAddress; - readonly binaryType: BinaryType; - readonly closed: boolean; - ref(): void; - unref(): void; - close(): void; - } - - export interface ConnectedSocket - extends BaseUDPSocket { - readonly remoteAddress: SocketAddress; - sendMany(packets: readonly Data[]): number; - send(data: Data): boolean; - reload(handler: ConnectedSocketHandler): void; - } - - export interface Socket - extends BaseUDPSocket { - sendMany(packets: readonly (Data | string | number)[]): number; - send(data: Data, port: number, address: string): boolean; - reload(handler: SocketHandler): void; - } - } - - /** - * Create a UDP socket - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.hostname The hostname to listen on - * @param options.port The port to listen on - * @param options.binaryType The binary type to use for the socket - * @param options.connect The hostname and port to connect to - */ - export function udpSocket( - options: udp.SocketOptions, - ): Promise>; - export function udpSocket( - options: udp.ConnectSocketOptions, - ): Promise>; - - namespace SpawnOptions { - /** - * Option for stdout/stderr - */ - type Readable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number; - - /** - * Option for stdin - */ - type Writable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number - | ReadableStream - | Blob - | Response - | Request; - - interface OptionsObject< - In extends Writable = Writable, - Out extends Readable = Readable, - Err extends Readable = Readable, - > { - /** - * The current working directory of the process - * - * Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * The environment variables of the process - * - * Defaults to `process.env` as it was when the current Bun process launched. - * - * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. - */ - env?: Record; - - /** - * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. - * This overrides the `stdin`, `stdout`, and `stderr` properties. - * - * For stdin you may pass: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. - * - `number`: The process will read from the file descriptor - * - * For stdout and stdin you may pass: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default ["ignore", "pipe", "inherit"] for `spawn` - * ["ignore", "pipe", "pipe"] for `spawnSync` - */ - stdio?: [In, Out, Err]; - /** - * The file descriptor for the standard input. It may be: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`: The process will read from the buffer - * - `number`: The process will read from the file descriptor - * - * @default "ignore" - */ - stdin?: In; - /** - * The file descriptor for the standard output. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "pipe" - */ - stdout?: Out; - /** - * The file descriptor for the standard error. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "inherit" for `spawn` - * "pipe" for `spawnSync` - */ - stderr?: Err; - - /** - * Callback that runs when the {@link Subprocess} exits - * - * This is called even if the process exits with a non-zero exit code. - * - * Warning: this may run before the `Bun.spawn` function returns. - * - * A simple alternative is `await subprocess.exited`. - * - * @example - * - * ```ts - * const subprocess = spawn({ - * cmd: ["echo", "hello"], - * onExit: (subprocess, code) => { - * console.log(`Process exited with code ${code}`); - * }, - * }); - * ``` - */ - onExit?( - subprocess: Subprocess, - exitCode: number | null, - signalCode: number | null, - /** - * If an error occurred in the call to waitpid2, this will be the error. - */ - error?: ErrorLike, - ): void | Promise; - - /** - * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for - * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized - * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - * - * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, - * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. - * - * Currently, this is only compatible with processes that are other `bun` instances. - */ - ipc?( - message: any, - /** - * The {@link Subprocess} that sent the message - */ - subprocess: Subprocess, - ): void; - - /** - * The serialization format to use for IPC messages. Defaults to `"advanced"`. - * - * To communicate with Node.js processes, use `"json"`. - * - * When `ipc` is not specified, this is ignored. - */ - serialization?: "json" | "advanced"; - - /** - * If true, the subprocess will have a hidden window. - */ - windowsHide?: boolean; - - /** - * If true, no quoting or escaping of arguments is done on Windows. - */ - windowsVerbatimArguments?: boolean; - - /** - * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. - * - * One use-case for this is for applications which wrap other applications or to simulate a symlink. - * - * @default cmds[0] - */ - argv0?: string; - - /** - * An {@link AbortSignal} that can be used to abort the subprocess. - * - * This is useful for aborting a subprocess when some other part of the - * program is aborted, such as a `fetch` response. - * - * Internally, this works by calling `subprocess.kill(1)`. - * - * @example - * ```ts - * const controller = new AbortController(); - * const { signal } = controller; - * const start = performance.now(); - * const subprocess = Bun.spawn({ - * cmd: ["sleep", "100"], - * signal, - * }); - * await Bun.sleep(1); - * controller.abort(); - * await subprocess.exited; - * const end = performance.now(); - * console.log(end - start); // 1ms instead of 101ms - * ``` - */ - signal?: AbortSignal; - } - - type OptionsToSubprocess = - Opts extends OptionsObject - ? Subprocess< - // "Writable extends In" means "if In === Writable", - // aka if true that means the user didn't specify anything - Writable extends In ? "ignore" : In, - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "inherit" : Err - > - : Subprocess; - - type OptionsToSyncSubprocess = - Opts extends OptionsObject - ? SyncSubprocess< - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "pipe" : Err - > - : SyncSubprocess; - - type ReadableIO = ReadableStream | number | undefined; - - type ReadableToIO = X extends "pipe" | undefined - ? ReadableStream - : X extends BunFile | ArrayBufferView | number - ? number - : undefined; - - type ReadableToSyncIO = X extends "pipe" | undefined - ? Buffer - : undefined; - - type WritableIO = FileSink | number | undefined; - - type WritableToIO = X extends "pipe" - ? FileSink - : X extends BunFile | ArrayBufferView | Blob | Request | Response | number - ? number - : undefined; - } - - interface ResourceUsage { - /** - * The number of voluntary and involuntary context switches that the process made. - */ - contextSwitches: { - /** - * Voluntary context switches (context switches that the process initiated). - */ - voluntary: number; - /** - * Involuntary context switches (context switches initiated by the system scheduler). - */ - involuntary: number; - }; - - /** - * The amount of CPU time used by the process, in microseconds. - */ - cpuTime: { - /** - * User CPU time used by the process, in microseconds. - */ - user: number; - /** - * System CPU time used by the process, in microseconds. - */ - system: number; - /** - * Total CPU time used by the process, in microseconds. - */ - total: number; - }; - /** - * The maximum amount of resident set size (in bytes) used by the process during its lifetime. - */ - maxRSS: number; - - /** - * IPC messages sent and received by the process. - */ - messages: { - /** - * The number of IPC messages sent. - */ - sent: number; - /** - * The number of IPC messages received. - */ - received: number; - }; - /** - * The number of IO operations done by the process. - */ - ops: { - /** - * The number of input operations via the file system. - */ - in: number; - /** - * The number of output operations via the file system. - */ - out: number; - }; - /** - * The amount of shared memory that the process used. - */ - shmSize: number; - /** - * The number of signals delivered to the process. - */ - signalCount: number; - /** - * The number of times the process was swapped out of main memory. - */ - swapCount: number; - } - - /** - * A process created by {@link Bun.spawn}. - * - * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSubprocess} (any, pipe, pipe) - * - {@link WritableSubprocess} (pipe, any, any) - * - {@link PipedSubprocess} (pipe, pipe, pipe) - * - {@link NullSubprocess} (ignore, ignore, ignore) - */ - interface Subprocess< - In extends SpawnOptions.Writable = SpawnOptions.Writable, - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > extends AsyncDisposable { - readonly stdin: SpawnOptions.WritableToIO; - readonly stdout: SpawnOptions.ReadableToIO; - readonly stderr: SpawnOptions.ReadableToIO; - - /** - * This returns the same value as {@link Subprocess.stdout} - * - * It exists for compatibility with {@link ReadableStream.pipeThrough} - */ - readonly readable: SpawnOptions.ReadableToIO; - - /** - * The process ID of the child process - * @example - * ```ts - * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); - * console.log(pid); // 1234 - * ``` - */ - readonly pid: number; - /** - * The exit code of the process - * - * The promise will resolve when the process exits - */ - readonly exited: Promise; - - /** - * Synchronously get the exit code of the process - * - * If the process hasn't exited yet, this will return `null` - */ - readonly exitCode: number | null; - - /** - * Synchronously get the signal code of the process - * - * If the process never sent a signal code, this will return `null` - * - * To receive signal code changes, use the `onExit` callback. - * - * If the signal code is unknown, it will return the original signal code - * number, but that case should essentially never happen. - */ - readonly signalCode: NodeJS.Signals | null; - - /** - * Has the process exited? - */ - readonly killed: boolean; - - /** - * Kill the process - * @param exitCode The exitCode to send to the process - */ - kill(exitCode?: number | NodeJS.Signals): void; - - /** - * This method will tell Bun to wait for this process to exit after you already - * called `unref()`. - * - * Before shutting down, Bun will wait for all subprocesses to exit by default - */ - ref(): void; - - /** - * Before shutting down, Bun will wait for all subprocesses to exit by default - * - * This method will tell Bun to not wait for this process to exit before shutting down. - */ - unref(): void; - - /** - * Send a message to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option, and is another instance of `bun`. - * - * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - */ - send(message: any): void; - - /** - * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option. - */ - disconnect(): void; - - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - * - * Only available after the process has exited - * - * If the process hasn't exited yet, this will return `undefined` - */ - resourceUsage(): ResourceUsage | undefined; - } - - /** - * A process created by {@link Bun.spawnSync}. - * - * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSyncSubprocess} (pipe, pipe) - * - {@link NullSyncSubprocess} (ignore, ignore) - */ - interface SyncSubprocess< - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > { - stdout: SpawnOptions.ReadableToSyncIO; - stderr: SpawnOptions.ReadableToSyncIO; - exitCode: number; - success: boolean; - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - */ - resourceUsage: ResourceUsage; - - signalCode?: string; - } - - /** - * Spawn a new process - * - * ```js - * const subprocess = Bun.spawn({ - * cmd: ["echo", "hello"], - * stdout: "pipe", - * }); - * const text = await readableStreamToText(subprocess.stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmd: string[]; // to support dynamically constructed commands - }, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawn(["echo", "hello"]); - * const text = await readableStreamToText(stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync({ - * cmd: ["echo", "hello"], - * }); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); - * ``` - */ - cmd: string[]; - - onExit?: never; - }, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** - * Synchronously spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync(["echo", "hello"]); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ - type ReadableSubprocess = Subprocess; - /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ - type WritableSubprocess = Subprocess<"pipe", any, any>; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ - type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ - type NullSubprocess = Subprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ - type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ - type NullSyncSubprocess = SyncSubprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - - // Blocked on https://github.com/oven-sh/bun/issues/8329 - // /** - // * - // * Count the visible width of a string, as it would be displayed in a terminal. - // * - // * By default, strips ANSI escape codes before measuring the string. This is - // * because ANSI escape codes are not visible characters. If passed a non-string, - // * it will return 0. - // * - // * @param str The string to measure - // * @param options - // */ - // function stringWidth( - // str: string, - // options?: { - // /** - // * Whether to include ANSI escape codes in the width calculation - // * - // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. - // * @default false - // */ - // countAnsiEscapeCodes?: boolean; - // }, - // ): number; - - class FileSystemRouter { - /** - * Create a new {@link FileSystemRouter}. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: process.cwd() + "/pages", - * style: "nextjs", - * }); - * - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} - * ``` - * @param options The options to use when creating the router - * @param options.dir The root directory containing the files to route - * @param options.style The style of router to use (only "nextjs" supported - * for now) - */ - constructor(options: { - /** - * The root directory containing the files to route - * - * There is no default value for this option. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: - */ - dir: string; - style: "nextjs"; - - /** The base path to use when routing */ - assetPrefix?: string; - origin?: string; - /** Limit the pages to those with particular file extensions. */ - fileExtensions?: string[]; - }); - - // todo: URL - match(input: string | Request | Response): MatchedRoute | null; - - readonly assetPrefix: string; - readonly origin: string; - readonly style: string; - readonly routes: Record; - - reload(): void; - } - - interface MatchedRoute { - /** - * A map of the parameters from the route - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: "/path/to/files", - * style: "nextjs", - * }); - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params.year); // "2020" - * console.log(params.month); // "01" - * console.log(params.day); // "01" - * console.log(params.slug); // "hello-world" - * ``` - */ - readonly params: Record; - readonly filePath: string; - readonly pathname: string; - readonly query: Record; - readonly name: string; - readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; - readonly src: string; - } - - /** - * The current version of Bun - * @example - * "0.2.0" - */ - const version: string; - - /** - * The current version of Bun with the shortened commit sha of the build - * @example "v1.1.30 (d09df1af)" - */ - const version_with_sha: string; - - /** - * The git sha at the time the currently-running version of Bun was compiled - * @example - * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" - */ - const revision: string; - - /** - * Find the index of a newline character in potentially ill-formed UTF-8 text. - * - * This is sort of like readline() except without the IO. - */ - function indexOfLine( - buffer: ArrayBufferView | ArrayBufferLike, - offset?: number, - ): number; - - interface GlobScanOptions { - /** - * The root directory to start matching from. Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * Allow patterns to match entries that begin with a period (`.`). - * - * @default false - */ - dot?: boolean; - - /** - * Return the absolute path for entries. - * - * @default false - */ - absolute?: boolean; - - /** - * Indicates whether to traverse descendants of symbolic link directories. - * - * @default false - */ - followSymlinks?: boolean; - - /** - * Throw an error when symbolic link is broken - * - * @default false - */ - throwErrorOnBrokenSymlink?: boolean; - - /** - * Return only files. - * - * @default true - */ - onlyFiles?: boolean; - } - - /** - * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). - * - * The supported pattern syntax for is: - * - * - `?` - * Matches any single character. - * - `*` - * Matches zero or more characters, except for path separators ('/' or '\'). - * - `**` - * Matches zero or more characters, including path separators. - * Must match a complete path segment, i.e. followed by a path separator or - * at the end of the pattern. - * - `[ab]` - * Matches one of the characters contained in the brackets. - * Character ranges (e.g. "[a-z]") are also supported. - * Use "[!ab]" or "[^ab]" to match any character *except* those contained - * in the brackets. - * - `{a,b}` - * Match one of the patterns contained in the braces. - * Any of the wildcards listed above can be used in the sub patterns. - * Braces may be nested up to 10 levels deep. - * - `!` - * Negates the result when at the start of the pattern. - * Multiple "!" characters negate the pattern multiple times. - * - `\` - * Used to escape any of the special characters above. - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - */ - export class Glob { - constructor(pattern: string); - - /** - * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for await (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scan( - optionsOrCwd?: string | GlobScanOptions, - ): AsyncIterableIterator; - - /** - * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; - - /** - * Match the glob against a string - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * expect(glob.match('foo.ts')).toBeTrue(); - * ``` - */ - match(str: string): boolean; - } - - /** - * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. - * - * When the same timestamp is used multiple times, a monotonically increasing - * counter is appended to allow sorting. The final 8 bytes are - * cryptographically random. When the timestamp changes, the counter resets to - * a psuedo-random integer. - * - * @param encoding "hex" | "base64" | "base64url" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - * - * @example - * ```js - * import { randomUUIDv7 } from "bun"; - * const array = [ - * randomUUIDv7(), - * randomUUIDv7(), - * randomUUIDv7(), - * ] - * [ - * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", - * "0192ce07-8c4f-7d67-805f-0f71581b5622", - * "0192ce07-8c4f-7d68-8170-6816e4451a58" - * ] - * ``` - */ - function randomUUIDv7( - /** - * @default "hex" - */ - encoding?: "hex" | "base64" | "base64url", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): string; - - /** - * Generate a UUIDv7 as a Buffer - * - * @param encoding "buffer" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - */ - function randomUUIDv7( - encoding: "buffer", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): Buffer; - - /** - * Types for `bun.lock` - */ - type BunLockFile = { - lockfileVersion: 0 | 1; - workspaces: { - [workspace: string]: BunLockFileWorkspacePackage; - }; - overrides?: Record; - patchedDependencies?: Record; - trustedDependencies?: string[]; - - /** - * ``` - * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } - * - * // first index is resolution for each type of package - * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] - * symlink -> [ "name@link:path", INFO ] - * folder -> [ "name@file:path", INFO ] - * workspace -> [ "name@workspace:path" ] // workspace is only path - * tarball -> [ "name@tarball", INFO ] - * root -> [ "name@root:", { bin, binDir } ] - * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] - * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] - * ``` - * */ - packages: { - [pkg: string]: BunLockFilePackageArray; - }; - }; - - type BunLockFileBasePackageInfo = { - dependencies?: Record; - devDependencies?: Record; - optionalDependencies?: Record; - peerDependencies?: Record; - optionalPeers?: string[]; - bin?: string | Record; - binDir?: string; - }; - - type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { - name?: string; - version?: string; - }; - - type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { - os?: string | string[]; - cpu?: string | string[]; - bundled?: true; - }; - - /** @see {@link BunLockFile.packages} for more info */ - type BunLockFilePackageArray = - /** npm */ - | [ - pkg: string, - registry: string, - info: BunLockFilePackageInfo, - integrity: string, - ] - /** symlink, folder, tarball */ - | [pkg: string, info: BunLockFilePackageInfo] - /** workspace */ - | [pkg: string] - /** git, github */ - | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] - /** root */ - | [pkg: string, info: Pick]; + */ + function build(config: BuildConfig): Promise; + /** + * A status that represents the outcome of a sent message. + * + * - if **0**, the message was **dropped**. + * - if **-1**, there is **backpressure** of messages. + * - if **>0**, it represents the **number of bytes sent**. + * + * @example + * ```js + * const status = ws.send("Hello!"); + * if (status === 0) { + * console.log("Message was dropped"); + * } else if (status === -1) { + * console.log("Backpressure was applied"); + * } else { + * console.log(`Success! Sent ${status} bytes`); + * } + * ``` + */ + type ServerWebSocketSendStatus = number; + + /** + * A state that represents if a WebSocket is connected. + * + * - `WebSocket.CONNECTING` is `0`, the connection is pending. + * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. + * - `WebSocket.CLOSING` is `2`, the connection is closing. + * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState + */ + type WebSocketReadyState = 0 | 1 | 2 | 3; + + /** + * A fast WebSocket designed for servers. + * + * Features: + * - **Message compression** - Messages can be compressed + * - **Backpressure** - If the client is not ready to receive data, the server will tell you. + * - **Dropped messages** - If the client cannot receive data, the server will tell you. + * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics + * + * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. + * + * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). + * + * @example + * import { serve } from "bun"; + * + * serve({ + * websocket: { + * open(ws) { + * console.log("Connected", ws.remoteAddress); + * }, + * message(ws, data) { + * console.log("Received", data); + * ws.send(data); + * }, + * close(ws, code, reason) { + * console.log("Disconnected", code, reason); + * }, + * } + * }); + */ + interface ServerWebSocket { + /** + * Sends a message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + * ws.send(new Uint8Array([1, 2, 3, 4])); + */ + send(data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a text message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + */ + sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send(new TextEncoder().encode("Hello!")); + * ws.send(new Uint8Array([1, 2, 3, 4]), true); + */ + sendBinary(data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Closes the connection. + * + * Here is a list of close codes: + * - `1000` means "normal closure" **(default)** + * - `1009` means a message was too big and was rejected + * - `1011` means the server encountered an error + * - `1012` means the server is restarting + * - `1013` means the server is too busy or the client is rate-limited + * - `4000` through `4999` are reserved for applications (you can use it!) + * + * To close the connection abruptly, use `terminate()`. + * + * @param code The close code to send + * @param reason The close reason to send + */ + close(code?: number, reason?: string): void; + + /** + * Abruptly close the connection. + * + * To gracefully close the connection, use `close()`. + */ + terminate(): void; + + /** + * Sends a ping. + * + * @param data The data to send + */ + ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a pong. + * + * @param data The data to send + */ + pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); + */ + publish(topic: string, data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a text message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + */ + publishText(topic: string, data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", new TextEncoder().encode("Hello!")); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); + */ + publishBinary(topic: string, data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Subscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + */ + subscribe(topic: string): void; + + /** + * Unsubscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.unsubscribe("chat"); + */ + unsubscribe(topic: string): void; + + /** + * Is the client subscribed to a topic? + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + * console.log(ws.isSubscribed("chat")); // true + */ + isSubscribed(topic: string): boolean; + + /** + * Batches `send()` and `publish()` operations, which makes it faster to send data. + * + * The `message`, `open`, and `drain` callbacks are automatically corked, so + * you only need to call this if you are sending messages outside of those + * callbacks or in async functions. + * + * @param callback The callback to run. + * @example + * ws.cork((ctx) => { + * ctx.send("These messages"); + * ctx.sendText("are sent"); + * ctx.sendBinary(new TextEncoder().encode("together!")); + * }); + */ + cork(callback: (ws: ServerWebSocket) => T): T; + + /** + * The IP address of the client. + * + * @example + * console.log(socket.remoteAddress); // "127.0.0.1" + */ + readonly remoteAddress: string; + + /** + * The ready state of the client. + * + * - if `0`, the client is connecting. + * - if `1`, the client is connected. + * - if `2`, the client is closing. + * - if `3`, the client is closed. + * + * @example + * console.log(socket.readyState); // 1 + */ + readonly readyState: WebSocketReadyState; + + /** + * Sets how binary data is returned in events. + * + * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** + * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. + * - if `uint8array`, binary data is returned as `Uint8Array` objects. + * + * @example + * let ws: WebSocket; + * ws.binaryType = "uint8array"; + * ws.addEventListener("message", ({ data }) => { + * console.log(data instanceof Uint8Array); // true + * }); + */ + binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; + + /** + * Custom data that you can assign to a client, can be read and written at any time. + * + * @example + * import { serve } from "bun"; + * + * serve({ + * fetch(request, server) { + * const data = { + * accessToken: request.headers.get("Authorization"), + * }; + * if (server.upgrade(request, { data })) { + * return; + * } + * return new Response(); + * }, + * websocket: { + * open(ws) { + * console.log(ws.data.accessToken); + * } + * } + * }); + */ + data: T; + + getBufferedAmount(): number; + } + + /** + * Compression options for WebSocket messages. + */ + type WebSocketCompressor = + | "disable" + | "shared" + | "dedicated" + | "3KB" + | "4KB" + | "8KB" + | "16KB" + | "32KB" + | "64KB" + | "128KB" + | "256KB"; + + /** + * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} + * + * @example + * ```ts + * import { websocket, serve } from "bun"; + * + * serve<{name: string}>({ + * port: 3000, + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log(`${ws.data.name}: ${message}`); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req, { + * data: { + * name: new URL(req.url).searchParams.get("name"), + * }, + * }); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * return; + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + */ + interface WebSocketHandler { + /** + * Called when the server receives an incoming message. + * + * If the message is not a `string`, its type is based on the value of `binaryType`. + * - if `nodebuffer`, then the message is a `Buffer`. + * - if `arraybuffer`, then the message is an `ArrayBuffer`. + * - if `uint8array`, then the message is a `Uint8Array`. + * + * @param ws The websocket that sent the message + * @param message The message received + */ + message(ws: ServerWebSocket, message: string | Buffer): void | Promise; + + /** + * Called when a connection is opened. + * + * @param ws The websocket that was opened + */ + open?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection was previously under backpressure, + * meaning it had too many queued messages, but is now ready to receive more data. + * + * @param ws The websocket that is ready for more data + */ + drain?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection is closed. + * + * @param ws The websocket that was closed + * @param code The close code + * @param message The close message + */ + close?(ws: ServerWebSocket, code: number, reason: string): void | Promise; + + /** + * Called when a ping is sent. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + ping?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Called when a pong is received. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + pong?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Sets the maximum size of messages in bytes. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + maxPayloadLength?: number; + + /** + * Sets the maximum number of bytes that can be buffered on a single connection. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + backpressureLimit?: number; + + /** + * Sets if the connection should be closed if `backpressureLimit` is reached. + * + * Default is `false`. + */ + closeOnBackpressureLimit?: boolean; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to no messages or pings. + * + * Default is 2 minutes, or `120` in seconds. + */ + idleTimeout?: number; + + /** + * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? + * + * Default is `false`. + */ + publishToSelf?: boolean; + + /** + * Should the server automatically send and respond to pings to clients? + * + * Default is `true`. + */ + sendPings?: boolean; + + /** + * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. + * + * Default is `false`. + */ + perMessageDeflate?: + | boolean + | { + /** + * Sets the compression level. + */ + compress?: WebSocketCompressor | boolean; + /** + * Sets the decompression level. + */ + decompress?: WebSocketCompressor | boolean; + }; + } + + namespace RouterTypes { + type ExtractRouteParams = T extends `${string}:${infer Param}/${infer Rest}` + ? { [K in Param]: string } & ExtractRouteParams + : T extends `${string}:${infer Param}` + ? { [K in Param]: string } + : T extends `${string}*` + ? {} + : {}; + + type RouteHandler = (req: BunRequest, server: Server) => Response | Promise; + + type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; + + type RouteHandlerObject = { + [K in HTTPMethod]?: RouteHandler; + }; + + type RouteValue = Response | false | RouteHandler | RouteHandlerObject; + } + + interface BunRequest extends Request { + params: RouterTypes.ExtractRouteParams; + } + + interface GenericServeOptions { + /** + * What URI should be used to make {@link Request.url} absolute? + * + * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one + * + * @example + * ```js + * "http://my-app.com" + * ``` + * + * @example + * ```js + * "https://wongmjane.com/" + * ``` + * + * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. + * + * @example + * "http://localhost:3000" + */ + // baseURI?: string; + + /** + * What is the maximum size of a request body? (in bytes) + * @default 1024 * 1024 * 128 // 128MB + */ + maxRequestBodySize?: number; + + /** + * Render contextual errors? This enables bun's error page + * @default process.env.NODE_ENV !== 'production' + */ + development?: + | boolean + | { + /** + * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) + * + * @default true if process.env.NODE_ENV !== 'production' + * + */ + hmr?: boolean; + }; + + error?: (this: Server, error: ErrorLike) => Response | Promise | undefined | Promise; + + /** + * Uniquely identify a server instance with an ID + * + * ### When bun is started with the `--hot` flag + * + * This string will be used to hot reload the server without interrupting + * pending requests or websockets. If not provided, a value will be + * generated. To disable hot reloading, set this value to `null`. + * + * ### When bun is not started with the `--hot` flag + * + * This string will currently do nothing. But in the future it could be useful for logs or metrics. + */ + id?: string | null; + } + + interface ServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * Whether the `SO_REUSEPORT` flag should be set. + * + * This allows multiple processes to bind to the same port, which is useful for load balancing. + * + * @default false + */ + reusePort?: boolean; + + /** + * Whether the `IPV6_V6ONLY` flag should be set. + * @default false + */ + ipv6Only?: boolean; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix?: never; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to inactivity. + * + * Default is `10` seconds. + */ + idleTimeout?: number; + + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | Promise; + } + + interface UnixServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | Promise; + } + + interface WebSocketServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | void | Promise; + } + + interface UnixWebSocketServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | undefined | Promise; + } + + interface TLSWebSocketServeOptions + extends WebSocketServeOptions, + TLSOptionsAsDeprecated { + unix?: never; + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSWebSocketServeOptions + extends UnixWebSocketServeOptions, + TLSOptionsAsDeprecated { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + tls?: TLSOptions | TLSOptions[]; + } + + interface ErrorLike extends Error { + code?: string; + errno?: number; + syscall?: string; + } + + interface TLSOptions { + /** + * Passphrase for the TLS key + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: string | Buffer | BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: string | Buffer | BunFile | Array | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: string | Buffer | BunFile | Array | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + // Note for contributors: TLSOptionsAsDeprecated should be considered immutable + // and new TLS option keys should only be supported on the `.tls` property (which comes + // from the TLSOptions interface above). + /** + * This exists because Bun.serve() extends the TLSOptions object, but + * they're now considered deprecated. You should be passing the + * options on `.tls` instead. + * + * @example + * ```ts + * //// OLD //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * passphrase: "secret", + * }); + * + * //// NEW //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * tls: { + * passphrase: "secret", + * }, + * }); + * ``` + */ + interface TLSOptionsAsDeprecated { + /** + * Passphrase for the TLS key + * + * @deprecated Use `.tls.passphrase` instead + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + * + * @deprecated Use `.tls.dhParamsFile` instead + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + * + * @deprecated Use `.tls.serverName` instead + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + * + * @deprecated Use `.tls.lowMemoryMode` instead + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + * + * @deprecated Use `.tls.rejectUnauthorized` instead + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + * + * @deprecated Use `.tls.requestCert` instead + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + * + * @deprecated Use `.tls.ca` instead + */ + ca?: string | Buffer | BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + * + * @deprecated Use `.tls.cert` instead + */ + cert?: string | Buffer | BunFile | Array | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + * + * @deprecated Use `.tls.key` instead + */ + key?: string | Buffer | BunFile | Array | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + * + * @deprecated `Use .tls.secureOptions` instead + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSServeOptions extends UnixServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface SocketAddress { + /** + * The IP address of the client. + */ + address: string; + /** + * The port of the client. + */ + port: number; + /** + * The IP family ("IPv4" or "IPv6"). + */ + family: "IPv4" | "IPv6"; + } + + /** + * HTTP & HTTPS Server + * + * To start the server, see {@link serve} + * + * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. + * That means starting a new server allocates about 500 KB of memory. Try to + * avoid starting and stopping the server often (unless it's a new instance of bun). + * + * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. + */ + interface Server extends Disposable { + /** + * Stop listening to prevent new connections from being accepted. + * + * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. + * + * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. + * @default false + */ + stop(closeActiveConnections?: boolean): Promise; + + /** + * Update the `fetch` and `error` handlers without restarting the server. + * + * This is useful if you want to change the behavior of your server without + * restarting it or for hot reloading. + * + * @example + * + * ```js + * // create the server + * const server = Bun.serve({ + * fetch(request) { + * return new Response("Hello World v1") + * } + * }); + * + * // Update the server to return a different response + * server.reload({ + * fetch(request) { + * return new Response("Hello World v2") + * } + * }); + * ``` + * + * Passing other options such as `port` or `hostname` won't do anything. + */ + reload }>( + options: ( + | (Omit & { + routes: R; + fetch?: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | (Omit & { + routes?: never; + fetch: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. + */ + static?: R; + }, + ): Server; + + /** + * Mock the fetch handler for a running server. + * + * This feature is not fully implemented yet. It doesn't normalize URLs + * consistently in all cases and it doesn't yet call the `error` handler + * consistently. This needs to be fixed + */ + fetch(request: Request | string): Response | Promise; + + /** + * Upgrade a {@link Request} to a {@link ServerWebSocket} + * + * @param request The {@link Request} to upgrade + * @param options Pass headers or attach data to the {@link ServerWebSocket} + * + * @returns `true` if the upgrade was successful and `false` if it failed + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * What you pass to `data` is available on the {@link ServerWebSocket.data} property + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + upgrade( + request: Request, + options?: { + /** + * Send any additional headers while upgrading, like cookies + */ + headers?: Bun.HeadersInit; + /** + * This value is passed to the {@link ServerWebSocket.data} property + */ + data?: T; + }, + ): boolean; + + /** + * Send a message to all connected {@link ServerWebSocket} subscribed to a topic + * + * @param topic The topic to publish to + * @param data The data to send + * @param compress Should the data be compressed? Ignored if the client does not support compression. + * + * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. + * + * @example + * + * ```js + * server.publish("chat", "Hello World"); + * ``` + * + * @example + * ```js + * server.publish("chat", new Uint8Array([1, 2, 3, 4])); + * ``` + * + * @example + * ```js + * server.publish("chat", new ArrayBuffer(4), true); + * ``` + * + * @example + * ```js + * server.publish("chat", new DataView(new ArrayBuffer(4))); + * ``` + */ + publish( + topic: string, + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * A count of connections subscribed to a given topic + * + * This operation will loop through each topic internally to get the count. + * + * @param topic the websocket topic to check how many subscribers are connected to + * @returns the number of subscribers + */ + subscriberCount(topic: string): number; + + /** + * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * return new Response(server.requestIP(request)); + * } + * } + * ``` + */ + requestIP(request: Request): SocketAddress | null; + + /** + * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * server.timeout(request, 60); + * await Bun.sleep(30000); + * return new Response("30 seconds have passed"); + * } + * } + * ``` + */ + timeout(request: Request, seconds: number): void; + /** + * Undo a call to {@link Server.unref} + * + * If the Server has already been stopped, this does nothing. + * + * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. + */ + ref(): void; + + /** + * Don't keep the process alive if this server is the only thing left. + * Active connections may continue to keep the process alive. + * + * By default, the server is ref'd. + * + * To prevent new connections from being accepted, use {@link Server.stop} + */ + unref(): void; + + /** + * How many requests are in-flight right now? + */ + readonly pendingRequests: number; + + /** + * How many {@link ServerWebSocket}s are in-flight right now? + */ + readonly pendingWebSockets: number; + + readonly url: URL; + + readonly port: number; + /** + * The hostname the server is listening on. Does not include the port + * @example + * ```js + * "localhost" + * ``` + */ + readonly hostname: string; + /** + * Is the server running in development mode? + * + * In development mode, `Bun.serve()` returns rendered error messages with + * stack traces instead of a generic 500 error. This makes debugging easier, + * but development mode shouldn't be used in production or you will risk + * leaking sensitive information. + */ + readonly development: boolean; + + /** + * An identifier of the server instance + * + * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. + * + * When bun is not started with the `--hot` flag, this ID is currently unused. + */ + readonly id: string; + } + + type Serve = + | ServeOptions + | TLSServeOptions + | UnixServeOptions + | UnixTLSServeOptions + | WebSocketServeOptions + | TLSWebSocketServeOptions + | UnixWebSocketServeOptions + | UnixTLSWebSocketServeOptions; + + /** + Bun.serve provides a high-performance HTTP server with built-in routing support. + It enables both function-based and object-based route handlers with type-safe + parameters and method-specific handling. + + @example Basic Usage + ```ts + Bun.serve({ + port: 3000, + fetch(req) { + return new Response("Hello World"); + } + }); + ``` + + @example Route-based Handlers + ```ts + Bun.serve({ + routes: { + // Static responses + "/": new Response("Home page"), + + // Function handlers with type-safe parameters + "/users/:id": (req) => { + // req.params.id is typed as string + return new Response(`User ${req.params.id}`); + }, + + // Method-specific handlers + "/api/posts": { + GET: () => new Response("Get posts"), + POST: async (req) => { + const body = await req.json(); + return new Response("Created post"); + }, + DELETE: (req) => new Response("Deleted post") + }, + + // Wildcard routes + "/static/*": (req) => { + // Handle any path under /static/ + return new Response("Static file"); + }, + + // Disable route (fall through to fetch handler) + "/api/legacy": false + }, + + // Fallback handler for unmatched routes + fetch(req) { + return new Response("Not Found", { status: 404 }); + } + }); + ``` + + @example Path Parameters + ```ts + Bun.serve({ + routes: { + // Single parameter + "/users/:id": (req: BunRequest<"/users/:id">) => { + return new Response(`User ID: ${req.params.id}`); + }, + + // Multiple parameters + "/posts/:postId/comments/:commentId": ( + req: BunRequest<"/posts/:postId/comments/:commentId"> + ) => { + return new Response(JSON.stringify(req.params)); + // Output: {"postId": "123", "commentId": "456"} + } + } + }); + ``` + + @example Route Precedence + ```ts + // Routes are matched in the following order: + // 1. Exact static routes ("/about") + // 2. Parameter routes ("/users/:id") + // 3. Wildcard routes ("/api/*") + + Bun.serve({ + routes: { + "/api/users": () => new Response("Users list"), + "/api/users/:id": (req) => new Response(`User ${req.params.id}`), + "/api/*": () => new Response("API catchall"), + "/*": () => new Response("Root catchall") + } + }); + ``` + + @example Error Handling + ```ts + Bun.serve({ + routes: { + "/error": () => { + throw new Error("Something went wrong"); + } + }, + error(error) { + // Custom error handler + console.error(error); + return new Response(`Error: ${error.message}`, { + status: 500 + }); + } + }); + ``` + + @example Server Lifecycle + ```ts + const server = Bun.serve({ + // Server config... + }); + + // Update routes at runtime + server.reload({ + routes: { + "/": () => new Response("Updated route") + } + }); + + // Stop the server + server.stop(); + ``` + + @example Development Mode + ```ts + Bun.serve({ + development: true, // Enable hot reloading + routes: { + // Routes will auto-reload on changes + } + }); + ``` + + @example Type-Safe Request Handling + ```ts + type Post = { + id: string; + title: string; + }; + + Bun.serve({ + routes: { + "/api/posts/:id": async ( + req: BunRequest<"/api/posts/:id"> + ) => { + if (req.method === "POST") { + const body: Post = await req.json(); + return Response.json(body); + } + return new Response("Method not allowed", { + status: 405 + }); + } + } + }); + ``` + @param options - Server configuration options + @param options.routes - Route definitions mapping paths to handlers + */ + function serve }>( + options: ( + | (DistributedOmit & { + routes: R; + fetch?: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | (DistributedOmit & { + routes?: never; + fetch: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for a while though. + */ + static?: R; + }, + ): Server; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * - `type` is auto-set based on the file extension when possible + * + * @example + * ```js + * const file = Bun.file("./hello.json"); + * console.log(file.type); // "application/json" + * console.log(await file.json()); // { hello: "world" } + * ``` + * + * @example + * ```js + * await Bun.write( + * Bun.file("./hello.txt"), + * "Hello, world!" + * ); + * ``` + * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: string | URL, options?: BlobPropertyBag): BunFile; + + /** + * A list of files embedded into the standalone executable. Lexigraphically sorted by name. + * + * If the process is not a standalone executable, this returns an empty array. + */ + const embeddedFiles: ReadonlyArray; + + /** + * `Blob` that leverages the fastest system calls available to operate on files. + * + * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. + * + * `Blob.size` will not be valid until the contents of the file are read at least once. + * `Blob.type` will have a default set based on the file extension + * + * @example + * ```js + * const file = Bun.file(new TextEncoder.encode("./hello.json")); + * console.log(file.type); // "application/json" + * ``` + * + * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * + * @example + * ```js + * const file = Bun.file(fd); + * ``` + * + * @param fileDescriptor The file descriptor of the file + */ + // tslint:disable-next-line:unified-signatures + function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; + + /** + * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. + * + * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. + */ + function allocUnsafe(size: number): Uint8Array; + + interface BunInspectOptions { + colors?: boolean; + depth?: number; + sorted?: boolean; + compact?: boolean; + } + + /** + * Pretty-print an object the same as {@link console.log} to a `string` + * + * Supports JSX + * + * @param args + */ + function inspect(arg: any, options?: BunInspectOptions): string; + namespace inspect { + /** + * That can be used to declare custom inspect functions. + */ + const custom: typeof import("util").inspect.custom; + + /** + * Pretty-print an object or array as a table + * + * Like {@link console.table}, except it returns a string + */ + function table(tabularData: object | unknown[], properties?: string[], options?: { colors?: boolean }): string; + function table(tabularData: object | unknown[], options?: { colors?: boolean }): string; + } + + interface MMapOptions { + /** + * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. + */ + sync?: boolean; + /** + * Allow other processes to see results instantly? + * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. + * @default true + */ + shared?: boolean; + } + /** + * Open a file as a live-updating `Uint8Array` without copying memory + * - Writing to the array writes to the file. + * - Reading from the array reads from the file. + * + * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. + * + * --- + * + * This API inherently has some rough edges: + * - It does not support empty files. It will throw a `SystemError` with `EINVAL` + * - Usage on shared/networked filesystems is discouraged. It will be very slow. + * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. + * + * --- + * + * To close the file, set the array to `null` and it will be garbage collected eventually. + */ + function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; + + /** Write to stdout */ + const stdout: BunFile; + /** Write to stderr */ + const stderr: BunFile; + /** + * Read from stdin + * + * This is read-only + */ + const stdin: BunFile; + + type StringLike = string | { toString(): string }; + + type ColorInput = + | { r: number; g: number; b: number; a?: number } + | [number, number, number] + | [number, number, number, number] + | Uint8Array + | Uint8ClampedArray + | Float32Array + | Float64Array + | string + | number + | { toString(): string }; + + function color( + input: ColorInput, + outputFormat?: /** + * True color ANSI color string, for use in terminals + * @example \x1b[38;2;100;200;200m + */ + | "ansi" + | "ansi-16" + | "ansi-16m" + /** + * 256 color ANSI color string, for use in terminals which don't support true color + * + * Tries to match closest 24-bit color to 256 color palette + */ + | "ansi-256" + /** + * Picks the format that produces the shortest output + */ + | "css" + /** + * Lowercase hex color string without alpha + * @example #ff9800 + */ + | "hex" + /** + * Uppercase hex color string without alpha + * @example #FF9800 + */ + | "HEX" + /** + * @example hsl(35.764706, 1, 0.5) + */ + | "hsl" + /** + * @example lab(0.72732764, 33.938198, -25.311619) + */ + | "lab" + /** + * @example 16750592 + */ + | "number" + /** + * RGB color string without alpha + * @example rgb(255, 152, 0) + */ + | "rgb" + /** + * RGB color string with alpha + * @example rgba(255, 152, 0, 1) + */ + | "rgba", + ): string | null; + + function color( + input: ColorInput, + /** + * An array of numbers representing the RGB color + * @example [100, 200, 200] + */ + outputFormat: "[rgb]", + ): [number, number, number] | null; + function color( + input: ColorInput, + /** + * An array of numbers representing the RGBA color + * @example [100, 200, 200, 255] + */ + outputFormat: "[rgba]", + ): [number, number, number, number] | null; + function color( + input: ColorInput, + /** + * An object representing the RGB color + * @example { r: 100, g: 200, b: 200 } + */ + outputFormat: "{rgb}", + ): { r: number; g: number; b: number } | null; + function color( + input: ColorInput, + /** + * An object representing the RGBA color + * @example { r: 100, g: 200, b: 200, a: 0.5 } + */ + outputFormat: "{rgba}", + ): { r: number; g: number; b: number; a: number } | null; + function color(input: ColorInput, outputFormat: "number"): number | null; + + interface Semver { + /** + * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. + */ + satisfies(version: StringLike, range: StringLike): boolean; + + /** + * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. + * Throws an error if either version is invalid. + */ + order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; + } + var semver: Semver; + + interface Unsafe { + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. + * + * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; + + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` + * + * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + // tslint:disable-next-line:unified-signatures + arrayBufferToString(buffer: Uint16Array): string; + + /** Mock bun's segfault handler. You probably don't want to use this */ + segfault(): void; + + /** + * Force the garbage collector to run extremely often, + * especially inside `bun:test`. + * + * - `0`: default, disable + * - `1`: asynchronously call the garbage collector more often + * - `2`: synchronously call the garbage collector more often. + * + * This is a global setting. It's useful for debugging seemingly random crashes. + * + * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. + * + * @param level + * @returns The previous level + */ + gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; + } + const unsafe: Unsafe; + + type DigestEncoding = "utf8" | "ucs2" | "utf16le" | "latin1" | "ascii" | "base64" | "base64url" | "hex"; + + /** + * Are ANSI colors enabled for stdin and stdout? + * + * Used for {@link console.log} + */ + const enableANSIColors: boolean; + + /** + * What script launched bun? + * + * Absolute file path + * + * @example "/never-gonna-give-you-up.js" + */ + const main: string; + + /** + * Manually trigger the garbage collector + * + * This does two things: + * 1. It tells JavaScriptCore to run the garbage collector + * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. + * + * @param force Synchronously run the garbage collector + */ + function gc(force: boolean): void; + + /** + * JavaScriptCore engine's internal heap snapshot + * + * I don't know how to make this something Chrome or Safari can read. + * + * If you have any ideas, please file an issue https://github.com/oven-sh/bun + */ + interface HeapSnapshot { + /** 2 */ + version: number; + + /** "Inspector" */ + type: string; + + nodes: number[]; + + nodeClassNames: string[]; + edges: number[]; + edgeTypes: string[]; + edgeNames: string[]; + } + + /** + * Returns the number of nanoseconds since the process was started. + * + * This function uses a high-resolution monotonic system timer to provide precise time measurements. + * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), + * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). + * + * Due to this limitation, while the internal counter may continue beyond this point, + * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond + * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but + * with reduced precision, which might affect time calculations and comparisons in long-running applications. + * + * @returns {number} The number of nanoseconds since the process was started, with precise values up to + * Number.MAX_SAFE_INTEGER. + */ + function nanoseconds(): number; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector + */ + function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code + * + * This is a JSON string that can be saved to a file. + * ```ts + * const snapshot = Bun.generateHeapSnapshot("v8"); + * await Bun.write("heap.heapsnapshot", snapshot); + * ``` + */ + function generateHeapSnapshot(format: "v8"): string; + + /** + * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. + */ + function shrink(): void; + + /** + * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` + * + * @param path path to open + */ + function openInEditor(path: string, options?: EditorOptions): void; + + var fetch: typeof globalThis.fetch & { + preconnect(url: string): void; + }; + + interface EditorOptions { + editor?: "vscode" | "subl"; + line?: number; + column?: number; + } + + /** + * This class only exists in types + */ + abstract class CryptoHashInterface { + /** + * Update the hash with data + * + * @param data + */ + update(data: Bun.BlobOrStringOrBuffer): T; + + /** + * Finalize the hash + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash(input: Bun.BlobOrStringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash(input: Bun.BlobOrStringOrBuffer, encoding: DigestEncoding): string; + } + + type SupportedCryptoAlgorithms = + | "blake2b256" + | "blake2b512" + | "md4" + | "md5" + | "ripemd160" + | "sha1" + | "sha224" + | "sha256" + | "sha384" + | "sha512" + | "sha512-224" + | "sha512-256" + | "sha3-224" + | "sha3-256" + | "sha3-384" + | "sha3-512" + | "shake128" + | "shake256"; + + /** + * Hardware-accelerated cryptographic hash functions + * + * Used for `crypto.createHash()` + */ + class CryptoHasher { + /** + * The algorithm chosen to hash the data + */ + readonly algorithm: SupportedCryptoAlgorithms; + + /** + * The length of the output hash in bytes + */ + readonly byteLength: number; + + /** + * Create a new hasher + * + * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms + * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. + */ + constructor(algorithm: SupportedCryptoAlgorithms, hmacKey?: string | NodeJS.TypedArray); + + /** + * Update the hash with data + * + * @param input + */ + update(input: Bun.BlobOrStringOrBuffer, inputEncoding?: CryptoEncoding): CryptoHasher; + + /** + * Perform a deep copy of the hasher + */ + copy(): CryptoHasher; + + /** + * Finalize the hash. Resets the CryptoHasher so it can be reused. + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(): Buffer; + digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash(algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer): Buffer; + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + hashInto: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + + /** + * List of supported hash algorithms + * + * These are hardware accelerated with BoringSSL + */ + static readonly algorithms: SupportedCryptoAlgorithms[]; + } + + /** + * Resolve a `Promise` after milliseconds. This is like + * {@link setTimeout} except it returns a `Promise`. + * + * @param ms milliseconds to delay resolving the promise. This is a minimum + * number. It may take longer. If a {@link Date} is passed, it will sleep until the + * {@link Date} is reached. + * + * @example + * ## Sleep for 1 second + * ```ts + * import { sleep } from "bun"; + * + * await sleep(1000); + * ``` + * ## Sleep for 10 milliseconds + * ```ts + * await Bun.sleep(10); + * ``` + * ## Sleep until `Date` + * + * ```ts + * const target = new Date(); + * target.setSeconds(target.getSeconds() + 1); + * await Bun.sleep(target); + * ``` + * Internally, `Bun.sleep` is the equivalent of + * ```ts + * await new Promise((resolve) => setTimeout(resolve, ms)); + * ``` + * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. + */ + function sleep(ms: number | Date): Promise; + + /** + * Sleep the thread for a given number of milliseconds + * + * This is a blocking function. + * + * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) + */ + function sleepSync(ms: number): void; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param encoding `DigestEncoding` to return the hash in + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; + + /** + * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} + * + * Consider using the ugly-named {@link SHA512_256} instead + */ + class SHA1 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 20; + } + class MD5 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class MD4 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class SHA224 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 28; + } + class SHA512 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 64; + } + class SHA384 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 48; + } + class SHA256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + /** + * See also {@link sha} + */ + class SHA512_256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + + /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ + interface ZlibCompressionOptions { + /** + * The compression level to use. Must be between `-1` and `9`. + * - A value of `-1` uses the default compression level (Currently `6`) + * - A value of `0` gives no compression + * - A value of `1` gives least compression, fastest speed + * - A value of `9` gives best compression, slowest speed + */ + level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * How much memory should be allocated for the internal compression state. + * + * A value of `1` uses minimum memory but is slow and reduces compression ratio. + * + * A value of `9` uses maximum memory for optimal speed. The default is `8`. + */ + memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * The base 2 logarithm of the window size (the size of the history buffer). + * + * Larger values of this parameter result in better compression at the expense of memory usage. + * + * The following value ranges are supported: + * - `9..15`: The output will have a zlib header and footer (Deflate) + * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) + * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) + * + * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. + */ + windowBits?: + | -9 + | -10 + | -11 + | -12 + | -13 + | -14 + | -15 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 25 + | 26 + | 27 + | 28 + | 29 + | 30 + | 31; + /** + * Tunes the compression algorithm. + * + * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** + * - `Z_FILTERED`: For data produced by a filter or predictor + * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) + * - `Z_RLE`: Limit match distances to one (run-length encoding) + * - `Z_FIXED` prevents the use of dynamic Huffman codes + * + * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. + * + * `Z_FILTERED` forces more Huffman coding and less string matching, it is + * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. + * Filtered data consists mostly of small values with a somewhat random distribution. + */ + strategy?: number; + + library?: "zlib"; + } + + interface LibdeflateCompressionOptions { + level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; + library?: "libdeflate"; + } + + /** + * Compresses a chunk of data with `zlib` DEFLATE algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function deflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Compresses a chunk of data with `zlib` GZIP algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function gzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` INFLATE algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function inflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` GUNZIP algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function gunzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + + type Target = + /** + * For generating bundles that are intended to be run by the Bun runtime. In many cases, + * it isn't necessary to bundle server-side code; you can directly execute the source code + * without modification. However, bundling your server code can reduce startup times and + * improve running performance. + * + * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which + * indicates to the Bun runtime that there's no need to re-transpile the file before execution. + */ + | "bun" + /** + * The plugin will be applied to Node.js builds + */ + | "node" + /** + * The plugin will be applied to browser builds + */ + | "browser"; + + /** https://bun.sh/docs/bundler/loaders */ + type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "file" | "napi" | "wasm" | "text" | "css" | "html"; + + interface PluginConstraints { + /** + * Only apply the plugin when the import specifier matches this regular expression + * + * @example + * ```ts + * // Only apply the plugin when the import specifier matches the regex + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { + * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; + * }); + * } + * }) + * ``` + */ + filter: RegExp; + + /** + * Only apply the plugin when the import specifier has a namespace matching + * this string + * + * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` + * has the namespace `"bun"`. + * + * The default namespace is `"file"` and it can be omitted from import + * specifiers. + */ + namespace?: string; + } + + interface OnLoadResultSourceCode { + /** + * The source code of the module + */ + contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; + /** + * The loader to use for this file + * + * "css" will be added in a future version of Bun. + */ + loader?: Loader; + } + + interface OnLoadResultObject { + /** + * The object to use as the module + * @example + * ```ts + * // In your loader + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * + * // In your script + * import {foo} from "hello:world"; + * console.log(foo); // "bar" + * ``` + */ + exports: Record; + /** + * The loader to use for this file + */ + loader: "object"; + } + + interface OnLoadArgs { + /** + * The resolved import specifier of the module being loaded + * @example + * ```ts + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * console.log(args.path); // "hello:world" + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * ``` + */ + path: string; + /** + * The namespace of the module being loaded + */ + namespace: string; + /** + * The default loader for this file extension + */ + loader: Loader; + /** + * Defer the execution of this callback until all other modules have been parsed. + * + * @returns Promise which will be resolved when all modules have been parsed + */ + defer: () => Promise; + } + + type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject | undefined | void; + type OnLoadCallback = (args: OnLoadArgs) => OnLoadResult | Promise; + type OnStartCallback = () => void | Promise; + + interface OnResolveArgs { + /** + * The import specifier of the module being loaded + */ + path: string; + /** + * The module that imported the module being resolved + */ + importer: string; + /** + * The namespace of the importer. + */ + namespace: string; + /** + * The directory to perform file-based resolutions in. + */ + resolveDir: string; + /** + * The kind of import this resolve is for. + */ + kind: ImportKind; + // resolveDir: string; + // pluginData: any; + } + + interface OnResolveResult { + /** + * The destination of the import + */ + path: string; + /** + * The namespace of the destination + * It will be concatenated with `path` to form the final import specifier + * @example + * ```ts + * "foo" // "foo:bar" + * ``` + */ + namespace?: string; + external?: boolean; + } + + type OnResolveCallback = ( + args: OnResolveArgs, + ) => OnResolveResult | Promise | undefined | null; + + type FFIFunctionCallable = Function & { + // Making a nominally typed function so that the user must get it from dlopen + readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + + interface PluginBuilder { + /** + * Register a callback which will be invoked when bundling starts. When + * using hot module reloading, this is called at the start of each + * incremental rebuild. + * + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onStart(() => { + * console.log("bundle just started!!") + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onStart(callback: OnStartCallback): this; + onBeforeParse( + constraints: PluginConstraints, + callback: { + napiModule: unknown; + symbol: string; + external?: unknown | undefined; + }, + ): this; + /** + * Register a callback to load imports with a specific import specifier + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; + /** + * Register a callback to resolve imports matching a filter and/or namespace + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onResolve({ filter: /^wat$/ }, (args) => { + * return { path: "/tmp/woah.js" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onResolve(constraints: PluginConstraints, callback: OnResolveCallback): this; + /** + * The config object passed to `Bun.build` as is. Can be mutated. + */ + config: BuildConfig & { plugins: BunPlugin[] }; + + /** + * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules + * + * @param specifier The module specifier to register the callback for + * @param callback The function to run when the module is imported or required + * + * ### Example + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.module("hello:world", () => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * + * // sometime later + * const { foo } = await import("hello:world"); + * console.log(foo); // "bar" + * + * // or + * const { foo } = require("hello:world"); + * console.log(foo); // "bar" + * ``` + * + * @returns `this` for method chaining + */ + module(specifier: string, callback: () => OnLoadResult | Promise): this; + } + + interface BunPlugin { + /** + * Human-readable name of the plugin + * + * In a future version of Bun, this will be used in error messages. + */ + name: string; + + /** + * The target JavaScript environment the plugin should be applied to. + * - `bun`: The default environment when using `bun run` or `bun` to load a script + * - `browser`: The plugin will be applied to browser builds + * - `node`: The plugin will be applied to Node.js builds + * + * If unspecified, it is assumed that the plugin is compatible with all targets. + * + * This field is not read by Bun.plugin + */ + target?: Target; + /** + * A function that will be called when the plugin is loaded. + * + * This function may be called in the same tick that it is registered, or it may be called later. It could potentially be called multiple times for different targets. + */ + setup( + /** + * A builder object that can be used to register plugin hooks + * @example + * ```ts + * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), + * })); + * ``` + */ + build: PluginBuilder, + ): void | Promise; + } + + /** + * Extend Bun's module resolution and loading behavior + * + * Plugins are applied in the order they are defined. + * + * Today, there are two kinds of hooks: + * - `onLoad` lets you return source code or an object that will become the module's exports + * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. + * + * Plugin hooks must define a `filter` RegExp and will only be matched if the + * import specifier contains a "." or a ":". + * + * ES Module resolution semantics mean that plugins may be initialized _after_ + * a module is resolved. You might need to load plugins at the very beginning + * of the application and then use a dynamic import to load the rest of the + * application. A future version of Bun may also support specifying plugins + * via `bunfig.toml`. + * + * @example + * A YAML loader plugin + * + * ```js + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) + * })); + * }); + * + * // You can use require() + * const {foo} = require("./file.yaml"); + * + * // Or import + * await import("./file.yaml"); + * + * ``` + */ + interface BunRegisterPlugin { + (options: T): ReturnType; + + /** + * Deactivate all plugins + * + * This prevents registered plugins from being applied to future builds. + */ + clearAll(): void; + } + + const plugin: BunRegisterPlugin; + + /** + * Is the current global scope the main thread? + */ + const isMainThread: boolean; + + /** + * Used when importing an HTML file at runtime. + * + * @example + * + * ```ts + * import app from "./index.html"; + * ``` + * + * Bun.build support for this isn't imlpemented yet. + */ + interface HTMLBundle { + index: string; + } + + interface Socket extends Disposable { + /** + * Write `data` to the socket + * + * @param data The data to write to the socket + * @param byteOffset The offset in the buffer to start writing from (defaults to 0) + * @param byteLength The number of bytes to write (defaults to the length of the buffer) + * + * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. + * + * This is unbuffered as of Bun v0.2.2. That means individual write() calls + * will be slow. In the future, Bun will buffer writes and flush them at the + * end of the tick, when the event loop is idle, or sooner if the buffer is full. + */ + write(data: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; + + /** + * The data context for the socket. + */ + data: Data; + + /** + * Like {@link Socket.write} except it includes a TCP FIN packet + * + * Use it to send your last message and close the connection. + */ + end(data?: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; + + /** + * Close the socket immediately + */ + end(): void; + + /** + * Keep Bun's process alive at least until this socket is closed + * + * After the socket has closed, the socket is unref'd, the process may exit, + * and this becomes a no-op + */ + ref(): void; + + /** + * Set a timeout until the socket automatically closes. + * + * To reset the timeout, call this function again. + * + * When a timeout happens, the `timeout` callback is called and the socket is closed. + */ + timeout(seconds: number): void; + + /** + * Forcefully close the socket. The other end may not receive all data, and + * the socket will be closed immediately. + * + * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to + * `0` and then calls `close(2)`. + */ + terminate(): void; + + /** + * Shutdown writes to a socket + * + * This makes the socket a half-closed socket. It can still receive data. + * + * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally + */ + shutdown(halfClose?: boolean): void; + + readonly readyState: "open" | "closing" | "closed"; + + /** + * Allow Bun's process to exit even if this socket is still open + * + * After the socket has closed, this function does nothing. + */ + unref(): void; + + /** + * Flush any buffered data to the socket + */ + flush(): void; + + /** + * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. + * + * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. + */ + reload(handler: SocketHandler): void; + + /** + * Get the server that created this socket + * + * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. + */ + readonly listener?: SocketListener; + + /** + * Remote IP address connected to the socket + */ + readonly remoteAddress: string; + + /** + * local port connected to the socket + */ + readonly localPort: number; + + /** + * This property is `true` if the peer certificate was signed by one of the CAs + * specified when creating the `Socket` instance, otherwise `false`. + */ + readonly authorized: boolean; + + /** + * String containing the selected ALPN protocol. + * Before a handshake has completed, this value is always null. + * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. + */ + readonly alpnProtocol: string | false | null; + + /** + * Disables TLS renegotiation for this `Socket` instance. Once called, attempts + * to renegotiate will trigger an `error` handler on the `Socket`. + * + * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) + */ + disableRenegotiation(): void; + + /** + * Keying material is used for validations to prevent different kind of attacks in + * network protocols, for example in the specifications of IEEE 802.1X. + * + * Example + * + * ```js + * const keyingMaterial = socket.exportKeyingMaterial( + * 128, + * 'client finished'); + * + * /* + * Example return value of keyingMaterial: + * + * + * ``` + * + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the [IANA Exporter Label + * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context Optionally provide a context. + * @return requested bytes of the keying material + */ + exportKeyingMaterial(length: number, label: string, context: Buffer): Buffer; + + /** + * Returns the reason why the peer's certificate was not been verified. This + * property is set only when `socket.authorized === false`. + */ + getAuthorizationError(): Error | null; + + /** + * Returns an object representing the local certificate. The returned object has + * some properties corresponding to the fields of the certificate. + * + * If there is no local certificate, an empty object will be returned. If the + * socket has been destroyed, `null` will be returned. + */ + getCertificate(): PeerCertificate | object | null; + getX509Certificate(): X509Certificate | undefined; + + /** + * Returns an object containing information on the negotiated cipher suite. + * + * For example, a TLSv1.2 protocol with AES256-SHA cipher: + * + * ```json + * { + * "name": "AES256-SHA", + * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", + * "version": "SSLv3" + * } + * ``` + * + */ + getCipher(): CipherNameAndProtocol; + + /** + * Returns an object representing the type, name, and size of parameter of + * an ephemeral key exchange in `perfect forward secrecy` on a client + * connection. It returns an empty object when the key exchange is not + * ephemeral. As this is only supported on a client socket; `null` is returned + * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. + * + * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. + */ + getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; + + /** + * Returns an object representing the peer's certificate. If the peer does not + * provide a certificate, an empty object will be returned. If the socket has been + * destroyed, `null` will be returned. + * + * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's + * certificate. + * @return A certificate object. + */ + getPeerCertificate(): PeerCertificate; + getPeerX509Certificate(): X509Certificate; + + /** + * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. + * @since v12.11.0 + * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. + */ + getSharedSigalgs(): string[]; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. + */ + getTLSFinishedMessage(): Buffer | undefined; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so + * far. + */ + getTLSPeerFinishedMessage(): Buffer | undefined; + + /** + * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. + * + * It may be useful for debugging. + * + * See `Session Resumption` for more information. + */ + getTLSTicket(): Buffer | undefined; + + /** + * Returns a string containing the negotiated SSL/TLS protocol version of the + * current connection. The value `'unknown'` will be returned for connected + * sockets that have not completed the handshaking process. The value `null` will + * be returned for server sockets or disconnected client sockets. + * + * Protocol versions are: + * + * * `'SSLv3'` + * * `'TLSv1'` + * * `'TLSv1.1'` + * * `'TLSv1.2'` + * * `'TLSv1.3'` + * + */ + getTLSVersion(): string; + + /** + * See `Session Resumption` for more information. + * @return `true` if the session was reused, `false` otherwise. + */ + isSessionReused(): boolean; + + /** + * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. + * Returns `true` if setting the limit succeeded; `false` otherwise. + * + * Smaller fragment sizes decrease the buffering latency on the client: larger + * fragments are buffered by the TLS layer until the entire fragment is received + * and its integrity is verified; large fragments can span multiple roundtrips + * and their processing can be delayed due to packet loss or reordering. However, + * smaller fragments add extra TLS framing bytes and CPU overhead, which may + * decrease overall server throughput. + * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. + */ + setMaxSendFragment(size: number): boolean; + + /** + * Enable/disable the use of Nagle's algorithm. + * Only available for already connected sockets, will return false otherwise + * @param noDelay Default: `true` + * @returns true if is able to setNoDelay and false if it fails. + */ + setNoDelay(noDelay?: boolean): boolean; + + /** + * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. + * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. + * Only available for already connected sockets, will return false otherwise. + * + * Enabling the keep-alive functionality will set the following socket options: + * SO_KEEPALIVE=1 + * TCP_KEEPIDLE=initialDelay + * TCP_KEEPCNT=10 + * TCP_KEEPINTVL=1 + * @param enable Default: `false` + * @param initialDelay Default: `0` + * @returns true if is able to setNoDelay and false if it fails. + */ + setKeepAlive(enable?: boolean, initialDelay?: number): boolean; + + /** + * The number of bytes written to the socket. + */ + readonly bytesWritten: number; + } + + interface SocketListener extends Disposable { + stop(closeActiveConnections?: boolean): void; + ref(): void; + unref(): void; + reload(options: Pick, "socket">): void; + data: Data; + } + interface TCPSocketListener extends SocketListener { + readonly port: number; + readonly hostname: string; + } + interface UnixSocketListener extends SocketListener { + readonly unix: string; + } + + interface TCPSocket extends Socket {} + interface TLSSocket extends Socket {} + + interface BinaryTypeList { + arraybuffer: ArrayBuffer; + buffer: Buffer; + uint8array: Uint8Array; + // TODO: DataView + // dataview: DataView; + } + type BinaryType = keyof BinaryTypeList; + + interface SocketHandler { + /** + * Is called when the socket connects, or in case of TLS if no handshake is provided + * this will be called only after handshake + * @param socket + */ + open?(socket: Socket): void | Promise; + close?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + data?(socket: Socket, data: BinaryTypeList[DataBinaryType]): void | Promise; + drain?(socket: Socket): void | Promise; + + /** + * When handshake is completed, this functions is called. + * @param socket + * @param success Indicates if the server authorized despite the authorizationError. + * @param authorizationError Certificate Authorization Error or null. + */ + handshake?(socket: Socket, success: boolean, authorizationError: Error | null): void; + + /** + * When the socket has been shutdown from the other end, this function is + * called. This is a TCP FIN packet. + */ + end?(socket: Socket): void | Promise; + + /** + * When the socket fails to be created, this function is called. + * + * The promise returned by `Bun.connect` rejects **after** this function is + * called. + * + * When `connectError` is specified, the rejected promise will not be + * added to the promise rejection queue (so it won't be reported as an + * unhandled promise rejection, since connectError handles it). + * + * When `connectError` is not specified, the rejected promise will be added + * to the promise rejection queue. + */ + connectError?(socket: Socket, error: Error): void | Promise; + + /** + * Called when a message times out. + */ + timeout?(socket: Socket): void | Promise; + /** + * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. + * + * @default "buffer" + * + * @remarks + * This lets you select the desired binary type for the `data` callback. + * It's a small performance optimization to let you avoid creating extra + * ArrayBufferView objects when possible. + * + * Bun originally defaulted to `Uint8Array` but when dealing with network + * data, it's more useful to be able to directly read from the bytes which + * `Buffer` allows. + */ + binaryType?: BinaryType; + } + + interface SocketOptions { + socket: SocketHandler; + data?: Data; + } + // interface TCPSocketOptions extends SocketOptions { + // hostname: string; + // port: number; + // } + + interface TCPSocketListenOptions extends SocketOptions { + hostname: string; + port: number; + tls?: TLSOptions; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface TCPSocketConnectOptions extends SocketOptions { + hostname: string; + port: number; + tls?: boolean; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface UnixSocketOptions extends SocketOptions { + tls?: TLSOptions; + unix: string; + } + + interface FdSocketOptions extends SocketOptions { + tls?: TLSOptions; + fd: number; + } + + /** + * Create a TCP client that connects to a server + * + * @param options The options to use when creating the client + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function connect(options: TCPSocketConnectOptions): Promise>; + function connect(options: UnixSocketOptions): Promise>; + + /** + * Create a TCP server that listens on a port + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function listen(options: TCPSocketListenOptions): TCPSocketListener; + function listen(options: UnixSocketOptions): UnixSocketListener; + + namespace udp { + type Data = string | ArrayBufferView | ArrayBufferLike; + + export interface SocketHandler { + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + } + + export interface ConnectedSocketHandler { + data?( + socket: ConnectedSocket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: ConnectedSocket): void | Promise; + error?(socket: ConnectedSocket, error: Error): void | Promise; + } + + export interface SocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: SocketHandler; + } + + export interface ConnectSocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: ConnectedSocketHandler; + connect: { + hostname: string; + port: number; + }; + } + + export interface BaseUDPSocket { + readonly hostname: string; + readonly port: number; + readonly address: SocketAddress; + readonly binaryType: BinaryType; + readonly closed: boolean; + ref(): void; + unref(): void; + close(): void; + } + + export interface ConnectedSocket extends BaseUDPSocket { + readonly remoteAddress: SocketAddress; + sendMany(packets: readonly Data[]): number; + send(data: Data): boolean; + reload(handler: ConnectedSocketHandler): void; + } + + export interface Socket extends BaseUDPSocket { + sendMany(packets: readonly (Data | string | number)[]): number; + send(data: Data, port: number, address: string): boolean; + reload(handler: SocketHandler): void; + } + } + + /** + * Create a UDP socket + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.hostname The hostname to listen on + * @param options.port The port to listen on + * @param options.binaryType The binary type to use for the socket + * @param options.connect The hostname and port to connect to + */ + export function udpSocket( + options: udp.SocketOptions, + ): Promise>; + export function udpSocket( + options: udp.ConnectSocketOptions, + ): Promise>; + + namespace SpawnOptions { + /** + * Option for stdout/stderr + */ + type Readable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number; + + /** + * Option for stdin + */ + type Writable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number + | ReadableStream + | Blob + | Response + | Request; + + interface OptionsObject< + In extends Writable = Writable, + Out extends Readable = Readable, + Err extends Readable = Readable, + > { + /** + * The current working directory of the process + * + * Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * The environment variables of the process + * + * Defaults to `process.env` as it was when the current Bun process launched. + * + * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. + */ + env?: Record; + + /** + * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. + * This overrides the `stdin`, `stdout`, and `stderr` properties. + * + * For stdin you may pass: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. + * - `number`: The process will read from the file descriptor + * + * For stdout and stdin you may pass: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default ["ignore", "pipe", "inherit"] for `spawn` + * ["ignore", "pipe", "pipe"] for `spawnSync` + */ + stdio?: [In, Out, Err]; + /** + * The file descriptor for the standard input. It may be: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`: The process will read from the buffer + * - `number`: The process will read from the file descriptor + * + * @default "ignore" + */ + stdin?: In; + /** + * The file descriptor for the standard output. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "pipe" + */ + stdout?: Out; + /** + * The file descriptor for the standard error. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "inherit" for `spawn` + * "pipe" for `spawnSync` + */ + stderr?: Err; + + /** + * Callback that runs when the {@link Subprocess} exits + * + * This is called even if the process exits with a non-zero exit code. + * + * Warning: this may run before the `Bun.spawn` function returns. + * + * A simple alternative is `await subprocess.exited`. + * + * @example + * + * ```ts + * const subprocess = spawn({ + * cmd: ["echo", "hello"], + * onExit: (subprocess, code) => { + * console.log(`Process exited with code ${code}`); + * }, + * }); + * ``` + */ + onExit?( + subprocess: Subprocess, + exitCode: number | null, + signalCode: number | null, + /** + * If an error occurred in the call to waitpid2, this will be the error. + */ + error?: ErrorLike, + ): void | Promise; + + /** + * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for + * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized + * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + * + * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, + * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. + * + * Currently, this is only compatible with processes that are other `bun` instances. + */ + ipc?( + message: any, + /** + * The {@link Subprocess} that sent the message + */ + subprocess: Subprocess, + ): void; + + /** + * The serialization format to use for IPC messages. Defaults to `"advanced"`. + * + * To communicate with Node.js processes, use `"json"`. + * + * When `ipc` is not specified, this is ignored. + */ + serialization?: "json" | "advanced"; + + /** + * If true, the subprocess will have a hidden window. + */ + windowsHide?: boolean; + + /** + * If true, no quoting or escaping of arguments is done on Windows. + */ + windowsVerbatimArguments?: boolean; + + /** + * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. + * + * One use-case for this is for applications which wrap other applications or to simulate a symlink. + * + * @default cmds[0] + */ + argv0?: string; + + /** + * An {@link AbortSignal} that can be used to abort the subprocess. + * + * This is useful for aborting a subprocess when some other part of the + * program is aborted, such as a `fetch` response. + * + * Internally, this works by calling `subprocess.kill(1)`. + * + * @example + * ```ts + * const controller = new AbortController(); + * const { signal } = controller; + * const start = performance.now(); + * const subprocess = Bun.spawn({ + * cmd: ["sleep", "100"], + * signal, + * }); + * await Bun.sleep(1); + * controller.abort(); + * await subprocess.exited; + * const end = performance.now(); + * console.log(end - start); // 1ms instead of 101ms + * ``` + */ + signal?: AbortSignal; + } + + type OptionsToSubprocess = + Opts extends OptionsObject + ? Subprocess< + // "Writable extends In" means "if In === Writable", + // aka if true that means the user didn't specify anything + Writable extends In ? "ignore" : In, + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "inherit" : Err + > + : Subprocess; + + type OptionsToSyncSubprocess = + Opts extends OptionsObject + ? SyncSubprocess + : SyncSubprocess; + + type ReadableIO = ReadableStream | number | undefined; + + type ReadableToIO = X extends "pipe" | undefined + ? ReadableStream + : X extends BunFile | ArrayBufferView | number + ? number + : undefined; + + type ReadableToSyncIO = X extends "pipe" | undefined ? Buffer : undefined; + + type WritableIO = FileSink | number | undefined; + + type WritableToIO = X extends "pipe" + ? FileSink + : X extends BunFile | ArrayBufferView | Blob | Request | Response | number + ? number + : undefined; + } + + interface ResourceUsage { + /** + * The number of voluntary and involuntary context switches that the process made. + */ + contextSwitches: { + /** + * Voluntary context switches (context switches that the process initiated). + */ + voluntary: number; + /** + * Involuntary context switches (context switches initiated by the system scheduler). + */ + involuntary: number; + }; + + /** + * The amount of CPU time used by the process, in microseconds. + */ + cpuTime: { + /** + * User CPU time used by the process, in microseconds. + */ + user: number; + /** + * System CPU time used by the process, in microseconds. + */ + system: number; + /** + * Total CPU time used by the process, in microseconds. + */ + total: number; + }; + /** + * The maximum amount of resident set size (in bytes) used by the process during its lifetime. + */ + maxRSS: number; + + /** + * IPC messages sent and received by the process. + */ + messages: { + /** + * The number of IPC messages sent. + */ + sent: number; + /** + * The number of IPC messages received. + */ + received: number; + }; + /** + * The number of IO operations done by the process. + */ + ops: { + /** + * The number of input operations via the file system. + */ + in: number; + /** + * The number of output operations via the file system. + */ + out: number; + }; + /** + * The amount of shared memory that the process used. + */ + shmSize: number; + /** + * The number of signals delivered to the process. + */ + signalCount: number; + /** + * The number of times the process was swapped out of main memory. + */ + swapCount: number; + } + + /** + * A process created by {@link Bun.spawn}. + * + * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSubprocess} (any, pipe, pipe) + * - {@link WritableSubprocess} (pipe, any, any) + * - {@link PipedSubprocess} (pipe, pipe, pipe) + * - {@link NullSubprocess} (ignore, ignore, ignore) + */ + interface Subprocess< + In extends SpawnOptions.Writable = SpawnOptions.Writable, + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > extends AsyncDisposable { + readonly stdin: SpawnOptions.WritableToIO; + readonly stdout: SpawnOptions.ReadableToIO; + readonly stderr: SpawnOptions.ReadableToIO; + + /** + * This returns the same value as {@link Subprocess.stdout} + * + * It exists for compatibility with {@link ReadableStream.pipeThrough} + */ + readonly readable: SpawnOptions.ReadableToIO; + + /** + * The process ID of the child process + * @example + * ```ts + * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); + * console.log(pid); // 1234 + * ``` + */ + readonly pid: number; + /** + * The exit code of the process + * + * The promise will resolve when the process exits + */ + readonly exited: Promise; + + /** + * Synchronously get the exit code of the process + * + * If the process hasn't exited yet, this will return `null` + */ + readonly exitCode: number | null; + + /** + * Synchronously get the signal code of the process + * + * If the process never sent a signal code, this will return `null` + * + * To receive signal code changes, use the `onExit` callback. + * + * If the signal code is unknown, it will return the original signal code + * number, but that case should essentially never happen. + */ + readonly signalCode: NodeJS.Signals | null; + + /** + * Has the process exited? + */ + readonly killed: boolean; + + /** + * Kill the process + * @param exitCode The exitCode to send to the process + */ + kill(exitCode?: number | NodeJS.Signals): void; + + /** + * This method will tell Bun to wait for this process to exit after you already + * called `unref()`. + * + * Before shutting down, Bun will wait for all subprocesses to exit by default + */ + ref(): void; + + /** + * Before shutting down, Bun will wait for all subprocesses to exit by default + * + * This method will tell Bun to not wait for this process to exit before shutting down. + */ + unref(): void; + + /** + * Send a message to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option, and is another instance of `bun`. + * + * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + */ + send(message: any): void; + + /** + * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option. + */ + disconnect(): void; + + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + * + * Only available after the process has exited + * + * If the process hasn't exited yet, this will return `undefined` + */ + resourceUsage(): ResourceUsage | undefined; + } + + /** + * A process created by {@link Bun.spawnSync}. + * + * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSyncSubprocess} (pipe, pipe) + * - {@link NullSyncSubprocess} (ignore, ignore) + */ + interface SyncSubprocess< + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > { + stdout: SpawnOptions.ReadableToSyncIO; + stderr: SpawnOptions.ReadableToSyncIO; + exitCode: number; + success: boolean; + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + */ + resourceUsage: ResourceUsage; + + signalCode?: string; + } + + /** + * Spawn a new process + * + * ```js + * const subprocess = Bun.spawn({ + * cmd: ["echo", "hello"], + * stdout: "pipe", + * }); + * const text = await readableStreamToText(subprocess.stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmd: string[]; // to support dynamically constructed commands + }, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawn(["echo", "hello"]); + * const text = await readableStreamToText(stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync({ + * cmd: ["echo", "hello"], + * }); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); + * ``` + */ + cmd: string[]; + + onExit?: never; + }, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** + * Synchronously spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync(["echo", "hello"]); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ + type ReadableSubprocess = Subprocess; + /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ + type WritableSubprocess = Subprocess<"pipe", any, any>; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ + type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ + type NullSubprocess = Subprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ + type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ + type NullSyncSubprocess = SyncSubprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + + // Blocked on https://github.com/oven-sh/bun/issues/8329 + // /** + // * + // * Count the visible width of a string, as it would be displayed in a terminal. + // * + // * By default, strips ANSI escape codes before measuring the string. This is + // * because ANSI escape codes are not visible characters. If passed a non-string, + // * it will return 0. + // * + // * @param str The string to measure + // * @param options + // */ + // function stringWidth( + // str: string, + // options?: { + // /** + // * Whether to include ANSI escape codes in the width calculation + // * + // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. + // * @default false + // */ + // countAnsiEscapeCodes?: boolean; + // }, + // ): number; + + class FileSystemRouter { + /** + * Create a new {@link FileSystemRouter}. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: process.cwd() + "/pages", + * style: "nextjs", + * }); + * + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} + * ``` + * @param options The options to use when creating the router + * @param options.dir The root directory containing the files to route + * @param options.style The style of router to use (only "nextjs" supported + * for now) + */ + constructor(options: { + /** + * The root directory containing the files to route + * + * There is no default value for this option. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: + */ + dir: string; + style: "nextjs"; + + /** The base path to use when routing */ + assetPrefix?: string; + origin?: string; + /** Limit the pages to those with particular file extensions. */ + fileExtensions?: string[]; + }); + + // todo: URL + match(input: string | Request | Response): MatchedRoute | null; + + readonly assetPrefix: string; + readonly origin: string; + readonly style: string; + readonly routes: Record; + + reload(): void; + } + + interface MatchedRoute { + /** + * A map of the parameters from the route + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: "/path/to/files", + * style: "nextjs", + * }); + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params.year); // "2020" + * console.log(params.month); // "01" + * console.log(params.day); // "01" + * console.log(params.slug); // "hello-world" + * ``` + */ + readonly params: Record; + readonly filePath: string; + readonly pathname: string; + readonly query: Record; + readonly name: string; + readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; + readonly src: string; + } + + /** + * The current version of Bun + * @example + * "0.2.0" + */ + const version: string; + + /** + * The current version of Bun with the shortened commit sha of the build + * @example "v1.1.30 (d09df1af)" + */ + const version_with_sha: string; + + /** + * The git sha at the time the currently-running version of Bun was compiled + * @example + * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" + */ + const revision: string; + + /** + * Find the index of a newline character in potentially ill-formed UTF-8 text. + * + * This is sort of like readline() except without the IO. + */ + function indexOfLine(buffer: ArrayBufferView | ArrayBufferLike, offset?: number): number; + + interface GlobScanOptions { + /** + * The root directory to start matching from. Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * Allow patterns to match entries that begin with a period (`.`). + * + * @default false + */ + dot?: boolean; + + /** + * Return the absolute path for entries. + * + * @default false + */ + absolute?: boolean; + + /** + * Indicates whether to traverse descendants of symbolic link directories. + * + * @default false + */ + followSymlinks?: boolean; + + /** + * Throw an error when symbolic link is broken + * + * @default false + */ + throwErrorOnBrokenSymlink?: boolean; + + /** + * Return only files. + * + * @default true + */ + onlyFiles?: boolean; + } + + /** + * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). + * + * The supported pattern syntax for is: + * + * - `?` + * Matches any single character. + * - `*` + * Matches zero or more characters, except for path separators ('/' or '\'). + * - `**` + * Matches zero or more characters, including path separators. + * Must match a complete path segment, i.e. followed by a path separator or + * at the end of the pattern. + * - `[ab]` + * Matches one of the characters contained in the brackets. + * Character ranges (e.g. "[a-z]") are also supported. + * Use "[!ab]" or "[^ab]" to match any character *except* those contained + * in the brackets. + * - `{a,b}` + * Match one of the patterns contained in the braces. + * Any of the wildcards listed above can be used in the sub patterns. + * Braces may be nested up to 10 levels deep. + * - `!` + * Negates the result when at the start of the pattern. + * Multiple "!" characters negate the pattern multiple times. + * - `\` + * Used to escape any of the special characters above. + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + */ + export class Glob { + constructor(pattern: string); + + /** + * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for await (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scan(optionsOrCwd?: string | GlobScanOptions): AsyncIterableIterator; + + /** + * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; + + /** + * Match the glob against a string + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * expect(glob.match('foo.ts')).toBeTrue(); + * ``` + */ + match(str: string): boolean; + } + + /** + * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. + * + * When the same timestamp is used multiple times, a monotonically increasing + * counter is appended to allow sorting. The final 8 bytes are + * cryptographically random. When the timestamp changes, the counter resets to + * a psuedo-random integer. + * + * @param encoding "hex" | "base64" | "base64url" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + * + * @example + * ```js + * import { randomUUIDv7 } from "bun"; + * const array = [ + * randomUUIDv7(), + * randomUUIDv7(), + * randomUUIDv7(), + * ] + * [ + * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", + * "0192ce07-8c4f-7d67-805f-0f71581b5622", + * "0192ce07-8c4f-7d68-8170-6816e4451a58" + * ] + * ``` + */ + function randomUUIDv7( + /** + * @default "hex" + */ + encoding?: "hex" | "base64" | "base64url", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): string; + + /** + * Generate a UUIDv7 as a Buffer + * + * @param encoding "buffer" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + */ + function randomUUIDv7( + encoding: "buffer", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): Buffer; + + /** + * Types for `bun.lock` + */ + type BunLockFile = { + lockfileVersion: 0 | 1; + workspaces: { + [workspace: string]: BunLockFileWorkspacePackage; + }; + overrides?: Record; + patchedDependencies?: Record; + trustedDependencies?: string[]; + + /** + * ``` + * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } + * + * // first index is resolution for each type of package + * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] + * symlink -> [ "name@link:path", INFO ] + * folder -> [ "name@file:path", INFO ] + * workspace -> [ "name@workspace:path" ] // workspace is only path + * tarball -> [ "name@tarball", INFO ] + * root -> [ "name@root:", { bin, binDir } ] + * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] + * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] + * ``` + * */ + packages: { + [pkg: string]: BunLockFilePackageArray; + }; + }; + + type BunLockFileBasePackageInfo = { + dependencies?: Record; + devDependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; + optionalPeers?: string[]; + bin?: string | Record; + binDir?: string; + }; + + type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { + name?: string; + version?: string; + }; + + type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { + os?: string | string[]; + cpu?: string | string[]; + bundled?: true; + }; + + /** @see {@link BunLockFile.packages} for more info */ + type BunLockFilePackageArray = + /** npm */ + | [pkg: string, registry: string, info: BunLockFilePackageInfo, integrity: string] + /** symlink, folder, tarball */ + | [pkg: string, info: BunLockFilePackageInfo] + /** workspace */ + | [pkg: string] + /** git, github */ + | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] + /** root */ + | [pkg: string, info: Pick]; } diff --git a/packages/bun-types/deprecated.d.ts b/packages/bun-types/deprecated.d.ts index 3eb174db4ded5a..5a90164689ded8 100644 --- a/packages/bun-types/deprecated.d.ts +++ b/packages/bun-types/deprecated.d.ts @@ -1,71 +1,66 @@ declare module "bun" { - /** - * @deprecated Renamed to `ErrorLike` - */ - type Errorlike = ErrorLike; - interface TLSOptions { - /** - * File path to a TLS key - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. - */ - keyFile?: string; - /** - * File path to a TLS certificate - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. - */ - certFile?: string; - /** - * File path to a .pem file for a custom root CA - * - * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. - */ - caFile?: string; - } + /** + * @deprecated Renamed to `ErrorLike` + */ + type Errorlike = ErrorLike; + interface TLSOptions { + /** + * File path to a TLS key + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. + */ + keyFile?: string; + /** + * File path to a TLS certificate + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. + */ + certFile?: string; + /** + * File path to a .pem file for a custom root CA + * + * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. + */ + caFile?: string; + } } declare namespace NodeJS { - interface Process { - /** - * @deprecated This is deprecated; use the "node:assert" module instead. - */ - assert(value: unknown, message?: string | Error): asserts value; - } + interface Process { + /** + * @deprecated This is deprecated; use the "node:assert" module instead. + */ + assert(value: unknown, message?: string | Error): asserts value; + } } declare namespace Bun { - interface MessageEvent { - /** @deprecated */ - initMessageEvent( - type: string, - bubbles?: boolean, - cancelable?: boolean, - data?: any, - origin?: string, - lastEventId?: string, - source?: null, - ): void; - } + interface MessageEvent { + /** @deprecated */ + initMessageEvent( + type: string, + bubbles?: boolean, + cancelable?: boolean, + data?: any, + origin?: string, + lastEventId?: string, + source?: null, + ): void; + } } interface CustomEvent { - /** @deprecated */ - initCustomEvent( - type: string, - bubbles?: boolean, - cancelable?: boolean, - detail?: T, - ): void; + /** @deprecated */ + initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void; } interface DOMException { - /** @deprecated */ - readonly code: number; + /** @deprecated */ + readonly code: number; } /** diff --git a/packages/bun-types/devserver.d.ts b/packages/bun-types/devserver.d.ts index e6b44c040f7127..a6ff7d1437b34b 100644 --- a/packages/bun-types/devserver.d.ts +++ b/packages/bun-types/devserver.d.ts @@ -1,24 +1,24 @@ export {}; declare global { - interface ImportMeta { - /** - * Hot module replacement - * - * https://bun.sh/docs/bundler/fullstack - */ - hot: { - /** - * import.meta.hot.data maintains state between module instances during hot replacement, enabling data transfer from previous to new versions. - * - * @example - * ```ts - * import.meta.hot.data = { - * bun: 'is cool', - * }; - * ``` - */ - data: any; - }; - } + interface ImportMeta { + /** + * Hot module replacement + * + * https://bun.sh/docs/bundler/fullstack + */ + hot: { + /** + * import.meta.hot.data maintains state between module instances during hot replacement, enabling data transfer from previous to new versions. + * + * @example + * ```ts + * import.meta.hot.data = { + * bun: 'is cool', + * }; + * ``` + */ + data: any; + }; + } } diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 599ffa198190b9..58e138bbad8c93 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,119 +1,114 @@ interface Headers { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; } var Headers: { - prototype: Headers; - new (init?: Bun.HeadersInit): Headers; + prototype: Headers; + new (init?: Bun.HeadersInit): Headers; }; interface Request { - headers: Headers; + headers: Headers; } var Request: { - prototype: Request; - new (requestInfo: string, requestInit?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, requestInit?: RequestInit): Request; + prototype: Request; + new (requestInfo: string, requestInit?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, requestInit?: RequestInit): Request; }; var Response: { - new ( - body?: Bun.BodyInit | null | undefined, - init?: Bun.ResponseInit | undefined, - ): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: Bun.ResponseInit | number): Response; + new (body?: Bun.BodyInit | null | undefined, init?: Bun.ResponseInit | undefined): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, options?: Bun.ResponseInit | number): Response; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, status?: number): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, status?: number): Response; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, options?: Bun.ResponseInit): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, options?: Bun.ResponseInit): Response; - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; }; type _BunTLSOptions = import("bun").TLSOptions; interface BunFetchRequestInitTLS extends _BunTLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable< - import("node:tls").ConnectionOptions["checkServerIdentity"] - >; + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable; } /** @@ -124,46 +119,43 @@ interface BunFetchRequestInitTLS extends _BunTLSOptions { * if passed to `new Request()`. This is why it's a separate type. */ interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; + /** + * Override the default TLS options + */ + tls?: BunFetchRequestInitTLS; } var fetch: { - /** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ - (request: Request, init?: BunFetchRequestInit): Promise; + /** + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ + (request: Request, init?: BunFetchRequestInit): Promise; - /** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ - (url: string | URL | Request, init?: BunFetchRequestInit): Promise; + /** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ + (url: string | URL | Request, init?: BunFetchRequestInit): Promise; - ( - input: string | URL | globalThis.Request, - init?: BunFetchRequestInit, - ): Promise; + (input: string | URL | globalThis.Request, init?: BunFetchRequestInit): Promise; - /** - * Start the DNS resolution, TCP connection, and TLS handshake for a request - * before the request is actually sent. - * - * This can reduce the latency of a request when you know there's some - * long-running task that will delay the request starting. - * - * This is a bun-specific API and is not part of the Fetch API specification. - */ - preconnect(url: string | URL): void; + /** + * Start the DNS resolution, TCP connection, and TLS handshake for a request + * before the request is actually sent. + * + * This can reduce the latency of a request when you know there's some + * long-running task that will delay the request starting. + * + * This is a bun-specific API and is not part of the Fetch API specification. + */ + preconnect(url: string | URL): void; }; diff --git a/packages/bun-types/ffi.d.ts b/packages/bun-types/ffi.d.ts index c705348c8298bf..1f0c1ffdfe8b78 100644 --- a/packages/bun-types/ffi.d.ts +++ b/packages/bun-types/ffi.d.ts @@ -15,1162 +15,1144 @@ * goes to Fabrice Bellard and TinyCC maintainers for making this possible. */ declare module "bun:ffi" { - enum FFIType { - char = 0, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int8_t = 1, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i8 = 1, + enum FFIType { + char = 0, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int8_t = 1, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i8 = 1, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint8_t = 2, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u8 = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint8_t = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u8 = 2, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int16_t = 3, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i16 = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int16_t = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i16 = 3, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint16_t = 4, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u16 = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint16_t = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u16 = 4, - /** - * 32-bit signed integer - */ - int32_t = 5, + /** + * 32-bit signed integer + */ + int32_t = 5, - /** - * 32-bit signed integer - * - * Alias of {@link FFIType.int32_t} - */ - i32 = 5, - /** - * 32-bit signed integer - * - * The same as `int` in C - * - * ```c - * int - * ``` - */ - int = 5, + /** + * 32-bit signed integer + * + * Alias of {@link FFIType.int32_t} + */ + i32 = 5, + /** + * 32-bit signed integer + * + * The same as `int` in C + * + * ```c + * int + * ``` + */ + int = 5, - /** - * 32-bit unsigned integer - * - * The same as `unsigned int` in C (on x64 & arm64) - * - * C: - * ```c - * unsigned int - * ``` - * JavaScript: - * ```js - * ptr(new Uint32Array(1)) - * ``` - */ - uint32_t = 6, - /** - * 32-bit unsigned integer - * - * Alias of {@link FFIType.uint32_t} - */ - u32 = 6, + /** + * 32-bit unsigned integer + * + * The same as `unsigned int` in C (on x64 & arm64) + * + * C: + * ```c + * unsigned int + * ``` + * JavaScript: + * ```js + * ptr(new Uint32Array(1)) + * ``` + */ + uint32_t = 6, + /** + * 32-bit unsigned integer + * + * Alias of {@link FFIType.uint32_t} + */ + u32 = 6, - /** - * int64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - int64_t = 7, - /** - * i64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - i64 = 7, + /** + * int64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + int64_t = 7, + /** + * i64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + i64 = 7, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - uint64_t = 8, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - u64 = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + uint64_t = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + u64 = 8, - /** - * Doubles are not supported yet! - */ - double = 9, - /** - * Doubles are not supported yet! - */ - f64 = 9, - /** - * Floats are not supported yet! - */ - float = 10, - /** - * Floats are not supported yet! - */ - f32 = 10, + /** + * Doubles are not supported yet! + */ + double = 9, + /** + * Doubles are not supported yet! + */ + f64 = 9, + /** + * Floats are not supported yet! + */ + float = 10, + /** + * Floats are not supported yet! + */ + f32 = 10, - /** - * Boolean value - * - * Must be `true` or `false`. `0` and `1` type coercion is not supported. - * - * In C, this corresponds to: - * ```c - * bool - * _Bool - * ``` - */ - bool = 11, + /** + * Boolean value + * + * Must be `true` or `false`. `0` and `1` type coercion is not supported. + * + * In C, this corresponds to: + * ```c + * bool + * _Bool + * ``` + */ + bool = 11, - /** - * Pointer value - * - * See {@link Bun.FFI.ptr} for more information - * - * In C: - * ```c - * void* - * ``` - * - * In JavaScript: - * ```js - * ptr(new Uint8Array(1)) - * ``` - */ - ptr = 12, - /** - * Pointer value - * - * alias of {@link FFIType.ptr} - */ - pointer = 12, + /** + * Pointer value + * + * See {@link Bun.FFI.ptr} for more information + * + * In C: + * ```c + * void* + * ``` + * + * In JavaScript: + * ```js + * ptr(new Uint8Array(1)) + * ``` + */ + ptr = 12, + /** + * Pointer value + * + * alias of {@link FFIType.ptr} + */ + pointer = 12, - /** - * void value - * - * void arguments are not supported - * - * void return type is the default return type - * - * In C: - * ```c - * void - * ``` - */ - void = 13, + /** + * void value + * + * void arguments are not supported + * + * void return type is the default return type + * + * In C: + * ```c + * void + * ``` + */ + void = 13, - /** - * When used as a `returns`, this will automatically become a {@link CString}. - * - * When used in `args` it is equivalent to {@link FFIType.pointer} - */ - cstring = 14, + /** + * When used as a `returns`, this will automatically become a {@link CString}. + * + * When used in `args` it is equivalent to {@link FFIType.pointer} + */ + cstring = 14, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `int64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - i64_fast = 15, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `int64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + i64_fast = 15, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `uint64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - u64_fast = 16, - function = 17, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `uint64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + u64_fast = 16, + function = 17, - napi_env = 18, - napi_value = 19, - buffer = 20, - } + napi_env = 18, + napi_value = 19, + buffer = 20, + } - type Pointer = number & { __pointer__: null }; + type Pointer = number & { __pointer__: null }; - interface FFITypeToArgsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: number | bigint; - [FFIType.i64]: number | bigint; - [FFIType.uint64_t]: number | bigint; - [FFIType.u64]: number | bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.void]: undefined; - [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | JSCallback; // cannot be null - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeToReturnsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: bigint; - [FFIType.i64]: bigint; - [FFIType.uint64_t]: bigint; - [FFIType.u64]: bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: Pointer | null; - [FFIType.pointer]: Pointer | null; - [FFIType.void]: undefined; - [FFIType.cstring]: CString; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | null; - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeStringToType { - ["char"]: FFIType.char; - ["int8_t"]: FFIType.int8_t; - ["i8"]: FFIType.i8; - ["uint8_t"]: FFIType.uint8_t; - ["u8"]: FFIType.u8; - ["int16_t"]: FFIType.int16_t; - ["i16"]: FFIType.i16; - ["uint16_t"]: FFIType.uint16_t; - ["u16"]: FFIType.u16; - ["int32_t"]: FFIType.int32_t; - ["i32"]: FFIType.i32; - ["int"]: FFIType.int; - ["uint32_t"]: FFIType.uint32_t; - ["u32"]: FFIType.u32; - ["int64_t"]: FFIType.int64_t; - ["i64"]: FFIType.i64; - ["uint64_t"]: FFIType.uint64_t; - ["u64"]: FFIType.u64; - ["double"]: FFIType.double; - ["f64"]: FFIType.f64; - ["float"]: FFIType.float; - ["f32"]: FFIType.f32; - ["bool"]: FFIType.bool; - ["ptr"]: FFIType.ptr; - ["pointer"]: FFIType.pointer; - ["void"]: FFIType.void; - ["cstring"]: FFIType.cstring; - ["function"]: FFIType.pointer; // for now - ["usize"]: FFIType.uint64_t; // for now - ["callback"]: FFIType.pointer; // for now - ["napi_env"]: FFIType.napi_env; - ["napi_value"]: FFIType.napi_value; - ["buffer"]: FFIType.buffer; - } + interface FFITypeToArgsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: number | bigint; + [FFIType.i64]: number | bigint; + [FFIType.uint64_t]: number | bigint; + [FFIType.u64]: number | bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.void]: undefined; + [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | JSCallback; // cannot be null + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeToReturnsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: bigint; + [FFIType.i64]: bigint; + [FFIType.uint64_t]: bigint; + [FFIType.u64]: bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: Pointer | null; + [FFIType.pointer]: Pointer | null; + [FFIType.void]: undefined; + [FFIType.cstring]: CString; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | null; + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeStringToType { + ["char"]: FFIType.char; + ["int8_t"]: FFIType.int8_t; + ["i8"]: FFIType.i8; + ["uint8_t"]: FFIType.uint8_t; + ["u8"]: FFIType.u8; + ["int16_t"]: FFIType.int16_t; + ["i16"]: FFIType.i16; + ["uint16_t"]: FFIType.uint16_t; + ["u16"]: FFIType.u16; + ["int32_t"]: FFIType.int32_t; + ["i32"]: FFIType.i32; + ["int"]: FFIType.int; + ["uint32_t"]: FFIType.uint32_t; + ["u32"]: FFIType.u32; + ["int64_t"]: FFIType.int64_t; + ["i64"]: FFIType.i64; + ["uint64_t"]: FFIType.uint64_t; + ["u64"]: FFIType.u64; + ["double"]: FFIType.double; + ["f64"]: FFIType.f64; + ["float"]: FFIType.float; + ["f32"]: FFIType.f32; + ["bool"]: FFIType.bool; + ["ptr"]: FFIType.ptr; + ["pointer"]: FFIType.pointer; + ["void"]: FFIType.void; + ["cstring"]: FFIType.cstring; + ["function"]: FFIType.pointer; // for now + ["usize"]: FFIType.uint64_t; // for now + ["callback"]: FFIType.pointer; // for now + ["napi_env"]: FFIType.napi_env; + ["napi_value"]: FFIType.napi_value; + ["buffer"]: FFIType.buffer; + } - type FFITypeOrString = FFIType | keyof FFITypeStringToType; + type FFITypeOrString = FFIType | keyof FFITypeStringToType; - interface FFIFunction { - /** - * Arguments to a FFI function (C ABI) - * - * Defaults to an empty array, which means no arguments. - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, FFIType, suffix } from "bun:ffi" - * - * const lib = dlopen(`adder.${suffix}`, { - * add: { - * // FFIType can be used or you can pass string labels. - * args: [FFIType.i32, "i32"], - * returns: "i32", - * }, - * }) - * lib.symbols.add(1, 2) - * ``` - * In C: - * ```c - * int add(int a, int b) { - * return a + b; - * } - * ``` - */ - readonly args?: readonly FFITypeOrString[]; - /** - * Return type to a FFI function (C ABI) - * - * Defaults to {@link FFIType.void} - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, CString } from "bun:ffi" - * - * const lib = dlopen('z', { - * version: { - * returns: "ptr", - * } - * }); - * console.log(new CString(lib.symbols.version())); - * ``` - * In C: - * ```c - * char* version() - * { - * return "1.0.0"; - * } - * ``` - */ - readonly returns?: FFITypeOrString; + interface FFIFunction { + /** + * Arguments to a FFI function (C ABI) + * + * Defaults to an empty array, which means no arguments. + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, FFIType, suffix } from "bun:ffi" + * + * const lib = dlopen(`adder.${suffix}`, { + * add: { + * // FFIType can be used or you can pass string labels. + * args: [FFIType.i32, "i32"], + * returns: "i32", + * }, + * }) + * lib.symbols.add(1, 2) + * ``` + * In C: + * ```c + * int add(int a, int b) { + * return a + b; + * } + * ``` + */ + readonly args?: readonly FFITypeOrString[]; + /** + * Return type to a FFI function (C ABI) + * + * Defaults to {@link FFIType.void} + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, CString } from "bun:ffi" + * + * const lib = dlopen('z', { + * version: { + * returns: "ptr", + * } + * }); + * console.log(new CString(lib.symbols.version())); + * ``` + * In C: + * ```c + * char* version() + * { + * return "1.0.0"; + * } + * ``` + */ + readonly returns?: FFITypeOrString; - /** - * Function pointer to the native function - * - * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. - * This pointer should not be null (0). - * - * This is useful if the library has already been loaded - * or if the module is also using Node-API. - */ - readonly ptr?: Pointer | bigint; + /** + * Function pointer to the native function + * + * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. + * This pointer should not be null (0). + * + * This is useful if the library has already been loaded + * or if the module is also using Node-API. + */ + readonly ptr?: Pointer | bigint; - /** - * Can C/FFI code call this function from a separate thread? - * - * Only supported with {@link JSCallback}. - * - * This does not make the function run in a separate thread. It is still up to the application/library - * to run their code in a separate thread. - * - * By default, {@link JSCallback} calls are not thread-safe. Turning this on - * incurs a small performance penalty for every function call. That small - * performance penalty needs to be less than the performance gain from - * running the function in a separate thread. - * - * @default false - */ - readonly threadsafe?: boolean; - } + /** + * Can C/FFI code call this function from a separate thread? + * + * Only supported with {@link JSCallback}. + * + * This does not make the function run in a separate thread. It is still up to the application/library + * to run their code in a separate thread. + * + * By default, {@link JSCallback} calls are not thread-safe. Turning this on + * incurs a small performance penalty for every function call. That small + * performance penalty needs to be less than the performance gain from + * running the function in a separate thread. + * + * @default false + */ + readonly threadsafe?: boolean; + } - type Symbols = Readonly>; + type Symbols = Readonly>; - // /** - // * Compile a callback function - // * - // * Returns a function pointer - // * - // */ - // export function callback(ffi: FFIFunction, cb: Function): number; + // /** + // * Compile a callback function + // * + // * Returns a function pointer + // * + // */ + // export function callback(ffi: FFIFunction, cb: Function): number; - interface Library { - symbols: ConvertFns; + interface Library { + symbols: ConvertFns; - /** - * `dlclose` the library, unloading the symbols and freeing allocated memory. - * - * Once called, the library is no longer usable. - * - * Calling a function from a library that has been closed is undefined behavior. - */ - close(): void; - } + /** + * `dlclose` the library, unloading the symbols and freeing allocated memory. + * + * Once called, the library is no longer usable. + * + * Calling a function from a library that has been closed is undefined behavior. + */ + close(): void; + } - type ToFFIType = T extends FFIType - ? T - : T extends string - ? FFITypeStringToType[T] - : never; + type ToFFIType = T extends FFIType ? T : T extends string ? FFITypeStringToType[T] : never; - const FFIFunctionCallableSymbol: unique symbol; - type ConvertFns = { - [K in keyof Fns]: { - ( - ...args: Fns[K]["args"] extends infer A extends - readonly FFITypeOrString[] - ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } - : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [unknown] extends [Fns[K]["args"]] - ? [] - : never - ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - ? undefined - : FFITypeToReturnsType[ToFFIType>]; - __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - }; + const FFIFunctionCallableSymbol: unique symbol; + type ConvertFns = { + [K in keyof Fns]: { + ( + ...args: Fns[K]["args"] extends infer A extends readonly FFITypeOrString[] + ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } + : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [unknown] extends [Fns[K]["args"]] + ? [] + : never + ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + ? undefined + : FFITypeToReturnsType[ToFFIType>]; + __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + }; - /** - * Open a library using `"bun:ffi"` - * - * @param name The name of the library or file path. This will be passed to `dlopen()` - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import {dlopen} from 'bun:ffi'; - * - * const lib = dlopen("duckdb.dylib", { - * get_version: { - * returns: "cstring", - * args: [], - * }, - * }); - * lib.symbols.get_version(); - * // "1.0.0" - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function dlopen>( - name: string | import("bun").BunFile | URL, - symbols: Fns, - ): Library; + /** + * Open a library using `"bun:ffi"` + * + * @param name The name of the library or file path. This will be passed to `dlopen()` + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import {dlopen} from 'bun:ffi'; + * + * const lib = dlopen("duckdb.dylib", { + * get_version: { + * returns: "cstring", + * args: [], + * }, + * }); + * lib.symbols.get_version(); + * // "1.0.0" + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function dlopen>( + name: string | import("bun").BunFile | URL, + symbols: Fns, + ): Library; - /** - * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. - * - * @param options - * @returns Library - * - * @example - * ## Hello, World! - * - * JavaScript: - * ```js - * import { cc } from "bun:ffi"; - * import hello from "./hello.c" with {type: "file"}; - * const {symbols: {hello}} = cc({ - * source: hello, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * // "Hello, World!" - * console.log(hello()); - * ``` - * - * `./hello.c`: - * ```c - * #include - * const char* hello() { - * return "Hello, World!"; - * } - * ``` - */ - function cc>(options: { - /** - * File path to an ISO C11 source file to compile and link - */ - source: string | import("bun").BunFile | URL; + /** + * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. + * + * @param options + * @returns Library + * + * @example + * ## Hello, World! + * + * JavaScript: + * ```js + * import { cc } from "bun:ffi"; + * import hello from "./hello.c" with {type: "file"}; + * const {symbols: {hello}} = cc({ + * source: hello, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * // "Hello, World!" + * console.log(hello()); + * ``` + * + * `./hello.c`: + * ```c + * #include + * const char* hello() { + * return "Hello, World!"; + * } + * ``` + */ + function cc>(options: { + /** + * File path to an ISO C11 source file to compile and link + */ + source: string | import("bun").BunFile | URL; - /** - * Library names to link against - * - * Equivalent to `-l` option in gcc/clang. - */ - library?: string[] | string; + /** + * Library names to link against + * + * Equivalent to `-l` option in gcc/clang. + */ + library?: string[] | string; - /** - * Include directories to pass to the compiler - * - * Equivalent to `-I` option in gcc/clang. - */ - include?: string[] | string; + /** + * Include directories to pass to the compiler + * + * Equivalent to `-I` option in gcc/clang. + */ + include?: string[] | string; - /** - * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - */ - symbols: Fns; + /** + * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + */ + symbols: Fns; - /** - * Map of symbols to define where the key is the symbol name and the value is the symbol value - * - * Equivalent to `-D` option in gcc/clang. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * define: { - * "NDEBUG": "1", - * }, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - define?: Record; + /** + * Map of symbols to define where the key is the symbol name and the value is the symbol value + * + * Equivalent to `-D` option in gcc/clang. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * define: { + * "NDEBUG": "1", + * }, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + define?: Record; - /** - * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. - * - * @default "-std=c11 -Wl,--export-all-symbols -g -O2" - * - * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * flags: ["-framework CoreFoundation", "-framework Security"], - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - flags?: string | string[]; - }): Library; + /** + * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. + * + * @default "-std=c11 -Wl,--export-all-symbols -g -O2" + * + * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * flags: ["-framework CoreFoundation", "-framework Security"], + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + flags?: string | string[]; + }): Library; - /** - * Turn a native library's function pointer into a JavaScript function - * - * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. - * - * @param fn {@link FFIFunction} declaration. `ptr` is required - * - * @example - * - * ```js - * import {CFunction} from 'bun:ffi'; - * - * const getVersion = new CFunction({ - * returns: "cstring", - * args: [], - * ptr: myNativeLibraryGetVersion, - * }); - * getVersion(); - * getVersion.close(); - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { - /** - * Free the memory allocated by the wrapping function - */ - close(): void; - }; + /** + * Turn a native library's function pointer into a JavaScript function + * + * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. + * + * @param fn {@link FFIFunction} declaration. `ptr` is required + * + * @example + * + * ```js + * import {CFunction} from 'bun:ffi'; + * + * const getVersion = new CFunction({ + * returns: "cstring", + * args: [], + * ptr: myNativeLibraryGetVersion, + * }); + * getVersion(); + * getVersion.close(); + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { + /** + * Free the memory allocated by the wrapping function + */ + close(): void; + }; - /** - * Link a map of symbols to JavaScript functions - * - * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. - * - * You could use this with Node-API to skip loading a second time. - * - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import { linkSymbols } from "bun:ffi"; - * - * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); - * - * const lib = linkSymbols({ - * // Unlike with dlopen(), the names here can be whatever you want - * getMajor: { - * returns: "cstring", - * args: [], - * - * // Since this doesn't use dlsym(), you have to provide a valid ptr - * // That ptr could be a number or a bigint - * // An invalid pointer will crash your program. - * ptr: majorPtr, - * }, - * getMinor: { - * returns: "cstring", - * args: [], - * ptr: minorPtr, - * }, - * getPatch: { - * returns: "cstring", - * args: [], - * ptr: patchPtr, - * }, - * }); - * - * const [major, minor, patch] = [ - * lib.symbols.getMajor(), - * lib.symbols.getMinor(), - * lib.symbols.getPatch(), - * ]; - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function linkSymbols>( - symbols: Fns, - ): Library; + /** + * Link a map of symbols to JavaScript functions + * + * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. + * + * You could use this with Node-API to skip loading a second time. + * + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import { linkSymbols } from "bun:ffi"; + * + * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); + * + * const lib = linkSymbols({ + * // Unlike with dlopen(), the names here can be whatever you want + * getMajor: { + * returns: "cstring", + * args: [], + * + * // Since this doesn't use dlsym(), you have to provide a valid ptr + * // That ptr could be a number or a bigint + * // An invalid pointer will crash your program. + * ptr: majorPtr, + * }, + * getMinor: { + * returns: "cstring", + * args: [], + * ptr: minorPtr, + * }, + * getPatch: { + * returns: "cstring", + * args: [], + * ptr: patchPtr, + * }, + * }); + * + * const [major, minor, patch] = [ + * lib.symbols.getMajor(), + * lib.symbols.getMinor(), + * lib.symbols.getPatch(), + * ]; + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function linkSymbols>(symbols: Fns): Library; - /** - * Read a pointer as a {@link Buffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toBuffer( - ptr: Pointer, - byteOffset?: number, - byteLength?: number, - ): Buffer; + /** + * Read a pointer as a {@link Buffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): Buffer; - /** - * Read a pointer as an {@link ArrayBuffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toArrayBuffer( - ptr: Pointer, - byteOffset?: number, - byteLength?: number, - ): ArrayBuffer; + /** + * Read a pointer as an {@link ArrayBuffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toArrayBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): ArrayBuffer; - namespace read { - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f64(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function ptr(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function intptr(ptr: Pointer, byteOffset?: number): number; - } + namespace read { + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f64(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function ptr(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function intptr(ptr: Pointer, byteOffset?: number): number; + } - /** - * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} - * - * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. - * - * This is for use with FFI functions. For performance reasons, FFI will - * not automatically convert typed arrays to C pointers. - * - * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for - * @param {number} byteOffset optional offset into the view in bytes - * - * @example - * - * From JavaScript: - * ```js - * const array = new Uint8Array(10); - * const rawPtr = ptr(array); - * myFFIFunction(rawPtr); - * ``` - * To C: - * ```c - * void myFFIFunction(char* rawPtr) { - * // Do something with rawPtr - * } - * ``` - */ - function ptr( - view: NodeJS.TypedArray | ArrayBufferLike | DataView, - byteOffset?: number, - ): Pointer; + /** + * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} + * + * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. + * + * This is for use with FFI functions. For performance reasons, FFI will + * not automatically convert typed arrays to C pointers. + * + * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for + * @param {number} byteOffset optional offset into the view in bytes + * + * @example + * + * From JavaScript: + * ```js + * const array = new Uint8Array(10); + * const rawPtr = ptr(array); + * myFFIFunction(rawPtr); + * ``` + * To C: + * ```c + * void myFFIFunction(char* rawPtr) { + * // Do something with rawPtr + * } + * ``` + */ + function ptr(view: NodeJS.TypedArray | ArrayBufferLike | DataView, byteOffset?: number): Pointer; - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ - class CString extends String { - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @param ptr The pointer to the C string - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); + class CString extends String { + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @param ptr The pointer to the C string + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); - /** - * The ptr to the C string - * - * This `CString` instance is a clone of the string, so it - * is safe to continue using this instance after the `ptr` has been - * freed. - */ - ptr: Pointer; - byteOffset?: number; - byteLength?: number; + /** + * The ptr to the C string + * + * This `CString` instance is a clone of the string, so it + * is safe to continue using this instance after the `ptr` has been + * freed. + */ + ptr: Pointer; + byteOffset?: number; + byteLength?: number; - /** - * Get the {@link ptr} as an `ArrayBuffer` - * - * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 - */ - get arrayBuffer(): ArrayBuffer; - } + /** + * Get the {@link ptr} as an `ArrayBuffer` + * + * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 + */ + get arrayBuffer(): ArrayBuffer; + } - /** - * Pass a JavaScript function to FFI (Foreign Function Interface) - */ - class JSCallback { - /** - * Enable a JavaScript callback function to be passed to C with bun:ffi - * - * @param callback The JavaScript function to be called - * @param definition The C function definition - */ - constructor(callback: (...args: any[]) => any, definition: FFIFunction); + /** + * Pass a JavaScript function to FFI (Foreign Function Interface) + */ + class JSCallback { + /** + * Enable a JavaScript callback function to be passed to C with bun:ffi + * + * @param callback The JavaScript function to be called + * @param definition The C function definition + */ + constructor(callback: (...args: any[]) => any, definition: FFIFunction); - /** - * The pointer to the C function - * - * Becomes `null` once {@link JSCallback.prototype.close} is called - */ - readonly ptr: Pointer | null; + /** + * The pointer to the C function + * + * Becomes `null` once {@link JSCallback.prototype.close} is called + */ + readonly ptr: Pointer | null; - /** - * Can the callback be called from a different thread? - */ - readonly threadsafe: boolean; + /** + * Can the callback be called from a different thread? + */ + readonly threadsafe: boolean; - /** - * Free the memory allocated for the callback - * - * If called multiple times, does nothing after the first call. - */ - close(): void; - } + /** + * Free the memory allocated for the callback + * + * If called multiple times, does nothing after the first call. + */ + close(): void; + } - /** - * View the generated C code for FFI bindings - * - * You probably won't need this unless there's a bug in the FFI bindings - * generator or you're just curious. - */ - function viewSource(symbols: Symbols, is_callback?: false): string[]; - function viewSource(callback: FFIFunction, is_callback: true): string; + /** + * View the generated C code for FFI bindings + * + * You probably won't need this unless there's a bug in the FFI bindings + * generator or you're just curious. + */ + function viewSource(symbols: Symbols, is_callback?: false): string[]; + function viewSource(callback: FFIFunction, is_callback: true): string; - /** - * Platform-specific file extension name for dynamic libraries - * - * "." is not included - * - * @example - * ```js - * "dylib" // macOS - * ``` - * - * @example - * ```js - * "so" // linux - * ``` - */ - const suffix: string; + /** + * Platform-specific file extension name for dynamic libraries + * + * "." is not included + * + * @example + * ```js + * "dylib" // macOS + * ``` + * + * @example + * ```js + * "so" // linux + * ``` + */ + const suffix: string; } diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index f8c1bab554eea7..cade6dc3be4798 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1,1875 +1,1770 @@ export {}; type _Event = { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly bubbles: boolean; + /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ + cancelBubble: () => void; + /** True if the event was created with the cancelable option */ + readonly cancelable: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly composed: boolean; + /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ + composedPath(): [EventTarget?]; + /** Alias for event.target. */ + readonly currentTarget: EventTarget | null; + /** Is true if cancelable is true and event.preventDefault() has been called. */ + readonly defaultPrevented: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly eventPhase: 0 | 2; + /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ + readonly isTrusted: boolean; + /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ + preventDefault(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + returnValue: boolean; + /** Alias for event.target. */ + readonly srcElement: EventTarget | null; + /** Stops the invocation of event listeners after the current one completes. */ + stopImmediatePropagation(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + stopPropagation(): void; + /** The `EventTarget` dispatching the event */ + readonly target: EventTarget | null; + /** The millisecond timestamp when the Event object was created. */ + readonly timeStamp: number; + /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ + readonly type: string; }; type _EventTarget = { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; + /** + * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. + * + * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. + * + * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. + * Specifically, the `capture` option is used as part of the key when registering a `listener`. + * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. + */ + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ + dispatchEvent(event: Event): boolean; + /** Removes the event listener in target's event listener list with the same type, callback, and options. */ + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; }; declare global { - var Bun: typeof import("bun"); - - namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - - /** Whether you are using Bun */ - isBun: true; - /** The current git sha of Bun **/ - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - } - - namespace Bun { - type ArrayBufferView = NodeJS.TypedArray | DataView; - type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type PathLike = import("bun").PathLike; - type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; - type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; - type ReadableStreamController = ReadableStreamDefaultController; - type ReadableStreamDefaultReadResult = - | ReadableStreamDefaultReadValueResult - | ReadableStreamDefaultReadDoneResult; - type ReadableStreamReader = ReadableStreamDefaultReader; - type Transferable = ArrayBuffer | import("worker_threads").MessagePort; - type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; - type DOMHighResTimeStamp = number; - type EventListenerOrEventListenerObject = - | EventListener - | EventListenerObject; - - type BlobOrStringOrBuffer = - | string - | NodeJS.TypedArray - | ArrayBufferLike - | Blob; - - type Platform = - | "aix" - | "android" - | "darwin" - | "freebsd" - | "haiku" - | "linux" - | "openbsd" - | "sunos" - | "win32" - | "cygwin" - | "netbsd"; - type Architecture = - | "arm" - | "arm64" - | "ia32" - | "mips" - | "mipsel" - | "ppc" - | "ppc64" - | "s390" - | "s390x" - | "x64"; - - 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. - */ - type UnhandledRejectionListener = ( - reason: unknown, - promise: Promise, - ) => void; - - type MultipleResolveListener = ( - type: MultipleResolveType, - promise: Promise, - value: unknown, - ) => void; - - type HeadersInit = - | Headers - | Record - | Array<[string, string]> - | IterableIterator<[string, string]>; - - type ResponseType = - | "basic" - | "cors" - | "default" - | "error" - | "opaque" - | "opaqueredirect"; - - type _TextEncoder = import("util").TextEncoder; - interface TextEncoder extends _TextEncoder { - new ( - encoding?: Bun.Encoding, - options?: { fatal?: boolean; ignoreBOM?: boolean }, - ): TextEncoder; - /** - * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object - * containing the read Unicode code units and written UTF-8 bytes. - * - * ```js - * const encoder = new TextEncoder(); - * const src = 'this is some data'; - * const dest = new Uint8Array(10); - * const { read, written } = encoder.encodeInto(src, dest); - * ``` - * @param src The text to encode. - * @param dest The array to hold the encode result. - */ - encodeInto( - src?: string, - dest?: Bun.BufferSource, - ): import("util").EncodeIntoResult; - } - - type _TextDecoder = import("util").TextDecoder; - interface TextDecoder extends _TextDecoder { - new ( - encoding?: Bun.Encoding, - options?: { fatal?: boolean; ignoreBOM?: boolean }, - ): TextDecoder; - } - - 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 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 extends Bun.EventInit { - detail?: T; - } - - /** A message received by a target object. */ - interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; - readonly source: Bun.MessageEventSource | null; - } - - interface ReadableStreamDefaultReadManyResult { - done: boolean; - /** Number of bytes */ - size: number; - value: T[]; - } - - interface ResponseInit { - headers?: HeadersInit; - /** @default 200 */ - status?: number; - - /** @default "OK" */ - statusText?: string; - } - - interface EventSourceEventMap { - error: Event; - message: MessageEvent; - open: Event; - } - - interface EventInit { - bubbles?: boolean; - cancelable?: boolean; - composed?: boolean; - } - - interface EventListenerOptions { - /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ - capture?: boolean; - } - - 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): void; - respondWith(response: Response | Promise): 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( - 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( - 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 { - ( - controller: TransformStreamDefaultController, - ): void | PromiseLike; - } - - interface TransformerStartCallback { - (controller: TransformStreamDefaultController): any; - } - - interface TransformerTransformCallback { - ( - chunk: I, - controller: TransformStreamDefaultController, - ): void | PromiseLike; - } - - interface UnderlyingSinkAbortCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSinkCloseCallback { - (): void | PromiseLike; - } - - interface UnderlyingSinkStartCallback { - (controller: WritableStreamDefaultController): any; - } - - interface UnderlyingSinkWriteCallback { - ( - chunk: W, - controller: WritableStreamDefaultController, - ): void | PromiseLike; - } - - interface UnderlyingSourceCancelCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSink { - abort?: UnderlyingSinkAbortCallback; - close?: UnderlyingSinkCloseCallback; - start?: UnderlyingSinkStartCallback; - type?: undefined | "default" | "bytes"; - write?: UnderlyingSinkWriteCallback; - } - - interface UnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull?: UnderlyingSourcePullCallback; - start?: UnderlyingSourceStartCallback; - /** - * Mode "bytes" is not currently supported. - */ - type?: undefined; - } - - interface DirectUnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull: ( - controller: ReadableStreamDirectController, - ) => void | PromiseLike; - type: "direct"; - } - - interface UnderlyingSourcePullCallback { - (controller: ReadableStreamController): void | PromiseLike; - } - - interface UnderlyingSourceStartCallback { - (controller: ReadableStreamController): 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( - type: K, - listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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 - | 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( - type: K, - listener: (this: Worker, ev: WorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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; - } - } - - type _ReadableStream = import("stream/web").ReadableStream; - interface ReadableStream extends _ReadableStream {} - var ReadableStream: { - prototype: ReadableStream; - new ( - underlyingSource?: Bun.UnderlyingSource, - strategy?: QueuingStrategy, - ): ReadableStream; - new ( - underlyingSource?: Bun.DirectUnderlyingSource, - strategy?: QueuingStrategy, - ): ReadableStream; - }; - - type _WritableStream = import("stream/web").WritableStream; - interface WritableStream extends _WritableStream {} - var WritableStream: { - prototype: WritableStream; - new ( - underlyingSink?: Bun.UnderlyingSink, - strategy?: QueuingStrategy, - ): WritableStream; - }; - - type _Worker = import("worker_threads").Worker; - interface Worker extends _Worker {} - var Worker: { - prototype: Worker; - new ( - scriptURL: string | URL, - options?: Bun.WorkerOptions | undefined, - ): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; - }; - - var WebSocket: typeof import("ws").WebSocket; - - type _Crypto = import("crypto").webcrypto.Crypto; - interface Crypto extends _Crypto {} - var Crypto: { - prototype: Crypto; - new (): Crypto; - }; - - var crypto: Crypto; - - /** - * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All - * instances of `TextEncoder` only support UTF-8 encoding. - * - * ```js - * const encoder = new TextEncoder(); - * const uint8array = encoder.encode('this is some data'); - * ``` - */ - interface TextEncoder extends Bun.TextEncoder {} - var TextEncoder: typeof TextEncoder; - - interface TextDecoder extends Bun.TextDecoder {} - var TextDecoder: typeof TextDecoder; - - type _Performance = import("perf_hooks").Performance; - interface Performance extends _Performance {} - var performance: Performance; - - interface Event extends _Event {} - var Event: { - prototype: Event; - new (type: string, eventInitDict?: Bun.EventInit): Event; - }; - - interface EventTarget extends _EventTarget {} - var EventTarget: { - prototype: EventTarget; - new (): EventTarget; - }; - - interface File extends Blob { - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new ( - parts: Bun.BlobPart[], - name: string, - options?: BlobPropertyBag & { lastModified?: Date | number }, - ): File; - readonly lastModified: number; - readonly name: string; - } - - var File: typeof File; - - type _RequestInit = import("undici-types").RequestInit; - interface RequestInit extends _RequestInit { - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: import("bun").S3Options; - } - - /** - * ShadowRealms are a distinct global environment, with its own global object - * containing its own intrinsics and built-ins (standard objects that are not - * bound to global variables, like the initial value of Object.prototype). - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - interface ShadowRealm { - /** - * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; - } - - var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; - }; - - function queueMicrotask(callback: (...args: any[]) => void): void; - /** - * Log an error using the default exception handler - * @param error Error or string - */ - function reportError(error: any): void; - - interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; - - [Symbol.toPrimitive](): number; - } - - /** - * Cancel a repeating timer by its timer ID. - * @param id timer id - */ - function clearInterval(id?: number | Timer): void; - /** - * Cancel a delayed function call by its timer ID. - * @param id timer id - */ - function clearTimeout(id?: number | Timer): void; - /** - * Cancel an immediate function call by its immediate ID. - * @param id immediate id - */ - function clearImmediate(id?: number | Timer): void; - /** - * Run a function immediately after main event loop is vacant - * @param handler function to call - */ - function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; - /** - * Run a function every `interval` milliseconds - * @param handler function to call - * @param interval milliseconds to wait between calls - */ - function setInterval( - handler: Bun.TimerHandler, - interval?: number, - ...arguments: any[] - ): Timer; - /** - * Run a function after `timeout` (milliseconds) - * @param handler function to call - * @param timeout milliseconds to wait between calls - */ - function setTimeout( - handler: Bun.TimerHandler, - timeout?: number, - ...arguments: any[] - ): Timer; - - function addEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - function addEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - function removeEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | Bun.EventListenerOptions, - ): void; - function removeEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | Bun.EventListenerOptions, - ): void; - - /** - * Events providing information related to errors in scripts or in files. - */ - interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; - } - - var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; - }; - - /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ - interface CloseEvent extends Event { - /** Returns the WebSocket connection close code provided by the server. */ - readonly code: number; - /** Returns the WebSocket connection close reason provided by the server. */ - readonly reason: string; - /** Returns true if the connection closed cleanly; false otherwise. */ - readonly wasClean: boolean; - } - - var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; - }; - - interface MessageEvent extends Bun.MessageEvent {} - var MessageEvent: { - prototype: MessageEvent; - new ( - type: string, - eventInitDict?: Bun.MessageEventInit, - ): MessageEvent; - }; - - interface CustomEvent extends Event { - /** Returns any custom data event was created with. Typically used for synthetic events. */ - readonly detail: T; - } - - var CustomEvent: { - prototype: CustomEvent; - new ( - type: string, - eventInitDict?: Bun.CustomEventInit, - ): CustomEvent; - }; - - // /** - // * The URL interface represents an object providing static methods used for - // * creating object URLs. - // */ - // interface URL extends _URL { - // new (url: string | URL, base?: string | URL): URL; - // /** Not implemented yet */ - // createObjectURL(obj: Blob): string; - // /** Not implemented yet */ - // revokeObjectURL(url: string): void; - - // /** - // * Check if `url` is a valid URL string - // * - // * @param url URL string to parse - // * @param base URL to resolve against - // */ - // canParse(url: string, base?: string): boolean; - // } - - interface EventListener { - (evt: Event): void; - } - - interface EventListenerObject { - handleEvent(object: Event): void; - } - - interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; - - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; - } - - interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; - // exit: Event; - } - - interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; - } - - /** - * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) - * - * Before using this, be aware of a few things: - * - * **Using this incorrectly will crash your application**. - * - * This API may change any time JavaScriptCore is updated. - * - * Bun may rewrite ESM import specifiers to point to bundled code. This will - * be confusing when using this API, as it will return a string like - * "/node_modules.server.bun". - * - * Bun may inject additional imports into your code. This usually has a `bun:` prefix. - */ - var Loader: { - /** - * ESM module registry - * - * This lets you implement live reload in Bun. If you - * delete a module specifier from this map, the next time it's imported, it - * will be re-transpiled and loaded again. - * - * The keys are the module specifiers and the - * values are metadata about the module. - * - * The keys are an implementation detail for Bun that will change between - * versions. - * - * - Userland modules are an absolute file path - * - Virtual modules have a `bun:` prefix or `node:` prefix - * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill - * - If you have a `node_modules.bun` file, many modules will point to that file - * - * Virtual modules and JS polyfills are embedded in bun's binary. They don't - * point to anywhere in your local filesystem. - */ - registry: Map< - string, - { - key: string; - /** - * This refers to the state the ESM module is in - * - * TODO: make an enum for this number - */ - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array< - (typeof Loader)["registry"] extends Map ? V : any - >; - /** - * Your application will probably crash if you mess with this. - */ - module: { - dependenciesMap: (typeof Loader)["registry"]; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - /** - * For an already-evaluated module, return the dependencies as module specifiers - * - * This list is already sorted and uniqued. - * - * @example - * - * For this code: - * ```js - * // /foo.js - * import classNames from 'classnames'; - * import React from 'react'; - * import {createElement} from 'react'; - * ``` - * - * This would return: - * ```js - * Loader.dependencyKeysIfEvaluated("/foo.js") - * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] - * ``` - * - * @param specifier - module specifier as it appears in transpiled source code - */ - dependencyKeysIfEvaluated: (specifier: string) => string[]; - /** - * The function JavaScriptCore internally calls when you use an import statement. - * - * This may return a path to `node_modules.server.bun`, which will be confusing. - * - * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} - * instead. - * - * @param specifier - module specifier as it appears in transpiled source code - * @param referrer - module specifier that is resolving this specifier - */ - resolve: (specifier: string, referrer: string) => string; - }; - - interface QueuingStrategy { - highWaterMark?: number; - size?: QueuingStrategySize; - } - - interface QueuingStrategyInit { - /** - * Creates a new ByteLengthQueuingStrategy with the provided high water mark. - * - * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. - */ - highWaterMark: number; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface ByteLengthQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - // changed from QueuingStrategySize - // to avoid conflict with lib.dom.d.ts - readonly size: QueuingStrategySize; - } - - var ByteLengthQueuingStrategy: { - prototype: ByteLengthQueuingStrategy; - new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; - }; - - interface ReadableStreamDefaultController { - readonly desiredSize: number | null; - close(): void; - enqueue(chunk?: R): void; - error(e?: any): void; - } - - interface ReadableStreamDirectController { - close(error?: Error): void; - write( - data: Bun.BufferSource | ArrayBuffer | string, - ): number | Promise; - end(): number | Promise; - flush(): number | Promise; - start(): void; - } - - var ReadableStreamDefaultController: { - prototype: ReadableStreamDefaultController; - new (): ReadableStreamDefaultController; - }; - - interface ReadableStreamDefaultReader - extends ReadableStreamGenericReader { - read(): Promise>; - /** - * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. - * Will only return a promise if the data is not immediately available. - */ - readMany(): - | Promise> - | Bun.ReadableStreamDefaultReadManyResult; - releaseLock(): void; - } - - var ReadableStreamDefaultReader: { - prototype: ReadableStreamDefaultReader; - new (stream: ReadableStream): ReadableStreamDefaultReader; - }; - - interface ReadableStreamGenericReader { - readonly closed: Promise; - cancel(reason?: any): Promise; - } - - interface ReadableStreamDefaultReadDoneResult { - done: true; - value?: undefined; - } - - interface ReadableStreamDefaultReadValueResult { - done: false; - value: T; - } - - interface ReadableWritablePair { - readable: ReadableStream; - /** - * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - */ - writable: WritableStream; - } - - interface WritableStreamDefaultController { - error(e?: any): void; - } - - var WritableStreamDefaultController: { - prototype: WritableStreamDefaultController; - new (): WritableStreamDefaultController; - }; - - /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ - interface WritableStreamDefaultWriter { - readonly closed: Promise; - readonly desiredSize: number | null; - readonly ready: Promise; - abort(reason?: any): Promise; - close(): Promise; - releaseLock(): void; - write(chunk?: W): Promise; - } - - var WritableStreamDefaultWriter: { - prototype: WritableStreamDefaultWriter; - new (stream: WritableStream): WritableStreamDefaultWriter; - }; - - interface TransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; - } - - var TransformStream: { - prototype: TransformStream; - new ( - transformer?: Transformer, - writableStrategy?: QueuingStrategy, - readableStrategy?: QueuingStrategy, - ): TransformStream; - }; - - interface TransformStreamDefaultController { - readonly desiredSize: number | null; - enqueue(chunk?: O): void; - error(reason?: any): void; - terminate(): void; - } - - var TransformStreamDefaultController: { - prototype: TransformStreamDefaultController; - new (): TransformStreamDefaultController; - }; - - interface StreamPipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - /** - * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - * - * Errors and closures of the source and destination streams propagate as follows: - * - * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. - * - * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. - * - * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. - * - * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. - * - * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. - */ - preventClose?: boolean; - signal?: AbortSignal; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface CountQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - readonly size: QueuingStrategySize; - } - - var CountQueuingStrategy: { - prototype: CountQueuingStrategy; - new (init: QueuingStrategyInit): CountQueuingStrategy; - }; - - interface QueuingStrategySize { - (chunk?: T): number; - } - - interface Transformer { - flush?: Bun.TransformerFlushCallback; - readableType?: undefined; - start?: Bun.TransformerStartCallback; - transform?: Bun.TransformerTransformCallback; - writableType?: undefined; - } - - interface Dict { - [key: string]: T | undefined; - } - - interface ReadOnlyDict { - readonly [key: string]: T | undefined; - } - - interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; - } - - /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ - interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; - } - - var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; - }; - - function alert(message?: string): void; - function confirm(message?: string): boolean; - function prompt(message?: string, _default?: string): string | null; - - type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; - var SubtleCrypto: { - prototype: _SubtleCrypto; - new (): _SubtleCrypto; - }; - - type _CryptoKey = import("crypto").webcrypto.CryptoKey; - interface CryptoKey extends _CryptoKey {} - var CryptoKey: { - prototype: CryptoKey; - new (): CryptoKey; - }; - - interface Position { - lineText: string; - file: string; - namespace: string; - line: number; - column: number; - length: number; - offset: number; - } - - class ResolveMessage { - readonly name: "ResolveMessage"; - readonly position: Position | null; - readonly code: string; - readonly message: string; - readonly referrer: string; - readonly specifier: string; - readonly importKind: - | "entry_point" - | "stmt" - | "require" - | "import" - | "dynamic" - | "require_resolve" - | "at" - | "at_conditional" - | "url" - | "internal"; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - - toString(): string; - } - - class BuildMessage { - readonly name: "BuildMessage"; - readonly position: Position | null; - readonly message: string; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - } - - // Declare "static" methods in Error - interface ErrorConstructor { - /** Create .stack property on a target object */ - // eslint-disable-next-line @typescript-eslint/ban-types - captureStackTrace(targetObject: object, constructorOpt?: Function): void; - - /** - * Optional override for formatting stack traces - * - * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces - */ - prepareStackTrace?: - | ((err: Error, stackTraces: NodeJS.CallSite[]) => any) - | undefined; - - stackTraceLimit: number; - } - - interface ArrayBufferConstructor { - new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; - } - - interface ArrayBuffer { - /** - * Read-only. The length of the ArrayBuffer (in bytes). - */ - readonly byteLength: number; - /** - * Resize an ArrayBuffer in-place. - */ - resize(byteLength: number): ArrayBuffer; - - /** - * Returns a section of an ArrayBuffer. - */ - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; - } - - interface SharedArrayBuffer { - /** - * Grow the SharedArrayBuffer in-place. - */ - grow(size: number): SharedArrayBuffer; - } - - interface ArrayConstructor { - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - ): Promise[]>; - - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. Results of the map function are also awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * await Array.fromAsync([1], (n) => n + 1); // [2] - * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. - * @param thisArg - The `this` to which `mapFn` is bound. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; - } - - interface ConsoleOptions { - stdout: import("stream").Writable; - stderr?: import("stream").Writable; - ignoreErrors?: boolean; - colorMode?: boolean | "auto"; - inspectOptions?: import("util").InspectOptions; - groupIndentation?: number; - } - - interface Console { - /** - * Asynchronously read lines from standard input (fd 0) - * - * ```ts - * for await (const line of console) { - * console.log(line); - * } - * ``` - */ - [Symbol.asyncIterator](): AsyncIterableIterator; - - /** - * Write text or bytes to stdout - * - * Unlike {@link console.log}, this does no formatting and doesn't add a - * newline or spaces between arguments. You can pass it strings or bytes or - * any combination of the two. - * - * ```ts - * console.write("hello world!", "\n"); // "hello world\n" - * ``` - * - * @param data - The data to write - * @returns The number of bytes written - * - * This function is not available in the browser. - */ - write(...data: Array): number; - - /** - * Clear the console - */ - clear(): void; - - assert(condition?: boolean, ...data: any[]): void; - - /** - * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) - * @param label label counter - */ - count(label?: string): void; - countReset(label?: string): void; - debug(...data: any[]): void; - dir(item?: any, options?: any): void; - dirxml(...data: any[]): void; - /** - * Log to stderr in your terminal - * - * Appears in red - * - * @param data something to display - */ - error(...data: any[]): void; - /** Does nothing currently */ - group(...data: any[]): void; - /** Does nothing currently */ - groupCollapsed(...data: any[]): void; - /** Does nothing currently */ - groupEnd(): void; - info(...data: any[]): void; - log(...data: any[]): void; - /** - * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just - * logging the argument if it can't be parsed as tabular. - * - * ```js - * // These can't be parsed as tabular data - * console.table(Symbol()); - * // Symbol() - * - * console.table(undefined); - * // undefined - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ b โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * ``` - * @param properties Alternate properties for constructing the table. - */ - table(tabularData?: any, properties?: string[]): void; - /** - * Begin a timer to log with {@link console.timeEnd} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - time(label?: string): void; - /** - * End a timer to log with {@link console.time} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - timeEnd(label?: string): void; - timeLog(label?: string, ...data: any[]): void; - timeStamp(label?: string): void; - trace(...data: any[]): void; - warn(...data: any[]): void; - - /** - * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. - */ - // Console: { - // new (options: ConsoleOptions): Console; - // new ( - // stdout: import("stream").Writable, - // stderr?: import("stream").Writable, - // ignoreErrors?: boolean, - // ): Console; - // }; - } - - var console: Console; - - interface ImportMeta { - /** - * `file://` url string for the current module. - * - * @example - * ```ts - * console.log(import.meta.url); - * "file:///Users/me/projects/my-app/src/my-app.ts" - * ``` - */ - url: string; - /** - * Absolute path to the source file - */ - readonly path: string; - /** - * Absolute path to the directory containing the source file. - * - * Does not have a trailing slash - */ - readonly dir: string; - /** - * Filename of the source file - */ - readonly file: string; - /** - * The environment variables of the process - * - * ```ts - * import.meta.env === process.env - * ``` - */ - readonly env: NodeJS.ProcessEnv; - - /** - * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead - * - * Resolve a module ID the same as if you imported it - * - * The `parent` argument is optional, and defaults to the current module's path. - */ - resolveSync(moduleId: string, parent?: string): string; - - /** - * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all - * calls to `require` with `import.meta.require` when transpiling ES Modules - * for the runtime. - * - * Warning: **This API is not stable** and may change or be removed in the - * future. Use at your own risk. - */ - require: NodeJS.Require; - - /** - * Did the current file start the process? - * - * @example - * ```ts - * if (import.meta.main) { - * console.log("I started the process!"); - * } - * ``` - * - * @example - * ```ts - * console.log( - * import.meta.main === (import.meta.path === Bun.main) - * ) - * ``` - */ - readonly main: boolean; - - /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ - dirname: string; - - /** Alias of `import.meta.path`. Exists for Node.js compatibility */ - filename: string; - } - - /** - * NodeJS-style `require` function - * - * @param moduleId - The module ID to resolve - */ - var require: NodeJS.Require; - - /** Same as module.exports */ - var exports: any; - - interface NodeModule { - exports: any; - } - - var module: NodeModule; - - /** - * Creates a deep clone of an object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) - */ - function structuredClone( - value: T, - options?: Bun.StructuredSerializeOptions, - ): T; - - /** - * Post a message to the parent thread. - * - * Only useful in a worker thread; calling this from the main thread does nothing. - */ - function postMessage(message: any, transfer?: Bun.Transferable[]): void; - - interface EventSourceInit { - withCredentials?: boolean; - } - - interface PromiseConstructor { - /** - * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called - * separately. - * - * This is useful when you want to return a Promise and have code outside the Promise - * resolve or reject it. - * - * ## Example - * ```ts - * const { promise, resolve, reject } = Promise.withResolvers(); - * - * setTimeout(() => { - * resolve("Hello world!"); - * }, 1000); - * - * await promise; // "Hello world!" - * ``` - * - * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). - */ - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; - } - - interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; - } - - var navigator: Navigator; - - interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; - } - - interface Blob { - /** - * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - */ - new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; - /** - * Read the data from the blob as a JSON object. - * - * This first decodes the data from UTF-8, then parses it as JSON. - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - json(): Promise; - - /** - * Read the data from the blob as a {@link FormData} object. - * - * This first decodes the data from UTF-8, then parses it as a - * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. - * - * The `type` property of the blob is used to determine the format of the - * body. - * - * This is a non-standard addition to the `Blob` API, to make it conform more - * closely to the `BodyMixin` API. - */ - formData(): Promise; - - arrayBuffer(): Promise; - - /** - * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` - */ - bytes(): Promise; - } - - var Blob: typeof Blob; + var Bun: typeof import("bun"); + + namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; + + /** Whether you are using Bun */ + isBun: true; + /** The current git sha of Bun **/ + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + } + + namespace Bun { + type ArrayBufferView = NodeJS.TypedArray | DataView; + type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; + type PathLike = import("bun").PathLike; + type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; + type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; + type ReadableStreamController = ReadableStreamDefaultController; + type ReadableStreamDefaultReadResult = + | ReadableStreamDefaultReadValueResult + | ReadableStreamDefaultReadDoneResult; + type ReadableStreamReader = ReadableStreamDefaultReader; + type Transferable = ArrayBuffer | import("worker_threads").MessagePort; + type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; + type DOMHighResTimeStamp = number; + type EventListenerOrEventListenerObject = EventListener | EventListenerObject; + + type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob; + + type Platform = + | "aix" + | "android" + | "darwin" + | "freebsd" + | "haiku" + | "linux" + | "openbsd" + | "sunos" + | "win32" + | "cygwin" + | "netbsd"; + type Architecture = "arm" | "arm64" | "ia32" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x" | "x64"; + + 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. + */ + type UnhandledRejectionListener = (reason: unknown, promise: Promise) => void; + + type MultipleResolveListener = (type: MultipleResolveType, promise: Promise, value: unknown) => void; + + type HeadersInit = Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; + + type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; + + type _TextEncoder = import("util").TextEncoder; + interface TextEncoder extends _TextEncoder { + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; + /** + * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object + * containing the read Unicode code units and written UTF-8 bytes. + * + * ```js + * const encoder = new TextEncoder(); + * const src = 'this is some data'; + * const dest = new Uint8Array(10); + * const { read, written } = encoder.encodeInto(src, dest); + * ``` + * @param src The text to encode. + * @param dest The array to hold the encode result. + */ + encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; + } + + type _TextDecoder = import("util").TextDecoder; + interface TextDecoder extends _TextDecoder { + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextDecoder; + } + + 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 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 extends Bun.EventInit { + detail?: T; + } + + /** A message received by a target object. */ + interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; + readonly source: Bun.MessageEventSource | null; + } + + interface ReadableStreamDefaultReadManyResult { + done: boolean; + /** Number of bytes */ + size: number; + value: T[]; + } + + interface ResponseInit { + headers?: HeadersInit; + /** @default 200 */ + status?: number; + + /** @default "OK" */ + statusText?: string; + } + + interface EventSourceEventMap { + error: Event; + message: MessageEvent; + open: Event; + } + + interface EventInit { + bubbles?: boolean; + cancelable?: boolean; + composed?: boolean; + } + + interface EventListenerOptions { + /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ + capture?: boolean; + } + + 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): void; + respondWith(response: Response | Promise): 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( + 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( + 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 { + (controller: TransformStreamDefaultController): void | PromiseLike; + } + + interface TransformerStartCallback { + (controller: TransformStreamDefaultController): any; + } + + interface TransformerTransformCallback { + (chunk: I, controller: TransformStreamDefaultController): void | PromiseLike; + } + + interface UnderlyingSinkAbortCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSinkCloseCallback { + (): void | PromiseLike; + } + + interface UnderlyingSinkStartCallback { + (controller: WritableStreamDefaultController): any; + } + + interface UnderlyingSinkWriteCallback { + (chunk: W, controller: WritableStreamDefaultController): void | PromiseLike; + } + + interface UnderlyingSourceCancelCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSink { + abort?: UnderlyingSinkAbortCallback; + close?: UnderlyingSinkCloseCallback; + start?: UnderlyingSinkStartCallback; + type?: undefined | "default" | "bytes"; + write?: UnderlyingSinkWriteCallback; + } + + interface UnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull?: UnderlyingSourcePullCallback; + start?: UnderlyingSourceStartCallback; + /** + * Mode "bytes" is not currently supported. + */ + type?: undefined; + } + + interface DirectUnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull: (controller: ReadableStreamDirectController) => void | PromiseLike; + type: "direct"; + } + + interface UnderlyingSourcePullCallback { + (controller: ReadableStreamController): void | PromiseLike; + } + + interface UnderlyingSourceStartCallback { + (controller: ReadableStreamController): 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( + type: K, + listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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 | (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( + type: K, + listener: (this: Worker, ev: WorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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; + } + } + + type _ReadableStream = import("stream/web").ReadableStream; + interface ReadableStream extends _ReadableStream {} + var ReadableStream: { + prototype: ReadableStream; + new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + }; + + type _WritableStream = import("stream/web").WritableStream; + interface WritableStream extends _WritableStream {} + var WritableStream: { + prototype: WritableStream; + new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; + }; + + type _Worker = import("worker_threads").Worker; + interface Worker extends _Worker {} + var Worker: { + prototype: Worker; + new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; + }; + + var WebSocket: typeof import("ws").WebSocket; + + type _Crypto = import("crypto").webcrypto.Crypto; + interface Crypto extends _Crypto {} + var Crypto: { + prototype: Crypto; + new (): Crypto; + }; + + var crypto: Crypto; + + /** + * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All + * instances of `TextEncoder` only support UTF-8 encoding. + * + * ```js + * const encoder = new TextEncoder(); + * const uint8array = encoder.encode('this is some data'); + * ``` + */ + interface TextEncoder extends Bun.TextEncoder {} + var TextEncoder: typeof TextEncoder; + + interface TextDecoder extends Bun.TextDecoder {} + var TextDecoder: typeof TextDecoder; + + type _Performance = import("perf_hooks").Performance; + interface Performance extends _Performance {} + var performance: Performance; + + interface Event extends _Event {} + var Event: { + prototype: Event; + new (type: string, eventInitDict?: Bun.EventInit): Event; + }; + + interface EventTarget extends _EventTarget {} + var EventTarget: { + prototype: EventTarget; + new (): EventTarget; + }; + + interface File extends Blob { + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; + readonly lastModified: number; + readonly name: string; + } + + var File: typeof File; + + type _RequestInit = import("undici-types").RequestInit; + interface RequestInit extends _RequestInit { + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: import("bun").S3Options; + } + + /** + * ShadowRealms are a distinct global environment, with its own global object + * containing its own intrinsics and built-ins (standard objects that are not + * bound to global variables, like the initial value of Object.prototype). + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + interface ShadowRealm { + /** + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; + } + + var ShadowRealm: { + prototype: ShadowRealm; + new (): ShadowRealm; + }; + + function queueMicrotask(callback: (...args: any[]) => void): void; + /** + * Log an error using the default exception handler + * @param error Error or string + */ + function reportError(error: any): void; + + interface Timer { + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; + + [Symbol.toPrimitive](): number; + } + + /** + * Cancel a repeating timer by its timer ID. + * @param id timer id + */ + function clearInterval(id?: number | Timer): void; + /** + * Cancel a delayed function call by its timer ID. + * @param id timer id + */ + function clearTimeout(id?: number | Timer): void; + /** + * Cancel an immediate function call by its immediate ID. + * @param id immediate id + */ + function clearImmediate(id?: number | Timer): void; + /** + * Run a function immediately after main event loop is vacant + * @param handler function to call + */ + function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; + /** + * Run a function every `interval` milliseconds + * @param handler function to call + * @param interval milliseconds to wait between calls + */ + function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; + /** + * Run a function after `timeout` (milliseconds) + * @param handler function to call + * @param timeout milliseconds to wait between calls + */ + function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; + + function addEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + function addEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + function removeEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | Bun.EventListenerOptions, + ): void; + function removeEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | Bun.EventListenerOptions, + ): void; + + /** + * Events providing information related to errors in scripts or in files. + */ + interface ErrorEvent extends Event { + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; + } + + var ErrorEvent: { + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; + }; + + /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ + interface CloseEvent extends Event { + /** Returns the WebSocket connection close code provided by the server. */ + readonly code: number; + /** Returns the WebSocket connection close reason provided by the server. */ + readonly reason: string; + /** Returns true if the connection closed cleanly; false otherwise. */ + readonly wasClean: boolean; + } + + var CloseEvent: { + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; + }; + + interface MessageEvent extends Bun.MessageEvent {} + var MessageEvent: { + prototype: MessageEvent; + new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; + }; + + interface CustomEvent extends Event { + /** Returns any custom data event was created with. Typically used for synthetic events. */ + readonly detail: T; + } + + var CustomEvent: { + prototype: CustomEvent; + new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; + }; + + // /** + // * The URL interface represents an object providing static methods used for + // * creating object URLs. + // */ + // interface URL extends _URL { + // new (url: string | URL, base?: string | URL): URL; + // /** Not implemented yet */ + // createObjectURL(obj: Blob): string; + // /** Not implemented yet */ + // revokeObjectURL(url: string): void; + + // /** + // * Check if `url` is a valid URL string + // * + // * @param url URL string to parse + // * @param base URL to resolve against + // */ + // canParse(url: string, base?: string): boolean; + // } + + interface EventListener { + (evt: Event): void; + } + + interface EventListenerObject { + handleEvent(object: Event): void; + } + + interface FetchEvent extends Event { + readonly request: Request; + readonly url: string; + + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; + } + + interface EventMap { + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; + // exit: Event; + } + + interface AddEventListenerOptions extends Bun.EventListenerOptions { + once?: boolean; + passive?: boolean; + signal?: AbortSignal; + } + + /** + * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) + * + * Before using this, be aware of a few things: + * + * **Using this incorrectly will crash your application**. + * + * This API may change any time JavaScriptCore is updated. + * + * Bun may rewrite ESM import specifiers to point to bundled code. This will + * be confusing when using this API, as it will return a string like + * "/node_modules.server.bun". + * + * Bun may inject additional imports into your code. This usually has a `bun:` prefix. + */ + var Loader: { + /** + * ESM module registry + * + * This lets you implement live reload in Bun. If you + * delete a module specifier from this map, the next time it's imported, it + * will be re-transpiled and loaded again. + * + * The keys are the module specifiers and the + * values are metadata about the module. + * + * The keys are an implementation detail for Bun that will change between + * versions. + * + * - Userland modules are an absolute file path + * - Virtual modules have a `bun:` prefix or `node:` prefix + * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill + * - If you have a `node_modules.bun` file, many modules will point to that file + * + * Virtual modules and JS polyfills are embedded in bun's binary. They don't + * point to anywhere in your local filesystem. + */ + registry: Map< + string, + { + key: string; + /** + * This refers to the state the ESM module is in + * + * TODO: make an enum for this number + */ + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; + /** + * Your application will probably crash if you mess with this. + */ + module: { + dependenciesMap: (typeof Loader)["registry"]; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; + /** + * For an already-evaluated module, return the dependencies as module specifiers + * + * This list is already sorted and uniqued. + * + * @example + * + * For this code: + * ```js + * // /foo.js + * import classNames from 'classnames'; + * import React from 'react'; + * import {createElement} from 'react'; + * ``` + * + * This would return: + * ```js + * Loader.dependencyKeysIfEvaluated("/foo.js") + * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] + * ``` + * + * @param specifier - module specifier as it appears in transpiled source code + */ + dependencyKeysIfEvaluated: (specifier: string) => string[]; + /** + * The function JavaScriptCore internally calls when you use an import statement. + * + * This may return a path to `node_modules.server.bun`, which will be confusing. + * + * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} + * instead. + * + * @param specifier - module specifier as it appears in transpiled source code + * @param referrer - module specifier that is resolving this specifier + */ + resolve: (specifier: string, referrer: string) => string; + }; + + interface QueuingStrategy { + highWaterMark?: number; + size?: QueuingStrategySize; + } + + interface QueuingStrategyInit { + /** + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. + */ + highWaterMark: number; + } + + /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ + interface ByteLengthQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + // changed from QueuingStrategySize + // to avoid conflict with lib.dom.d.ts + readonly size: QueuingStrategySize; + } + + var ByteLengthQueuingStrategy: { + prototype: ByteLengthQueuingStrategy; + new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; + }; + + interface ReadableStreamDefaultController { + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; + } + + interface ReadableStreamDirectController { + close(error?: Error): void; + write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; + end(): number | Promise; + flush(): number | Promise; + start(): void; + } + + var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; + }; + + interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { + read(): Promise>; + /** + * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. + * Will only return a promise if the data is not immediately available. + */ + readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; + releaseLock(): void; + } + + var ReadableStreamDefaultReader: { + prototype: ReadableStreamDefaultReader; + new (stream: ReadableStream): ReadableStreamDefaultReader; + }; + + interface ReadableStreamGenericReader { + readonly closed: Promise; + cancel(reason?: any): Promise; + } + + interface ReadableStreamDefaultReadDoneResult { + done: true; + value?: undefined; + } + + interface ReadableStreamDefaultReadValueResult { + done: false; + value: T; + } + + interface ReadableWritablePair { + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; + } + + interface WritableStreamDefaultController { + error(e?: any): void; + } + + var WritableStreamDefaultController: { + prototype: WritableStreamDefaultController; + new (): WritableStreamDefaultController; + }; + + /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ + interface WritableStreamDefaultWriter { + readonly closed: Promise; + readonly desiredSize: number | null; + readonly ready: Promise; + abort(reason?: any): Promise; + close(): Promise; + releaseLock(): void; + write(chunk?: W): Promise; + } + + var WritableStreamDefaultWriter: { + prototype: WritableStreamDefaultWriter; + new (stream: WritableStream): WritableStreamDefaultWriter; + }; + + interface TransformStream { + readonly readable: ReadableStream; + readonly writable: WritableStream; + } + + var TransformStream: { + prototype: TransformStream; + new ( + transformer?: Transformer, + writableStrategy?: QueuingStrategy, + readableStrategy?: QueuingStrategy, + ): TransformStream; + }; + + interface TransformStreamDefaultController { + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; + } + + var TransformStreamDefaultController: { + prototype: TransformStreamDefaultController; + new (): TransformStreamDefaultController; + }; + + interface StreamPipeOptions { + preventAbort?: boolean; + preventCancel?: boolean; + /** + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + * + * Errors and closures of the source and destination streams propagate as follows: + * + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. + * + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. + * + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. + * + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. + */ + preventClose?: boolean; + signal?: AbortSignal; + } + + /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ + interface CountQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + readonly size: QueuingStrategySize; + } + + var CountQueuingStrategy: { + prototype: CountQueuingStrategy; + new (init: QueuingStrategyInit): CountQueuingStrategy; + }; + + interface QueuingStrategySize { + (chunk?: T): number; + } + + interface Transformer { + flush?: Bun.TransformerFlushCallback; + readableType?: undefined; + start?: Bun.TransformerStartCallback; + transform?: Bun.TransformerTransformCallback; + writableType?: undefined; + } + + interface Dict { + [key: string]: T | undefined; + } + + interface ReadOnlyDict { + readonly [key: string]: T | undefined; + } + + interface ErrnoException extends Error { + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; + } + + /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ + interface DOMException extends Error { + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; + } + + var DOMException: { + prototype: DOMException; + new (message?: string, name?: string): DOMException; + }; + + function alert(message?: string): void; + function confirm(message?: string): boolean; + function prompt(message?: string, _default?: string): string | null; + + type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; + var SubtleCrypto: { + prototype: _SubtleCrypto; + new (): _SubtleCrypto; + }; + + type _CryptoKey = import("crypto").webcrypto.CryptoKey; + interface CryptoKey extends _CryptoKey {} + var CryptoKey: { + prototype: CryptoKey; + new (): CryptoKey; + }; + + interface Position { + lineText: string; + file: string; + namespace: string; + line: number; + column: number; + length: number; + offset: number; + } + + class ResolveMessage { + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; + } + + class BuildMessage { + readonly name: "BuildMessage"; + readonly position: Position | null; + readonly message: string; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + } + + // Declare "static" methods in Error + interface ErrorConstructor { + /** Create .stack property on a target object */ + // eslint-disable-next-line @typescript-eslint/ban-types + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; + + stackTraceLimit: number; + } + + interface ArrayBufferConstructor { + new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; + } + + interface ArrayBuffer { + /** + * Read-only. The length of the ArrayBuffer (in bytes). + */ + readonly byteLength: number; + /** + * Resize an ArrayBuffer in-place. + */ + resize(byteLength: number): ArrayBuffer; + + /** + * Returns a section of an ArrayBuffer. + */ + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; + } + + interface SharedArrayBuffer { + /** + * Grow the SharedArrayBuffer in-place. + */ + grow(size: number): SharedArrayBuffer; + } + + interface ArrayConstructor { + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; + + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. Results of the map function are also awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * await Array.fromAsync([1], (n) => n + 1); // [2] + * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. + * @param thisArg - The `this` to which `mapFn` is bound. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; + } + + interface ConsoleOptions { + stdout: import("stream").Writable; + stderr?: import("stream").Writable; + ignoreErrors?: boolean; + colorMode?: boolean | "auto"; + inspectOptions?: import("util").InspectOptions; + groupIndentation?: number; + } + + interface Console { + /** + * Asynchronously read lines from standard input (fd 0) + * + * ```ts + * for await (const line of console) { + * console.log(line); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterableIterator; + + /** + * Write text or bytes to stdout + * + * Unlike {@link console.log}, this does no formatting and doesn't add a + * newline or spaces between arguments. You can pass it strings or bytes or + * any combination of the two. + * + * ```ts + * console.write("hello world!", "\n"); // "hello world\n" + * ``` + * + * @param data - The data to write + * @returns The number of bytes written + * + * This function is not available in the browser. + */ + write(...data: Array): number; + + /** + * Clear the console + */ + clear(): void; + + assert(condition?: boolean, ...data: any[]): void; + + /** + * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) + * @param label label counter + */ + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: any): void; + dirxml(...data: any[]): void; + /** + * Log to stderr in your terminal + * + * Appears in red + * + * @param data something to display + */ + error(...data: any[]): void; + /** Does nothing currently */ + group(...data: any[]): void; + /** Does nothing currently */ + groupCollapsed(...data: any[]): void; + /** Does nothing currently */ + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + /** + * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just + * logging the argument if it can't be parsed as tabular. + * + * ```js + * // These can't be parsed as tabular data + * console.table(Symbol()); + * // Symbol() + * + * console.table(undefined); + * // undefined + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ b โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * ``` + * @param properties Alternate properties for constructing the table. + */ + table(tabularData?: any, properties?: string[]): void; + /** + * Begin a timer to log with {@link console.timeEnd} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + time(label?: string): void; + /** + * End a timer to log with {@link console.time} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + timeStamp(label?: string): void; + trace(...data: any[]): void; + warn(...data: any[]): void; + + /** + * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. + */ + // Console: { + // new (options: ConsoleOptions): Console; + // new ( + // stdout: import("stream").Writable, + // stderr?: import("stream").Writable, + // ignoreErrors?: boolean, + // ): Console; + // }; + } + + var console: Console; + + interface ImportMeta { + /** + * `file://` url string for the current module. + * + * @example + * ```ts + * console.log(import.meta.url); + * "file:///Users/me/projects/my-app/src/my-app.ts" + * ``` + */ + url: string; + /** + * Absolute path to the source file + */ + readonly path: string; + /** + * Absolute path to the directory containing the source file. + * + * Does not have a trailing slash + */ + readonly dir: string; + /** + * Filename of the source file + */ + readonly file: string; + /** + * The environment variables of the process + * + * ```ts + * import.meta.env === process.env + * ``` + */ + readonly env: NodeJS.ProcessEnv; + + /** + * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead + * + * Resolve a module ID the same as if you imported it + * + * The `parent` argument is optional, and defaults to the current module's path. + */ + resolveSync(moduleId: string, parent?: string): string; + + /** + * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all + * calls to `require` with `import.meta.require` when transpiling ES Modules + * for the runtime. + * + * Warning: **This API is not stable** and may change or be removed in the + * future. Use at your own risk. + */ + require: NodeJS.Require; + + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; + + /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ + dirname: string; + + /** Alias of `import.meta.path`. Exists for Node.js compatibility */ + filename: string; + } + + /** + * NodeJS-style `require` function + * + * @param moduleId - The module ID to resolve + */ + var require: NodeJS.Require; + + /** Same as module.exports */ + var exports: any; + + interface NodeModule { + exports: any; + } + + var module: NodeModule; + + /** + * Creates a deep clone of an object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) + */ + function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; + + /** + * Post a message to the parent thread. + * + * Only useful in a worker thread; calling this from the main thread does nothing. + */ + function postMessage(message: any, transfer?: Bun.Transferable[]): void; + + interface EventSourceInit { + withCredentials?: boolean; + } + + interface PromiseConstructor { + /** + * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called + * separately. + * + * This is useful when you want to return a Promise and have code outside the Promise + * resolve or reject it. + * + * ## Example + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); + * + * setTimeout(() => { + * resolve("Hello world!"); + * }, 1000); + * + * await promise; // "Hello world!" + * ``` + * + * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). + */ + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; + } + + interface Navigator { + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; + } + + var navigator: Navigator; + + interface BlobPropertyBag { + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; + } + + interface Blob { + /** + * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + */ + new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; + /** + * Read the data from the blob as a JSON object. + * + * This first decodes the data from UTF-8, then parses it as JSON. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + json(): Promise; + + /** + * Read the data from the blob as a {@link FormData} object. + * + * This first decodes the data from UTF-8, then parses it as a + * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. + * + * The `type` property of the blob is used to determine the format of the + * body. + * + * This is a non-standard addition to the `Blob` API, to make it conform more + * closely to the `BodyMixin` API. + */ + formData(): Promise; + + arrayBuffer(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + */ + bytes(): Promise; + } + + var Blob: typeof Blob; } diff --git a/packages/bun-types/html-rewriter.d.ts b/packages/bun-types/html-rewriter.d.ts index 6bec7fea979ab2..4b2b2954cff397 100644 --- a/packages/bun-types/html-rewriter.d.ts +++ b/packages/bun-types/html-rewriter.d.ts @@ -1,129 +1,129 @@ declare namespace HTMLRewriterTypes { - interface HTMLRewriterElementContentHandlers { - element?(element: Element): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - } + interface HTMLRewriterElementContentHandlers { + element?(element: Element): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + } - interface HTMLRewriterDocumentContentHandlers { - doctype?(doctype: Doctype): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - end?(end: DocumentEnd): void | Promise; - } + interface HTMLRewriterDocumentContentHandlers { + doctype?(doctype: Doctype): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + end?(end: DocumentEnd): void | Promise; + } - interface Text { - /** The text content */ - readonly text: string; - /** Whether this chunk is the last piece of text in a text node */ - readonly lastInTextNode: boolean; - /** Whether this chunk was removed */ - readonly removed: boolean; - /** Insert content before this chunk */ - before(content: Content, options?: ContentOptions): Text; - /** Insert content after this chunk */ - after(content: Content, options?: ContentOptions): Text; - /** Replace this chunk with new content */ - replace(content: Content, options?: ContentOptions): Text; - /** Remove this chunk */ - remove(): Text; - } + interface Text { + /** The text content */ + readonly text: string; + /** Whether this chunk is the last piece of text in a text node */ + readonly lastInTextNode: boolean; + /** Whether this chunk was removed */ + readonly removed: boolean; + /** Insert content before this chunk */ + before(content: Content, options?: ContentOptions): Text; + /** Insert content after this chunk */ + after(content: Content, options?: ContentOptions): Text; + /** Replace this chunk with new content */ + replace(content: Content, options?: ContentOptions): Text; + /** Remove this chunk */ + remove(): Text; + } - interface Doctype { - /** The doctype name (e.g. "html" for ) */ - readonly name: string | null; - /** The doctype public identifier */ - readonly publicId: string | null; - /** The doctype system identifier */ - readonly systemId: string | null; - /** Whether this doctype was removed */ - readonly removed: boolean; - /** Remove this doctype */ - remove(): Doctype; - } + interface Doctype { + /** The doctype name (e.g. "html" for ) */ + readonly name: string | null; + /** The doctype public identifier */ + readonly publicId: string | null; + /** The doctype system identifier */ + readonly systemId: string | null; + /** Whether this doctype was removed */ + readonly removed: boolean; + /** Remove this doctype */ + remove(): Doctype; + } - interface DocumentEnd { - /** Append content at the end of the document */ - append(content: Content, options?: ContentOptions): DocumentEnd; - } + interface DocumentEnd { + /** Append content at the end of the document */ + append(content: Content, options?: ContentOptions): DocumentEnd; + } - interface ContentOptions { - /** Whether to parse the content as HTML */ - html?: boolean; - } + interface ContentOptions { + /** Whether to parse the content as HTML */ + html?: boolean; + } - type Content = string; + type Content = string; - interface Comment { - /** The comment text */ - text: string; - /** Whether this comment was removed */ - readonly removed: boolean; - /** Insert content before this comment */ - before(content: Content, options?: ContentOptions): Comment; - /** Insert content after this comment */ - after(content: Content, options?: ContentOptions): Comment; - /** Replace this comment with new content */ - replace(content: Content, options?: ContentOptions): Comment; - /** Remove this comment */ - remove(): Comment; - } + interface Comment { + /** The comment text */ + text: string; + /** Whether this comment was removed */ + readonly removed: boolean; + /** Insert content before this comment */ + before(content: Content, options?: ContentOptions): Comment; + /** Insert content after this comment */ + after(content: Content, options?: ContentOptions): Comment; + /** Replace this comment with new content */ + replace(content: Content, options?: ContentOptions): Comment; + /** Remove this comment */ + remove(): Comment; + } - interface Element { - /** The tag name in lowercase (e.g. "div", "span") */ - tagName: string; - /** Iterator for the element's attributes */ - readonly attributes: IterableIterator<[string, string]>; - /** Whether this element was removed */ - readonly removed: boolean; - /** Whether the element is explicitly self-closing, e.g. */ - readonly selfClosing: boolean; - /** - * Whether the element can have inner content. Returns `true` unless - * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) - * - or it's self-closing in a foreign context (eg. in SVG, MathML). - */ - readonly canHaveContent: boolean; - /** The element's namespace URI */ - readonly namespaceURI: string; - /** Get an attribute value by name */ - getAttribute(name: string): string | null; - /** Check if an attribute exists */ - hasAttribute(name: string): boolean; - /** Set an attribute value */ - setAttribute(name: string, value: string): Element; - /** Remove an attribute */ - removeAttribute(name: string): Element; - /** Insert content before this element */ - before(content: Content, options?: ContentOptions): Element; - /** Insert content after this element */ - after(content: Content, options?: ContentOptions): Element; - /** Insert content at the start of this element */ - prepend(content: Content, options?: ContentOptions): Element; - /** Insert content at the end of this element */ - append(content: Content, options?: ContentOptions): Element; - /** Replace this element with new content */ - replace(content: Content, options?: ContentOptions): Element; - /** Remove this element and its contents */ - remove(): Element; - /** Remove this element but keep its contents */ - removeAndKeepContent(): Element; - /** Set the inner content of this element */ - setInnerContent(content: Content, options?: ContentOptions): Element; - /** Add a handler for the end tag of this element */ - onEndTag(handler: (tag: EndTag) => void | Promise): void; - } + interface Element { + /** The tag name in lowercase (e.g. "div", "span") */ + tagName: string; + /** Iterator for the element's attributes */ + readonly attributes: IterableIterator<[string, string]>; + /** Whether this element was removed */ + readonly removed: boolean; + /** Whether the element is explicitly self-closing, e.g. */ + readonly selfClosing: boolean; + /** + * Whether the element can have inner content. Returns `true` unless + * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) + * - or it's self-closing in a foreign context (eg. in SVG, MathML). + */ + readonly canHaveContent: boolean; + /** The element's namespace URI */ + readonly namespaceURI: string; + /** Get an attribute value by name */ + getAttribute(name: string): string | null; + /** Check if an attribute exists */ + hasAttribute(name: string): boolean; + /** Set an attribute value */ + setAttribute(name: string, value: string): Element; + /** Remove an attribute */ + removeAttribute(name: string): Element; + /** Insert content before this element */ + before(content: Content, options?: ContentOptions): Element; + /** Insert content after this element */ + after(content: Content, options?: ContentOptions): Element; + /** Insert content at the start of this element */ + prepend(content: Content, options?: ContentOptions): Element; + /** Insert content at the end of this element */ + append(content: Content, options?: ContentOptions): Element; + /** Replace this element with new content */ + replace(content: Content, options?: ContentOptions): Element; + /** Remove this element and its contents */ + remove(): Element; + /** Remove this element but keep its contents */ + removeAndKeepContent(): Element; + /** Set the inner content of this element */ + setInnerContent(content: Content, options?: ContentOptions): Element; + /** Add a handler for the end tag of this element */ + onEndTag(handler: (tag: EndTag) => void | Promise): void; + } - interface EndTag { - /** The tag name in lowercase */ - name: string; - /** Insert content before this end tag */ - before(content: Content, options?: ContentOptions): EndTag; - /** Insert content after this end tag */ - after(content: Content, options?: ContentOptions): EndTag; - /** Remove this end tag */ - remove(): EndTag; - } + interface EndTag { + /** The tag name in lowercase */ + name: string; + /** Insert content before this end tag */ + before(content: Content, options?: ContentOptions): EndTag; + /** Insert content after this end tag */ + after(content: Content, options?: ContentOptions): EndTag; + /** Remove this end tag */ + remove(): EndTag; + } } /** @@ -149,41 +149,36 @@ declare namespace HTMLRewriterTypes { * ``` */ declare class HTMLRewriter { - constructor(); - /** - * Add handlers for elements matching a CSS selector - * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") - * @param handlers - Object containing handler functions for elements, comments, and text nodes - */ - on( - selector: string, - handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers, - ): HTMLRewriter; + constructor(); + /** + * Add handlers for elements matching a CSS selector + * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") + * @param handlers - Object containing handler functions for elements, comments, and text nodes + */ + on(selector: string, handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers): HTMLRewriter; - /** - * Add handlers for document-level events - * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end - */ - onDocument( - handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers, - ): HTMLRewriter; + /** + * Add handlers for document-level events + * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end + */ + onDocument(handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers): HTMLRewriter; - /** - * Transform HTML content - * @param input - The HTML to transform - * @returns A new {@link Response} with the transformed HTML - */ - transform(input: Response | Blob | Bun.BufferSource): Response; - /** - * Transform HTML content - * @param input - The HTML string to transform - * @returns A new {@link String} containing the transformed HTML - */ - transform(input: string): string; - /** - * Transform HTML content - * @param input - The HTML to transform as a {@link ArrayBuffer} - * @returns A new {@link ArrayBuffer} with the transformed HTML - */ - transform(input: ArrayBuffer): ArrayBuffer; + /** + * Transform HTML content + * @param input - The HTML to transform + * @returns A new {@link Response} with the transformed HTML + */ + transform(input: Response | Blob | Bun.BufferSource): Response; + /** + * Transform HTML content + * @param input - The HTML string to transform + * @returns A new {@link String} containing the transformed HTML + */ + transform(input: string): string; + /** + * Transform HTML content + * @param input - The HTML to transform as a {@link ArrayBuffer} + * @returns A new {@link ArrayBuffer} with the transformed HTML + */ + transform(input: ArrayBuffer): ArrayBuffer; } diff --git a/packages/bun-types/jsc.d.ts b/packages/bun-types/jsc.d.ts index c5942da2813fb5..2a07534586516c 100644 --- a/packages/bun-types/jsc.d.ts +++ b/packages/bun-types/jsc.d.ts @@ -1,243 +1,229 @@ declare module "bun:jsc" { - /** - * This used to be called "describe" but it could be confused with the test runner. - */ - function jscDescribe(value: any): string; - function jscDescribeArray(args: any[]): string; - function gcAndSweep(): number; - function fullGC(): number; - function edenGC(): number; - function heapSize(): number; - function heapStats(): { - heapSize: number; - heapCapacity: number; - extraMemorySize: number; - objectCount: number; - protectedObjectCount: number; - globalObjectCount: number; - protectedGlobalObjectCount: number; - objectTypeCounts: Record; - protectedObjectTypeCounts: Record; - }; - function memoryUsage(): { - current: number; - peak: number; - currentCommit: number; - peakCommit: number; - pageFaults: number; - }; - function getRandomSeed(): number; - function setRandomSeed(value: number): void; - function isRope(input: string): boolean; - function callerSourceOrigin(): string; - function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; - function noOSRExitFuzzing( - func: (...args: any[]) => any, - ): (...args: any[]) => any; - function optimizeNextInvocation(func: (...args: any[]) => any): void; - function numberOfDFGCompiles(func: (...args: any[]) => any): number; - function releaseWeakRefs(): void; - function totalCompileTime(func: (...args: any[]) => any): number; - function reoptimizationRetryCount(func: (...args: any[]) => any): number; - function drainMicrotasks(): void; + /** + * This used to be called "describe" but it could be confused with the test runner. + */ + function jscDescribe(value: any): string; + function jscDescribeArray(args: any[]): string; + function gcAndSweep(): number; + function fullGC(): number; + function edenGC(): number; + function heapSize(): number; + function heapStats(): { + heapSize: number; + heapCapacity: number; + extraMemorySize: number; + objectCount: number; + protectedObjectCount: number; + globalObjectCount: number; + protectedGlobalObjectCount: number; + objectTypeCounts: Record; + protectedObjectTypeCounts: Record; + }; + function memoryUsage(): { + current: number; + peak: number; + currentCommit: number; + peakCommit: number; + pageFaults: number; + }; + function getRandomSeed(): number; + function setRandomSeed(value: number): void; + function isRope(input: string): boolean; + function callerSourceOrigin(): string; + function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; + function noOSRExitFuzzing(func: (...args: any[]) => any): (...args: any[]) => any; + function optimizeNextInvocation(func: (...args: any[]) => any): void; + function numberOfDFGCompiles(func: (...args: any[]) => any): number; + function releaseWeakRefs(): void; + function totalCompileTime(func: (...args: any[]) => any): number; + function reoptimizationRetryCount(func: (...args: any[]) => any): number; + function drainMicrotasks(): void; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A SharedArrayBuffer that can be sent to another Bun instance. - */ - function serialize( - value: any, - options?: { binaryType?: "arraybuffer" }, - ): SharedArrayBuffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A SharedArrayBuffer that can be sent to another Bun instance. + */ + function serialize(value: any, options?: { binaryType?: "arraybuffer" }): SharedArrayBuffer; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A Buffer that can be sent to another Bun instance. - */ - function serialize( - value: any, - options?: { binaryType: "nodebuffer" }, - ): Buffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A Buffer that can be sent to another Bun instance. + */ + function serialize(value: any, options?: { binaryType: "nodebuffer" }): Buffer; - /** - * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. - * - * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. - */ - function deserialize( - value: ArrayBufferLike | NodeJS.TypedArray | Buffer, - ): any; + /** + * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. + * + * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. + */ + function deserialize(value: ArrayBufferLike | NodeJS.TypedArray | Buffer): any; - /** - * Set the timezone used by Intl, Date, etc. - * - * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" - * - * @returns The normalized time zone string - * - * You can also set process.env.TZ to the time zone you want to use. - * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` - */ - function setTimeZone(timeZone: string): string; + /** + * Set the timezone used by Intl, Date, etc. + * + * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" + * + * @returns The normalized time zone string + * + * You can also set process.env.TZ to the time zone you want to use. + * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` + */ + function setTimeZone(timeZone: string): string; - interface SamplingProfile { - /** - * A formatted summary of the top functions - * - * Example output: - * ```js - * - * Sampling rate: 100.000000 microseconds. Total samples: 6858 - * Top functions as - * 2948 '#:8' - * 393 'visit#:8' - * 263 'push#:8' - * 164 'scan_ref_scoped#:8' - * 164 'walk#:8' - * 144 'pop#:8' - * 107 'extract_candidates#:8' - * 94 'get#:8' - * 82 'Function#:4294967295' - * 79 'set#:8' - * 67 'forEach#:5' - * 58 'collapse#:8' - * ``` - */ - functions: string; - /** - * A formatted summary of the top bytecodes - * - * Example output: - * ```js - * Tier breakdown: - * ----------------------------------- - * LLInt: 106 (1.545640%) - * Baseline: 2355 (34.339458%) - * DFG: 3290 (47.973170%) - * FTL: 833 (12.146398%) - * js builtin: 132 (1.924759%) - * Wasm: 0 (0.000000%) - * Host: 111 (1.618548%) - * RegExp: 15 (0.218723%) - * C/C++: 0 (0.000000%) - * Unknown Executable: 148 (2.158064%) - * - * Hottest bytecodes as - * 273 'visit#:DFG:bc#63' - * 121 'walk#:DFG:bc#7' - * 119 '#:Baseline:bc#1' - * 82 'Function#:None:' - * 66 '#:DFG:bc#11' - * 65 '#:DFG:bc#33' - * 58 '#:Baseline:bc#7' - * 53 '#:Baseline:bc#23' - * 50 'forEach#:DFG:bc#83' - * 49 'pop#:FTL:bc#65' - * 47 '#:DFG:bc#99' - * 45 '#:DFG:bc#16' - * 44 '#:DFG:bc#7' - * 44 '#:Baseline:bc#30' - * 44 'push#:FTL:bc#214' - * 41 '#:DFG:bc#50' - * 39 'get#:DFG:bc#27' - * 39 '#:Baseline:bc#0' - * 36 '#:DFG:bc#27' - * 36 'Dictionary#:DFG:bc#41' - * 36 'visit#:DFG:bc#81' - * 36 'get#:FTL:bc#11' - * 32 'push#:FTL:bc#49' - * 31 '#:DFG:bc#76' - * 31 '#:DFG:bc#10' - * 31 '#:DFG:bc#73' - * 29 'set#:DFG:bc#28' - * 28 'in_boolean_context#:DFG:bc#104' - * 28 '#:Baseline:' - * 28 'regExpSplitFast#:None:' - * 26 'visit#:DFG:bc#95' - * 26 'pop#:FTL:bc#120' - * 25 '#:DFG:bc#23' - * 25 'push#:FTL:bc#152' - * 24 'push#:FTL:bc#262' - * 24 '#:FTL:bc#10' - * 23 'is_identifier_char#:DFG:bc#22' - * 23 'visit#:DFG:bc#22' - * 22 '#:FTL:bc#27' - * 22 'indexOf#:None:' - * ``` - */ - bytecodes: string; + interface SamplingProfile { + /** + * A formatted summary of the top functions + * + * Example output: + * ```js + * + * Sampling rate: 100.000000 microseconds. Total samples: 6858 + * Top functions as + * 2948 '#:8' + * 393 'visit#:8' + * 263 'push#:8' + * 164 'scan_ref_scoped#:8' + * 164 'walk#:8' + * 144 'pop#:8' + * 107 'extract_candidates#:8' + * 94 'get#:8' + * 82 'Function#:4294967295' + * 79 'set#:8' + * 67 'forEach#:5' + * 58 'collapse#:8' + * ``` + */ + functions: string; + /** + * A formatted summary of the top bytecodes + * + * Example output: + * ```js + * Tier breakdown: + * ----------------------------------- + * LLInt: 106 (1.545640%) + * Baseline: 2355 (34.339458%) + * DFG: 3290 (47.973170%) + * FTL: 833 (12.146398%) + * js builtin: 132 (1.924759%) + * Wasm: 0 (0.000000%) + * Host: 111 (1.618548%) + * RegExp: 15 (0.218723%) + * C/C++: 0 (0.000000%) + * Unknown Executable: 148 (2.158064%) + * + * Hottest bytecodes as + * 273 'visit#:DFG:bc#63' + * 121 'walk#:DFG:bc#7' + * 119 '#:Baseline:bc#1' + * 82 'Function#:None:' + * 66 '#:DFG:bc#11' + * 65 '#:DFG:bc#33' + * 58 '#:Baseline:bc#7' + * 53 '#:Baseline:bc#23' + * 50 'forEach#:DFG:bc#83' + * 49 'pop#:FTL:bc#65' + * 47 '#:DFG:bc#99' + * 45 '#:DFG:bc#16' + * 44 '#:DFG:bc#7' + * 44 '#:Baseline:bc#30' + * 44 'push#:FTL:bc#214' + * 41 '#:DFG:bc#50' + * 39 'get#:DFG:bc#27' + * 39 '#:Baseline:bc#0' + * 36 '#:DFG:bc#27' + * 36 'Dictionary#:DFG:bc#41' + * 36 'visit#:DFG:bc#81' + * 36 'get#:FTL:bc#11' + * 32 'push#:FTL:bc#49' + * 31 '#:DFG:bc#76' + * 31 '#:DFG:bc#10' + * 31 '#:DFG:bc#73' + * 29 'set#:DFG:bc#28' + * 28 'in_boolean_context#:DFG:bc#104' + * 28 '#:Baseline:' + * 28 'regExpSplitFast#:None:' + * 26 'visit#:DFG:bc#95' + * 26 'pop#:FTL:bc#120' + * 25 '#:DFG:bc#23' + * 25 'push#:FTL:bc#152' + * 24 'push#:FTL:bc#262' + * 24 '#:FTL:bc#10' + * 23 'is_identifier_char#:DFG:bc#22' + * 23 'visit#:DFG:bc#22' + * 22 '#:FTL:bc#27' + * 22 'indexOf#:None:' + * ``` + */ + bytecodes: string; - /** - * Stack traces of the top functions - */ - stackTraces: string[]; - } + /** + * Stack traces of the top functions + */ + stackTraces: string[]; + } - /** - * Run JavaScriptCore's sampling profiler for a particular function - * - * This is pretty low-level. - * - * Things to know: - * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation - * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile - * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile - * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile - */ - function profile any>( - callback: T, - sampleInterval?: number, - ...args: Parameters - ): ReturnType extends Promise - ? Promise - : SamplingProfile; + /** + * Run JavaScriptCore's sampling profiler for a particular function + * + * This is pretty low-level. + * + * Things to know: + * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation + * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile + * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile + * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile + */ + function profile any>( + callback: T, + sampleInterval?: number, + ...args: Parameters + ): ReturnType extends Promise ? Promise : SamplingProfile; - /** - * This returns objects which native code has explicitly protected from being - * garbage collected - * - * By calling this function you create another reference to the object, which - * will further prevent it from being garbage collected - * - * This function is mostly a debugging tool for bun itself. - * - * Warning: not all objects returned are supposed to be observable from JavaScript - */ - function getProtectedObjects(): any[]; + /** + * This returns objects which native code has explicitly protected from being + * garbage collected + * + * By calling this function you create another reference to the object, which + * will further prevent it from being garbage collected + * + * This function is mostly a debugging tool for bun itself. + * + * Warning: not all objects returned are supposed to be observable from JavaScript + */ + function getProtectedObjects(): any[]; - /** - * Start a remote debugging socket server on the given port. - * - * This exposes JavaScriptCore's built-in debugging server. - * - * This is untested. May not be supported yet on macOS - */ - function startRemoteDebugger(host?: string, port?: number): void; + /** + * Start a remote debugging socket server on the given port. + * + * This exposes JavaScriptCore's built-in debugging server. + * + * This is untested. May not be supported yet on macOS + */ + function startRemoteDebugger(host?: string, port?: number): void; - /** - * Run JavaScriptCore's sampling profiler - */ - function startSamplingProfiler(optionalDirectory?: string): void; + /** + * Run JavaScriptCore's sampling profiler + */ + function startSamplingProfiler(optionalDirectory?: string): void; - /** - * Non-recursively estimate the memory usage of an object, excluding the memory usage of - * properties or other objects it references. For more accurate per-object - * memory usage, use {@link Bun.generateHeapSnapshot}. - * - * This is a best-effort estimate. It may not be 100% accurate. When it's - * wrong, it may mean the memory is non-contiguous (such as a large array). - * - * Passing a primitive type that isn't heap allocated returns 0. - */ - function estimateShallowMemoryUsageOf( - value: object | CallableFunction | bigint | symbol | string, - ): number; + /** + * Non-recursively estimate the memory usage of an object, excluding the memory usage of + * properties or other objects it references. For more accurate per-object + * memory usage, use {@link Bun.generateHeapSnapshot}. + * + * This is a best-effort estimate. It may not be 100% accurate. When it's + * wrong, it may mean the memory is non-contiguous (such as a large array). + * + * Passing a primitive type that isn't heap allocated returns 0. + */ + function estimateShallowMemoryUsageOf(value: object | CallableFunction | bigint | symbol | string): number; } diff --git a/packages/bun-types/overrides.d.ts b/packages/bun-types/overrides.d.ts index e679e20ae30824..2c9563224342e2 100644 --- a/packages/bun-types/overrides.d.ts +++ b/packages/bun-types/overrides.d.ts @@ -3,72 +3,62 @@ export {}; import type { BunFile, Env, PathLike } from "bun"; declare global { - namespace NodeJS { - interface ProcessVersions extends Dict { - bun: string; - } - interface ProcessEnv extends Env {} - } + namespace NodeJS { + interface ProcessVersions extends Dict { + bun: string; + } + interface ProcessEnv extends Env {} + } } declare module "fs/promises" { - function exists(path: PathLike): Promise; + function exists(path: PathLike): Promise; } declare module "tls" { - interface BunConnectionOptions - extends Omit { - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: - | string - | Buffer - | NodeJS.TypedArray - | BunFile - | Array - | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: - | string - | Buffer - | NodeJS.TypedArray - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: - | string - | Buffer - | BunFile - | NodeJS.TypedArray - | Array - | undefined; - } + interface BunConnectionOptions extends Omit { + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: string | Buffer | NodeJS.TypedArray | BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: + | string + | Buffer + | NodeJS.TypedArray + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: + | string + | Buffer + | BunFile + | NodeJS.TypedArray + | Array + | undefined; + } - function connect( - options: BunConnectionOptions, - secureConnectListener?: () => void, - ): TLSSocket; + function connect(options: BunConnectionOptions, secureConnectListener?: () => void): TLSSocket; } diff --git a/packages/bun-types/sqlite.d.ts b/packages/bun-types/sqlite.d.ts index 303469772cb98c..dd370d3f46bcc2 100644 --- a/packages/bun-types/sqlite.d.ts +++ b/packages/bun-types/sqlite.d.ts @@ -24,1143 +24,1118 @@ * | `null` | `NULL` | */ declare module "bun:sqlite" { - export class Database implements Disposable { - /** - * Open or create a SQLite3 database - * - * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. - * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. - * - * @example - * - * ```ts - * const db = new Database("mydb.sqlite"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open an in-memory database - * - * ```ts - * const db = new Database(":memory:"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open read-only - * - * ```ts - * const db = new Database("mydb.sqlite", {readonly: true}); - * ``` - */ - constructor( - filename?: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; + export class Database implements Disposable { + /** + * Open or create a SQLite3 database + * + * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. + * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. + * + * @example + * + * ```ts + * const db = new Database("mydb.sqlite"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open an in-memory database + * + * ```ts + * const db = new Database(":memory:"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open read-only + * + * ```ts + * const db = new Database("mydb.sqlite", {readonly: true}); + * ``` + */ + constructor( + filename?: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; - /** - * When set to `true`, integers are returned as `bigint` types. - * - * When set to `false`, integers are returned as `number` types and truncated to 52 bits. - * - * @default false - * @since v1.1.14 - */ - safeIntegers?: boolean; + /** + * When set to `true`, integers are returned as `bigint` types. + * + * When set to `false`, integers are returned as `number` types and truncated to 52 bits. + * + * @default false + * @since v1.1.14 + */ + safeIntegers?: boolean; - /** - * When set to `false` or `undefined`: - * - Queries missing bound parameters will NOT throw an error - * - Bound named parameters in JavaScript need to exactly match the SQL query. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: false }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); - * ``` - * - * When set to `true`: - * - Queries missing bound parameters will throw an error - * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: true }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); - * ``` - * @since v1.1.14 - */ - strict?: boolean; - }, - ); + /** + * When set to `false` or `undefined`: + * - Queries missing bound parameters will NOT throw an error + * - Bound named parameters in JavaScript need to exactly match the SQL query. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: false }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); + * ``` + * + * When set to `true`: + * - Queries missing bound parameters will throw an error + * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: true }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); + * ``` + * @since v1.1.14 + */ + strict?: boolean; + }, + ); - /** - * This is an alias of `new Database()` - * - * See {@link Database} - */ - static open( - filename: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; - }, - ): Database; + /** + * This is an alias of `new Database()` + * + * See {@link Database} + */ + static open( + filename: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; + }, + ): Database; - /** - * Execute a SQL query **without returning any results**. - * - * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * ``` - * - * Useful for queries like: - * - `CREATE TABLE` - * - `INSERT INTO` - * - `UPDATE` - * - `DELETE FROM` - * - `DROP TABLE` - * - `PRAGMA` - * - `ATTACH DATABASE` - * - `DETACH DATABASE` - * - `REINDEX` - * - `VACUUM` - * - `EXPLAIN ANALYZE` - * - `CREATE INDEX` - * - `CREATE TRIGGER` - * - `CREATE VIEW` - * - `CREATE VIRTUAL TABLE` - * - `CREATE TEMPORARY TABLE` - * - * @param sql The SQL query to run - * - * @param bindings Optional bindings for the query - * - * @returns `Database` instance - * - * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. - * - * * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run( - sqlQuery: string, - ...bindings: ParamsType[] - ): Changes; - /** + /** + * Execute a SQL query **without returning any results**. + * + * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * ``` + * + * Useful for queries like: + * - `CREATE TABLE` + * - `INSERT INTO` + * - `UPDATE` + * - `DELETE FROM` + * - `DROP TABLE` + * - `PRAGMA` + * - `ATTACH DATABASE` + * - `DETACH DATABASE` + * - `REINDEX` + * - `VACUUM` + * - `EXPLAIN ANALYZE` + * - `CREATE INDEX` + * - `CREATE TRIGGER` + * - `CREATE VIEW` + * - `CREATE VIRTUAL TABLE` + * - `CREATE TEMPORARY TABLE` + * + * @param sql The SQL query to run + * + * @param bindings Optional bindings for the query + * + * @returns `Database` instance + * + * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. + * + * * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(sqlQuery: string, ...bindings: ParamsType[]): Changes; + /** This is an alias of {@link Database.prototype.run} */ - exec( - sqlQuery: string, - ...bindings: ParamsType[] - ): Changes; + exec(sqlQuery: string, ...bindings: ParamsType[]): Changes; - /** - * Compile a SQL query and return a {@link Statement} object. This is the - * same as {@link prepare} except that it caches the compiled query. - * - * This **does not execute** the query, but instead prepares it for later - * execution and caches the compiled query if possible. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * - * // run the query again - * stmt.all(); - * ``` - * - * @param sql The SQL query to compile - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - query( - sqlQuery: string, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. This is the + * same as {@link prepare} except that it caches the compiled query. + * + * This **does not execute** the query, but instead prepares it for later + * execution and caches the compiled query if possible. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * + * // run the query again + * stmt.all(); + * ``` + * + * @param sql The SQL query to compile + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + query( + sqlQuery: string, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Compile a SQL query and return a {@link Statement} object. - * - * This does not cache the compiled query and does not execute the query. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * ``` - * - * @param sql The SQL query to compile - * @param params Optional bindings for the query - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - prepare< - ReturnType, - ParamsType extends SQLQueryBindings | SQLQueryBindings[], - >( - sqlQuery: string, - params?: ParamsType, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. + * + * This does not cache the compiled query and does not execute the query. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * ``` + * + * @param sql The SQL query to compile + * @param params Optional bindings for the query + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + prepare( + sqlQuery: string, + params?: ParamsType, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Is the database in a transaction? - * - * @returns `true` if the database is in a transaction, `false` otherwise - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * db.run("BEGIN"); - * db.run("INSERT INTO foo VALUES (?)", ["qux"]); - * console.log(db.inTransaction()); - * ``` - */ - get inTransaction(): boolean; + /** + * Is the database in a transaction? + * + * @returns `true` if the database is in a transaction, `false` otherwise + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * db.run("BEGIN"); + * db.run("INSERT INTO foo VALUES (?)", ["qux"]); + * console.log(db.inTransaction()); + * ``` + */ + get inTransaction(): boolean; - /** - * Close the database connection. - * - * It is safe to call this method multiple times. If the database is already - * closed, this is a no-op. Running queries after the database has been - * closed will throw an error. - * - * @example - * ```ts - * db.close(); - * ``` - * This is called automatically when the database instance is garbage collected. - * - * Internally, this calls `sqlite3_close_v2`. - */ - close( - /** - * If `true`, then the database will throw an error if it is in use - * @default false - * - * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. - * - * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). - * - * Bun will automatically call close by default when the database instance is garbage collected. - * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. - */ - throwOnError?: boolean, - ): void; + /** + * Close the database connection. + * + * It is safe to call this method multiple times. If the database is already + * closed, this is a no-op. Running queries after the database has been + * closed will throw an error. + * + * @example + * ```ts + * db.close(); + * ``` + * This is called automatically when the database instance is garbage collected. + * + * Internally, this calls `sqlite3_close_v2`. + */ + close( + /** + * If `true`, then the database will throw an error if it is in use + * @default false + * + * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. + * + * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). + * + * Bun will automatically call close by default when the database instance is garbage collected. + * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. + */ + throwOnError?: boolean, + ): void; - /** - * The filename passed when `new Database()` was called - * @example - * ```ts - * const db = new Database("mydb.sqlite"); - * console.log(db.filename); - * // => "mydb.sqlite" - * ``` - */ - readonly filename: string; + /** + * The filename passed when `new Database()` was called + * @example + * ```ts + * const db = new Database("mydb.sqlite"); + * console.log(db.filename); + * // => "mydb.sqlite" + * ``` + */ + readonly filename: string; - /** - * The underlying `sqlite3` database handle - * - * In native code, this is not a file descriptor, but an index into an array of database handles - */ - readonly handle: number; + /** + * The underlying `sqlite3` database handle + * + * In native code, this is not a file descriptor, but an index into an array of database handles + */ + readonly handle: number; - /** - * Load a SQLite3 extension - * - * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} - * - * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. - * - * @param extension name/path of the extension to load - * @param entryPoint optional entry point of the extension - */ - loadExtension(extension: string, entryPoint?: string): void; + /** + * Load a SQLite3 extension + * + * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} + * + * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. + * + * @param extension name/path of the extension to load + * @param entryPoint optional entry point of the extension + */ + loadExtension(extension: string, entryPoint?: string): void; - /** - * Change the dynamic library path to SQLite - * - * @note macOS-only - * - * This only works before SQLite is loaded, so - * that's before you call `new Database()`. - * - * It can only be run once because this will load - * the SQLite library into the process. - * - * @param path The path to the SQLite library - */ - static setCustomSQLite(path: string): boolean; + /** + * Change the dynamic library path to SQLite + * + * @note macOS-only + * + * This only works before SQLite is loaded, so + * that's before you call `new Database()`. + * + * It can only be run once because this will load + * the SQLite library into the process. + * + * @param path The path to the SQLite library + */ + static setCustomSQLite(path: string): boolean; - [Symbol.dispose](): void; + [Symbol.dispose](): void; - /** - * Creates a function that always runs inside a transaction. When the - * function is invoked, it will begin a new transaction. When the function - * returns, the transaction will be committed. If an exception is thrown, - * the transaction will be rolled back (and the exception will propagate as - * usual). - * - * @param insideTransaction The callback which runs inside a transaction - * - * @example - * ```ts - * // setup - * import { Database } from "bun:sqlite"; - * const db = Database.open(":memory:"); - * db.exec( - * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" - * ); - * - * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); - * const insertMany = db.transaction((cats) => { - * for (const cat of cats) insert.run(cat); - * }); - * - * insertMany([ - * { $name: "Joey", $age: 2 }, - * { $name: "Sally", $age: 4 }, - * { $name: "Junior", $age: 1 }, - * ]); - * ``` - */ - transaction(insideTransaction: (...args: any) => void): CallableFunction & { - /** - * uses "BEGIN DEFERRED" - */ - deferred: (...args: any) => void; - /** - * uses "BEGIN IMMEDIATE" - */ - immediate: (...args: any) => void; - /** - * uses "BEGIN EXCLUSIVE" - */ - exclusive: (...args: any) => void; - }; + /** + * Creates a function that always runs inside a transaction. When the + * function is invoked, it will begin a new transaction. When the function + * returns, the transaction will be committed. If an exception is thrown, + * the transaction will be rolled back (and the exception will propagate as + * usual). + * + * @param insideTransaction The callback which runs inside a transaction + * + * @example + * ```ts + * // setup + * import { Database } from "bun:sqlite"; + * const db = Database.open(":memory:"); + * db.exec( + * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" + * ); + * + * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); + * const insertMany = db.transaction((cats) => { + * for (const cat of cats) insert.run(cat); + * }); + * + * insertMany([ + * { $name: "Joey", $age: 2 }, + * { $name: "Sally", $age: 4 }, + * { $name: "Junior", $age: 1 }, + * ]); + * ``` + */ + transaction(insideTransaction: (...args: any) => void): CallableFunction & { + /** + * uses "BEGIN DEFERRED" + */ + deferred: (...args: any) => void; + /** + * uses "BEGIN IMMEDIATE" + */ + immediate: (...args: any) => void; + /** + * uses "BEGIN EXCLUSIVE" + */ + exclusive: (...args: any) => void; + }; - /** - * Save the database to an in-memory {@link Buffer} object. - * - * Internally, this calls `sqlite3_serialize`. - * - * @param name Name to save the database as @default "main" - * @returns Buffer containing the serialized database - */ - serialize(name?: string): Buffer; + /** + * Save the database to an in-memory {@link Buffer} object. + * + * Internally, this calls `sqlite3_serialize`. + * + * @param name Name to save the database as @default "main" + * @returns Buffer containing the serialized database + */ + serialize(name?: string): Buffer; - /** - * Load a serialized SQLite3 database - * - * Internally, this calls `sqlite3_deserialize`. - * - * @param serialized Data to load - * @returns `Database` instance - * - * @example - * ```ts - * test("supports serialize/deserialize", () => { - * const db = Database.open(":memory:"); - * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); - * db.exec('INSERT INTO test (name) VALUES ("Hello")'); - * db.exec('INSERT INTO test (name) VALUES ("World")'); - * - * const input = db.serialize(); - * const db2 = new Database(input); - * - * const stmt = db2.prepare("SELECT * FROM test"); - * expect(JSON.stringify(stmt.get())).toBe( - * JSON.stringify({ - * id: 1, - * name: "Hello", - * }), - * ); - * - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * ]), - * ); - * db2.exec("insert into test (name) values ('foo')"); - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * { - * id: 3, - * name: "foo", - * }, - * ]), - * ); - * - * const db3 = Database.deserialize(input, true); - * try { - * db3.exec("insert into test (name) values ('foo')"); - * throw new Error("Expected error"); - * } catch (e) { - * expect(e.message).toBe("attempt to write a readonly database"); - * } - * }); - * ``` - */ - static deserialize( - serialized: NodeJS.TypedArray | ArrayBufferLike, - isReadOnly?: boolean, - ): Database; + /** + * Load a serialized SQLite3 database + * + * Internally, this calls `sqlite3_deserialize`. + * + * @param serialized Data to load + * @returns `Database` instance + * + * @example + * ```ts + * test("supports serialize/deserialize", () => { + * const db = Database.open(":memory:"); + * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); + * db.exec('INSERT INTO test (name) VALUES ("Hello")'); + * db.exec('INSERT INTO test (name) VALUES ("World")'); + * + * const input = db.serialize(); + * const db2 = new Database(input); + * + * const stmt = db2.prepare("SELECT * FROM test"); + * expect(JSON.stringify(stmt.get())).toBe( + * JSON.stringify({ + * id: 1, + * name: "Hello", + * }), + * ); + * + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * ]), + * ); + * db2.exec("insert into test (name) values ('foo')"); + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * { + * id: 3, + * name: "foo", + * }, + * ]), + * ); + * + * const db3 = Database.deserialize(input, true); + * try { + * db3.exec("insert into test (name) values ('foo')"); + * throw new Error("Expected error"); + * } catch (e) { + * expect(e.message).toBe("attempt to write a readonly database"); + * } + * }); + * ``` + */ + static deserialize(serialized: NodeJS.TypedArray | ArrayBufferLike, isReadOnly?: boolean): Database; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(op: number, arg?: ArrayBufferView | number): number; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl( - zDbName: string, - op: number, - arg?: ArrayBufferView | number, - ): number; - } + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(op: number, arg?: ArrayBufferView | number): number; + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(zDbName: string, op: number, arg?: ArrayBufferView | number): number; + } - /** - * A prepared statement. - * - * This is returned by {@link Database.prepare} and {@link Database.query}. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.all("baz"); - * // => [{bar: "baz"}] - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.get("baz"); - * // => {bar: "baz"} - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.run("baz"); - * // => undefined - * ``` - */ - export class Statement< - ReturnType = unknown, - ParamsType extends SQLQueryBindings[] = any[], - > implements Disposable - { - /** - * Creates a new prepared statement from native code. - * - * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. - */ - constructor(nativeHandle: any); + /** + * A prepared statement. + * + * This is returned by {@link Database.prepare} and {@link Database.query}. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.all("baz"); + * // => [{bar: "baz"}] + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.get("baz"); + * // => {bar: "baz"} + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.run("baz"); + * // => undefined + * ``` + */ + export class Statement implements Disposable { + /** + * Creates a new prepared statement from native code. + * + * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. + */ + constructor(nativeHandle: any); - /** - * Execute the prepared statement and return all results as objects. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.all("baz"); - * // => [{bar: "baz"}] - * - * stmt.all(); - * // => [] - * - * stmt.all("foo"); - * // => [{bar: "foo"}] - * ``` - */ - all(...params: ParamsType): ReturnType[]; + /** + * Execute the prepared statement and return all results as objects. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.all("baz"); + * // => [{bar: "baz"}] + * + * stmt.all(); + * // => [] + * + * stmt.all("foo"); + * // => [{bar: "foo"}] + * ``` + */ + all(...params: ParamsType): ReturnType[]; - /** - * Execute the prepared statement and return **the first** result. - * - * If no result is returned, this returns `null`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.get("baz"); - * // => {bar: "baz"} - * - * stmt.get(); - * // => null - * - * stmt.get("foo"); - * // => {bar: "foo"} - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - get(...params: ParamsType): ReturnType | null; + /** + * Execute the prepared statement and return **the first** result. + * + * If no result is returned, this returns `null`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.get("baz"); + * // => {bar: "baz"} + * + * stmt.get(); + * // => null + * + * stmt.get("foo"); + * // => {bar: "foo"} + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + get(...params: ParamsType): ReturnType | null; - /** - * Execute the prepared statement and return an - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - */ - iterate(...params: ParamsType): IterableIterator; - [Symbol.iterator](): IterableIterator; + /** + * Execute the prepared statement and return an + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + */ + iterate(...params: ParamsType): IterableIterator; + [Symbol.iterator](): IterableIterator; - /** - * Execute the prepared statement. This returns `undefined`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("UPDATE foo SET bar = ?"); - * stmt.run("baz"); - * // => undefined - * - * stmt.run(); - * // => undefined - * - * stmt.run("foo"); - * // => undefined - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(...params: ParamsType): Changes; + /** + * Execute the prepared statement. This returns `undefined`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("UPDATE foo SET bar = ?"); + * stmt.run("baz"); + * // => undefined + * + * stmt.run(); + * // => undefined + * + * stmt.run("foo"); + * // => undefined + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(...params: ParamsType): Changes; - /** - * Execute the prepared statement and return the results as an array of arrays. - * - * In Bun v0.6.7 and earlier, this method returned `null` if there were no - * results instead of `[]`. This was changed in v0.6.8 to align - * more with what people expect. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.values("baz"); - * // => [['baz']] - * - * stmt.values(); - * // => [['baz']] - * - * stmt.values("foo"); - * // => [['foo']] - * - * stmt.values("not-found"); - * // => [] - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | ---------------|-------------| - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - values( - ...params: ParamsType - ): Array>; + /** + * Execute the prepared statement and return the results as an array of arrays. + * + * In Bun v0.6.7 and earlier, this method returned `null` if there were no + * results instead of `[]`. This was changed in v0.6.8 to align + * more with what people expect. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.values("baz"); + * // => [['baz']] + * + * stmt.values(); + * // => [['baz']] + * + * stmt.values("foo"); + * // => [['foo']] + * + * stmt.values("not-found"); + * // => [] + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | ---------------|-------------| + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + values(...params: ParamsType): Array>; - /** - * The names of the columns returned by the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); - * - * console.log(stmt.columnNames); - * // => ["bar"] - * ``` - */ - readonly columnNames: string[]; + /** + * The names of the columns returned by the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); + * + * console.log(stmt.columnNames); + * // => ["bar"] + * ``` + */ + readonly columnNames: string[]; - /** - * The number of parameters expected in the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * console.log(stmt.paramsCount); - * // => 1 - * ``` - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); - * console.log(stmt.paramsCount); - * // => 2 - * ``` - */ - readonly paramsCount: number; + /** + * The number of parameters expected in the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * console.log(stmt.paramsCount); + * // => 1 + * ``` + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); + * console.log(stmt.paramsCount); + * // => 2 + * ``` + */ + readonly paramsCount: number; - /** - * Finalize the prepared statement, freeing the resources used by the - * statement and preventing it from being executed again. - * - * This is called automatically when the prepared statement is garbage collected. - * - * It is safe to call this multiple times. Calling this on a finalized - * statement has no effect. - * - * Internally, this calls `sqlite3_finalize`. - */ - finalize(): void; + /** + * Finalize the prepared statement, freeing the resources used by the + * statement and preventing it from being executed again. + * + * This is called automatically when the prepared statement is garbage collected. + * + * It is safe to call this multiple times. Calling this on a finalized + * statement has no effect. + * + * Internally, this calls `sqlite3_finalize`. + */ + finalize(): void; - /** - * Calls {@link finalize} if it wasn't already called. - */ - [Symbol.dispose](): void; + /** + * Calls {@link finalize} if it wasn't already called. + */ + [Symbol.dispose](): void; - /** - * Return the expanded SQL string for the prepared statement. - * - * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); - * console.log(stmt.toString()); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * console.log(stmt); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * ``` - */ - toString(): string; + /** + * Return the expanded SQL string for the prepared statement. + * + * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); + * console.log(stmt.toString()); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * console.log(stmt); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * ``` + */ + toString(): string; - /** - * - * Make {@link get} and {@link all} return an instance of the provided - * `Class` instead of the default `Object`. - * - * @param Class A class to use - * @returns The same statement instance, modified to return an instance of `Class` - * - * This lets you attach methods, getters, and setters to the returned - * objects. - * - * For performance reasons, constructors for classes are not called, which means - * initializers will not be called and private fields will not be - * accessible. - * - * @example - * - * ## Custom class - * ```ts - * class User { - * rawBirthdate: string; - * get birthdate() { - * return new Date(this.rawBirthdate); - * } - * } - * - * const db = new Database(":memory:"); - * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); - * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); - * const query = db.query("SELECT * FROM users"); - * query.as(User); - * const user = query.get(); - * console.log(user.birthdate); - * // => Date(1995, 12, 19) - * ``` - */ - as(Class: new (...args: any[]) => T): Statement; + /** + * + * Make {@link get} and {@link all} return an instance of the provided + * `Class` instead of the default `Object`. + * + * @param Class A class to use + * @returns The same statement instance, modified to return an instance of `Class` + * + * This lets you attach methods, getters, and setters to the returned + * objects. + * + * For performance reasons, constructors for classes are not called, which means + * initializers will not be called and private fields will not be + * accessible. + * + * @example + * + * ## Custom class + * ```ts + * class User { + * rawBirthdate: string; + * get birthdate() { + * return new Date(this.rawBirthdate); + * } + * } + * + * const db = new Database(":memory:"); + * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); + * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); + * const query = db.query("SELECT * FROM users"); + * query.as(User); + * const user = query.get(); + * console.log(user.birthdate); + * // => Date(1995, 12, 19) + * ``` + */ + as(Class: new (...args: any[]) => T): Statement; - /** - * Native object representing the underlying `sqlite3_stmt` - * - * This is left untyped because the ABI of the native bindings may change at any time. - */ - readonly native: any; - } + /** + * Native object representing the underlying `sqlite3_stmt` + * + * This is left untyped because the ABI of the native bindings may change at any time. + */ + readonly native: any; + } - /** - * Constants from `sqlite3.h` - * - * This list isn't exhaustive, but some of the ones which are relevant - */ - export const constants: { - /** - * Open the database as read-only (no write operations, no create). - * @constant 0x00000001 - */ - SQLITE_OPEN_READONLY: number; - /** - * Open the database for reading and writing - * @constant 0x00000002 - */ - SQLITE_OPEN_READWRITE: number; - /** - * Allow creating a new database - * @constant 0x00000004 - */ - SQLITE_OPEN_CREATE: number; - /** - * @constant 0x00000008 - */ - SQLITE_OPEN_DELETEONCLOSE: number; - /** - * @constant 0x00000010 - */ - SQLITE_OPEN_EXCLUSIVE: number; - /** - * @constant 0x00000020 - */ - SQLITE_OPEN_AUTOPROXY: number; - /** - * @constant 0x00000040 - */ - SQLITE_OPEN_URI: number; - /** - * @constant 0x00000080 - */ - SQLITE_OPEN_MEMORY: number; - /** - * @constant 0x00000100 - */ - SQLITE_OPEN_MAIN_DB: number; - /** - * @constant 0x00000200 - */ - SQLITE_OPEN_TEMP_DB: number; - /** - * @constant 0x00000400 - */ - SQLITE_OPEN_TRANSIENT_DB: number; - /** - * @constant 0x00000800 - */ - SQLITE_OPEN_MAIN_JOURNAL: number; - /** - * @constant 0x00001000 - */ - SQLITE_OPEN_TEMP_JOURNAL: number; - /** - * @constant 0x00002000 - */ - SQLITE_OPEN_SUBJOURNAL: number; - /** - * @constant 0x00004000 - */ - SQLITE_OPEN_SUPER_JOURNAL: number; - /** - * @constant 0x00008000 - */ - SQLITE_OPEN_NOMUTEX: number; - /** - * @constant 0x00010000 - */ - SQLITE_OPEN_FULLMUTEX: number; - /** - * @constant 0x00020000 - */ - SQLITE_OPEN_SHAREDCACHE: number; - /** - * @constant 0x00040000 - */ - SQLITE_OPEN_PRIVATECACHE: number; - /** - * @constant 0x00080000 - */ - SQLITE_OPEN_WAL: number; - /** - * @constant 0x01000000 - */ - SQLITE_OPEN_NOFOLLOW: number; - /** - * @constant 0x02000000 - */ - SQLITE_OPEN_EXRESCODE: number; - /** - * @constant 0x01 - */ - SQLITE_PREPARE_PERSISTENT: number; - /** - * @constant 0x02 - */ - SQLITE_PREPARE_NORMALIZE: number; - /** - * @constant 0x04 - */ - SQLITE_PREPARE_NO_VTAB: number; + /** + * Constants from `sqlite3.h` + * + * This list isn't exhaustive, but some of the ones which are relevant + */ + export const constants: { + /** + * Open the database as read-only (no write operations, no create). + * @constant 0x00000001 + */ + SQLITE_OPEN_READONLY: number; + /** + * Open the database for reading and writing + * @constant 0x00000002 + */ + SQLITE_OPEN_READWRITE: number; + /** + * Allow creating a new database + * @constant 0x00000004 + */ + SQLITE_OPEN_CREATE: number; + /** + * @constant 0x00000008 + */ + SQLITE_OPEN_DELETEONCLOSE: number; + /** + * @constant 0x00000010 + */ + SQLITE_OPEN_EXCLUSIVE: number; + /** + * @constant 0x00000020 + */ + SQLITE_OPEN_AUTOPROXY: number; + /** + * @constant 0x00000040 + */ + SQLITE_OPEN_URI: number; + /** + * @constant 0x00000080 + */ + SQLITE_OPEN_MEMORY: number; + /** + * @constant 0x00000100 + */ + SQLITE_OPEN_MAIN_DB: number; + /** + * @constant 0x00000200 + */ + SQLITE_OPEN_TEMP_DB: number; + /** + * @constant 0x00000400 + */ + SQLITE_OPEN_TRANSIENT_DB: number; + /** + * @constant 0x00000800 + */ + SQLITE_OPEN_MAIN_JOURNAL: number; + /** + * @constant 0x00001000 + */ + SQLITE_OPEN_TEMP_JOURNAL: number; + /** + * @constant 0x00002000 + */ + SQLITE_OPEN_SUBJOURNAL: number; + /** + * @constant 0x00004000 + */ + SQLITE_OPEN_SUPER_JOURNAL: number; + /** + * @constant 0x00008000 + */ + SQLITE_OPEN_NOMUTEX: number; + /** + * @constant 0x00010000 + */ + SQLITE_OPEN_FULLMUTEX: number; + /** + * @constant 0x00020000 + */ + SQLITE_OPEN_SHAREDCACHE: number; + /** + * @constant 0x00040000 + */ + SQLITE_OPEN_PRIVATECACHE: number; + /** + * @constant 0x00080000 + */ + SQLITE_OPEN_WAL: number; + /** + * @constant 0x01000000 + */ + SQLITE_OPEN_NOFOLLOW: number; + /** + * @constant 0x02000000 + */ + SQLITE_OPEN_EXRESCODE: number; + /** + * @constant 0x01 + */ + SQLITE_PREPARE_PERSISTENT: number; + /** + * @constant 0x02 + */ + SQLITE_PREPARE_NORMALIZE: number; + /** + * @constant 0x04 + */ + SQLITE_PREPARE_NO_VTAB: number; - /** - * @constant 1 - */ - SQLITE_FCNTL_LOCKSTATE: number; - /** - * @constant 2 - */ - SQLITE_FCNTL_GET_LOCKPROXYFILE: number; - /** - * @constant 3 - */ - SQLITE_FCNTL_SET_LOCKPROXYFILE: number; - /** - * @constant 4 - */ - SQLITE_FCNTL_LAST_ERRNO: number; - /** - * @constant 5 - */ - SQLITE_FCNTL_SIZE_HINT: number; - /** - * @constant 6 - */ - SQLITE_FCNTL_CHUNK_SIZE: number; - /** - * @constant 7 - */ - SQLITE_FCNTL_FILE_POINTER: number; - /** - * @constant 8 - */ - SQLITE_FCNTL_SYNC_OMITTED: number; - /** - * @constant 9 - */ - SQLITE_FCNTL_WIN32_AV_RETRY: number; - /** - * @constant 10 - * - * Control whether or not the WAL is persisted - * Some versions of macOS configure WAL to be persistent by default. - * - * You can change this with code like the below: - * ```ts - * import { Database } from "bun:sqlite"; - * - * const db = Database.open("mydb.sqlite"); - * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); - * // enable WAL - * db.exec("PRAGMA journal_mode = WAL"); - * // .. do some work - * db.close(); - * ``` - * - */ - SQLITE_FCNTL_PERSIST_WAL: number; - /** - * @constant 11 - */ - SQLITE_FCNTL_OVERWRITE: number; - /** - * @constant 12 - */ - SQLITE_FCNTL_VFSNAME: number; - /** - * @constant 13 - */ - SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; - /** - * @constant 14 - */ - SQLITE_FCNTL_PRAGMA: number; - /** - * @constant 15 - */ - SQLITE_FCNTL_BUSYHANDLER: number; - /** - * @constant 16 - */ - SQLITE_FCNTL_TEMPFILENAME: number; - /** - * @constant 18 - */ - SQLITE_FCNTL_MMAP_SIZE: number; - /** - * @constant 19 - */ - SQLITE_FCNTL_TRACE: number; - /** - * @constant 20 - */ - SQLITE_FCNTL_HAS_MOVED: number; - /** - * @constant 21 - */ - SQLITE_FCNTL_SYNC: number; - /** - * @constant 22 - */ - SQLITE_FCNTL_COMMIT_PHASETWO: number; - /** - * @constant 23 - */ - SQLITE_FCNTL_WIN32_SET_HANDLE: number; - /** - * @constant 24 - */ - SQLITE_FCNTL_WAL_BLOCK: number; - /** - * @constant 25 - */ - SQLITE_FCNTL_ZIPVFS: number; - /** - * @constant 26 - */ - SQLITE_FCNTL_RBU: number; - /** - * @constant 27 - */ - SQLITE_FCNTL_VFS_POINTER: number; - /** - * @constant 28 - */ - SQLITE_FCNTL_JOURNAL_POINTER: number; - /** - * @constant 29 - */ - SQLITE_FCNTL_WIN32_GET_HANDLE: number; - /** - * @constant 30 - */ - SQLITE_FCNTL_PDB: number; - /** - * @constant 31 - */ - SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; - /** - * @constant 32 - */ - SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; - /** - * @constant 33 - */ - SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; - /** - * @constant 34 - */ - SQLITE_FCNTL_LOCK_TIMEOUT: number; - /** - * @constant 35 - */ - SQLITE_FCNTL_DATA_VERSION: number; - /** - * @constant 36 - */ - SQLITE_FCNTL_SIZE_LIMIT: number; - /** - * @constant 37 - */ - SQLITE_FCNTL_CKPT_DONE: number; - /** - * @constant 38 - */ - SQLITE_FCNTL_RESERVE_BYTES: number; - /** - * @constant 39 - */ - SQLITE_FCNTL_CKPT_START: number; - /** - * @constant 40 - */ - SQLITE_FCNTL_EXTERNAL_READER: number; - /** - * @constant 41 - */ - SQLITE_FCNTL_CKSM_FILE: number; - /** - * @constant 42 - */ - SQLITE_FCNTL_RESET_CACHE: number; - }; + /** + * @constant 1 + */ + SQLITE_FCNTL_LOCKSTATE: number; + /** + * @constant 2 + */ + SQLITE_FCNTL_GET_LOCKPROXYFILE: number; + /** + * @constant 3 + */ + SQLITE_FCNTL_SET_LOCKPROXYFILE: number; + /** + * @constant 4 + */ + SQLITE_FCNTL_LAST_ERRNO: number; + /** + * @constant 5 + */ + SQLITE_FCNTL_SIZE_HINT: number; + /** + * @constant 6 + */ + SQLITE_FCNTL_CHUNK_SIZE: number; + /** + * @constant 7 + */ + SQLITE_FCNTL_FILE_POINTER: number; + /** + * @constant 8 + */ + SQLITE_FCNTL_SYNC_OMITTED: number; + /** + * @constant 9 + */ + SQLITE_FCNTL_WIN32_AV_RETRY: number; + /** + * @constant 10 + * + * Control whether or not the WAL is persisted + * Some versions of macOS configure WAL to be persistent by default. + * + * You can change this with code like the below: + * ```ts + * import { Database } from "bun:sqlite"; + * + * const db = Database.open("mydb.sqlite"); + * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); + * // enable WAL + * db.exec("PRAGMA journal_mode = WAL"); + * // .. do some work + * db.close(); + * ``` + * + */ + SQLITE_FCNTL_PERSIST_WAL: number; + /** + * @constant 11 + */ + SQLITE_FCNTL_OVERWRITE: number; + /** + * @constant 12 + */ + SQLITE_FCNTL_VFSNAME: number; + /** + * @constant 13 + */ + SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; + /** + * @constant 14 + */ + SQLITE_FCNTL_PRAGMA: number; + /** + * @constant 15 + */ + SQLITE_FCNTL_BUSYHANDLER: number; + /** + * @constant 16 + */ + SQLITE_FCNTL_TEMPFILENAME: number; + /** + * @constant 18 + */ + SQLITE_FCNTL_MMAP_SIZE: number; + /** + * @constant 19 + */ + SQLITE_FCNTL_TRACE: number; + /** + * @constant 20 + */ + SQLITE_FCNTL_HAS_MOVED: number; + /** + * @constant 21 + */ + SQLITE_FCNTL_SYNC: number; + /** + * @constant 22 + */ + SQLITE_FCNTL_COMMIT_PHASETWO: number; + /** + * @constant 23 + */ + SQLITE_FCNTL_WIN32_SET_HANDLE: number; + /** + * @constant 24 + */ + SQLITE_FCNTL_WAL_BLOCK: number; + /** + * @constant 25 + */ + SQLITE_FCNTL_ZIPVFS: number; + /** + * @constant 26 + */ + SQLITE_FCNTL_RBU: number; + /** + * @constant 27 + */ + SQLITE_FCNTL_VFS_POINTER: number; + /** + * @constant 28 + */ + SQLITE_FCNTL_JOURNAL_POINTER: number; + /** + * @constant 29 + */ + SQLITE_FCNTL_WIN32_GET_HANDLE: number; + /** + * @constant 30 + */ + SQLITE_FCNTL_PDB: number; + /** + * @constant 31 + */ + SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; + /** + * @constant 32 + */ + SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; + /** + * @constant 33 + */ + SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; + /** + * @constant 34 + */ + SQLITE_FCNTL_LOCK_TIMEOUT: number; + /** + * @constant 35 + */ + SQLITE_FCNTL_DATA_VERSION: number; + /** + * @constant 36 + */ + SQLITE_FCNTL_SIZE_LIMIT: number; + /** + * @constant 37 + */ + SQLITE_FCNTL_CKPT_DONE: number; + /** + * @constant 38 + */ + SQLITE_FCNTL_RESERVE_BYTES: number; + /** + * @constant 39 + */ + SQLITE_FCNTL_CKPT_START: number; + /** + * @constant 40 + */ + SQLITE_FCNTL_EXTERNAL_READER: number; + /** + * @constant 41 + */ + SQLITE_FCNTL_CKSM_FILE: number; + /** + * @constant 42 + */ + SQLITE_FCNTL_RESET_CACHE: number; + }; - /** - * The native module implementing the sqlite3 C bindings - * - * It is lazily-initialized, so this will return `undefined` until the first - * call to new Database(). - * - * The native module makes no gurantees about ABI stability, so it is left - * untyped - * - * If you need to use it directly for some reason, please let us know because - * that probably points to a deficiency in this API. - */ - export var native: any; + /** + * The native module implementing the sqlite3 C bindings + * + * It is lazily-initialized, so this will return `undefined` until the first + * call to new Database(). + * + * The native module makes no gurantees about ABI stability, so it is left + * untyped + * + * If you need to use it directly for some reason, please let us know because + * that probably points to a deficiency in this API. + */ + export var native: any; - export type SQLQueryBindings = - | string - | bigint - | NodeJS.TypedArray - | number - | boolean - | null - | Record< - string, - string | bigint | NodeJS.TypedArray | number | boolean | null - >; + export type SQLQueryBindings = + | string + | bigint + | NodeJS.TypedArray + | number + | boolean + | null + | Record; - export default Database; + export default Database; - /** - * Errors from SQLite have a name `SQLiteError`. - * - */ - export class SQLiteError extends Error { - readonly name: "SQLiteError"; + /** + * Errors from SQLite have a name `SQLiteError`. + * + */ + export class SQLiteError extends Error { + readonly name: "SQLiteError"; - /** - * The SQLite3 extended error code - * - * This corresponds to `sqlite3_extended_errcode`. - * - * @since v1.0.21 - */ - errno: number; + /** + * The SQLite3 extended error code + * + * This corresponds to `sqlite3_extended_errcode`. + * + * @since v1.0.21 + */ + errno: number; - /** - * The name of the SQLite3 error code - * - * @example - * "SQLITE_CONSTRAINT_UNIQUE" - * - * @since v1.0.21 - */ - code?: string; + /** + * The name of the SQLite3 error code + * + * @example + * "SQLITE_CONSTRAINT_UNIQUE" + * + * @since v1.0.21 + */ + code?: string; - /** - * The UTF-8 byte offset of the sqlite3 query that failed, if known - * - * This corresponds to `sqlite3_error_offset`. - * - * @since v1.0.21 - */ - readonly byteOffset: number; - } + /** + * The UTF-8 byte offset of the sqlite3 query that failed, if known + * + * This corresponds to `sqlite3_error_offset`. + * + * @since v1.0.21 + */ + readonly byteOffset: number; + } - /** - * An object representing the changes made to the database since the last `run` or `exec` call. - * - * @since Bun v1.1.14 - */ - export interface Changes { - /** - * The number of rows changed by the last `run` or `exec` call. - */ - changes: number; + /** + * An object representing the changes made to the database since the last `run` or `exec` call. + * + * @since Bun v1.1.14 + */ + export interface Changes { + /** + * The number of rows changed by the last `run` or `exec` call. + */ + changes: number; - /** - * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. - */ - lastInsertRowid: number | bigint; - } + /** + * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. + */ + lastInsertRowid: number | bigint; + } } diff --git a/packages/bun-types/test.d.ts b/packages/bun-types/test.d.ts index e2d4a01871c381..9c5ef1a2da6670 100644 --- a/packages/bun-types/test.d.ts +++ b/packages/bun-types/test.d.ts @@ -14,1060 +14,995 @@ * ``` */ declare module "bun:test" { - /** - * -- Mocks -- - */ - export type Mock any> = JestMock.Mock; - - export const mock: { - any>(Function?: T): Mock; - - /** - * Replace the module `id` with the return value of `factory`. - * - * This is useful for mocking modules. - * - * @param id module ID to mock - * @param factory a function returning an object that will be used as the exports of the mocked module - * - * @example - * ## Example - * ```ts - * import { mock } from "bun:test"; - * - * mock.module("fs/promises", () => { - * return { - * readFile: () => Promise.resolve("hello world"), - * }; - * }); - * - * import { readFile } from "fs/promises"; - * - * console.log(await readFile("hello.txt", "utf8")); // hello world - * ``` - * - * ## More notes - * - * If the module is already loaded, exports are overwritten with the return - * value of `factory`. If the export didn't exist before, it will not be - * added to existing import statements. This is due to how ESM works. - */ - module(id: string, factory: () => any): void | Promise; - /** - * Restore the previous value of mocks. - */ - restore(): void; - }; - - /** - * Control the system time used by: - * - `Date.now()` - * - `new Date()` - * - `Intl.DateTimeFormat().format()` - * - * In the future, we may add support for more functions, but we haven't done that yet. - * - * @param now The time to set the system time to. If not provided, the system time will be reset. - * @returns `this` - * @since v0.6.13 - * - * ## Set Date to a specific time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); - * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z - * ``` - * ## Reset Date to the current time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(); - * ``` - */ - export function setSystemTime(now?: Date | number): ThisType; - - interface Jest { - restoreAllMocks(): void; - clearAllMocks(): void; - fn any>(func?: T): Mock; - setSystemTime(now?: number | Date): void; - setTimeout(milliseconds: number): void; - } - export const jest: Jest; - export namespace jest { - /** - * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. - */ - type Mock any = (...args: any[]) => any> = - JestMock.Mock; - /** - * Wraps a class, function or object type with Jest mock type definitions. - */ - // type Mocked = JestMock.Mocked; - /** - * Wraps a class type with Jest mock type definitions. - */ - // type MockedClass = JestMock.MockedClass; - /** - * Wraps a function type with Jest mock type definitions. - */ - // type MockedFunction any> = JestMock.MockedFunction; - /** - * Wraps an object type with Jest mock type definitions. - */ - // type MockedObject = JestMock.MockedObject; - /** - * Constructs the type of a replaced property. - */ - type Replaced = JestMock.Replaced; - /** - * Constructs the type of a spied class or function. - */ - type Spied any)> = - JestMock.Spied; - /** - * Constructs the type of a spied class. - */ - type SpiedClass = JestMock.SpiedClass; - /** - * Constructs the type of a spied function. - */ - type SpiedFunction any> = - JestMock.SpiedFunction; - /** - * Constructs the type of a spied getter. - */ - type SpiedGetter = JestMock.SpiedGetter; - /** - * Constructs the type of a spied setter. - */ - type SpiedSetter = JestMock.SpiedSetter; - } - - export function spyOn( - obj: T, - methodOrPropertyValue: K, - ): Mock any ? T[K] : never>; - - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export interface Describe { - (label: string, fn: () => void): void; - /** - * Skips all other tests, except this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - only(label: string, fn: () => void): void; - /** - * Skips this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - skip(label: string, fn: () => void): void; - /** - * Marks this group of tests as to be written or to be fixed. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - todo(label: string, fn?: () => void): void; - /** - * Runs this group of tests, only if `condition` is true. - * - * This is the opposite of `describe.skipIf()`. - * - * @param condition if these tests should run - */ - if(condition: boolean): (label: string, fn: () => void) => void; - /** - * Skips this group of tests, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - skipIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Marks this group of tests as to be written or to be fixed, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - todoIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): ( - label: string, - fn: (...args: [...T]) => void | Promise, - options?: number | TestOptions, - ) => void; - each( - table: readonly T[], - ): ( - label: string, - fn: (...args: Readonly) => void | Promise, - options?: number | TestOptions, - ) => void; - each( - table: T[], - ): ( - label: string, - fn: (...args: T[]) => void | Promise, - options?: number | TestOptions, - ) => void; - } - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export const describe: Describe; - /** - * Runs a function, once, before all the tests. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, tests will not run in this file. - * - * @example - * let database; - * beforeAll(async () => { - * database = await connect("localhost"); - * }); - * - * @param fn the function to run - */ - export function beforeAll( - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Runs a function before each test. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, the test will not run. - * - * @param fn the function to run - */ - export function beforeEach( - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Runs a function, once, after all the tests. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @example - * let database; - * afterAll(async () => { - * if (database) { - * await database.close(); - * } - * }); - * - * @param fn the function to run - */ - export function afterAll( - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Runs a function after each test. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @param fn the function to run - */ - export function afterEach( - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will - * override this value. The default timeout is 5000ms (5 seconds). - * - * @param milliseconds the number of milliseconds for the default timeout - */ - export function setDefaultTimeout(milliseconds: number): void; - export interface TestOptions { - /** - * Sets the timeout for the test in milliseconds. - * - * If the test does not complete within this time, the test will fail with: - * ```ts - * 'Timeout: test {name} timed out after 5000ms' - * ``` - * - * @default 5000 // 5 seconds - */ - timeout?: number; - /** - * Sets the number of times to retry the test if it fails. - * - * @default 0 - */ - retry?: number; - /** - * Sets the number of times to repeat the test, regardless of whether it passed or failed. - * - * @default 0 - */ - repeats?: number; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * test("can set a timeout", async () => { - * await Bun.sleep(100); - * }, 50); // or { timeout: 50 } - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - export interface Test { - ( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - /** - * - If a `number`, sets the timeout for the test in milliseconds. - * - If an `object`, sets the options for the test. - * - `timeout` sets the timeout for the test in milliseconds. - * - `retry` sets the number of times to retry the test if it fails. - * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. - */ - options?: number | TestOptions, - ): void; - /** - * Skips all other tests, except this test when run with the `--only` option. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - only( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Skips this test. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - skip( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as to be written or to be fixed. - * - * These tests will not be executed unless the `--todo` flag is passed. With the flag, - * if the test passes, the test will be marked as `fail` in the results; you will have to - * remove the `.todo` or check that your test - * is implemented correctly. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - todo( - label: string, - fn?: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as failing. - * - * Use `test.failing` when you are writing a test and expecting it to fail. - * These tests will behave the other way normal tests do. If failing test - * will throw any errors then it will pass. If it does not throw it will - * fail. - * - * `test.failing` is very similar to {@link test.todo} except that it always - * runs, regardless of the `--todo` flag. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - failing( - label: string, - fn?: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Runs this test, if `condition` is true. - * - * This is the opposite of `test.skipIf()`. - * - * @param condition if the test should run - */ - if( - condition: boolean, - ): ( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Skips this test, if `condition` is true. - * - * @param condition if the test should be skipped - */ - skipIf( - condition: boolean, - ): ( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Marks this test as to be written or to be fixed, if `condition` is true. - * - * @param condition if the test should be marked TODO - */ - todoIf( - condition: boolean, - ): ( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): ( - label: string, - fn: (...args: [...T]) => void | Promise, - options?: number | TestOptions, - ) => void; - each( - table: readonly T[], - ): ( - label: string, - fn: (...args: Readonly) => void | Promise, - options?: number | TestOptions, - ) => void; - each( - table: T[], - ): ( - label: string, - fn: (...args: T[]) => void | Promise, - options?: number | TestOptions, - ) => void; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * @param label the label for the test - * @param fn the test function - */ - export const test: Test; - export { test as it }; - - /** - * Asserts that a value matches some criteria. - * - * @link https://jestjs.io/docs/expect#reference - * @example - * expect(1 + 1).toBe(2); - * expect([1,2,3]).toContain(2); - * expect(null).toBeNull(); - * - * @param actual The actual (received) value - */ - export const expect: Expect; - - type ExpectNot = Omit & - AsymmetricMatchersBuiltinNegated; - - export interface Expect extends AsymmetricMatchers { - // the `expect()` callable signature - /** - * @param actual the actual value - * @param customFailMessage an optional custom message to display if the test fails. - * */ - - (actual?: T, customFailMessage?: string): Matchers; - - /** - * Access to negated asymmetric matchers. - * - * @example - * expect("abc").toEqual(expect.stringContaining("abc")); // will pass - * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail - */ - not: ExpectNot; - - /** - * Create an asymmetric matcher for a promise resolved value. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass - * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail - * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail - */ - resolvesTo: AsymmetricMatchers; - - /** - * Create an asymmetric matcher for a promise rejected value. - * - * @example - * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass - * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail - * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail - */ - rejectsTo: AsymmetricMatchers; - - /** - * Register new custom matchers. - * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. - * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` - * - * @example - * expect.extend({ - * toBeWithinRange(actual, min, max) { - * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') - * throw new Error('Invalid usage'); - * const pass = actual >= min && actual <= max; - * return { - * pass: pass, - * message: () => `expected ${this.utils.printReceived(actual)} ` + - * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, - * }; - * }, - * }); - * - * test('some test', () => { - * expect(50).toBeWithinRange(0, 100); // will pass - * expect(50).toBeWithinRange(100, 200); // will fail - * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass - * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass - * }); - */ - extend(matchers: ExpectExtendMatchers): void; - - /** - * Throw an error if this function is called. - * - * @param msg Optional message to display if the test fails - * @returns never - * - * @example - * ## Example - * - * ```ts - * import { expect, test } from "bun:test"; - * - * test("!!abc!! is not a module", () => { - * try { - * require("!!abc!!"); - * expect.unreachable(); - * } catch(e) { - * expect(e.name).not.toBe("UnreachableError"); - * } - * }); - * ``` - */ - unreachable(msg?: string | Error): never; - - /** - * Ensures that an assertion is made - */ - hasAssertions(): void; - - /** - * Ensures that a specific number of assertions are made - */ - assertions(neededAssertions: number): void; - } - - /** - * You can extend this interface with declaration merging, in order to add type support for custom matchers. - * @template T Type of the actual value - * - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface Matchers extends MatchersBuiltin {} - - /** - * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} - - export interface AsymmetricMatchersBuiltin { - /** - * Matches anything that was created with the given constructor. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * @example - * - * function randocall(fn) { - * return fn(Math.floor(Math.random() * 6 + 1)); - * } - * - * test('randocall calls its callback with a number', () => { - * const mock = jest.fn(); - * randocall(mock); - * expect(mock).toBeCalledWith(expect.any(Number)); - * }); - */ - any( - constructor: ((...args: any[]) => any) | { new (...args: any[]): any }, - ): AsymmetricMatcher; - /** - * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead - * of a literal value. For example, if you want to check that a mock function is called with a - * non-null argument: - * - * @example - * - * test('map calls its argument with a non-null argument', () => { - * const mock = jest.fn(); - * [1].map(x => mock(x)); - * expect(mock).toBeCalledWith(expect.anything()); - * }); - */ - anything(): AsymmetricMatcher; - /** - * Matches any array made up entirely of elements in the provided array. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - /** - * Matches any object that recursively matches the provided keys. - * This is often handy in conjunction with other asymmetric matchers. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - /** - * Matches any received string that contains the exact expected string - */ - stringContaining(str: string | String): AsymmetricMatcher; - /** - * Matches any string that contains the exact provided string - */ - stringMatching(regex: string | String | RegExp): AsymmetricMatcher; - /** - * Useful when comparing floating point numbers in object properties or array item. - * If you need to compare a number, use `.toBeCloseTo` instead. - * - * The optional `numDigits` argument limits the number of digits to check after the decimal point. - * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - interface AsymmetricMatchersBuiltinNegated { - /** - * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail - * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - */ - resolvesTo: ExpectNot; - - /** - * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. - * - * @example - * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail - * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - */ - rejectsTo: ExpectNot; - - /** - * `expect.not.arrayContaining(array)` matches a received array which - * does not contain all of the elements in the expected array. That is, - * the expected array is not a subset of the received array. It is the - * inverse of `expect.arrayContaining`. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - - /** - * `expect.not.objectContaining(object)` matches any received object - * that does not recursively match the expected properties. That is, the - * expected object is not a subset of the received object. Therefore, - * it matches a received object which contains properties that are not - * in the expected object. It is the inverse of `expect.objectContaining`. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - - /** - * `expect.not.stringContaining(string)` matches the received string - * that does not contain the exact expected string. It is the inverse of - * `expect.stringContaining`. - */ - stringContaining(str: string | String): AsymmetricMatcher; - - /** - * `expect.not.stringMatching(string | regexp)` matches the received - * string that does not match the expected regexp. It is the inverse of - * `expect.stringMatching`. - */ - stringMatching(str: string | String | RegExp): AsymmetricMatcher; - - /** - * `expect.not.closeTo` matches a number not close to the provided value. - * Useful when comparing floating point numbers in object properties or array item. - * It is the inverse of `expect.closeTo`. - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - export interface MatchersBuiltin { - /** - * Negates the result of a subsequent assertion. - * If you know how to test something, `.not` lets you test its opposite. - * - * @example - * expect(1).not.toBe(0); - * expect(null).not.toBeNull(); - * - * @example - * expect(42).toEqual(42); // will pass - * expect(42).not.toEqual(42); // will fail - */ - not: Matchers; - - /** - * Expects the value to be a promise that resolves. - * - * @example - * expect(Promise.resolve(1)).resolves.toBe(1); - */ - resolves: Matchers>; - - /** - * Expects the value to be a promise that rejects. - * - * @example - * expect(Promise.reject("error")).rejects.toBe("error"); - */ - rejects: Matchers; - - /** - * Assertion which passes. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass - * @example - * expect().pass(); - * expect().pass("message is optional"); - * expect().not.pass(); - * expect().not.pass("hi"); - * - * @param message the message to display if the test fails (optional) - */ - pass: (message?: string) => void; - /** - * Assertion which fails. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail - * @example - * expect().fail(); - * expect().fail("message is optional"); - * expect().not.fail(); - * expect().not.fail("hi"); - */ - fail: (message?: string) => void; - /** - * Asserts that a value equals what is expected. - * - * - For non-primitive values, like objects and arrays, - * use `toEqual()` instead. - * - For floating-point numbers, use `toBeCloseTo()` instead. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([123]).toBe([123]); // fail, use toEqual() - * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() - * - * @param expected the expected value - */ - toBe(expected: T): void; - /** - * Asserts that a number is odd. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd - * @example - * expect(1).toBeOdd(); - * expect(2).not.toBeOdd(); - */ - toBeOdd(): void; - /** - * Asserts that a number is even. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven - * @example - * expect(2).toBeEven(); - * expect(1).not.toBeEven(); - */ - toBeEven(): void; - /** - * Asserts that value is close to the expected by floating point precision. - * - * For example, the following fails because arithmetic on decimal (base 10) - * values often have rounding errors in limited precision binary (base 2) representation. - * - * @example - * expect(0.2 + 0.1).toBe(0.3); // fails - * - * Use `toBeCloseTo` to compare floating point numbers for approximate equality. - * - * @example - * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes - * - * @param expected the expected value - * @param numDigits the number of digits to check after the decimal point. Default is `2` - */ - toBeCloseTo(expected: number, numDigits?: number): void; - /** - * Asserts that a value is deeply equal to what is expected. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([456]).toEqual([456]); - * expect({ value: 1 }).toEqual({ value: 1 }); - * - * @param expected the expected value - */ - toEqual(expected: T): void; - /** - * Asserts that a value is deeply and strictly equal to - * what is expected. - * - * There are two key differences from `toEqual()`: - * 1. It checks that the class is the same. - * 2. It checks that `undefined` values match as well. - * - * @example - * class Dog { - * type = "dog"; - * } - * const actual = new Dog(); - * expect(actual).toStrictEqual(new Dog()); - * expect(actual).toStrictEqual({ type: "dog" }); // fail - * - * @example - * const actual = { value: 1, name: undefined }; - * expect(actual).toEqual({ value: 1 }); - * expect(actual).toStrictEqual({ value: 1 }); // fail - * - * @param expected the expected value - */ - toStrictEqual(expected: T): void; - /** - * Asserts that the value is deep equal to an element in the expected array. - * - * The value must be an array or iterable, which includes strings. - * - * @example - * expect(1).toBeOneOf([1,2,3]); - * expect("foo").toBeOneOf(["foo", "bar"]); - * expect(true).toBeOneOf(new Set([true])); - * - * @param expected the expected value - */ - toBeOneOf(expected: Array | Iterable): void; - /** - * Asserts that a value contains what is expected. - * - * The value must be an array or iterable, which - * includes strings. - * - * @example - * expect([1, 2, 3]).toContain(1); - * expect(new Set([true])).toContain(true); - * expect("hello").toContain("o"); - * - * @param expected the expected value - */ - toContain(expected: unknown): void; - /** - * Asserts that an `object` contains a key. - * - * The value must be an object - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); - * - * @param expected the expected value - */ - toContainKey(expected: unknown): void; - /** - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); - * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); - * - * @param expected the expected value - */ - toContainAllKeys(expected: unknown): void; - /** - * Asserts that an `object` contains at least one of the provided keys. - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); - * - * @param expected the expected value - */ - toContainAnyKeys(expected: unknown): void; - - /** + /** + * -- Mocks -- + */ + export type Mock any> = JestMock.Mock; + + export const mock: { + any>(Function?: T): Mock; + + /** + * Replace the module `id` with the return value of `factory`. + * + * This is useful for mocking modules. + * + * @param id module ID to mock + * @param factory a function returning an object that will be used as the exports of the mocked module + * + * @example + * ## Example + * ```ts + * import { mock } from "bun:test"; + * + * mock.module("fs/promises", () => { + * return { + * readFile: () => Promise.resolve("hello world"), + * }; + * }); + * + * import { readFile } from "fs/promises"; + * + * console.log(await readFile("hello.txt", "utf8")); // hello world + * ``` + * + * ## More notes + * + * If the module is already loaded, exports are overwritten with the return + * value of `factory`. If the export didn't exist before, it will not be + * added to existing import statements. This is due to how ESM works. + */ + module(id: string, factory: () => any): void | Promise; + /** + * Restore the previous value of mocks. + */ + restore(): void; + }; + + /** + * Control the system time used by: + * - `Date.now()` + * - `new Date()` + * - `Intl.DateTimeFormat().format()` + * + * In the future, we may add support for more functions, but we haven't done that yet. + * + * @param now The time to set the system time to. If not provided, the system time will be reset. + * @returns `this` + * @since v0.6.13 + * + * ## Set Date to a specific time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); + * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z + * ``` + * ## Reset Date to the current time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(); + * ``` + */ + export function setSystemTime(now?: Date | number): ThisType; + + interface Jest { + restoreAllMocks(): void; + clearAllMocks(): void; + fn any>(func?: T): Mock; + setSystemTime(now?: number | Date): void; + setTimeout(milliseconds: number): void; + } + export const jest: Jest; + export namespace jest { + /** + * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. + */ + type Mock any = (...args: any[]) => any> = JestMock.Mock; + /** + * Wraps a class, function or object type with Jest mock type definitions. + */ + // type Mocked = JestMock.Mocked; + /** + * Wraps a class type with Jest mock type definitions. + */ + // type MockedClass = JestMock.MockedClass; + /** + * Wraps a function type with Jest mock type definitions. + */ + // type MockedFunction any> = JestMock.MockedFunction; + /** + * Wraps an object type with Jest mock type definitions. + */ + // type MockedObject = JestMock.MockedObject; + /** + * Constructs the type of a replaced property. + */ + type Replaced = JestMock.Replaced; + /** + * Constructs the type of a spied class or function. + */ + type Spied any)> = JestMock.Spied; + /** + * Constructs the type of a spied class. + */ + type SpiedClass = JestMock.SpiedClass; + /** + * Constructs the type of a spied function. + */ + type SpiedFunction any> = JestMock.SpiedFunction; + /** + * Constructs the type of a spied getter. + */ + type SpiedGetter = JestMock.SpiedGetter; + /** + * Constructs the type of a spied setter. + */ + type SpiedSetter = JestMock.SpiedSetter; + } + + export function spyOn( + obj: T, + methodOrPropertyValue: K, + ): Mock any ? T[K] : never>; + + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export interface Describe { + (label: string, fn: () => void): void; + /** + * Skips all other tests, except this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + only(label: string, fn: () => void): void; + /** + * Skips this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + skip(label: string, fn: () => void): void; + /** + * Marks this group of tests as to be written or to be fixed. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + todo(label: string, fn?: () => void): void; + /** + * Runs this group of tests, only if `condition` is true. + * + * This is the opposite of `describe.skipIf()`. + * + * @param condition if these tests should run + */ + if(condition: boolean): (label: string, fn: () => void) => void; + /** + * Skips this group of tests, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + skipIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Marks this group of tests as to be written or to be fixed, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + todoIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; + each( + table: readonly T[], + ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; + each( + table: T[], + ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; + } + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export const describe: Describe; + /** + * Runs a function, once, before all the tests. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, tests will not run in this file. + * + * @example + * let database; + * beforeAll(async () => { + * database = await connect("localhost"); + * }); + * + * @param fn the function to run + */ + export function beforeAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Runs a function before each test. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, the test will not run. + * + * @param fn the function to run + */ + export function beforeEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Runs a function, once, after all the tests. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @example + * let database; + * afterAll(async () => { + * if (database) { + * await database.close(); + * } + * }); + * + * @param fn the function to run + */ + export function afterAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Runs a function after each test. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @param fn the function to run + */ + export function afterEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will + * override this value. The default timeout is 5000ms (5 seconds). + * + * @param milliseconds the number of milliseconds for the default timeout + */ + export function setDefaultTimeout(milliseconds: number): void; + export interface TestOptions { + /** + * Sets the timeout for the test in milliseconds. + * + * If the test does not complete within this time, the test will fail with: + * ```ts + * 'Timeout: test {name} timed out after 5000ms' + * ``` + * + * @default 5000 // 5 seconds + */ + timeout?: number; + /** + * Sets the number of times to retry the test if it fails. + * + * @default 0 + */ + retry?: number; + /** + * Sets the number of times to repeat the test, regardless of whether it passed or failed. + * + * @default 0 + */ + repeats?: number; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * test("can set a timeout", async () => { + * await Bun.sleep(100); + * }, 50); // or { timeout: 50 } + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + export interface Test { + ( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + /** + * - If a `number`, sets the timeout for the test in milliseconds. + * - If an `object`, sets the options for the test. + * - `timeout` sets the timeout for the test in milliseconds. + * - `retry` sets the number of times to retry the test if it fails. + * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. + */ + options?: number | TestOptions, + ): void; + /** + * Skips all other tests, except this test when run with the `--only` option. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + only( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Skips this test. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + skip( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as to be written or to be fixed. + * + * These tests will not be executed unless the `--todo` flag is passed. With the flag, + * if the test passes, the test will be marked as `fail` in the results; you will have to + * remove the `.todo` or check that your test + * is implemented correctly. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + todo( + label: string, + fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as failing. + * + * Use `test.failing` when you are writing a test and expecting it to fail. + * These tests will behave the other way normal tests do. If failing test + * will throw any errors then it will pass. If it does not throw it will + * fail. + * + * `test.failing` is very similar to {@link test.todo} except that it always + * runs, regardless of the `--todo` flag. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + failing(label: string, fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Runs this test, if `condition` is true. + * + * This is the opposite of `test.skipIf()`. + * + * @param condition if the test should run + */ + if( + condition: boolean, + ): ( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Skips this test, if `condition` is true. + * + * @param condition if the test should be skipped + */ + skipIf( + condition: boolean, + ): ( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Marks this test as to be written or to be fixed, if `condition` is true. + * + * @param condition if the test should be marked TODO + */ + todoIf( + condition: boolean, + ): ( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; + each( + table: readonly T[], + ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; + each( + table: T[], + ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * @param label the label for the test + * @param fn the test function + */ + export const test: Test; + export { test as it }; + + /** + * Asserts that a value matches some criteria. + * + * @link https://jestjs.io/docs/expect#reference + * @example + * expect(1 + 1).toBe(2); + * expect([1,2,3]).toContain(2); + * expect(null).toBeNull(); + * + * @param actual The actual (received) value + */ + export const expect: Expect; + + type ExpectNot = Omit & AsymmetricMatchersBuiltinNegated; + + export interface Expect extends AsymmetricMatchers { + // the `expect()` callable signature + /** + * @param actual the actual value + * @param customFailMessage an optional custom message to display if the test fails. + * */ + + (actual?: T, customFailMessage?: string): Matchers; + + /** + * Access to negated asymmetric matchers. + * + * @example + * expect("abc").toEqual(expect.stringContaining("abc")); // will pass + * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail + */ + not: ExpectNot; + + /** + * Create an asymmetric matcher for a promise resolved value. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass + * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail + * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail + */ + resolvesTo: AsymmetricMatchers; + + /** + * Create an asymmetric matcher for a promise rejected value. + * + * @example + * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass + * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail + * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail + */ + rejectsTo: AsymmetricMatchers; + + /** + * Register new custom matchers. + * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. + * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` + * + * @example + * expect.extend({ + * toBeWithinRange(actual, min, max) { + * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') + * throw new Error('Invalid usage'); + * const pass = actual >= min && actual <= max; + * return { + * pass: pass, + * message: () => `expected ${this.utils.printReceived(actual)} ` + + * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, + * }; + * }, + * }); + * + * test('some test', () => { + * expect(50).toBeWithinRange(0, 100); // will pass + * expect(50).toBeWithinRange(100, 200); // will fail + * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass + * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass + * }); + */ + extend(matchers: ExpectExtendMatchers): void; + + /** + * Throw an error if this function is called. + * + * @param msg Optional message to display if the test fails + * @returns never + * + * @example + * ## Example + * + * ```ts + * import { expect, test } from "bun:test"; + * + * test("!!abc!! is not a module", () => { + * try { + * require("!!abc!!"); + * expect.unreachable(); + * } catch(e) { + * expect(e.name).not.toBe("UnreachableError"); + * } + * }); + * ``` + */ + unreachable(msg?: string | Error): never; + + /** + * Ensures that an assertion is made + */ + hasAssertions(): void; + + /** + * Ensures that a specific number of assertions are made + */ + assertions(neededAssertions: number): void; + } + + /** + * You can extend this interface with declaration merging, in order to add type support for custom matchers. + * @template T Type of the actual value + * + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface Matchers extends MatchersBuiltin {} + + /** + * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} + + export interface AsymmetricMatchersBuiltin { + /** + * Matches anything that was created with the given constructor. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * @example + * + * function randocall(fn) { + * return fn(Math.floor(Math.random() * 6 + 1)); + * } + * + * test('randocall calls its callback with a number', () => { + * const mock = jest.fn(); + * randocall(mock); + * expect(mock).toBeCalledWith(expect.any(Number)); + * }); + */ + any(constructor: ((...args: any[]) => any) | { new (...args: any[]): any }): AsymmetricMatcher; + /** + * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead + * of a literal value. For example, if you want to check that a mock function is called with a + * non-null argument: + * + * @example + * + * test('map calls its argument with a non-null argument', () => { + * const mock = jest.fn(); + * [1].map(x => mock(x)); + * expect(mock).toBeCalledWith(expect.anything()); + * }); + */ + anything(): AsymmetricMatcher; + /** + * Matches any array made up entirely of elements in the provided array. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + /** + * Matches any object that recursively matches the provided keys. + * This is often handy in conjunction with other asymmetric matchers. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + /** + * Matches any received string that contains the exact expected string + */ + stringContaining(str: string | String): AsymmetricMatcher; + /** + * Matches any string that contains the exact provided string + */ + stringMatching(regex: string | String | RegExp): AsymmetricMatcher; + /** + * Useful when comparing floating point numbers in object properties or array item. + * If you need to compare a number, use `.toBeCloseTo` instead. + * + * The optional `numDigits` argument limits the number of digits to check after the decimal point. + * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + interface AsymmetricMatchersBuiltinNegated { + /** + * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail + * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + */ + resolvesTo: ExpectNot; + + /** + * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. + * + * @example + * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail + * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + */ + rejectsTo: ExpectNot; + + /** + * `expect.not.arrayContaining(array)` matches a received array which + * does not contain all of the elements in the expected array. That is, + * the expected array is not a subset of the received array. It is the + * inverse of `expect.arrayContaining`. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + + /** + * `expect.not.objectContaining(object)` matches any received object + * that does not recursively match the expected properties. That is, the + * expected object is not a subset of the received object. Therefore, + * it matches a received object which contains properties that are not + * in the expected object. It is the inverse of `expect.objectContaining`. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + + /** + * `expect.not.stringContaining(string)` matches the received string + * that does not contain the exact expected string. It is the inverse of + * `expect.stringContaining`. + */ + stringContaining(str: string | String): AsymmetricMatcher; + + /** + * `expect.not.stringMatching(string | regexp)` matches the received + * string that does not match the expected regexp. It is the inverse of + * `expect.stringMatching`. + */ + stringMatching(str: string | String | RegExp): AsymmetricMatcher; + + /** + * `expect.not.closeTo` matches a number not close to the provided value. + * Useful when comparing floating point numbers in object properties or array item. + * It is the inverse of `expect.closeTo`. + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + export interface MatchersBuiltin { + /** + * Negates the result of a subsequent assertion. + * If you know how to test something, `.not` lets you test its opposite. + * + * @example + * expect(1).not.toBe(0); + * expect(null).not.toBeNull(); + * + * @example + * expect(42).toEqual(42); // will pass + * expect(42).not.toEqual(42); // will fail + */ + not: Matchers; + + /** + * Expects the value to be a promise that resolves. + * + * @example + * expect(Promise.resolve(1)).resolves.toBe(1); + */ + resolves: Matchers>; + + /** + * Expects the value to be a promise that rejects. + * + * @example + * expect(Promise.reject("error")).rejects.toBe("error"); + */ + rejects: Matchers; + + /** + * Assertion which passes. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass + * @example + * expect().pass(); + * expect().pass("message is optional"); + * expect().not.pass(); + * expect().not.pass("hi"); + * + * @param message the message to display if the test fails (optional) + */ + pass: (message?: string) => void; + /** + * Assertion which fails. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail + * @example + * expect().fail(); + * expect().fail("message is optional"); + * expect().not.fail(); + * expect().not.fail("hi"); + */ + fail: (message?: string) => void; + /** + * Asserts that a value equals what is expected. + * + * - For non-primitive values, like objects and arrays, + * use `toEqual()` instead. + * - For floating-point numbers, use `toBeCloseTo()` instead. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([123]).toBe([123]); // fail, use toEqual() + * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() + * + * @param expected the expected value + */ + toBe(expected: T): void; + /** + * Asserts that a number is odd. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd + * @example + * expect(1).toBeOdd(); + * expect(2).not.toBeOdd(); + */ + toBeOdd(): void; + /** + * Asserts that a number is even. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven + * @example + * expect(2).toBeEven(); + * expect(1).not.toBeEven(); + */ + toBeEven(): void; + /** + * Asserts that value is close to the expected by floating point precision. + * + * For example, the following fails because arithmetic on decimal (base 10) + * values often have rounding errors in limited precision binary (base 2) representation. + * + * @example + * expect(0.2 + 0.1).toBe(0.3); // fails + * + * Use `toBeCloseTo` to compare floating point numbers for approximate equality. + * + * @example + * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes + * + * @param expected the expected value + * @param numDigits the number of digits to check after the decimal point. Default is `2` + */ + toBeCloseTo(expected: number, numDigits?: number): void; + /** + * Asserts that a value is deeply equal to what is expected. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([456]).toEqual([456]); + * expect({ value: 1 }).toEqual({ value: 1 }); + * + * @param expected the expected value + */ + toEqual(expected: T): void; + /** + * Asserts that a value is deeply and strictly equal to + * what is expected. + * + * There are two key differences from `toEqual()`: + * 1. It checks that the class is the same. + * 2. It checks that `undefined` values match as well. + * + * @example + * class Dog { + * type = "dog"; + * } + * const actual = new Dog(); + * expect(actual).toStrictEqual(new Dog()); + * expect(actual).toStrictEqual({ type: "dog" }); // fail + * + * @example + * const actual = { value: 1, name: undefined }; + * expect(actual).toEqual({ value: 1 }); + * expect(actual).toStrictEqual({ value: 1 }); // fail + * + * @param expected the expected value + */ + toStrictEqual(expected: T): void; + /** + * Asserts that the value is deep equal to an element in the expected array. + * + * The value must be an array or iterable, which includes strings. + * + * @example + * expect(1).toBeOneOf([1,2,3]); + * expect("foo").toBeOneOf(["foo", "bar"]); + * expect(true).toBeOneOf(new Set([true])); + * + * @param expected the expected value + */ + toBeOneOf(expected: Array | Iterable): void; + /** + * Asserts that a value contains what is expected. + * + * The value must be an array or iterable, which + * includes strings. + * + * @example + * expect([1, 2, 3]).toContain(1); + * expect(new Set([true])).toContain(true); + * expect("hello").toContain("o"); + * + * @param expected the expected value + */ + toContain(expected: unknown): void; + /** + * Asserts that an `object` contains a key. + * + * The value must be an object + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); + * + * @param expected the expected value + */ + toContainKey(expected: unknown): void; + /** + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); + * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); + * + * @param expected the expected value + */ + toContainAllKeys(expected: unknown): void; + /** + * Asserts that an `object` contains at least one of the provided keys. + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); + * + * @param expected the expected value + */ + toContainAnyKeys(expected: unknown): void; + + /** * Asserts that an `object` contain the provided value. * * The value must be an object @@ -1094,1189 +1029,1148 @@ declare module "bun:test" { * * @param expected the expected value */ - toContainValue(expected: unknown): void; - - /** - * Asserts that an `object` contain the provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainValues(['foo']); - * expect(o).toContainValues(['baz', 'bar']); - * expect(o).not.toContainValues(['qux', 'foo']); - * @param expected the expected value - */ - toContainValues(expected: unknown): void; - - /** - * Asserts that an `object` contain all the provided values. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAllValues(['foo', 'bar', 'baz']); - * expect(o).toContainAllValues(['baz', 'bar', 'foo']); - * expect(o).not.toContainAllValues(['bar', 'foo']); - * @param expected the expected value - */ - toContainAllValues(expected: unknown): void; - - /** - * Asserts that an `object` contain any provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAnyValues(['qux', 'foo']); - * expect(o).toContainAnyValues(['qux', 'bar']); - * expect(o).toContainAnyValues(['qux', 'baz']); - * expect(o).not.toContainAnyValues(['qux']); - * @param expected the expected value - */ - toContainAnyValues(expected: unknown): void; - - /** - * Asserts that an `object` contains all the provided keys. - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); - * - * @param expected the expected value - */ - toContainKeys(expected: unknown): void; - /** - * Asserts that a value contains and equals what is expected. - * - * This matcher will perform a deep equality check for members - * of arrays, rather than checking for object identity. - * - * @example - * expect([{ a: 1 }]).toContainEqual({ a: 1 }); - * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); - * - * @param expected the expected value - */ - toContainEqual(expected: unknown): void; - /** - * Asserts that a value has a `.length` property - * that is equal to the expected length. - * - * @example - * expect([]).toHaveLength(0); - * expect("hello").toHaveLength(4); - * - * @param length the expected length - */ - toHaveLength(length: number): void; - /** - * Asserts that a value has a property with the - * expected name, and value if provided. - * - * @example - * expect(new Set()).toHaveProperty("size"); - * expect(new Uint8Array()).toHaveProperty("byteLength", 0); - * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); - * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); - * - * @param keyPath the expected property name or path, or an index - * @param value the expected property value, if provided - */ - toHaveProperty( - keyPath: string | number | Array, - value?: unknown, - ): void; - /** - * Asserts that a value is "truthy". - * - * To assert that a value equals `true`, use `toBe(true)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeTruthy(): void; - /** - * Asserts that a value is "falsy". - * - * To assert that a value equals `false`, use `toBe(false)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeFalsy(): void; - /** - * Asserts that a value is defined. (e.g. is not `undefined`) - * - * @example - * expect(true).toBeDefined(); - * expect(undefined).toBeDefined(); // fail - */ - toBeDefined(): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that a value is `undefined`. - * - * @example - * expect(undefined).toBeUndefined(); - * expect(null).toBeUndefined(); // fail - */ - toBeUndefined(): void; - /** - * Asserts that a value is `null`. - * - * @example - * expect(null).toBeNull(); - * expect(undefined).toBeNull(); // fail - */ - toBeNull(): void; - /** - * Asserts that a value is `NaN`. - * - * Same as using `Number.isNaN()`. - * - * @example - * expect(NaN).toBeNaN(); - * expect(Infinity).toBeNaN(); // fail - * expect("notanumber").toBeNaN(); // fail - */ - toBeNaN(): void; - /** - * Asserts that a value is a `number` and is greater than the expected value. - * - * @example - * expect(1).toBeGreaterThan(0); - * expect(3.14).toBeGreaterThan(3); - * expect(9).toBeGreaterThan(9); // fail - * - * @param expected the expected number - */ - toBeGreaterThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is greater than or equal to the expected value. - * - * @example - * expect(1).toBeGreaterThanOrEqual(0); - * expect(3.14).toBeGreaterThanOrEqual(3); - * expect(9).toBeGreaterThanOrEqual(9); - * - * @param expected the expected number - */ - toBeGreaterThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than the expected value. - * - * @example - * expect(-1).toBeLessThan(0); - * expect(3).toBeLessThan(3.14); - * expect(9).toBeLessThan(9); // fail - * - * @param expected the expected number - */ - toBeLessThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than or equal to the expected value. - * - * @example - * expect(-1).toBeLessThanOrEqual(0); - * expect(3).toBeLessThanOrEqual(3.14); - * expect(9).toBeLessThanOrEqual(9); - * - * @param expected the expected number - */ - toBeLessThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrow("Oops!"); - * expect(fail).toThrow(/oops/i); - * expect(fail).toThrow(Error); - * expect(fail).toThrow(); - * - * @param expected the expected error, error message, or error pattern - */ - toThrow(expected?: unknown): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowError("Oops!"); - * expect(fail).toThrowError(/oops/i); - * expect(fail).toThrowError(Error); - * expect(fail).toThrowError(); - * - * @param expected the expected error, error message, or error pattern - * @alias toThrow - */ - toThrowError(expected?: unknown): void; - /** - * Asserts that a value matches a regular expression or includes a substring. - * - * @example - * expect("dog").toMatch(/dog/); - * expect("dog").toMatch("og"); - * - * @param expected the expected substring or pattern. - */ - toMatch(expected: string | RegExp): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot('hint message'); - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(hint?: string): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot(); - * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); - * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(propertyMatchers?: object, hint?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect("Hello").toMatchInlineSnapshot(); - * expect("Hello").toMatchInlineSnapshot(`"Hello"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(value?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` - * { - * "v": Any, - * } - * `); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingSnapshot(); - * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingSnapshot(hint?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingInlineSnapshot(); - * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingInlineSnapshot(value?: string): void; - /** - * Asserts that an object matches a subset of properties. - * - * @example - * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); - * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); - * - * @param subset Subset of properties to match with. - */ - toMatchObject(subset: object): void; - /** - * Asserts that a value is empty. - * - * @example - * expect("").toBeEmpty(); - * expect([]).toBeEmpty(); - * expect({}).toBeEmpty(); - * expect(new Set()).toBeEmpty(); - */ - toBeEmpty(): void; - /** - * Asserts that a value is an empty `object`. - * - * @example - * expect({}).toBeEmptyObject(); - * expect({ a: 'hello' }).not.toBeEmptyObject(); - */ - toBeEmptyObject(): void; - /** - * Asserts that a value is `null` or `undefined`. - * - * @example - * expect(null).toBeNil(); - * expect(undefined).toBeNil(); - */ - toBeNil(): void; - /** - * Asserts that a value is a `array`. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray - * @example - * expect([1]).toBeArray(); - * expect(new Array(1)).toBeArray(); - * expect({}).not.toBeArray(); - */ - toBeArray(): void; - /** - * Asserts that a value is a `array` of a certain length. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize - * @example - * expect([]).toBeArrayOfSize(0); - * expect([1]).toBeArrayOfSize(1); - * expect(new Array(1)).toBeArrayOfSize(1); - * expect({}).not.toBeArrayOfSize(0); - */ - toBeArrayOfSize(size: number): void; - /** - * Asserts that a value is a `boolean`. - * - * @example - * expect(true).toBeBoolean(); - * expect(false).toBeBoolean(); - * expect(null).not.toBeBoolean(); - * expect(0).not.toBeBoolean(); - */ - toBeBoolean(): void; - /** - * Asserts that a value is `true`. - * - * @example - * expect(true).toBeTrue(); - * expect(false).not.toBeTrue(); - * expect(1).not.toBeTrue(); - */ - toBeTrue(): void; - /** - * Asserts that a value matches a specific type. - * - * @link https://vitest.dev/api/expect.html#tobetypeof - * @example - * expect(1).toBeTypeOf("number"); - * expect("hello").toBeTypeOf("string"); - * expect([]).not.toBeTypeOf("boolean"); - */ - toBeTypeOf( - type: - | "bigint" - | "boolean" - | "function" - | "number" - | "object" - | "string" - | "symbol" - | "undefined", - ): void; - /** - * Asserts that a value is `false`. - * - * @example - * expect(false).toBeFalse(); - * expect(true).not.toBeFalse(); - * expect(0).not.toBeFalse(); - */ - toBeFalse(): void; - /** - * Asserts that a value is a `number`. - * - * @example - * expect(1).toBeNumber(); - * expect(3.14).toBeNumber(); - * expect(NaN).toBeNumber(); - * expect(BigInt(1)).not.toBeNumber(); - */ - toBeNumber(): void; - /** - * Asserts that a value is a `number`, and is an integer. - * - * @example - * expect(1).toBeInteger(); - * expect(3.14).not.toBeInteger(); - * expect(NaN).not.toBeInteger(); - */ - toBeInteger(): void; - /** - * Asserts that a value is an `object`. - * - * @example - * expect({}).toBeObject(); - * expect("notAnObject").not.toBeObject(); - * expect(NaN).not.toBeObject(); - */ - toBeObject(): void; - /** - * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. - * - * @example - * expect(1).toBeFinite(); - * expect(3.14).toBeFinite(); - * expect(NaN).not.toBeFinite(); - * expect(Infinity).not.toBeFinite(); - */ - toBeFinite(): void; - /** - * Asserts that a value is a positive `number`. - * - * @example - * expect(1).toBePositive(); - * expect(-3.14).not.toBePositive(); - * expect(NaN).not.toBePositive(); - */ - toBePositive(): void; - /** - * Asserts that a value is a negative `number`. - * - * @example - * expect(-3.14).toBeNegative(); - * expect(1).not.toBeNegative(); - * expect(NaN).not.toBeNegative(); - */ - toBeNegative(): void; - /** - * Asserts that a value is a number between a start and end value. - * - * @param start the start number (inclusive) - * @param end the end number (exclusive) - */ - toBeWithin(start: number, end: number): void; - /** - * Asserts that a value is equal to the expected string, ignoring any whitespace. - * - * @example - * expect(" foo ").toEqualIgnoringWhitespace("foo"); - * expect("bar").toEqualIgnoringWhitespace(" bar "); - * - * @param expected the expected string - */ - toEqualIgnoringWhitespace(expected: string): void; - /** - * Asserts that a value is a `symbol`. - * - * @example - * expect(Symbol("foo")).toBeSymbol(); - * expect("foo").not.toBeSymbol(); - */ - toBeSymbol(): void; - /** - * Asserts that a value is a `function`. - * - * @example - * expect(() => {}).toBeFunction(); - */ - toBeFunction(): void; - /** - * Asserts that a value is a `Date` object. - * - * To check if a date is valid, use `toBeValidDate()` instead. - * - * @example - * expect(new Date()).toBeDate(); - * expect(new Date(null)).toBeDate(); - * expect("2020-03-01").not.toBeDate(); - */ - toBeDate(): void; - /** - * Asserts that a value is a valid `Date` object. - * - * @example - * expect(new Date()).toBeValidDate(); - * expect(new Date(null)).not.toBeValidDate(); - * expect("2020-03-01").not.toBeValidDate(); - */ - toBeValidDate(): void; - /** - * Asserts that a value is a `string`. - * - * @example - * expect("foo").toBeString(); - * expect(new String("bar")).toBeString(); - * expect(123).not.toBeString(); - */ - toBeString(): void; - /** - * Asserts that a value includes a `string`. - * - * For non-string values, use `toContain()` instead. - * - * @param expected the expected substring - */ - toInclude(expected: string): void; - /** - * Asserts that a value includes a `string` {times} times. - * @param expected the expected substring - * @param times the number of times the substring should occur - */ - toIncludeRepeated(expected: string, times: number): void; - /** - * Checks whether a value satisfies a custom condition. - * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. - * @example - * expect(1).toSatisfy((val) => val > 0); - * expect("foo").toSatisfy((val) => val === "foo"); - * expect("bar").not.toSatisfy((val) => val === "bun"); - * @link https://vitest.dev/api/expect.html#tosatisfy - * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy - */ - toSatisfy(predicate: (value: T) => boolean): void; - /** - * Asserts that a value starts with a `string`. - * - * @param expected the string to start with - */ - toStartWith(expected: string): void; - /** - * Asserts that a value ends with a `string`. - * - * @param expected the string to end with - */ - toEndWith(expected: string): void; - /** - * Ensures that a mock function has returned successfully at least once. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturned(): void; - - /** - * Ensures that a mock function has returned successfully at `times` times. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturnedTimes(times: number): void; - - /** - * Ensures that a mock function is called. - */ - toHaveBeenCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - * @alias toHaveBeenCalled - */ - toBeCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - */ - toHaveBeenCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledTimes - */ - toBeCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - */ - toHaveBeenCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledWith - */ - toBeCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the last call. - */ - toHaveBeenLastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - lastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - */ - toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - nthCalledWith(n: number, ...expected: unknown[]): void; - } - - /** - * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. - */ - // Defined as an alias of `any` so that it does not trigger any type mismatch - export type AsymmetricMatcher = any; - - export interface MatcherResult { - pass: boolean; - message?: string | (() => string); - } - - export type CustomMatcher = ( - this: MatcherContext, - expected: E, - ...matcherArguments: P - ) => MatcherResult | Promise; - - /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ - export type CustomMatchersDetected = Omit< - Matchers, - keyof MatchersBuiltin - > & - Omit; - - /** - * If the types has been defined through declaration merging, enforce it. - * Otherwise enforce the generic custom matcher signature. - */ - export type ExpectExtendMatchers = { - [k in keyof M]: k extends keyof CustomMatchersDetected - ? CustomMatcher> - : CustomMatcher; - }; - - /** Custom equality tester */ - export type Tester = ( - this: TesterContext, - a: any, - b: any, - customTesters: Tester[], - ) => boolean | undefined; - - export type EqualsFunction = ( - a: unknown, - b: unknown, - //customTesters?: Array, - //strictCheck?: boolean, - ) => boolean; - - export interface TesterContext { - equals: EqualsFunction; - } - - interface MatcherState { - //assertionCalls: number; - //currentConcurrentTestName?: () => string | undefined; - //currentTestName?: string; - //error?: Error; - //expand: boolean; - //expectedAssertionsNumber: number | null; - //expectedAssertionsNumberError?: Error; - //isExpectingAssertions: boolean; - //isExpectingAssertionsError?: Error; - isNot: boolean; - //numPassingAsserts: number; - promise: string; - //suppressedErrors: Array; - //testPath?: string; - } - - type MatcherHintColor = (arg: string) => string; // subset of Chalk type - - interface MatcherUtils { - //customTesters: Array; - //dontThrow(): void; // (internally used by jest snapshot) - equals: EqualsFunction; - utils: Readonly<{ - stringify(value: unknown): string; - printReceived(value: unknown): string; - printExpected(value: unknown): string; - matcherHint( - matcherName: string, - received?: unknown, - expected?: unknown, - options?: { - isNot?: boolean; - promise?: string; - isDirectExpectCall?: boolean; // (internal) - comment?: string; - expectedColor?: MatcherHintColor; - receivedColor?: MatcherHintColor; - secondArgument?: string; - secondArgumentColor?: MatcherHintColor; - }, - ): string; - //iterableEquality: Tester; - //subsetEquality: Tester; - // ... - }>; - } - - type MatcherContext = MatcherUtils & MatcherState; + toContainValue(expected: unknown): void; + + /** + * Asserts that an `object` contain the provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainValues(['foo']); + * expect(o).toContainValues(['baz', 'bar']); + * expect(o).not.toContainValues(['qux', 'foo']); + * @param expected the expected value + */ + toContainValues(expected: unknown): void; + + /** + * Asserts that an `object` contain all the provided values. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAllValues(['foo', 'bar', 'baz']); + * expect(o).toContainAllValues(['baz', 'bar', 'foo']); + * expect(o).not.toContainAllValues(['bar', 'foo']); + * @param expected the expected value + */ + toContainAllValues(expected: unknown): void; + + /** + * Asserts that an `object` contain any provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAnyValues(['qux', 'foo']); + * expect(o).toContainAnyValues(['qux', 'bar']); + * expect(o).toContainAnyValues(['qux', 'baz']); + * expect(o).not.toContainAnyValues(['qux']); + * @param expected the expected value + */ + toContainAnyValues(expected: unknown): void; + + /** + * Asserts that an `object` contains all the provided keys. + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); + * + * @param expected the expected value + */ + toContainKeys(expected: unknown): void; + /** + * Asserts that a value contains and equals what is expected. + * + * This matcher will perform a deep equality check for members + * of arrays, rather than checking for object identity. + * + * @example + * expect([{ a: 1 }]).toContainEqual({ a: 1 }); + * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); + * + * @param expected the expected value + */ + toContainEqual(expected: unknown): void; + /** + * Asserts that a value has a `.length` property + * that is equal to the expected length. + * + * @example + * expect([]).toHaveLength(0); + * expect("hello").toHaveLength(4); + * + * @param length the expected length + */ + toHaveLength(length: number): void; + /** + * Asserts that a value has a property with the + * expected name, and value if provided. + * + * @example + * expect(new Set()).toHaveProperty("size"); + * expect(new Uint8Array()).toHaveProperty("byteLength", 0); + * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); + * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); + * + * @param keyPath the expected property name or path, or an index + * @param value the expected property value, if provided + */ + toHaveProperty(keyPath: string | number | Array, value?: unknown): void; + /** + * Asserts that a value is "truthy". + * + * To assert that a value equals `true`, use `toBe(true)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeTruthy(): void; + /** + * Asserts that a value is "falsy". + * + * To assert that a value equals `false`, use `toBe(false)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeFalsy(): void; + /** + * Asserts that a value is defined. (e.g. is not `undefined`) + * + * @example + * expect(true).toBeDefined(); + * expect(undefined).toBeDefined(); // fail + */ + toBeDefined(): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that a value is `undefined`. + * + * @example + * expect(undefined).toBeUndefined(); + * expect(null).toBeUndefined(); // fail + */ + toBeUndefined(): void; + /** + * Asserts that a value is `null`. + * + * @example + * expect(null).toBeNull(); + * expect(undefined).toBeNull(); // fail + */ + toBeNull(): void; + /** + * Asserts that a value is `NaN`. + * + * Same as using `Number.isNaN()`. + * + * @example + * expect(NaN).toBeNaN(); + * expect(Infinity).toBeNaN(); // fail + * expect("notanumber").toBeNaN(); // fail + */ + toBeNaN(): void; + /** + * Asserts that a value is a `number` and is greater than the expected value. + * + * @example + * expect(1).toBeGreaterThan(0); + * expect(3.14).toBeGreaterThan(3); + * expect(9).toBeGreaterThan(9); // fail + * + * @param expected the expected number + */ + toBeGreaterThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is greater than or equal to the expected value. + * + * @example + * expect(1).toBeGreaterThanOrEqual(0); + * expect(3.14).toBeGreaterThanOrEqual(3); + * expect(9).toBeGreaterThanOrEqual(9); + * + * @param expected the expected number + */ + toBeGreaterThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than the expected value. + * + * @example + * expect(-1).toBeLessThan(0); + * expect(3).toBeLessThan(3.14); + * expect(9).toBeLessThan(9); // fail + * + * @param expected the expected number + */ + toBeLessThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than or equal to the expected value. + * + * @example + * expect(-1).toBeLessThanOrEqual(0); + * expect(3).toBeLessThanOrEqual(3.14); + * expect(9).toBeLessThanOrEqual(9); + * + * @param expected the expected number + */ + toBeLessThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrow("Oops!"); + * expect(fail).toThrow(/oops/i); + * expect(fail).toThrow(Error); + * expect(fail).toThrow(); + * + * @param expected the expected error, error message, or error pattern + */ + toThrow(expected?: unknown): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowError("Oops!"); + * expect(fail).toThrowError(/oops/i); + * expect(fail).toThrowError(Error); + * expect(fail).toThrowError(); + * + * @param expected the expected error, error message, or error pattern + * @alias toThrow + */ + toThrowError(expected?: unknown): void; + /** + * Asserts that a value matches a regular expression or includes a substring. + * + * @example + * expect("dog").toMatch(/dog/); + * expect("dog").toMatch("og"); + * + * @param expected the expected substring or pattern. + */ + toMatch(expected: string | RegExp): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot('hint message'); + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(hint?: string): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot(); + * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); + * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(propertyMatchers?: object, hint?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect("Hello").toMatchInlineSnapshot(); + * expect("Hello").toMatchInlineSnapshot(`"Hello"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(value?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` + * { + * "v": Any, + * } + * `); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingSnapshot(); + * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingSnapshot(hint?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingInlineSnapshot(); + * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingInlineSnapshot(value?: string): void; + /** + * Asserts that an object matches a subset of properties. + * + * @example + * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); + * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); + * + * @param subset Subset of properties to match with. + */ + toMatchObject(subset: object): void; + /** + * Asserts that a value is empty. + * + * @example + * expect("").toBeEmpty(); + * expect([]).toBeEmpty(); + * expect({}).toBeEmpty(); + * expect(new Set()).toBeEmpty(); + */ + toBeEmpty(): void; + /** + * Asserts that a value is an empty `object`. + * + * @example + * expect({}).toBeEmptyObject(); + * expect({ a: 'hello' }).not.toBeEmptyObject(); + */ + toBeEmptyObject(): void; + /** + * Asserts that a value is `null` or `undefined`. + * + * @example + * expect(null).toBeNil(); + * expect(undefined).toBeNil(); + */ + toBeNil(): void; + /** + * Asserts that a value is a `array`. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray + * @example + * expect([1]).toBeArray(); + * expect(new Array(1)).toBeArray(); + * expect({}).not.toBeArray(); + */ + toBeArray(): void; + /** + * Asserts that a value is a `array` of a certain length. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize + * @example + * expect([]).toBeArrayOfSize(0); + * expect([1]).toBeArrayOfSize(1); + * expect(new Array(1)).toBeArrayOfSize(1); + * expect({}).not.toBeArrayOfSize(0); + */ + toBeArrayOfSize(size: number): void; + /** + * Asserts that a value is a `boolean`. + * + * @example + * expect(true).toBeBoolean(); + * expect(false).toBeBoolean(); + * expect(null).not.toBeBoolean(); + * expect(0).not.toBeBoolean(); + */ + toBeBoolean(): void; + /** + * Asserts that a value is `true`. + * + * @example + * expect(true).toBeTrue(); + * expect(false).not.toBeTrue(); + * expect(1).not.toBeTrue(); + */ + toBeTrue(): void; + /** + * Asserts that a value matches a specific type. + * + * @link https://vitest.dev/api/expect.html#tobetypeof + * @example + * expect(1).toBeTypeOf("number"); + * expect("hello").toBeTypeOf("string"); + * expect([]).not.toBeTypeOf("boolean"); + */ + toBeTypeOf(type: "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"): void; + /** + * Asserts that a value is `false`. + * + * @example + * expect(false).toBeFalse(); + * expect(true).not.toBeFalse(); + * expect(0).not.toBeFalse(); + */ + toBeFalse(): void; + /** + * Asserts that a value is a `number`. + * + * @example + * expect(1).toBeNumber(); + * expect(3.14).toBeNumber(); + * expect(NaN).toBeNumber(); + * expect(BigInt(1)).not.toBeNumber(); + */ + toBeNumber(): void; + /** + * Asserts that a value is a `number`, and is an integer. + * + * @example + * expect(1).toBeInteger(); + * expect(3.14).not.toBeInteger(); + * expect(NaN).not.toBeInteger(); + */ + toBeInteger(): void; + /** + * Asserts that a value is an `object`. + * + * @example + * expect({}).toBeObject(); + * expect("notAnObject").not.toBeObject(); + * expect(NaN).not.toBeObject(); + */ + toBeObject(): void; + /** + * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. + * + * @example + * expect(1).toBeFinite(); + * expect(3.14).toBeFinite(); + * expect(NaN).not.toBeFinite(); + * expect(Infinity).not.toBeFinite(); + */ + toBeFinite(): void; + /** + * Asserts that a value is a positive `number`. + * + * @example + * expect(1).toBePositive(); + * expect(-3.14).not.toBePositive(); + * expect(NaN).not.toBePositive(); + */ + toBePositive(): void; + /** + * Asserts that a value is a negative `number`. + * + * @example + * expect(-3.14).toBeNegative(); + * expect(1).not.toBeNegative(); + * expect(NaN).not.toBeNegative(); + */ + toBeNegative(): void; + /** + * Asserts that a value is a number between a start and end value. + * + * @param start the start number (inclusive) + * @param end the end number (exclusive) + */ + toBeWithin(start: number, end: number): void; + /** + * Asserts that a value is equal to the expected string, ignoring any whitespace. + * + * @example + * expect(" foo ").toEqualIgnoringWhitespace("foo"); + * expect("bar").toEqualIgnoringWhitespace(" bar "); + * + * @param expected the expected string + */ + toEqualIgnoringWhitespace(expected: string): void; + /** + * Asserts that a value is a `symbol`. + * + * @example + * expect(Symbol("foo")).toBeSymbol(); + * expect("foo").not.toBeSymbol(); + */ + toBeSymbol(): void; + /** + * Asserts that a value is a `function`. + * + * @example + * expect(() => {}).toBeFunction(); + */ + toBeFunction(): void; + /** + * Asserts that a value is a `Date` object. + * + * To check if a date is valid, use `toBeValidDate()` instead. + * + * @example + * expect(new Date()).toBeDate(); + * expect(new Date(null)).toBeDate(); + * expect("2020-03-01").not.toBeDate(); + */ + toBeDate(): void; + /** + * Asserts that a value is a valid `Date` object. + * + * @example + * expect(new Date()).toBeValidDate(); + * expect(new Date(null)).not.toBeValidDate(); + * expect("2020-03-01").not.toBeValidDate(); + */ + toBeValidDate(): void; + /** + * Asserts that a value is a `string`. + * + * @example + * expect("foo").toBeString(); + * expect(new String("bar")).toBeString(); + * expect(123).not.toBeString(); + */ + toBeString(): void; + /** + * Asserts that a value includes a `string`. + * + * For non-string values, use `toContain()` instead. + * + * @param expected the expected substring + */ + toInclude(expected: string): void; + /** + * Asserts that a value includes a `string` {times} times. + * @param expected the expected substring + * @param times the number of times the substring should occur + */ + toIncludeRepeated(expected: string, times: number): void; + /** + * Checks whether a value satisfies a custom condition. + * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. + * @example + * expect(1).toSatisfy((val) => val > 0); + * expect("foo").toSatisfy((val) => val === "foo"); + * expect("bar").not.toSatisfy((val) => val === "bun"); + * @link https://vitest.dev/api/expect.html#tosatisfy + * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy + */ + toSatisfy(predicate: (value: T) => boolean): void; + /** + * Asserts that a value starts with a `string`. + * + * @param expected the string to start with + */ + toStartWith(expected: string): void; + /** + * Asserts that a value ends with a `string`. + * + * @param expected the string to end with + */ + toEndWith(expected: string): void; + /** + * Ensures that a mock function has returned successfully at least once. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturned(): void; + + /** + * Ensures that a mock function has returned successfully at `times` times. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturnedTimes(times: number): void; + + /** + * Ensures that a mock function is called. + */ + toHaveBeenCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + * @alias toHaveBeenCalled + */ + toBeCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + */ + toHaveBeenCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledTimes + */ + toBeCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + */ + toHaveBeenCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledWith + */ + toBeCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the last call. + */ + toHaveBeenLastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + lastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + */ + toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + nthCalledWith(n: number, ...expected: unknown[]): void; + } + + /** + * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. + */ + // Defined as an alias of `any` so that it does not trigger any type mismatch + export type AsymmetricMatcher = any; + + export interface MatcherResult { + pass: boolean; + message?: string | (() => string); + } + + export type CustomMatcher = ( + this: MatcherContext, + expected: E, + ...matcherArguments: P + ) => MatcherResult | Promise; + + /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ + export type CustomMatchersDetected = Omit, keyof MatchersBuiltin> & + Omit; + + /** + * If the types has been defined through declaration merging, enforce it. + * Otherwise enforce the generic custom matcher signature. + */ + export type ExpectExtendMatchers = { + [k in keyof M]: k extends keyof CustomMatchersDetected + ? CustomMatcher> + : CustomMatcher; + }; + + /** Custom equality tester */ + export type Tester = (this: TesterContext, a: any, b: any, customTesters: Tester[]) => boolean | undefined; + + export type EqualsFunction = ( + a: unknown, + b: unknown, + //customTesters?: Array, + //strictCheck?: boolean, + ) => boolean; + + export interface TesterContext { + equals: EqualsFunction; + } + + interface MatcherState { + //assertionCalls: number; + //currentConcurrentTestName?: () => string | undefined; + //currentTestName?: string; + //error?: Error; + //expand: boolean; + //expectedAssertionsNumber: number | null; + //expectedAssertionsNumberError?: Error; + //isExpectingAssertions: boolean; + //isExpectingAssertionsError?: Error; + isNot: boolean; + //numPassingAsserts: number; + promise: string; + //suppressedErrors: Array; + //testPath?: string; + } + + type MatcherHintColor = (arg: string) => string; // subset of Chalk type + + interface MatcherUtils { + //customTesters: Array; + //dontThrow(): void; // (internally used by jest snapshot) + equals: EqualsFunction; + utils: Readonly<{ + stringify(value: unknown): string; + printReceived(value: unknown): string; + printExpected(value: unknown): string; + matcherHint( + matcherName: string, + received?: unknown, + expected?: unknown, + options?: { + isNot?: boolean; + promise?: string; + isDirectExpectCall?: boolean; // (internal) + comment?: string; + expectedColor?: MatcherHintColor; + receivedColor?: MatcherHintColor; + secondArgument?: string; + secondArgumentColor?: MatcherHintColor; + }, + ): string; + //iterableEquality: Tester; + //subsetEquality: Tester; + // ... + }>; + } + + type MatcherContext = MatcherUtils & MatcherState; } declare module "test" { - export type * from "bun:test"; + export type * from "bun:test"; } declare namespace JestMock { - /** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - export interface ClassLike { - new (...args: any): any; - } - - export type ConstructorLikeKeys = keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - }; - - // export const fn: ( - // implementation?: T | undefined, - // ) => Mock; - - export type FunctionLike = (...args: any) => any; - - export type MethodLikeKeys = keyof { - [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; - }; - - export interface Mock any> - extends MockInstance { - (...args: Parameters): ReturnType; - } - - /** - * All what the internal typings need is to be sure that we have any-function. - * `FunctionLike` type ensures that and helps to constrain the type as well. - * The default of `UnknownFunction` makes sure that `any`s do not leak to the - * user side. For instance, calling `fn()` without implementation will return - * a mock of `(...args: Array) => unknown` type. If implementation - * is provided, its typings are inferred correctly. - */ - // export interface Mock - // extends Function, - // MockInstance { - // new (...args: Parameters): ReturnType; - // (...args: Parameters): ReturnType; - // } - - // export type Mocked = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunction - // : T extends object - // ? MockedObject - // : T; - - // export const mocked: { - // ( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // ( - // source: T_1, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // }; - - // export type MockedClass = MockInstance< - // (...args: ConstructorParameters) => Mocked> - // > & - // MockedObject; - - // export type MockedFunction = MockInstance & - // MockedObject; - - // type MockedFunctionShallow = MockInstance & T; - - // export type MockedObject = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunction - // : T[K] extends object - // ? MockedObject - // : T[K]; - // } & T; - - // type MockedObjectShallow = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunctionShallow - // : T[K]; - // } & T; - - // export type MockedShallow = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunctionShallow - // : T extends object - // ? MockedObjectShallow - // : T; - - // export type MockFunctionMetadata< - // T = unknown, - // MetadataType = MockMetadataType, - // > = MockMetadata; - - // export type MockFunctionMetadataType = MockMetadataType; - - type MockFunctionResult = - | MockFunctionResultIncomplete - | MockFunctionResultReturn - | MockFunctionResultThrow; - - interface MockFunctionResultIncomplete { - type: "incomplete"; - /** - * Result of a single call to a mock function that has not yet completed. - * This occurs if you test the result from within the mock function itself, - * or from within a function that was called by the mock. - */ - value: undefined; - } - - interface MockFunctionResultReturn { - type: "return"; - /** - * Result of a single call to a mock function that returned. - */ - value: ReturnType; - } - - interface MockFunctionResultThrow { - type: "throw"; - /** - * Result of a single call to a mock function that threw. - */ - value: unknown; - } - - interface MockFunctionState { - /** - * List of the call arguments of all calls that have been made to the mock. - */ - calls: Array>; - /** - * List of all the object instances that have been instantiated from the mock. - */ - instances: Array>; - /** - * List of all the function contexts that have been applied to calls to the mock. - */ - contexts: Array>; - /** - * List of the call order indexes of the mock. Jest is indexing the order of - * invocations of all mocks in a test file. The index is starting with `1`. - */ - invocationCallOrder: number[]; - /** - * List of the call arguments of the last call that was made to the mock. - * If the function was not called, it will return `undefined`. - */ - lastCall?: Parameters; - /** - * List of the results of all calls that have been made to the mock. - */ - results: Array>; - } - - export interface MockInstance { - _isMockFunction: true; - _protoImpl: Function; - getMockImplementation(): T | undefined; - getMockName(): string; - mock: MockFunctionState; - mockClear(): this; - mockReset(): this; - mockRestore(): void; - mockImplementation(fn: T): this; - mockImplementationOnce(fn: T): this; - withImplementation(fn: T, callback: () => Promise): Promise; - withImplementation(fn: T, callback: () => void): void; - mockName(name: string): this; - mockReturnThis(): this; - mockReturnValue(value: ReturnType): this; - mockReturnValueOnce(value: ReturnType): this; - mockResolvedValue(value: ResolveType): this; - mockResolvedValueOnce(value: ResolveType): this; - mockRejectedValue(value: RejectType): this; - mockRejectedValueOnce(value: RejectType): this; - } - - // export type MockMetadata = { - // ref?: number; - // members?: Record>; - // mockImpl?: T; - // name?: string; - // refID?: number; - // type?: MetadataType; - // value?: T; - // length?: number; - // }; - - // export type MockMetadataType = - // | "object" - // | "array" - // | "regexp" - // | "function" - // | "constant" - // | "collection" - // | "null" - // | "undefined"; - - // export class ModuleMocker { - // private readonly _environmentGlobal; - // private _mockState; - // private _mockConfigRegistry; - // private _spyState; - // private _invocationCallCounter; - // /** - // * @see README.md - // * @param global Global object of the test environment, used to create - // * mocks - // */ - // constructor(global: typeof globalThis); - // private _getSlots; - // private _ensureMockConfig; - // private _ensureMockState; - // private _defaultMockConfig; - // private _defaultMockState; - // private _makeComponent; - // private _createMockFunction; - // private _generateMock; - // /** - // * Check whether the given property of an object has been already replaced. - // */ - // private _findReplacedProperty; - // /** - // * @see README.md - // * @param metadata Metadata for the mock in the schema returned by the - // * getMetadata method of this module. - // */ - // generateFromMetadata(metadata: MockMetadata): Mocked; - // /** - // * @see README.md - // * @param component The component for which to retrieve metadata. - // */ - // getMetadata( - // component: T, - // _refs?: Map, - // ): MockMetadata | null; - // isMockFunction( - // fn: MockInstance, - // ): fn is MockInstance; - // isMockFunction

, R>( - // fn: (...args: P) => R, - // ): fn is Mock<(...args: P) => R>; - // isMockFunction(fn: unknown): fn is Mock; - // fn(implementation?: T): Mock; - // private _attachMockImplementation; - // spyOn< - // T extends object, - // K extends PropertyLikeKeys, - // A extends "get" | "set", - // >( - // object: T, - // methodKey: K, - // accessType: A, - // ): A extends "get" - // ? SpiedGetter - // : A extends "set" - // ? SpiedSetter - // : never; - // spyOn< - // T extends object, - // K extends ConstructorLikeKeys | MethodLikeKeys, - // V extends Required[K], - // >( - // object: T, - // methodKey: K, - // ): V extends ClassLike | FunctionLike ? Spied : never; - // private _spyOnProperty; - // replaceProperty< - // T extends object, - // K extends PropertyLikeKeys, - // V extends T[K], - // >(object: T, propertyKey: K, value: V): Replaced; - // clearAllMocks(): void; - // resetAllMocks(): void; - // restoreAllMocks(): void; - // private _typeOf; - // mocked( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // mocked( - // source: T, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // } - - export type PropertyLikeKeys = Exclude< - keyof T, - ConstructorLikeKeys | MethodLikeKeys - >; - - export type RejectType = - ReturnType extends PromiseLike ? unknown : never; - - export interface Replaced { - /** - * Restore property to its original value known at the time of mocking. - */ - restore(): void; - /** - * Change the value of the property. - */ - replaceValue(value: T): this; - } - - export function replaceProperty< - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike - ? K_1 - : never]: T[K_1]; - } - >, - V extends T[K_2], - >(object: T, propertyKey: K_2, value: V): Replaced; - - export type ResolveType = - ReturnType extends PromiseLike ? U : never; - - export type Spied = T extends ClassLike - ? SpiedClass - : T extends FunctionLike - ? SpiedFunction - : never; - - export type SpiedClass = MockInstance< - (...args: ConstructorParameters) => InstanceType - >; - - export type SpiedFunction = - MockInstance<(...args: Parameters) => ReturnType>; - - export type SpiedGetter = MockInstance<() => T>; - - export type SpiedSetter = MockInstance<(arg: T) => void>; - - export interface SpyInstance - extends MockInstance {} - - export const spyOn: { - < - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike - ? K - : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike - ? K_1 - : never]: T[K_1]; - } - >, - V extends Required[K_2], - A extends "set" | "get", - >( - object: T, - methodKey: K_2, - accessType: A, - ): A extends "get" - ? SpiedGetter - : A extends "set" - ? SpiedSetter - : never; - < - T_1 extends object, - K_5 extends - | keyof { - [K_3 in keyof T_1 as Required[K_3] extends ClassLike - ? K_3 - : never]: T_1[K_3]; - } - | keyof { - [K_4 in keyof T_1 as Required[K_4] extends FunctionLike - ? K_4 - : never]: T_1[K_4]; - }, - V_1 extends Required[K_5], - >( - object: T_1, - methodKey: K_5, - ): V_1 extends ClassLike | FunctionLike ? Spied : never; - }; - - export interface UnknownClass { - new (...args: unknown[]): unknown; - } - - export type UnknownFunction = (...args: unknown[]) => unknown; + /** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + export interface ClassLike { + new (...args: any): any; + } + + export type ConstructorLikeKeys = keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + }; + + // export const fn: ( + // implementation?: T | undefined, + // ) => Mock; + + export type FunctionLike = (...args: any) => any; + + export type MethodLikeKeys = keyof { + [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; + }; + + export interface Mock any> extends MockInstance { + (...args: Parameters): ReturnType; + } + + /** + * All what the internal typings need is to be sure that we have any-function. + * `FunctionLike` type ensures that and helps to constrain the type as well. + * The default of `UnknownFunction` makes sure that `any`s do not leak to the + * user side. For instance, calling `fn()` without implementation will return + * a mock of `(...args: Array) => unknown` type. If implementation + * is provided, its typings are inferred correctly. + */ + // export interface Mock + // extends Function, + // MockInstance { + // new (...args: Parameters): ReturnType; + // (...args: Parameters): ReturnType; + // } + + // export type Mocked = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunction + // : T extends object + // ? MockedObject + // : T; + + // export const mocked: { + // ( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // ( + // source: T_1, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // }; + + // export type MockedClass = MockInstance< + // (...args: ConstructorParameters) => Mocked> + // > & + // MockedObject; + + // export type MockedFunction = MockInstance & + // MockedObject; + + // type MockedFunctionShallow = MockInstance & T; + + // export type MockedObject = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunction + // : T[K] extends object + // ? MockedObject + // : T[K]; + // } & T; + + // type MockedObjectShallow = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunctionShallow + // : T[K]; + // } & T; + + // export type MockedShallow = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunctionShallow + // : T extends object + // ? MockedObjectShallow + // : T; + + // export type MockFunctionMetadata< + // T = unknown, + // MetadataType = MockMetadataType, + // > = MockMetadata; + + // export type MockFunctionMetadataType = MockMetadataType; + + type MockFunctionResult = + | MockFunctionResultIncomplete + | MockFunctionResultReturn + | MockFunctionResultThrow; + + interface MockFunctionResultIncomplete { + type: "incomplete"; + /** + * Result of a single call to a mock function that has not yet completed. + * This occurs if you test the result from within the mock function itself, + * or from within a function that was called by the mock. + */ + value: undefined; + } + + interface MockFunctionResultReturn { + type: "return"; + /** + * Result of a single call to a mock function that returned. + */ + value: ReturnType; + } + + interface MockFunctionResultThrow { + type: "throw"; + /** + * Result of a single call to a mock function that threw. + */ + value: unknown; + } + + interface MockFunctionState { + /** + * List of the call arguments of all calls that have been made to the mock. + */ + calls: Array>; + /** + * List of all the object instances that have been instantiated from the mock. + */ + instances: Array>; + /** + * List of all the function contexts that have been applied to calls to the mock. + */ + contexts: Array>; + /** + * List of the call order indexes of the mock. Jest is indexing the order of + * invocations of all mocks in a test file. The index is starting with `1`. + */ + invocationCallOrder: number[]; + /** + * List of the call arguments of the last call that was made to the mock. + * If the function was not called, it will return `undefined`. + */ + lastCall?: Parameters; + /** + * List of the results of all calls that have been made to the mock. + */ + results: Array>; + } + + export interface MockInstance { + _isMockFunction: true; + _protoImpl: Function; + getMockImplementation(): T | undefined; + getMockName(): string; + mock: MockFunctionState; + mockClear(): this; + mockReset(): this; + mockRestore(): void; + mockImplementation(fn: T): this; + mockImplementationOnce(fn: T): this; + withImplementation(fn: T, callback: () => Promise): Promise; + withImplementation(fn: T, callback: () => void): void; + mockName(name: string): this; + mockReturnThis(): this; + mockReturnValue(value: ReturnType): this; + mockReturnValueOnce(value: ReturnType): this; + mockResolvedValue(value: ResolveType): this; + mockResolvedValueOnce(value: ResolveType): this; + mockRejectedValue(value: RejectType): this; + mockRejectedValueOnce(value: RejectType): this; + } + + // export type MockMetadata = { + // ref?: number; + // members?: Record>; + // mockImpl?: T; + // name?: string; + // refID?: number; + // type?: MetadataType; + // value?: T; + // length?: number; + // }; + + // export type MockMetadataType = + // | "object" + // | "array" + // | "regexp" + // | "function" + // | "constant" + // | "collection" + // | "null" + // | "undefined"; + + // export class ModuleMocker { + // private readonly _environmentGlobal; + // private _mockState; + // private _mockConfigRegistry; + // private _spyState; + // private _invocationCallCounter; + // /** + // * @see README.md + // * @param global Global object of the test environment, used to create + // * mocks + // */ + // constructor(global: typeof globalThis); + // private _getSlots; + // private _ensureMockConfig; + // private _ensureMockState; + // private _defaultMockConfig; + // private _defaultMockState; + // private _makeComponent; + // private _createMockFunction; + // private _generateMock; + // /** + // * Check whether the given property of an object has been already replaced. + // */ + // private _findReplacedProperty; + // /** + // * @see README.md + // * @param metadata Metadata for the mock in the schema returned by the + // * getMetadata method of this module. + // */ + // generateFromMetadata(metadata: MockMetadata): Mocked; + // /** + // * @see README.md + // * @param component The component for which to retrieve metadata. + // */ + // getMetadata( + // component: T, + // _refs?: Map, + // ): MockMetadata | null; + // isMockFunction( + // fn: MockInstance, + // ): fn is MockInstance; + // isMockFunction

, R>( + // fn: (...args: P) => R, + // ): fn is Mock<(...args: P) => R>; + // isMockFunction(fn: unknown): fn is Mock; + // fn(implementation?: T): Mock; + // private _attachMockImplementation; + // spyOn< + // T extends object, + // K extends PropertyLikeKeys, + // A extends "get" | "set", + // >( + // object: T, + // methodKey: K, + // accessType: A, + // ): A extends "get" + // ? SpiedGetter + // : A extends "set" + // ? SpiedSetter + // : never; + // spyOn< + // T extends object, + // K extends ConstructorLikeKeys | MethodLikeKeys, + // V extends Required[K], + // >( + // object: T, + // methodKey: K, + // ): V extends ClassLike | FunctionLike ? Spied : never; + // private _spyOnProperty; + // replaceProperty< + // T extends object, + // K extends PropertyLikeKeys, + // V extends T[K], + // >(object: T, propertyKey: K, value: V): Replaced; + // clearAllMocks(): void; + // resetAllMocks(): void; + // restoreAllMocks(): void; + // private _typeOf; + // mocked( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // mocked( + // source: T, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // } + + export type PropertyLikeKeys = Exclude | MethodLikeKeys>; + + export type RejectType = ReturnType extends PromiseLike ? unknown : never; + + export interface Replaced { + /** + * Restore property to its original value known at the time of mocking. + */ + restore(): void; + /** + * Change the value of the property. + */ + replaceValue(value: T): this; + } + + export function replaceProperty< + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; + } + >, + V extends T[K_2], + >(object: T, propertyKey: K_2, value: V): Replaced; + + export type ResolveType = ReturnType extends PromiseLike ? U : never; + + export type Spied = T extends ClassLike + ? SpiedClass + : T extends FunctionLike + ? SpiedFunction + : never; + + export type SpiedClass = MockInstance< + (...args: ConstructorParameters) => InstanceType + >; + + export type SpiedFunction = MockInstance< + (...args: Parameters) => ReturnType + >; + + export type SpiedGetter = MockInstance<() => T>; + + export type SpiedSetter = MockInstance<(arg: T) => void>; + + export interface SpyInstance extends MockInstance {} + + export const spyOn: { + < + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; + } + >, + V extends Required[K_2], + A extends "set" | "get", + >( + object: T, + methodKey: K_2, + accessType: A, + ): A extends "get" ? SpiedGetter : A extends "set" ? SpiedSetter : never; + < + T_1 extends object, + K_5 extends + | keyof { + [K_3 in keyof T_1 as Required[K_3] extends ClassLike ? K_3 : never]: T_1[K_3]; + } + | keyof { + [K_4 in keyof T_1 as Required[K_4] extends FunctionLike ? K_4 : never]: T_1[K_4]; + }, + V_1 extends Required[K_5], + >( + object: T_1, + methodKey: K_5, + ): V_1 extends ClassLike | FunctionLike ? Spied : never; + }; + + export interface UnknownClass { + new (...args: unknown[]): unknown; + } + + export type UnknownFunction = (...args: unknown[]) => unknown; } diff --git a/packages/bun-types/test/array-buffer.test.ts b/packages/bun-types/test/array-buffer.test.ts index 9fd63d35108368..a3253138e308c2 100644 --- a/packages/bun-types/test/array-buffer.test.ts +++ b/packages/bun-types/test/array-buffer.test.ts @@ -1,5 +1,5 @@ const buffer = new ArrayBuffer(1024, { - maxByteLength: 2048, + maxByteLength: 2048, }); console.log(buffer.byteLength); // 1024 diff --git a/packages/bun-types/test/array.test.ts b/packages/bun-types/test/array.test.ts index d9fce478c69188..af57108192d40d 100644 --- a/packages/bun-types/test/array.test.ts +++ b/packages/bun-types/test/array.test.ts @@ -1,18 +1,16 @@ import { expectType } from "./utilities.test"; async function* listReleases() { - for (let page = 1; ; page++) { - const response = await fetch( - `https://api.github.com/repos/oven-sh/bun/releases?page=${page}`, - ); - const releases = (await response.json()) as Array<{ data: string }>; - if (!releases.length) { - break; - } - for (const release of releases) { - yield release; - } - } + for (let page = 1; ; page++) { + const response = await fetch(`https://api.github.com/repos/oven-sh/bun/releases?page=${page}`); + const releases = (await response.json()) as Array<{ data: string }>; + if (!releases.length) { + break; + } + for (const release of releases) { + yield release; + } + } } await Array.fromAsync(listReleases()); @@ -20,12 +18,12 @@ await Array.fromAsync(listReleases()); // Tests from issue #8484 // https://github.com/oven-sh/bun/issues/8484 async function* naturals() { - for (let i = 0; i < 10; i++) { - yield i; - } + for (let i = 0; i < 10; i++) { + yield i; + } } -const test1 = await Array.fromAsync(naturals(), (n) => Promise.resolve(`${n}`)); +const test1 = await Array.fromAsync(naturals(), n => Promise.resolve(`${n}`)); expectType(test1); const test2 = await Array.fromAsync([Promise.resolve(1), Promise.resolve(2)]); diff --git a/packages/bun-types/test/broadcast.test.ts b/packages/bun-types/test/broadcast.test.ts index 1458e0c0615365..1d853f7fec23dc 100644 --- a/packages/bun-types/test/broadcast.test.ts +++ b/packages/bun-types/test/broadcast.test.ts @@ -1,9 +1,9 @@ const channel = new BroadcastChannel("my-channel"); const message = { hello: "world" }; -channel.onmessage = (event) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - console.log((event as any).data); // { hello: "world" } +channel.onmessage = event => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + console.log((event as any).data); // { hello: "world" } }; channel.postMessage(message); diff --git a/packages/bun-types/test/bun.test.ts b/packages/bun-types/test/bun.test.ts index b3cfb1bfeed41b..ae642ff6f1e53c 100644 --- a/packages/bun-types/test/bun.test.ts +++ b/packages/bun-types/test/bun.test.ts @@ -1,51 +1,51 @@ import { BunFile, BunPlugin, FileBlob } from "bun"; import * as tsd from "./utilities.test"; { - const _plugin: BunPlugin = { - name: "asdf", - setup() {}, - }; - _plugin; + const _plugin: BunPlugin = { + name: "asdf", + setup() {}, + }; + _plugin; } { - // tslint:disable-next-line:no-void-expression - const arg = Bun.plugin({ - name: "arg", - setup() {}, - }); + // tslint:disable-next-line:no-void-expression + const arg = Bun.plugin({ + name: "arg", + setup() {}, + }); - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - tsd.expectType(arg); + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + tsd.expectType(arg); } { - // tslint:disable-next-line:no-void-expression - const arg = Bun.plugin({ - name: "arg", - async setup() {}, - }); + // tslint:disable-next-line:no-void-expression + const arg = Bun.plugin({ + name: "arg", + async setup() {}, + }); - tsd.expectType>(arg); + tsd.expectType>(arg); } { - const f = Bun.file("asdf"); - tsd.expectType(f); - tsd.expectType(f); + const f = Bun.file("asdf"); + tsd.expectType(f); + tsd.expectType(f); } { - Bun.spawn(["anything"], { - env: process.env, - }); - Bun.spawn(["anything"], { - env: { ...process.env }, - }); - Bun.spawn(["anything"], { - env: { ...process.env, dummy: "" }, - }); + Bun.spawn(["anything"], { + env: process.env, + }); + Bun.spawn(["anything"], { + env: { ...process.env }, + }); + Bun.spawn(["anything"], { + env: { ...process.env, dummy: "" }, + }); } { - Bun.TOML.parse("asdf = asdf"); + Bun.TOML.parse("asdf = asdf"); } DOMException; diff --git a/packages/bun-types/test/console.test.ts b/packages/bun-types/test/console.test.ts index b00be4b0c7e101..779bbab1984711 100644 --- a/packages/bun-types/test/console.test.ts +++ b/packages/bun-types/test/console.test.ts @@ -5,19 +5,19 @@ c1.log(); c2.log(); async () => { - // tslint:disable-next-line:await-promise - for await (const line of c1) { - console.log("Received:", line); - } + // tslint:disable-next-line:await-promise + for await (const line of c1) { + console.log("Received:", line); + } - // tslint:disable-next-line:await-promise - for await (const line of c2) { - console.log("Received:", line); - } - // tslint:disable-next-line:await-promise - for await (const line of console) { - console.log("Received:", line); - } + // tslint:disable-next-line:await-promise + for await (const line of c2) { + console.log("Received:", line); + } + // tslint:disable-next-line:await-promise + for await (const line of console) { + console.log("Received:", line); + } - return null; + return null; }; diff --git a/packages/bun-types/test/diag.test.ts b/packages/bun-types/test/diag.test.ts index df3aef7e3c6e82..35f41ce050664d 100644 --- a/packages/bun-types/test/diag.test.ts +++ b/packages/bun-types/test/diag.test.ts @@ -5,7 +5,7 @@ const channel = diagnostics_channel.channel("my-channel"); // Subscribe to the channel channel.subscribe((message, name) => { - console.log("Received message:", message); + console.log("Received message:", message); }); // Publish a message to the channel diff --git a/packages/bun-types/test/dom.test.ts b/packages/bun-types/test/dom.test.ts index 804f5cead79e61..c3d8a4383640e5 100644 --- a/packages/bun-types/test/dom.test.ts +++ b/packages/bun-types/test/dom.test.ts @@ -3,23 +3,23 @@ import { INSPECT_MAX_BYTES } from "buffer"; INSPECT_MAX_BYTES; { - new Blob([]); + new Blob([]); } { - new MessagePort(); + new MessagePort(); } { - new MessageChannel(); + new MessageChannel(); } { - new BroadcastChannel("zxgdfg"); + new BroadcastChannel("zxgdfg"); } { - new Response("asdf"); + new Response("asdf"); } { - Response.json({ asdf: "asdf" }).ok; - const r = Response.json({ hello: "world" }); - r.body; + Response.json({ asdf: "asdf" }).ok; + const r = Response.json({ hello: "world" }); + r.body; } diff --git a/packages/bun-types/test/env.test.ts b/packages/bun-types/test/env.test.ts index aa26b9f002ee84..f9b1d53be648b4 100644 --- a/packages/bun-types/test/env.test.ts +++ b/packages/bun-types/test/env.test.ts @@ -1,19 +1,19 @@ import { expectType } from "./utilities.test"; declare module "bun" { - interface Env { - FOO: "FOO"; - } + interface Env { + FOO: "FOO"; + } } expectType<"FOO">(process.env.FOO); declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace NodeJS { - interface ProcessEnv { - BAR: "BAR"; - } - } + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace NodeJS { + interface ProcessEnv { + BAR: "BAR"; + } + } } expectType<"BAR">(process.env.BAR); diff --git a/packages/bun-types/test/events.test.ts b/packages/bun-types/test/events.test.ts index b3404096aa7185..d774a4b619d0dd 100644 --- a/packages/bun-types/test/events.test.ts +++ b/packages/bun-types/test/events.test.ts @@ -13,8 +13,8 @@ import { expectType } from "./utilities.test"; const e2 = new EventEmitter(); e2.on("qwer", (_: any) => { - _; + _; }); -e2.on("asdf", (arg) => { - expectType(arg); +e2.on("asdf", arg => { + expectType(arg); }); diff --git a/packages/bun-types/test/ffi.test.ts b/packages/bun-types/test/ffi.test.ts index c7a74e0cdb5ff4..277c45b5ec57a6 100644 --- a/packages/bun-types/test/ffi.test.ts +++ b/packages/bun-types/test/ffi.test.ts @@ -1,12 +1,4 @@ -import { - CString, - dlopen, - FFIType, - JSCallback, - Pointer, - read, - suffix, -} from "bun:ffi"; +import { CString, dlopen, FFIType, JSCallback, Pointer, read, suffix } from "bun:ffi"; import * as tsd from "./utilities.test"; // `suffix` is either "dylib", "so", or "dll" depending on the platform @@ -14,60 +6,60 @@ import * as tsd from "./utilities.test"; const path = `libsqlite3.${suffix}`; const lib = dlopen( - path, // a library name or file path - { - sqlite3_libversion: { - // no arguments, returns a string - args: [], - returns: FFIType.cstring, - }, - add: { - args: [FFIType.i32, FFIType.i32], - returns: FFIType.i32, - }, - ptr_type: { - args: [FFIType.pointer], - returns: FFIType.pointer, - }, - fn_type: { - args: [FFIType.function], - returns: FFIType.function, - }, - allArgs: { - args: [ - FFIType.char, // string - FFIType.int8_t, - FFIType.i8, - FFIType.uint8_t, - FFIType.u8, - FFIType.int16_t, - FFIType.i16, - FFIType.uint16_t, - FFIType.u16, - FFIType.int32_t, - FFIType.i32, - FFIType.int, - FFIType.uint32_t, - FFIType.u32, - FFIType.int64_t, - FFIType.i64, - FFIType.uint64_t, - FFIType.u64, - FFIType.double, - FFIType.f64, - FFIType.float, - FFIType.f32, - FFIType.bool, - FFIType.ptr, - FFIType.pointer, - FFIType.void, - FFIType.cstring, - FFIType.i64_fast, - FFIType.u64_fast, - ], - returns: FFIType.void, - }, - }, + path, // a library name or file path + { + sqlite3_libversion: { + // no arguments, returns a string + args: [], + returns: FFIType.cstring, + }, + add: { + args: [FFIType.i32, FFIType.i32], + returns: FFIType.i32, + }, + ptr_type: { + args: [FFIType.pointer], + returns: FFIType.pointer, + }, + fn_type: { + args: [FFIType.function], + returns: FFIType.function, + }, + allArgs: { + args: [ + FFIType.char, // string + FFIType.int8_t, + FFIType.i8, + FFIType.uint8_t, + FFIType.u8, + FFIType.int16_t, + FFIType.i16, + FFIType.uint16_t, + FFIType.u16, + FFIType.int32_t, + FFIType.i32, + FFIType.int, + FFIType.uint32_t, + FFIType.u32, + FFIType.int64_t, + FFIType.i64, + FFIType.uint64_t, + FFIType.u64, + FFIType.double, + FFIType.f64, + FFIType.float, + FFIType.f32, + FFIType.bool, + FFIType.ptr, + FFIType.pointer, + FFIType.void, + FFIType.cstring, + FFIType.i64_fast, + FFIType.u64_fast, + ], + returns: FFIType.void, + }, + }, ); declare const ptr: Pointer; @@ -77,46 +69,44 @@ tsd.expectType(lib.symbols.add(1, 2)); tsd.expectType(lib.symbols.ptr_type(ptr)); -tsd.expectType( - lib.symbols.fn_type(new JSCallback(() => {}, {})), -); +tsd.expectType(lib.symbols.fn_type(new JSCallback(() => {}, {}))); function _arg( - ...params: [ - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - boolean, - Pointer, - Pointer, - // tslint:disable-next-line: void-return - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - void, - CString, - number | bigint, - number | bigint, - ] + ...params: [ + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + boolean, + Pointer, + Pointer, + // tslint:disable-next-line: void-return + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + void, + CString, + number | bigint, + number | bigint, + ] ) { - console.log("asdf"); + console.log("asdf"); } _arg; @@ -153,20 +143,20 @@ tsd.expectTypeEquals(true); // tslint:disable-next-line:no-object-literal-type-assertion const as_const_test = { - sqlite3_libversion: { - args: [], - returns: FFIType.cstring, - }, - multi_args: { - args: [FFIType.i32, FFIType.f32], - returns: FFIType.void, - }, - no_returns: { - args: [FFIType.i32], - }, - no_args: { - returns: FFIType.i32, - }, + sqlite3_libversion: { + args: [], + returns: FFIType.cstring, + }, + multi_args: { + args: [FFIType.i32, FFIType.f32], + returns: FFIType.void, + }, + no_returns: { + args: [FFIType.i32], + }, + no_args: { + returns: FFIType.i32, + }, } as const; const lib2 = dlopen(path, as_const_test); @@ -175,10 +165,7 @@ tsd.expectType(lib2.symbols.sqlite3_libversion()); // tslint:disable-next-line:no-void-expression // eslint-disable-next-line @typescript-eslint/no-invalid-void-type tsd.expectType(lib2.symbols.multi_args(1, 2)); -tsd.expectTypeEquals< - ReturnType<(typeof lib2)["symbols"]["no_returns"]>, - undefined ->(true); +tsd.expectTypeEquals, undefined>(true); tsd.expectTypeEquals, []>(true); tsd.expectType(read.u8(ptr)); diff --git a/packages/bun-types/test/fs.test.ts b/packages/bun-types/test/fs.test.ts index 5fe2e4c920835c..863c528d1ba72b 100644 --- a/packages/bun-types/test/fs.test.ts +++ b/packages/bun-types/test/fs.test.ts @@ -11,10 +11,10 @@ tsd.expectType>(fs.promises.exists("/etc/passwd")); // file path watch(".", (eventType, filename) => { - console.log(`event type = ${eventType}`); - if (filename) { - console.log(`filename = ${filename}`); - } + console.log(`event type = ${eventType}`); + if (filename) { + console.log(`filename = ${filename}`); + } }); await Bun.file("sdf").exists(); diff --git a/packages/bun-types/test/fsrouter.test.ts b/packages/bun-types/test/fsrouter.test.ts index 2e26f90bb0e066..1a1b9975560bff 100644 --- a/packages/bun-types/test/fsrouter.test.ts +++ b/packages/bun-types/test/fsrouter.test.ts @@ -2,8 +2,8 @@ import { FileSystemRouter } from "bun"; import { expectType } from "./utilities.test"; const router = new FileSystemRouter({ - dir: "/pages", - style: "nextjs", + dir: "/pages", + style: "nextjs", }); const match = router.match("/"); diff --git a/packages/bun-types/test/globals.test.ts b/packages/bun-types/test/globals.test.ts index 3644f515ba4c0d..d2fb69e4c9eb89 100644 --- a/packages/bun-types/test/globals.test.ts +++ b/packages/bun-types/test/globals.test.ts @@ -26,16 +26,14 @@ expectType(new Bun.SHA512_256().update("test").digest("hex")); expectType(Bun.deflateSync(new Uint8Array(128))); expectType(Bun.gzipSync(new Uint8Array(128))); expectType( - Bun.deflateSync(new Uint8Array(128), { - level: -1, - memLevel: 8, - strategy: 0, - windowBits: 15, - }), -); -expectType( - Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 }), + Bun.deflateSync(new Uint8Array(128), { + level: -1, + memLevel: 8, + strategy: 0, + windowBits: 15, + }), ); +expectType(Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 })); expectType(Bun.inflateSync(new Uint8Array(64))); // Pretend this is DEFLATE compressed data expectType(Bun.gunzipSync(new Uint8Array(64))); // Pretend this is GZIP compressed data expectAssignable({ windowBits: -11 }); @@ -47,9 +45,7 @@ expectType(Bun.pathToFileURL("/foo/bar.txt")); expectType(Bun.fileURLToPath(new URL("file:///foo/bar.txt"))); // Testing ../fs.d.ts -expectType( - fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString(), -); +expectType(fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString()); expectType(fs.existsSync("./index.d.ts")); // tslint:disable-next-line:no-void-expression // eslint-disable-next-line @typescript-eslint/no-invalid-void-type @@ -62,9 +58,7 @@ expectType(fs.appendFileSync("./index.d.ts", "test")); expectType(fs.mkdirSync("./index.d.ts")); // Testing ^promises.d.ts -expectType( - (await fsPromises.readFile("./index.d.ts", { encoding: "utf-8" })).toString(), -); +expectType((await fsPromises.readFile("./index.d.ts", { encoding: "utf-8" })).toString()); expectType>(fsPromises.access("./index.d.ts")); expectType>(fsPromises.appendFile("./index.d.ts", "test")); expectType>(fsPromises.mkdir("./index.d.ts")); @@ -142,7 +136,7 @@ function stuff(arg: ReadableStreamDefaultReader): any; function stuff(arg: ReadableStreamDefaultController): any; function stuff(arg: WritableStreamDefaultWriter): any; function stuff(arg: any) { - return "asfd"; + return "asfd"; } stuff("asdf" as any as Blob); @@ -163,145 +157,145 @@ const readableStream = new ReadableStream(); const writableStream = new WritableStream(); { - const a = new ByteLengthQueuingStrategy({ highWaterMark: 0 }); - a.highWaterMark; + const a = new ByteLengthQueuingStrategy({ highWaterMark: 0 }); + a.highWaterMark; } { - const a = new ReadableStreamDefaultController(); - a.close(); + const a = new ReadableStreamDefaultController(); + a.close(); } { - const a = new ReadableStreamDefaultReader(readableStream); - await a.cancel(); + const a = new ReadableStreamDefaultReader(readableStream); + await a.cancel(); } { - const a = new WritableStreamDefaultController(); - a.error(); + const a = new WritableStreamDefaultController(); + a.error(); } { - const a = new WritableStreamDefaultWriter(writableStream); - await a.close(); + const a = new WritableStreamDefaultWriter(writableStream); + await a.close(); } { - const a = new TransformStream(); - a.readable; + const a = new TransformStream(); + a.readable; } { - const a = new TransformStreamDefaultController(); - a.enqueue("asdf"); + const a = new TransformStreamDefaultController(); + a.enqueue("asdf"); } { - const a = new CountQueuingStrategy({ highWaterMark: 0 }); - a.highWaterMark; + const a = new CountQueuingStrategy({ highWaterMark: 0 }); + a.highWaterMark; } { - const a = new DOMException(); - a.DATA_CLONE_ERR; + const a = new DOMException(); + a.DATA_CLONE_ERR; } { - const a = new SubtleCrypto(); - await a.decrypt("asdf", new CryptoKey(), new Uint8Array()); + const a = new SubtleCrypto(); + await a.decrypt("asdf", new CryptoKey(), new Uint8Array()); } { - const a = new CryptoKey(); - a.algorithm; + const a = new CryptoKey(); + a.algorithm; } { - const a = new BuildError(); - a.level; + const a = new BuildError(); + a.level; } { - const a = new ResolveError(); - a.level; + const a = new ResolveError(); + a.level; } { - const a = new AbortController(); - a; + const a = new AbortController(); + a; } { - const a = new AbortSignal(); - a.aborted; + const a = new AbortSignal(); + a.aborted; } { - const a = new Request("asdf"); - await a.json(); - a.cache; + const a = new Request("asdf"); + await a.json(); + a.cache; } { - const a = new Response(); - await a.text(); - a.ok; + const a = new Response(); + await a.text(); + a.ok; } { - const a = new FormData(); - a.delete("asdf"); + const a = new FormData(); + a.delete("asdf"); } { - const a = new Headers(); - a.append("asdf", "asdf"); + const a = new Headers(); + a.append("asdf", "asdf"); } { - const a = new EventTarget(); - a.dispatchEvent(new Event("asdf")); + const a = new EventTarget(); + a.dispatchEvent(new Event("asdf")); } { - const a = new Event("asdf"); - a.bubbles; - a.composedPath()[0]; + const a = new Event("asdf"); + a.bubbles; + a.composedPath()[0]; } { - const a = new Blob(); - a.size; + const a = new Blob(); + a.size; } { - const a = new File(["asdf"], "stuff.txt "); - a.name; + const a = new File(["asdf"], "stuff.txt "); + a.name; } { - performance.now(); + performance.now(); } { - const a = new URL("asdf"); - a.host; - a.href; + const a = new URL("asdf"); + a.host; + a.href; } { - const a = new URLSearchParams(); - a; + const a = new URLSearchParams(); + a; } { - const a = new TextDecoder(); - a.decode(new Uint8Array()); + const a = new TextDecoder(); + a.decode(new Uint8Array()); } { - const a = new TextEncoder(); - a.encode("asdf"); + const a = new TextEncoder(); + a.encode("asdf"); } { - const a = new BroadcastChannel("stuff"); - a.close(); + const a = new BroadcastChannel("stuff"); + a.close(); } { - const a = new MessageChannel(); - a.port1; + const a = new MessageChannel(); + a.port1; } { - const a = new MessagePort(); - a.close(); + const a = new MessagePort(); + a.close(); } { - var a!: RequestInit; - a.mode; - a.credentials; + var a!: RequestInit; + a.mode; + a.credentials; } { - var b!: ResponseInit; - b.status; + var b!: ResponseInit; + b.status; } { - const ws = new WebSocket("ws://www.host.com/path"); - ws.send("asdf"); + const ws = new WebSocket("ws://www.host.com/path"); + ws.send("asdf"); } atob("asf"); diff --git a/packages/bun-types/test/http.test.ts b/packages/bun-types/test/http.test.ts index 49ee1e02c1b9f0..c78ab80c233ce8 100644 --- a/packages/bun-types/test/http.test.ts +++ b/packages/bun-types/test/http.test.ts @@ -29,7 +29,7 @@ export {}; // URLSearchParams should be iterable const sp = new URLSearchParams("q=foo&bar=baz"); for (const q of sp) { - console.log(q); + console.log(q); } fetch; diff --git a/packages/bun-types/test/jsc.test.ts b/packages/bun-types/test/jsc.test.ts index 181c5d84179a69..c1a531f1153af3 100644 --- a/packages/bun-types/test/jsc.test.ts +++ b/packages/bun-types/test/jsc.test.ts @@ -6,5 +6,5 @@ const buffer = serialize(obj); const clone = deserialize(buffer); if (deepEquals(obj, clone)) { - console.log("They are equal!"); + console.log("They are equal!"); } diff --git a/packages/bun-types/test/mocks.test.ts b/packages/bun-types/test/mocks.test.ts index 87eb74dcea59db..8c891743356fcc 100644 --- a/packages/bun-types/test/mocks.test.ts +++ b/packages/bun-types/test/mocks.test.ts @@ -2,7 +2,7 @@ import { jest, mock } from "bun:test"; import { expectType } from "./utilities.test"; const mock1 = mock((arg: string) => { - return arg.length; + return arg.length; }); const arg1 = mock1("1"); diff --git a/packages/bun-types/test/net.test.ts b/packages/bun-types/test/net.test.ts index 2756dd4d1dd7d4..76ad4b01516fe9 100644 --- a/packages/bun-types/test/net.test.ts +++ b/packages/bun-types/test/net.test.ts @@ -1,11 +1,11 @@ import * as net from "node:net"; const socket = net.connect({ - port: 80, - host: "localhost", + port: 80, + host: "localhost", }); socket.connect({ - port: 80, - host: "localhost", + port: 80, + host: "localhost", }); diff --git a/packages/bun-types/test/process.test.ts b/packages/bun-types/test/process.test.ts index 04c8d17b249856..6ea7cf043d902c 100644 --- a/packages/bun-types/test/process.test.ts +++ b/packages/bun-types/test/process.test.ts @@ -2,15 +2,15 @@ process.memoryUsage(); process.cpuUsage().system; process.cpuUsage().user; process.on("SIGINT", () => { - console.log("Interrupt from keyboard"); + console.log("Interrupt from keyboard"); }); -process.on("beforeExit", (code) => { - console.log("Event loop is empty and no work is left to schedule.", code); +process.on("beforeExit", code => { + console.log("Event loop is empty and no work is left to schedule.", code); }); -process.on("exit", (code) => { - console.log("Exiting with code:", code); +process.on("exit", code => { + console.log("Exiting with code:", code); }); process.kill(123, "SIGTERM"); @@ -21,7 +21,7 @@ process.getgroups!(); process.getuid!(); process.once("SIGINT", () => { - console.log("Interrupt from keyboard"); + console.log("Interrupt from keyboard"); }); // commented methods are not yet implemented diff --git a/packages/bun-types/test/readline.test.ts b/packages/bun-types/test/readline.test.ts index 7b4be00a01a201..967d9b06d5db79 100644 --- a/packages/bun-types/test/readline.test.ts +++ b/packages/bun-types/test/readline.test.ts @@ -1,10 +1,10 @@ import * as readline from "node:readline/promises"; const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: true, + input: process.stdin, + output: process.stdout, + terminal: true, }); -await rl.question("What is your age?\n").then((answer) => { - console.log("Your age is: " + answer); +await rl.question("What is your age?\n").then(answer => { + console.log("Your age is: " + answer); }); diff --git a/packages/bun-types/test/serve.test.ts b/packages/bun-types/test/serve.test.ts index 60903bf71fc7fc..1ddd23a0c6dff3 100644 --- a/packages/bun-types/test/serve.test.ts +++ b/packages/bun-types/test/serve.test.ts @@ -1,160 +1,160 @@ Bun.serve({ - fetch(req) { - console.log(req.url); // => http://localhost:3000/ - return new Response("Hello World"); - }, + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, }); Bun.serve({ - fetch(req) { - console.log(req.url); // => http://localhost:3000/ - return new Response("Hello World"); - }, - keyFile: "ca.pem", - certFile: "cert.pem", + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, + keyFile: "ca.pem", + certFile: "cert.pem", }); Bun.serve({ - websocket: { - message(ws, message) { - ws.send(message); - }, - }, - - fetch(req, server) { - // Upgrade to a ServerWebSocket if we can - // This automatically checks for the `Sec-WebSocket-Key` header - // meaning you don't have to check headers, you can just call `upgrade()` - if (server.upgrade(req)) { - // When upgrading, we return undefined since we don't want to send a Response - return; - } - - return new Response("Regular HTTP response"); - }, + websocket: { + message(ws, message) { + ws.send(message); + }, + }, + + fetch(req, server) { + // Upgrade to a ServerWebSocket if we can + // This automatically checks for the `Sec-WebSocket-Key` header + // meaning you don't have to check headers, you can just call `upgrade()` + if (server.upgrade(req)) { + // When upgrading, we return undefined since we don't want to send a Response + return; + } + + return new Response("Regular HTTP response"); + }, }); Bun.serve<{ - name: string; + name: string; }>({ - fetch(req, server) { - const url = new URL(req.url); - if (url.pathname === "/chat") { - if ( - server.upgrade(req, { - data: { - name: new URL(req.url).searchParams.get("name") || "Friend", - }, - headers: { - "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), - }, - }) - ) { - return; - } - } - - return new Response("Expected a websocket connection", { status: 400 }); - }, - - websocket: { - open(ws) { - console.log("WebSocket opened"); - ws.subscribe("the-group-chat"); - }, - - message(ws, message) { - ws.publish("the-group-chat", `${ws.data.name}: ${message.toString()}`); - }, - - close(ws, code, reason) { - ws.publish("the-group-chat", `${ws.data.name} left the chat`); - }, - - drain(ws) { - console.log("Please send me data. I am ready to receive it."); - }, - - perMessageDeflate: true, - }, + fetch(req, server) { + const url = new URL(req.url); + if (url.pathname === "/chat") { + if ( + server.upgrade(req, { + data: { + name: new URL(req.url).searchParams.get("name") || "Friend", + }, + headers: { + "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), + }, + }) + ) { + return; + } + } + + return new Response("Expected a websocket connection", { status: 400 }); + }, + + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("the-group-chat"); + }, + + message(ws, message) { + ws.publish("the-group-chat", `${ws.data.name}: ${message.toString()}`); + }, + + close(ws, code, reason) { + ws.publish("the-group-chat", `${ws.data.name} left the chat`); + }, + + drain(ws) { + console.log("Please send me data. I am ready to receive it."); + }, + + perMessageDeflate: true, + }, }); Bun.serve({ - fetch(req) { - throw new Error("woops!"); - }, - error(error) { - return new Response(`

${error.message}\n${error.stack}
`, { - headers: { - "Content-Type": "text/html", - }, - }); - }, + fetch(req) { + throw new Error("woops!"); + }, + error(error) { + return new Response(`
${error.message}\n${error.stack}
`, { + headers: { + "Content-Type": "text/html", + }, + }); + }, }); export {}; Bun.serve({ - port: 1234, - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, + port: 1234, + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch() { - return new Response(); - }, + unix: "/tmp/bun.sock", + fetch() { + return new Response(); + }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, + unix: "/tmp/bun.sock", + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch() { - return new Response(); - }, - tls: {}, + unix: "/tmp/bun.sock", + fetch() { + return new Response(); + }, + tls: {}, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, - tls: {}, + unix: "/tmp/bun.sock", + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, + tls: {}, }); Bun.serve({ - fetch(req, server) { - server.upgrade(req); - }, - websocket: { - open(ws) { - console.log("WebSocket opened"); - ws.subscribe("test-channel"); - }, - - message(ws, message) { - ws.publish("test-channel", `${message.toString()}`); - }, - perMessageDeflate: true, - }, + fetch(req, server) { + server.upgrade(req); + }, + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("test-channel"); + }, + + message(ws, message) { + ws.publish("test-channel", `${message.toString()}`); + }, + perMessageDeflate: true, + }, }); // Bun.serve({ // unix: "/tmp/bun.sock", diff --git a/packages/bun-types/test/spawn.test.ts b/packages/bun-types/test/spawn.test.ts index 9dbfef61bf9264..a6c8fddff15b5d 100644 --- a/packages/bun-types/test/spawn.test.ts +++ b/packages/bun-types/test/spawn.test.ts @@ -1,176 +1,145 @@ -import { - FileSink, - NullSubprocess, - PipedSubprocess, - ReadableSubprocess, - SyncSubprocess, - WritableSubprocess, -} from "bun"; +import { FileSink, NullSubprocess, PipedSubprocess, ReadableSubprocess, SyncSubprocess, WritableSubprocess } from "bun"; import * as tsd from "./utilities.test"; Bun.spawn(["echo", "hello"]); function depromise(_promise: Promise): T { - return "asdf" as any as T; + return "asdf" as any as T; } { - const proc = Bun.spawn(["echo", "hello"], { - cwd: "./path/to/subdir", // specify a working direcory - env: { ...process.env, FOO: "bar" }, // specify environment variables - onExit(proc, exitCode, signalCode, error) { - // exit handler - }, - }); - - proc.pid; // process ID of subprocess - - tsd.expectType>(proc.stdout); - tsd.expectType(proc.stderr); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + cwd: "./path/to/subdir", // specify a working direcory + env: { ...process.env, FOO: "bar" }, // specify environment variables + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + proc.pid; // process ID of subprocess + + tsd.expectType>(proc.stdout); + tsd.expectType(proc.stderr); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["cat"], { - stdin: depromise( - fetch( - "https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js", - ), - ), - }); - - const text = depromise(new Response(proc.stdout).text()); - console.log(text); // "const input = "hello world".repeat(400); ..." + const proc = Bun.spawn(["cat"], { + stdin: depromise(fetch("https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js")), + }); + + const text = depromise(new Response(proc.stdout).text()); + console.log(text); // "const input = "hello world".repeat(400); ..." } { - const proc = Bun.spawn(["cat"], { - stdin: "pipe", // return a FileSink for writing - }); - - // enqueue string data - proc.stdin.write("hello"); - - // enqueue binary data - const enc = new TextEncoder(); - proc.stdin.write(enc.encode(" world!")); - enc.encodeInto(" world!", {} as any as Uint8Array); - // Bun-specific overloads - // these fail when lib.dom.d.ts is present - enc.encodeInto(" world!", new Uint32Array(124)); - enc.encodeInto(" world!", {} as any as DataView); - - // send buffered data - await proc.stdin.flush(); - - // close the input stream - await proc.stdin.end(); + const proc = Bun.spawn(["cat"], { + stdin: "pipe", // return a FileSink for writing + }); + + // enqueue string data + proc.stdin.write("hello"); + + // enqueue binary data + const enc = new TextEncoder(); + proc.stdin.write(enc.encode(" world!")); + enc.encodeInto(" world!", {} as any as Uint8Array); + // Bun-specific overloads + // these fail when lib.dom.d.ts is present + enc.encodeInto(" world!", new Uint32Array(124)); + enc.encodeInto(" world!", {} as any as DataView); + + // send buffered data + await proc.stdin.flush(); + + // close the input stream + await proc.stdin.end(); } { - const proc = Bun.spawn(["echo", "hello"]); - const text = depromise(new Response(proc.stdout).text()); - console.log(text); // => "hello" + const proc = Bun.spawn(["echo", "hello"]); + const text = depromise(new Response(proc.stdout).text()); + console.log(text); // => "hello" } { - const proc = Bun.spawn(["echo", "hello"], { - onExit(proc, exitCode, signalCode, error) { - // exit handler - }, - }); - - await proc.exited; // resolves when process exit - proc.killed; // boolean โ€” was the process killed? - proc.exitCode; // null | number - proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... - proc.kill(); - proc.killed; // true - - proc.kill(); // specify an exit code - proc.unref(); + const proc = Bun.spawn(["echo", "hello"], { + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + await proc.exited; // resolves when process exit + proc.killed; // boolean โ€” was the process killed? + proc.exitCode; // null | number + proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... + proc.kill(); + proc.killed; // true + + proc.kill(); // specify an exit code + proc.unref(); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["pipe", "pipe", "pipe"], - }); - tsd.expectType(proc.stdin); - tsd.expectType>(proc.stdout); - tsd.expectType>(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["pipe", "pipe", "pipe"], + }); + tsd.expectType(proc.stdin); + tsd.expectType>(proc.stdout); + tsd.expectType>(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["inherit", "inherit", "inherit"], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["inherit", "inherit", "inherit"], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["ignore", "ignore", "ignore"], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["ignore", "ignore", "ignore"], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [null, null, null], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [null, null, null], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Request("1"), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Request("1"), null, null], + }); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Response("1"), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Response("1"), null, null], + }); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Uint8Array([]), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Uint8Array([]), null, null], + }); + tsd.expectType(proc.stdin); } -tsd.expectAssignable( - Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), -); -tsd.expectNotAssignable( - Bun.spawn([], { stdio: ["inherit", "inherit", "inherit"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), -); -tsd.expectNotAssignable( - Bun.spawn([], { stdio: ["pipe", "ignore", "pipe"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["pipe", "ignore", "inherit"] }), -); -tsd.expectNotAssignable( - Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["ignore", "inherit", "ignore"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: [null, null, null] }), -); +tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); +tsd.expectNotAssignable(Bun.spawn([], { stdio: ["inherit", "inherit", "inherit"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); +tsd.expectNotAssignable(Bun.spawn([], { stdio: ["pipe", "ignore", "pipe"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "ignore", "inherit"] })); +tsd.expectNotAssignable(Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["ignore", "inherit", "ignore"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: [null, null, null] })); tsd.expectNotAssignable(Bun.spawn([], {})); tsd.expectNotAssignable(Bun.spawn([], {})); diff --git a/packages/bun-types/test/sqlite.test.ts b/packages/bun-types/test/sqlite.test.ts index 7cb261f571f397..32cd98057e3d7a 100644 --- a/packages/bun-types/test/sqlite.test.ts +++ b/packages/bun-types/test/sqlite.test.ts @@ -3,14 +3,14 @@ import { expectType } from "./utilities.test"; const db = new Database(":memory:"); const query1 = db.query< - { name: string; dob: number }, // return type first - { $id: string } + { name: string; dob: number }, // return type first + { $id: string } >("select name, dob from users where id = $id"); query1.all({ $id: "asdf" }); // => {name: string; dob:string}[] const query2 = db.query< - { name: string; dob: number }, - [string, number] // pass tuple for positional params + { name: string; dob: number }, + [string, number] // pass tuple for positional params >("select ?1 as name, ?2 as dob"); const allResults = query2.all("Shaq", 50); // => {name: string; dob:string}[] const getResults = query2.get("Shaq", 50); // => {name: string; dob:string}[] @@ -25,9 +25,9 @@ expectType<{ name: string; dob: number } | null>(getResults); expectType(runResults); const query3 = db.prepare< - { name: string; dob: number }, // return type first - // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [{ $id: string }] + { name: string; dob: number }, // return type first + // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [{ $id: string }] >("select name, dob from users where id = $id"); const allResults3 = query3.all({ $id: "asdf" }); expectType>(allResults3); diff --git a/packages/bun-types/test/streams.test.ts b/packages/bun-types/test/streams.test.ts index 3a303a618b8bc9..50c6fdeb65dd6f 100644 --- a/packages/bun-types/test/streams.test.ts +++ b/packages/bun-types/test/streams.test.ts @@ -1,23 +1,23 @@ new ReadableStream({ - start(controller) { - controller.enqueue("hello"); - controller.enqueue("world"); - controller.close(); - }, + start(controller) { + controller.enqueue("hello"); + controller.enqueue("world"); + controller.close(); + }, }); // this will have type errors when lib.dom.d.ts is present // afaik this isn't fixable new ReadableStream({ - type: "direct", - pull(controller) { - // eslint-disable-next-line - controller.write("hello"); - // eslint-disable-next-line - controller.write("world"); - controller.close(); - }, - cancel() { - // called if stream.cancel() is called - }, + type: "direct", + pull(controller) { + // eslint-disable-next-line + controller.write("hello"); + // eslint-disable-next-line + controller.write("world"); + controller.close(); + }, + cancel() { + // called if stream.cancel() is called + }, }); diff --git a/packages/bun-types/test/tcp.test.ts b/packages/bun-types/test/tcp.test.ts index f9f1038f2fbb43..fe1b66a64880c5 100644 --- a/packages/bun-types/test/tcp.test.ts +++ b/packages/bun-types/test/tcp.test.ts @@ -1,134 +1,134 @@ import * as Bun from "bun"; await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLocaleLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLocaleLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, - tls: { - certFile: "asdf", - keyFile: "adsf", - }, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, + tls: { + certFile: "asdf", + keyFile: "adsf", + }, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, - tls: { - cert: "asdf", - key: Bun.file("adsf"), - ca: Buffer.from("asdf"), - }, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, + tls: { + cert: "asdf", + key: Bun.file("adsf"), + ca: Buffer.from("asdf"), + }, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); const listener = Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); listener.data.arg = "asdf"; @@ -140,8 +140,8 @@ listener.data.arg = 234; // }); listener.reload({ - socket: { - open() {}, - // ...listener. - }, + socket: { + open() {}, + // ...listener. + }, }); diff --git a/packages/bun-types/test/test.test.ts b/packages/bun-types/test/test.test.ts index 6f7d1a4951dab3..31a580aba2cfd5 100644 --- a/packages/bun-types/test/test.test.ts +++ b/packages/bun-types/test/test.test.ts @@ -1,13 +1,4 @@ -import { - afterAll, - afterEach, - beforeAll, - beforeEach, - describe, - expect, - spyOn, - test, -} from "bun:test"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { expectType } from "./utilities.test"; const spy = spyOn(console, "log"); @@ -16,119 +7,119 @@ expectType(spy.mock.calls); const hooks = [beforeAll, beforeEach, afterAll, afterEach]; for (const hook of hooks) { - hook(() => { - // ... - }); - // eslint-disable-next-line - hook(async () => { - // ... - return; - }); - hook((done: (err?: unknown) => void) => { - done(); - done(new Error()); - done("Error"); - }); + hook(() => { + // ... + }); + // eslint-disable-next-line + hook(async () => { + // ... + return; + }); + hook((done: (err?: unknown) => void) => { + done(); + done(new Error()); + done("Error"); + }); } describe("bun:test", () => { - describe("expect()", () => { - test("toThrow()", () => { - function fail() { - throw new Error("Bad"); - } - expect(fail).toThrow(); - expect(fail).toThrow("Bad"); - expect(fail).toThrow(/bad/i); - expect(fail).toThrow(Error); - expect(fail).toThrow(new Error("Bad")); - }); - }); - test("expect()", () => { - expect(1).toBe(1); - expect(1).not.toBe(2); - // @ts-expect-error - expect({ a: 1 }).toEqual({ a: 1, b: undefined }); - expect({ a: 1 }).toStrictEqual({ a: 1 }); - expect(new Set()).toHaveProperty("size"); - expect(new Uint8Array()).toHaveProperty("byteLength", 0); - expect([]).toHaveLength(0); - expect(["bun"]).toContain("bun"); - expect(true).toBeTruthy(); - expect(false).toBeFalsy(); - expect(Math.PI).toBeGreaterThan(3.14); - expect(Math.PI).toBeGreaterThan(3n); - expect(Math.PI).toBeGreaterThanOrEqual(3.14); - expect(Math.PI).toBeGreaterThanOrEqual(3n); - expect(NaN).toBeNaN(); - expect(null).toBeNull(); - expect(undefined).toBeUndefined(); - expect(undefined).not.toBeDefined(); - }); + describe("expect()", () => { + test("toThrow()", () => { + function fail() { + throw new Error("Bad"); + } + expect(fail).toThrow(); + expect(fail).toThrow("Bad"); + expect(fail).toThrow(/bad/i); + expect(fail).toThrow(Error); + expect(fail).toThrow(new Error("Bad")); + }); + }); + test("expect()", () => { + expect(1).toBe(1); + expect(1).not.toBe(2); + // @ts-expect-error + expect({ a: 1 }).toEqual({ a: 1, b: undefined }); + expect({ a: 1 }).toStrictEqual({ a: 1 }); + expect(new Set()).toHaveProperty("size"); + expect(new Uint8Array()).toHaveProperty("byteLength", 0); + expect([]).toHaveLength(0); + expect(["bun"]).toContain("bun"); + expect(true).toBeTruthy(); + expect(false).toBeFalsy(); + expect(Math.PI).toBeGreaterThan(3.14); + expect(Math.PI).toBeGreaterThan(3n); + expect(Math.PI).toBeGreaterThanOrEqual(3.14); + expect(Math.PI).toBeGreaterThanOrEqual(3n); + expect(NaN).toBeNaN(); + expect(null).toBeNull(); + expect(undefined).toBeUndefined(); + expect(undefined).not.toBeDefined(); + }); }); // inference should work when data is passed directly in test.each([ - ["a", true, 5], - ["b", false, 1234], + ["a", true, 5], + ["b", false, 1234], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([ - ["a", true, 5], - ["b", false, 5], + ["a", true, 5], + ["b", false, 5], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([{ asdf: "asdf" }, { asdf: "asdf" }])("test.each", (a, b, c) => { - expectType<{ asdf: string }>(a); - expectType<{ asdf: string }>(c); + expectType<{ asdf: string }>(a); + expectType<{ asdf: string }>(c); }); // no inference on data const data = [ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ]; test.each(data)("test.each", (...args) => { - expectType(args[0]); + expectType(args[0]); }); describe.each(data)("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); // as const const dataAsConst = [ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ] as const; test.each(dataAsConst)("test.each", (...args) => { - expectType(args[0]); - expectType(args[1]); - expectType(args[2]); + expectType(args[0]); + expectType(args[1]); + expectType(args[2]); }); describe.each(dataAsConst)("test.each", (...args) => { - expectType(args[0]); - expectType(args[1]); - expectType(args[2]); + expectType(args[0]); + expectType(args[1]); + expectType(args[2]); }); describe.each(dataAsConst)("test.each", (a, b, c) => { - expectType<"a" | "b">(a); - expectType(b); - expectType<5 | "asdf">(c); + expectType<"a" | "b">(a); + expectType(b); + expectType<5 | "asdf">(c); }); diff --git a/packages/bun-types/test/tls.test.ts b/packages/bun-types/test/tls.test.ts index df6f1979c53b95..fb2aa7d9b885a1 100644 --- a/packages/bun-types/test/tls.test.ts +++ b/packages/bun-types/test/tls.test.ts @@ -3,30 +3,30 @@ import tls from "node:tls"; tls.getCiphers()[0]; tls.connect({ - host: "localhost", - port: 80, - ca: "asdf", - cert: "path to cert", + host: "localhost", + port: 80, + ca: "asdf", + cert: "path to cert", }); tls.connect({ - host: "localhost", - port: 80, - ca: Bun.file("asdf"), - cert: Bun.file("path to cert"), - ciphers: "adsf", + host: "localhost", + port: 80, + ca: Bun.file("asdf"), + cert: Bun.file("path to cert"), + ciphers: "adsf", }); tls.connect({ - host: "localhost", - port: 80, - ca: Buffer.from("asdf"), - cert: Buffer.from("asdf"), + host: "localhost", + port: 80, + ca: Buffer.from("asdf"), + cert: Buffer.from("asdf"), }); tls.connect({ - host: "localhost", - port: 80, - ca: new Uint8Array([1, 2, 3]), - cert: new Uint8Array([1, 2, 3]), + host: "localhost", + port: 80, + ca: new Uint8Array([1, 2, 3]), + cert: new Uint8Array([1, 2, 3]), }); diff --git a/packages/bun-types/test/tty.test.ts b/packages/bun-types/test/tty.test.ts index f6aff4b61e7e52..7e9f45115c731f 100644 --- a/packages/bun-types/test/tty.test.ts +++ b/packages/bun-types/test/tty.test.ts @@ -1,10 +1,10 @@ import * as tty from "tty"; const rs = new tty.ReadStream(234, { - allowHalfOpen: true, - readable: true, - signal: new AbortSignal(), - writable: true, + allowHalfOpen: true, + readable: true, + signal: new AbortSignal(), + writable: true, }); const ws = new tty.WriteStream(234); diff --git a/packages/bun-types/test/utilities.test.ts b/packages/bun-types/test/utilities.test.ts index ef198a27614e3d..9fb6f411160b93 100644 --- a/packages/bun-types/test/utilities.test.ts +++ b/packages/bun-types/test/utilities.test.ts @@ -5,6 +5,4 @@ export declare const expectAssignable: (expression: T) => void; // eslint-disable-next-line @definitelytyped/no-unnecessary-generics export declare const expectNotAssignable: (expression: any) => void; // eslint-disable-next-line @definitelytyped/no-unnecessary-generics -export declare const expectTypeEquals: ( - expression: T extends S ? (S extends T ? true : false) : false, -) => void; +export declare const expectTypeEquals: (expression: T extends S ? (S extends T ? true : false) : false) => void; diff --git a/packages/bun-types/test/wasm.test.ts b/packages/bun-types/test/wasm.test.ts index f745fbe84e94ec..3b8785ec732709 100644 --- a/packages/bun-types/test/wasm.test.ts +++ b/packages/bun-types/test/wasm.test.ts @@ -1,42 +1,42 @@ async () => { - // Fetch and compile a WebAssembly module - const response = await fetch("module.wasm"); - const buffer = await response.arrayBuffer(); - const module = await WebAssembly.compile(buffer); - - // Create a WebAssembly Memory object - const memory = new WebAssembly.Memory({ initial: 1 }); - - // Create a WebAssembly Table object - const table = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); - - // Instantiate the WebAssembly module - const instance = await WebAssembly.instantiate(module, { - js: { - log: (arg: any) => console.log("Logging from WASM:", arg), - tableFunc: () => console.log("Table function called"), - }, - env: { - memory: memory, - table: table, - }, - }); - - // Exported WebAssembly functions - const { exportedFunction } = instance.exports; - exportedFunction; - - // Call an exported WebAssembly function - // exportedFunction(); - - // Interact with WebAssembly memory - const uint8Array = new Uint8Array(memory.buffer); - uint8Array[0] = 1; // Modify memory - - // Use the WebAssembly Table - table.set(0, instance.exports.exportedTableFunction); - // eslint-disable-next-line - table.get(0)(); // Call a function stored in the table - - // Additional operations with instance, memory, and table can be performed here + // Fetch and compile a WebAssembly module + const response = await fetch("module.wasm"); + const buffer = await response.arrayBuffer(); + const module = await WebAssembly.compile(buffer); + + // Create a WebAssembly Memory object + const memory = new WebAssembly.Memory({ initial: 1 }); + + // Create a WebAssembly Table object + const table = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); + + // Instantiate the WebAssembly module + const instance = await WebAssembly.instantiate(module, { + js: { + log: (arg: any) => console.log("Logging from WASM:", arg), + tableFunc: () => console.log("Table function called"), + }, + env: { + memory: memory, + table: table, + }, + }); + + // Exported WebAssembly functions + const { exportedFunction } = instance.exports; + exportedFunction; + + // Call an exported WebAssembly function + // exportedFunction(); + + // Interact with WebAssembly memory + const uint8Array = new Uint8Array(memory.buffer); + uint8Array[0] = 1; // Modify memory + + // Use the WebAssembly Table + table.set(0, instance.exports.exportedTableFunction); + // eslint-disable-next-line + table.get(0)(); // Call a function stored in the table + + // Additional operations with instance, memory, and table can be performed here }; diff --git a/packages/bun-types/test/worker.test.ts b/packages/bun-types/test/worker.test.ts index a6a32787b4a99e..335f2652a9fe23 100644 --- a/packages/bun-types/test/worker.test.ts +++ b/packages/bun-types/test/worker.test.ts @@ -3,17 +3,17 @@ import * as tsd from "./utilities.test"; const webWorker = new Worker("./worker.js"); -webWorker.addEventListener("message", (event) => { - tsd.expectType(event); +webWorker.addEventListener("message", event => { + tsd.expectType(event); }); -webWorker.addEventListener("error", (event) => { - tsd.expectType(event); +webWorker.addEventListener("error", event => { + tsd.expectType(event); }); -webWorker.addEventListener("messageerror", (event) => { - tsd.expectType(event); +webWorker.addEventListener("messageerror", event => { + tsd.expectType(event); }); -webWorker.onmessage = (ev) => "asdf"; -webWorker.onmessageerror = (ev) => "asdf"; +webWorker.onmessage = ev => "asdf"; +webWorker.onmessageerror = ev => "asdf"; webWorker.postMessage("asdf", []); webWorker.terminate(); webWorker.addEventListener("close", () => {}); @@ -24,8 +24,8 @@ webWorker.unref(); webWorker.threadId; const nodeWorker = new NodeWorker("./worker.ts"); -nodeWorker.on("message", (event) => { - console.log("Message from worker:", event); +nodeWorker.on("message", event => { + console.log("Message from worker:", event); }); nodeWorker.postMessage("Hello from main thread!"); @@ -33,8 +33,8 @@ const workerURL = new URL("worker.ts", "/path/to/").href; const _worker2 = new Worker(workerURL); nodeWorker.postMessage("hello"); -webWorker.onmessage = (event) => { - console.log(event.data); +webWorker.onmessage = event => { + console.log(event.data); }; // On the worker thread, `postMessage` is automatically "routed" to the parent thread. @@ -49,13 +49,13 @@ await nodeWorker.terminate(); // Bun.pathToFileURL const _worker3 = new Worker(new URL("worker.ts", "/path/to/").href, { - ref: true, - smol: true, - credentials: "same-origin", - name: "a name", - env: { - envValue: "hello", - }, + ref: true, + smol: true, + credentials: "same-origin", + name: "a name", + env: { + envValue: "hello", + }, }); export { _worker2, _worker3, nodeWorker as worker }; diff --git a/packages/bun-types/test/ws.test.ts b/packages/bun-types/test/ws.test.ts index 83bfd0e4723b43..fdc4072af2403f 100644 --- a/packages/bun-types/test/ws.test.ts +++ b/packages/bun-types/test/ws.test.ts @@ -5,7 +5,7 @@ const ws = new WebSocket("ws://www.host.com/path"); ws.send("asdf"); const wss = new WebSocketServer({ - port: 8080, - perMessageDeflate: false, + port: 8080, + perMessageDeflate: false, }); wss; diff --git a/packages/bun-types/wasm.d.ts b/packages/bun-types/wasm.d.ts index ccbc0d1ef97d21..b4975f140a94e2 100644 --- a/packages/bun-types/wasm.d.ts +++ b/packages/bun-types/wasm.d.ts @@ -1,291 +1,270 @@ export {}; -type _Global = - typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; - } - ? T - : Bun.WebAssembly.Global; +type _Global = typeof globalThis extends { + onerror: any; + WebAssembly: { Global: infer T }; +} + ? T + : Bun.WebAssembly.Global; type _CompileError = typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; + onerror: any; + WebAssembly: { CompileError: infer T }; } - ? T - : Bun.WebAssembly.CompileError; + ? T + : Bun.WebAssembly.CompileError; type _LinkError = typeof globalThis extends { - onerror: any; - WebAssembly: { LinkError: infer T }; + onerror: any; + WebAssembly: { LinkError: infer T }; } - ? T - : Bun.WebAssembly.LinkError; + ? T + : Bun.WebAssembly.LinkError; type _RuntimeError = typeof globalThis extends { - onerror: any; - WebAssembly: { RuntimeError: infer T }; + onerror: any; + WebAssembly: { RuntimeError: infer T }; } - ? T - : Bun.WebAssembly.RuntimeError; + ? T + : Bun.WebAssembly.RuntimeError; type _Memory = typeof globalThis extends { - onerror: any; - WebAssembly: { Memory: infer T }; + onerror: any; + WebAssembly: { Memory: infer T }; } - ? T - : Bun.WebAssembly.Memory; + ? T + : Bun.WebAssembly.Memory; type _Instance = typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; + onerror: any; + WebAssembly: { Instance: infer T }; } - ? T - : Bun.WebAssembly.Instance; + ? T + : Bun.WebAssembly.Instance; type _Module = typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; + onerror: any; + WebAssembly: { Module: infer T }; } - ? T - : Bun.WebAssembly.Module; + ? T + : Bun.WebAssembly.Module; type _Table = typeof globalThis extends { - onerror: any; - WebAssembly: { Table: infer T }; + onerror: any; + WebAssembly: { Table: infer T }; } - ? T - : Bun.WebAssembly.Table; + ? T + : Bun.WebAssembly.Table; declare global { - namespace Bun { - namespace WebAssembly { - type ImportExportKind = "function" | "global" | "memory" | "table"; - type TableKind = "anyfunc" | "externref"; - // eslint-disable-next-line @typescript-eslint/ban-types - type ExportValue = - | Function - | Global - | WebAssembly.Memory - | WebAssembly.Table; - type Exports = Record; - type ImportValue = ExportValue | number; - type Imports = Record; - type ModuleImports = Record; - - interface ValueTypeMap { - // eslint-disable-next-line @typescript-eslint/ban-types - anyfunc: Function; - externref: any; - f32: number; - f64: number; - i32: number; - i64: bigint; - v128: never; - } - - type ValueType = keyof ValueTypeMap; - - interface GlobalDescriptor { - mutable?: boolean; - value: T; - } - - interface Global { - // { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ - value: ValueTypeMap[T]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ - valueOf(): ValueTypeMap[T]; - } - - interface CompileError extends Error {} - - interface LinkError extends Error {} - - interface RuntimeError extends Error {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ - interface Instance { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ - readonly exports: Exports; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ - interface Memory { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ - readonly buffer: ArrayBuffer; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ - grow(delta: number): number; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ - interface Module {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ - interface Table { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ - readonly length: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ - get(index: number): any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ - grow(delta: number, value?: any): number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ - set(index: number, value?: any): void; - } - - interface MemoryDescriptor { - initial: number; - maximum?: number; - shared?: boolean; - } - - interface ModuleExportDescriptor { - kind: ImportExportKind; - name: string; - } - - interface ModuleImportDescriptor { - kind: ImportExportKind; - module: string; - name: string; - } - - interface TableDescriptor { - element: TableKind; - initial: number; - maximum?: number; - } - - interface WebAssemblyInstantiatedSource { - instance: Instance; - module: Module; - } - } - } - - namespace WebAssembly { - interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} - interface GlobalDescriptor< - T extends keyof ValueTypeMap = keyof ValueTypeMap, - > extends Bun.WebAssembly.GlobalDescriptor {} - interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} - interface ModuleExportDescriptor - extends Bun.WebAssembly.ModuleExportDescriptor {} - interface ModuleImportDescriptor - extends Bun.WebAssembly.ModuleImportDescriptor {} - interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} - interface WebAssemblyInstantiatedSource - extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} - - interface LinkError extends _LinkError {} - var LinkError: { - prototype: LinkError; - new (message?: string): LinkError; - (message?: string): LinkError; - }; - - interface CompileError extends _CompileError {} - var CompileError: typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; - } - ? T - : { - prototype: CompileError; - new (message?: string): CompileError; - (message?: string): CompileError; - }; - - interface RuntimeError extends _RuntimeError {} - var RuntimeError: { - prototype: RuntimeError; - new (message?: string): RuntimeError; - (message?: string): RuntimeError; - }; - - interface Global - extends _Global {} - var Global: typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; - } - ? T - : { - prototype: Global; - new ( - descriptor: GlobalDescriptor, - v?: ValueTypeMap[T], - ): Global; - }; - - interface Instance extends _Instance {} - var Instance: typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; - } - ? T - : { - prototype: Instance; - new ( - module: Module, - importObject?: Bun.WebAssembly.Imports, - ): Instance; - }; - - interface Memory extends _Memory {} - var Memory: { - prototype: Memory; - new (descriptor: MemoryDescriptor): Memory; - }; - - interface Module extends _Module {} - var Module: typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; - } - ? T - : { - prototype: Module; - new (bytes: Bun.BufferSource): Module; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ - customSections( - moduleObject: Module, - sectionName: string, - ): ArrayBuffer[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ - exports(moduleObject: Module): ModuleExportDescriptor[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ - imports(moduleObject: Module): ModuleImportDescriptor[]; - }; - - interface Table extends _Table {} - var Table: { - prototype: Table; - new (descriptor: TableDescriptor, value?: any): Table; - }; - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ - function compile(bytes: Bun.BufferSource): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ - function compileStreaming( - source: Response | PromiseLike, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ - function instantiate( - bytes: Bun.BufferSource, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - function instantiate( - moduleObject: Module, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ - function instantiateStreaming( - source: Response | PromiseLike, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ - function validate(bytes: Bun.BufferSource): boolean; - } + namespace Bun { + namespace WebAssembly { + type ImportExportKind = "function" | "global" | "memory" | "table"; + type TableKind = "anyfunc" | "externref"; + // eslint-disable-next-line @typescript-eslint/ban-types + type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table; + type Exports = Record; + type ImportValue = ExportValue | number; + type Imports = Record; + type ModuleImports = Record; + + interface ValueTypeMap { + // eslint-disable-next-line @typescript-eslint/ban-types + anyfunc: Function; + externref: any; + f32: number; + f64: number; + i32: number; + i64: bigint; + v128: never; + } + + type ValueType = keyof ValueTypeMap; + + interface GlobalDescriptor { + mutable?: boolean; + value: T; + } + + interface Global { + // { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ + value: ValueTypeMap[T]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ + valueOf(): ValueTypeMap[T]; + } + + interface CompileError extends Error {} + + interface LinkError extends Error {} + + interface RuntimeError extends Error {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ + interface Instance { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ + readonly exports: Exports; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ + interface Memory { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ + readonly buffer: ArrayBuffer; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ + grow(delta: number): number; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ + interface Module {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ + interface Table { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ + readonly length: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ + get(index: number): any; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ + grow(delta: number, value?: any): number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ + set(index: number, value?: any): void; + } + + interface MemoryDescriptor { + initial: number; + maximum?: number; + shared?: boolean; + } + + interface ModuleExportDescriptor { + kind: ImportExportKind; + name: string; + } + + interface ModuleImportDescriptor { + kind: ImportExportKind; + module: string; + name: string; + } + + interface TableDescriptor { + element: TableKind; + initial: number; + maximum?: number; + } + + interface WebAssemblyInstantiatedSource { + instance: Instance; + module: Module; + } + } + } + + namespace WebAssembly { + interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} + interface GlobalDescriptor + extends Bun.WebAssembly.GlobalDescriptor {} + interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} + interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} + interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} + interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} + interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} + + interface LinkError extends _LinkError {} + var LinkError: { + prototype: LinkError; + new (message?: string): LinkError; + (message?: string): LinkError; + }; + + interface CompileError extends _CompileError {} + var CompileError: typeof globalThis extends { + onerror: any; + WebAssembly: { CompileError: infer T }; + } + ? T + : { + prototype: CompileError; + new (message?: string): CompileError; + (message?: string): CompileError; + }; + + interface RuntimeError extends _RuntimeError {} + var RuntimeError: { + prototype: RuntimeError; + new (message?: string): RuntimeError; + (message?: string): RuntimeError; + }; + + interface Global extends _Global {} + var Global: typeof globalThis extends { + onerror: any; + WebAssembly: { Global: infer T }; + } + ? T + : { + prototype: Global; + new ( + descriptor: GlobalDescriptor, + v?: ValueTypeMap[T], + ): Global; + }; + + interface Instance extends _Instance {} + var Instance: typeof globalThis extends { + onerror: any; + WebAssembly: { Instance: infer T }; + } + ? T + : { + prototype: Instance; + new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; + }; + + interface Memory extends _Memory {} + var Memory: { + prototype: Memory; + new (descriptor: MemoryDescriptor): Memory; + }; + + interface Module extends _Module {} + var Module: typeof globalThis extends { + onerror: any; + WebAssembly: { Module: infer T }; + } + ? T + : { + prototype: Module; + new (bytes: Bun.BufferSource): Module; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ + customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ + exports(moduleObject: Module): ModuleExportDescriptor[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + + interface Table extends _Table {} + var Table: { + prototype: Table; + new (descriptor: TableDescriptor, value?: any): Table; + }; + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ + function compile(bytes: Bun.BufferSource): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ + function compileStreaming(source: Response | PromiseLike): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ + function instantiate( + bytes: Bun.BufferSource, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ + function instantiateStreaming( + source: Response | PromiseLike, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ + function validate(bytes: Bun.BufferSource): boolean; + } } From fab9ab9846d0978dc63e70ff005c65b976ab78e8 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Wed, 5 Mar 2025 21:55:32 +0000 Subject: [PATCH 03/72] attempt --- packages/bun-types/ambient.d.ts | 28 +- packages/bun-types/bun.d.ts | 14584 +++++++++-------- packages/bun-types/deprecated.d.ts | 105 +- packages/bun-types/devserver.d.ts | 40 +- packages/bun-types/fetch.d.ts | 256 +- packages/bun-types/ffi.d.ts | 2196 +-- packages/bun-types/globals.d.ts | 3625 ++-- packages/bun-types/html-rewriter.d.ts | 297 +- packages/bun-types/jsc.d.ts | 446 +- packages/bun-types/new/index.d.ts | 49 +- packages/bun-types/overrides.d.ts | 112 +- packages/bun-types/sqlite.d.ts | 2167 +-- packages/bun-types/test.d.ts | 4360 ++--- packages/bun-types/test/array-buffer.test.ts | 2 +- packages/bun-types/test/array.test.ts | 30 +- packages/bun-types/test/broadcast.test.ts | 6 +- packages/bun-types/test/bun.test.ts | 62 +- packages/bun-types/test/console.test.ts | 26 +- packages/bun-types/test/diag.test.ts | 2 +- packages/bun-types/test/dom.test.ts | 16 +- packages/bun-types/test/env.test.ts | 18 +- packages/bun-types/test/events.test.ts | 6 +- packages/bun-types/test/ffi.test.ts | 223 +- packages/bun-types/test/fs.test.ts | 8 +- packages/bun-types/test/fsrouter.test.ts | 4 +- packages/bun-types/test/globals.test.ts | 170 +- packages/bun-types/test/http.test.ts | 2 +- packages/bun-types/test/jsc.test.ts | 2 +- packages/bun-types/test/mocks.test.ts | 2 +- packages/bun-types/test/net.test.ts | 8 +- packages/bun-types/test/process.test.ts | 12 +- packages/bun-types/test/readline.test.ts | 10 +- packages/bun-types/test/serve.test.ts | 246 +- packages/bun-types/test/spawn.test.ts | 243 +- packages/bun-types/test/sqlite.test.ts | 14 +- packages/bun-types/test/streams.test.ts | 32 +- packages/bun-types/test/tcp.test.ts | 216 +- packages/bun-types/test/test.test.ts | 171 +- packages/bun-types/test/tls.test.ts | 34 +- packages/bun-types/test/tty.test.ts | 8 +- packages/bun-types/test/utilities.test.ts | 4 +- packages/bun-types/test/wasm.test.ts | 80 +- packages/bun-types/test/worker.test.ts | 38 +- packages/bun-types/test/ws.test.ts | 4 +- packages/bun-types/wasm.d.ts | 509 +- test/integration/bun-types/fixture/index.ts | 5 + 46 files changed, 15597 insertions(+), 14881 deletions(-) diff --git a/packages/bun-types/ambient.d.ts b/packages/bun-types/ambient.d.ts index 05d908557716b6..db712274c46e99 100644 --- a/packages/bun-types/ambient.d.ts +++ b/packages/bun-types/ambient.d.ts @@ -1,31 +1,31 @@ declare module "*.txt" { - var text: string; - export = text; + var text: string; + export = text; } declare module "*.toml" { - var contents: any; - export = contents; + var contents: any; + export = contents; } declare module "*.jsonc" { - var contents: any; - export = contents; + var contents: any; + export = contents; } declare module "*/bun.lock" { - var contents: import("bun").BunLockFile; - export = contents; + var contents: import("bun").BunLockFile; + export = contents; } declare module "*.html" { - // In Bun v1.2, we might change this to Bun.HTMLBundle - var contents: any; - export = contents; + // In Bun v1.2, we might change this to Bun.HTMLBundle + var contents: any; + export = contents; } declare module "*.svg" { - // Bun 1.2.3 added support for frontend dev server - var contents: `${string}.svg`; - export = contents; + // Bun 1.2.3 added support for frontend dev server + var contents: `${string}.svg`; + export = contents; } diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 3fed4ec2bc191b..fd9d4cc27d5e92 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -1,72 +1,72 @@ declare 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; - - bytes(): Uint8Array; + 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; + + bytes(): Uint8Array; } /** @@ -85,3024 +85,3119 @@ declare class _ShellError extends Error implements ShellOutput { * This module aliases `globalThis.Bun`. */ declare module "bun" { - import type { FFIFunctionCallableSymbol } from "bun:ffi"; - import type { Encoding as CryptoEncoding } from "crypto"; - import type { X509Certificate } from "node:crypto"; - import type { Stats } from "node:fs"; - import type { CipherNameAndProtocol, EphemeralKeyInfo, PeerCertificate } from "tls"; - - type DistributedOmit = T extends T ? Omit : never; - type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; - - 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 - | string - | { raw: string } - | Subprocess - | SpawnOptions.Readable - | SpawnOptions.Writable - | ReadableStream; - - class ShellPromise extends Promise { - 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 | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - } - - type ShellError = _ShellError; - - export interface Shell { - (strings: TemplateStringsArray, ...expressions: ShellExpression[]): ShellPromise; - - readonly ShellError: typeof _ShellError; - - /** - * 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): 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; + import type { FFIFunctionCallableSymbol } from "bun:ffi"; + import type { Encoding as CryptoEncoding } from "crypto"; + import type { X509Certificate } from "node:crypto"; + import type { Stats } from "node:fs"; + import type { + CipherNameAndProtocol, + EphemeralKeyInfo, + PeerCertificate, + } from "tls"; + + type DistributedOmit = T extends T ? Omit : never; + type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; + + 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 + | string + | { raw: string } + | Subprocess + | SpawnOptions.Readable + | SpawnOptions.Writable + | ReadableStream; + + class ShellPromise extends Promise { + 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 | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + } + + type ShellError = _ShellError; + + export interface Shell { + ( + strings: TemplateStringsArray, + ...expressions: ShellExpression[] + ): ShellPromise; + + readonly ShellError: typeof _ShellError; + + /** + * 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): 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; + + /** + * 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; + + /** + * 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 | S3File | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + 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, + maxLength?: number, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + maxLength: number, + asUint8Array: false, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + 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, + ): Promise | 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, + ): Promise | 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; + + /** + * 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, + multipartBoundaryExcludingDashes?: + | string + | NodeJS.TypedArray + | ArrayBufferView, + ): Promise; + + /** + * 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; + + /** + * 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; + + /** + * 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( + stream: ReadableStream, + ): Promise | T[]; + + /** + * Escape the following characters in a string: + * + * - `"` 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. + * + * @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 { + (promise: T | Promise): Promise | T; + status( + promise: T | Promise, + ): "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; + + /** + * + * **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; + }; + + ADDRCONFIG: number; + ALL: number; + 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; + } + + /** + * 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; + /** + * Close the file descriptor. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; + + 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; + + /** + * 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; + + /** + * Deletes the file. + */ + unlink(): Promise; + + /** + * Deletes the file. ( same as unlink ) + */ + delete(): Promise; + + /** + * Provides useful information about the file. + */ + stat(): Promise; + } + interface NetworkSink extends FileSink { + /** + * Write a chunk of data to the network. + * + * If the network is not writable yet, the data is buffered. + */ + write( + chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + ): number; + /** + * Flush the internal buffer, committing the data to the network. + */ + flush(): number | Promise; + /** + * Finish the upload. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; + + /** + * Get the stat of the file. + */ + stat(): Promise; + } + + var S3Client: S3Client; + var s3: S3Client; + + /** + * Configuration options for S3 operations + */ + interface S3Options extends BlobPropertyBag { + /** + * The Access Control List (ACL) policy for the file. + * Controls who can access the file and what permissions they have. + * + * @example + * // Setting public read access + * const file = s3("public-file.txt", { + * acl: "public-read", + * bucket: "my-bucket" + * }); + * + * @example + * // Using with presigned URLs + * const url = file.presign({ + * acl: "public-read", + * expiresIn: 3600 + * }); + */ + acl?: + | "private" + | "public-read" + | "public-read-write" + | "aws-exec-read" + | "authenticated-read" + | "bucket-owner-read" + | "bucket-owner-full-control" + | "log-delivery-write"; + + /** + * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. + * + * @example + * // Using explicit bucket + * const file = s3("my-file.txt", { bucket: "my-bucket" }); + * + * @example + * // Using environment variables + * // With S3_BUCKET=my-bucket in .env + * const file = s3("my-file.txt"); + */ + bucket?: string; + + /** + * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. + * + * @example + * const file = s3("my-file.txt", { + * bucket: "my-bucket", + * region: "us-west-2" + * }); + */ + region?: string; + + /** + * The access key ID for authentication. + * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. + */ + accessKeyId?: string; + + /** + * The secret access key for authentication. + * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. + */ + secretAccessKey?: string; + + /** + * Optional session token for temporary credentials. + * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. + * + * @example + * // Using temporary credentials + * const file = s3("my-file.txt", { + * accessKeyId: tempAccessKey, + * secretAccessKey: tempSecretKey, + * sessionToken: tempSessionToken + * }); + */ + sessionToken?: string; + + /** + * The S3-compatible service endpoint URL. + * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. + * + * @example + * // AWS S3 + * const file = s3("my-file.txt", { + * endpoint: "https://s3.us-east-1.amazonaws.com" + * }); + * + * @example + * // Cloudflare R2 + * const file = s3("my-file.txt", { + * endpoint: "https://.r2.cloudflarestorage.com" + * }); + * + * @example + * // DigitalOcean Spaces + * const file = s3("my-file.txt", { + * endpoint: "https://.digitaloceanspaces.com" + * }); + * + * @example + * // MinIO (local development) + * const file = s3("my-file.txt", { + * endpoint: "http://localhost:9000" + * }); + */ + endpoint?: string; + + /** + * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` + * + * @example + * // Using virtual hosted style + * const file = s3("my-file.txt", { + * virtualHostedStyle: true, + * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" + * }); + */ + virtualHostedStyle?: boolean; + + /** + * The size of each part in multipart uploads (in bytes). + * - Minimum: 5 MiB + * - Maximum: 5120 MiB + * - Default: 5 MiB + * + * @example + * // Configuring multipart uploads + * const file = s3("large-file.dat", { + * partSize: 10 * 1024 * 1024, // 10 MiB parts + * queueSize: 4 // Upload 4 parts in parallel + * }); + * + * const writer = file.writer(); + * // ... write large file in chunks + */ + partSize?: number; + + /** + * Number of parts to upload in parallel for multipart uploads. + * - Default: 5 + * - Maximum: 255 + * + * Increasing this value can improve upload speeds for large files + * but will use more memory. + */ + queueSize?: number; + + /** + * Number of retry attempts for failed uploads. + * - Default: 3 + * - Maximum: 255 + * + * @example + * // Setting retry attempts + * const file = s3("my-file.txt", { + * retry: 5 // Retry failed uploads up to 5 times + * }); + */ + retry?: number; + + /** + * The Content-Type of the file. + * Automatically set based on file extension when possible. + * + * @example + * // Setting explicit content type + * const file = s3("data.bin", { + * type: "application/octet-stream" + * }); + */ + type?: string; + + /** + * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. + * + * @example + * // Setting explicit Storage class + * const file = s3("my-file.json", { + * storageClass: "STANDARD_IA" + * }); + */ + storageClass?: + | "STANDARD" + | "DEEP_ARCHIVE" + | "EXPRESS_ONEZONE" + | "GLACIER" + | "GLACIER_IR" + | "INTELLIGENT_TIERING" + | "ONEZONE_IA" + | "OUTPOSTS" + | "REDUCED_REDUNDANCY" + | "SNOW" + | "STANDARD_IA"; + + /** + * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. + */ + highWaterMark?: number; + } + + /** + * Options for generating presigned URLs + */ + interface S3FilePresignOptions extends S3Options { + /** + * Number of seconds until the presigned URL expires. + * - Default: 86400 (1 day) + * + * @example + * // Short-lived URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Long-lived public URL + * const url = file.presign({ + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + expiresIn?: number; + + /** + * The HTTP method allowed for the presigned URL. + * + * @example + * // GET URL for downloads + * const downloadUrl = file.presign({ + * method: "GET", + * expiresIn: 3600 + * }); + * + * @example + * // PUT URL for uploads + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "application/json" + * }); + */ + method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; + } + + interface S3Stats { + size: number; + lastModified: Date; + etag: string; + type: string; + } + + /** + * Represents a file in an S3-compatible storage service. + * Extends the Blob interface for compatibility with web APIs. + */ + interface S3File extends Blob { + /** + * The size of the file in bytes. + * This is a Promise because it requires a network request to determine the size. + * + * @example + * // Getting file size + * const size = await file.size; + * console.log(`File size: ${size} bytes`); + * + * @example + * // Check if file is larger than 1MB + * if (await file.size > 1024 * 1024) { + * console.log("Large file detected"); + * } + */ + /** + * TODO: figure out how to get the typescript types to not error for this property. + */ + // size: Promise; + + /** + * Creates a new S3File representing a slice of the original file. + * Uses HTTP Range headers for efficient partial downloads. + * + * @param begin - Starting byte offset + * @param end - Ending byte offset (exclusive) + * @param contentType - Optional MIME type for the slice + * @returns A new S3File representing the specified range + * + * @example + * // Reading file header + * const header = file.slice(0, 1024); + * const headerText = await header.text(); + * + * @example + * // Reading with content type + * const jsonSlice = file.slice(1024, 2048, "application/json"); + * const data = await jsonSlice.json(); + * + * @example + * // Reading from offset to end + * const remainder = file.slice(1024); + * const content = await remainder.text(); + */ + slice(begin?: number, end?: number, contentType?: string): S3File; + slice(begin?: number, contentType?: string): S3File; + slice(contentType?: string): S3File; + + /** + * Creates a writable stream for uploading data. + * Suitable for large files as it uses multipart upload. + * + * @param options - Configuration for the upload + * @returns A NetworkSink for writing data + * + * @example + * // Basic streaming write + * const writer = file.writer({ + * type: "application/json" + * }); + * writer.write('{"hello": '); + * writer.write('"world"}'); + * await writer.end(); + * + * @example + * // Optimized large file upload + * const writer = file.writer({ + * partSize: 10 * 1024 * 1024, // 10MB parts + * queueSize: 4, // Upload 4 parts in parallel + * retry: 3 // Retry failed parts + * }); + * + * // Write large chunks of data efficiently + * for (const chunk of largeDataChunks) { + * writer.write(chunk); + * } + * await writer.end(); + * + * @example + * // Error handling + * const writer = file.writer(); + * try { + * writer.write(data); + * await writer.end(); + * } catch (err) { + * console.error('Upload failed:', err); + * // Writer will automatically abort multipart upload on error + * } + */ + writer(options?: S3Options): NetworkSink; + + /** + * Gets a readable stream of the file's content. + * Useful for processing large files without loading them entirely into memory. + * + * @returns A ReadableStream for the file content + * + * @example + * // Basic streaming read + * const stream = file.stream(); + * for await (const chunk of stream) { + * console.log('Received chunk:', chunk); + * } + * + * @example + * // Piping to response + * const stream = file.stream(); + * return new Response(stream, { + * headers: { 'Content-Type': file.type } + * }); + * + * @example + * // Processing large files + * const stream = file.stream(); + * const textDecoder = new TextDecoder(); + * for await (const chunk of stream) { + * const text = textDecoder.decode(chunk); + * // Process text chunk by chunk + * } + */ + readonly readable: ReadableStream; + stream(): ReadableStream; + + /** + * The name or path of the file in the bucket. + * + * @example + * const file = s3("folder/image.jpg"); + * console.log(file.name); // "folder/image.jpg" + */ + readonly name?: string; + + /** + * The bucket name containing the file. + * + * @example + * const file = s3("s3://my-bucket/file.txt"); + * console.log(file.bucket); // "my-bucket" + */ + readonly bucket?: string; + + /** + * Checks if the file exists in S3. + * Uses HTTP HEAD request to efficiently check existence without downloading. + * + * @returns Promise resolving to true if file exists, false otherwise + * + * @example + * // Basic existence check + * if (await file.exists()) { + * console.log("File exists in S3"); + * } + * + * @example + * // With error handling + * try { + * const exists = await file.exists(); + * if (!exists) { + * console.log("File not found"); + * } + * } catch (err) { + * console.error("Error checking file:", err); + * } + */ + exists(): Promise; + + /** + * Uploads data to S3. + * Supports various input types and automatically handles large files. + * + * @param data - The data to upload + * @param options - Upload configuration options + * @returns Promise resolving to number of bytes written + * + * @example + * // Writing string data + * await file.write("Hello World", { + * type: "text/plain" + * }); + * + * @example + * // Writing JSON + * const data = { hello: "world" }; + * await file.write(JSON.stringify(data), { + * type: "application/json" + * }); + * + * @example + * // Writing from Response + * const response = await fetch("https://example.com/data"); + * await file.write(response); + * + * @example + * // Writing with ACL + * await file.write(data, { + * acl: "public-read", + * type: "application/octet-stream" + * }); + */ + write( + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob, + options?: S3Options, + ): Promise; + + /** + * Generates a presigned URL for the file. + * Allows temporary access to the file without exposing credentials. + * + * @param options - Configuration for the presigned URL + * @returns Presigned URL string + * + * @example + * // Basic download URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Upload URL with specific content type + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * @example + * // URL with custom permissions + * const url = file.presign({ + * method: "GET", + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(options?: S3FilePresignOptions): string; + + /** + * Deletes the file from S3. + * + * @returns Promise that resolves when deletion is complete + * + * @example + * // Basic deletion + * await file.delete(); + * + * @example + * // With error handling + * try { + * await file.delete(); + * console.log("File deleted successfully"); + * } catch (err) { + * console.error("Failed to delete file:", err); + * } + */ + delete(): Promise; + + /** + * Alias for delete() method. + * Provided for compatibility with Node.js fs API naming. + * + * @example + * await file.unlink(); + */ + unlink: S3File["delete"]; + + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @returns Promise resolving to S3Stat + */ + stat(): Promise; + } + + /** + * A configured S3 bucket instance for managing files. + * The instance is callable to create S3File instances and provides methods + * for common operations. + * + * @example + * // Basic bucket setup + * const bucket = new S3Client({ + * bucket: "my-bucket", + * accessKeyId: "key", + * secretAccessKey: "secret" + * }); + * + * // Get file instance + * const file = bucket("image.jpg"); + * + * // Common operations + * await bucket.write("data.json", JSON.stringify({hello: "world"})); + * const url = bucket.presign("file.pdf"); + * await bucket.unlink("old.txt"); + */ + type S3Client = { + /** + * Create a new instance of an S3 bucket so that credentials can be managed + * from a single instance instead of being passed to every method. + * + * @param options The default options to use for the S3 client. Can be + * overriden by passing options to the methods. + * + * ## Keep S3 credentials in a single instance + * + * @example + * const bucket = new Bun.S3Client({ + * accessKeyId: "your-access-key", + * secretAccessKey: "your-secret-key", + * bucket: "my-bucket", + * endpoint: "https://s3.us-east-1.amazonaws.com", + * sessionToken: "your-session-token", + * }); + * + * // S3Client is callable, so you can do this: + * const file = bucket.file("my-file.txt"); + * + * // or this: + * await file.write("Hello Bun!"); + * await file.text(); + * + * // To delete the file: + * await bucket.delete("my-file.txt"); + * + * // To write a file without returning the instance: + * await bucket.write("my-file.txt", "Hello Bun!"); + * + */ + new (options?: S3Options): S3Client; + + /** + * Creates an S3File instance for the given path. + * + * @example + * const file = bucket.file("image.jpg"); + * await file.write(imageData); + * const configFile = bucket("config.json", { + * type: "application/json", + * acl: "private" + * }); + */ + file(path: string, options?: S3Options): S3File; + + /** + * Writes data directly to a path in the bucket. + * Supports strings, buffers, streams, and web API types. + * + * @example + * // Write string + * await bucket.write("hello.txt", "Hello World"); + * + * // Write JSON with type + * await bucket.write( + * "data.json", + * JSON.stringify({hello: "world"}), + * {type: "application/json"} + * ); + * + * // Write from fetch + * const res = await fetch("https://example.com/data"); + * await bucket.write("data.bin", res); + * + * // Write with ACL + * await bucket.write("public.html", html, { + * acl: "public-read", + * type: "text/html" + * }); + */ + write( + path: string, + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob + | File, + options?: S3Options, + ): Promise; + + /** + * Generate a presigned URL for temporary access to a file. + * Useful for generating upload/download URLs without exposing credentials. + * + * @example + * // Download URL + * const downloadUrl = bucket.presign("file.pdf", { + * expiresIn: 3600 // 1 hour + * }); + * + * // Upload URL + * const uploadUrl = bucket.presign("uploads/image.jpg", { + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * // Long-lived public URL + * const publicUrl = bucket.presign("public/doc.pdf", { + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(path: string, options?: S3FilePresignOptions): string; + + /** + * Delete a file from the bucket. + * + * @example + * // Simple delete + * await bucket.unlink("old-file.txt"); + * + * // With error handling + * try { + * await bucket.unlink("file.dat"); + * console.log("File deleted"); + * } catch (err) { + * console.error("Delete failed:", err); + * } + */ + unlink(path: string, options?: S3Options): Promise; + delete: S3Client["unlink"]; + + /** + * Get the size of a file in bytes. + * Uses HEAD request to efficiently get size. + * + * @example + * // Get size + * const bytes = await bucket.size("video.mp4"); + * console.log(`Size: ${bytes} bytes`); + * + * // Check if file is large + * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { + * console.log("File is larger than 100MB"); + * } + */ + size(path: string, options?: S3Options): Promise; + + /** + * Check if a file exists in the bucket. + * Uses HEAD request to check existence. + * + * @example + * // Check existence + * if (await bucket.exists("config.json")) { + * const file = bucket("config.json"); + * const config = await file.json(); + * } + * + * // With error handling + * try { + * if (!await bucket.exists("required.txt")) { + * throw new Error("Required file missing"); + * } + * } catch (err) { + * console.error("Check failed:", err); + * } + */ + exists(path: string, options?: S3Options): Promise; + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @param path The path to the file. + * @param options The options to use for the S3 client. + */ + stat(path: string, options?: S3Options): Promise; + }; + /** + * Configuration options for SQL client connection and behavior + * @example + * const config: SQLOptions = { + * host: 'localhost', + * port: 5432, + * user: 'dbuser', + * password: 'secretpass', + * database: 'myapp', + * idleTimeout: 30000, + * max: 20, + * onconnect: (client) => { + * console.log('Connected to database'); + * } + * }; + */ + type 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); + /** Database password for authentication (alias for password) */ + pass?: string | (() => Promise); + /** 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 extends Promise { + /** Indicates if the query is currently executing */ + active: boolean; + /** Indicates if the query has been cancelled */ + cancelled: boolean; + /** Cancels the executing query */ + cancel(): SQLQuery; + /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ + simple(): SQLQuery; + /** Executes the query */ + execute(): SQLQuery; + /** Returns the raw query result */ + raw(): SQLQuery; + /** Returns only the values from the query result */ + values(): SQLQuery; + } + + /** + * Callback function type for transaction contexts + * @param sql Function to execute SQL queries within the transaction + */ + type SQLTransactionContextCallback = ( + sql: TransactionSQL, + ) => Promise | Array; + /** + * Callback function type for savepoint contexts + * @param sql Function to execute SQL queries within the savepoint + */ + type SQLSavepointContextCallback = ( + sql: SavepointSQL, + ) => Promise | Array; + + /** + * Main SQL client interface providing connection and transaction management + */ + interface SQL { + /** Creates a new SQL client instance + * @example + * const sql = new SQL("postgres://localhost:5432/mydb"); + * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); + */ + new (connectionString: string | URL): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); + */ + new (connectionString: string | URL, options: SQLOptions): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); + */ + new (options?: SQLOptions): SQL; + /** Executes a SQL query using template literals + * @example + * const [user] = await sql`select * from users where id = ${1}`; + */ + (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; + /** + * Helper function to allow easy use to insert values into a query + * @example + * const result = await sql`insert into users ${sql(users)} RETURNING *`; + */ + (obj: any): SQLQuery; + /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.commitDistributed("my_distributed_transaction"); + */ + commitDistributed(name: string): Promise; + /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.rollbackDistributed("my_distributed_transaction"); + */ + rollbackDistributed(name: string): Promise; + /** Waits for the database connection to be established + * @example + * await sql.connect(); + */ + connect(): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @example + * await sql.close({ timeout: 1 }); + */ + close(options?: { timeout?: number }): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @alias close + * @example + * await sql.end({ timeout: 1 }); + */ + end(options?: { timeout?: number }): Promise; + /** Flushes any pending operations */ + flush(): void; + /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. + * This can be used for running queries on an isolated connection. + * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). + * @example + * const reserved = await sql.reserve(); + * await reserved`select * from users`; + * await reserved.release(); + * // with in a production scenario would be something more like + * const reserved = await sql.reserve(); + * try { + * // ... queries + * } finally { + * await reserved.release(); + * } + * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose + * { + * // always release after context (safer) + * using reserved = await sql.reserve() + * await reserved`select * from users` + * } + */ + reserve(): Promise; + /** Begins a new transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(fn: SQLTransactionContextCallback): Promise; + /** Begins a new transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(options: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction( + options: string, + fn: SQLTransactionContextCallback, + ): Promise; + /** Begins a distributed transaction + * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. + * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. + * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. + * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. + * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. + * @example + * await sql.beginDistributed("numbers", async sql => { + * await sql`create table if not exists numbers (a int)`; + * await sql`insert into numbers values(1)`; + * }); + * // later you can call + * await sql.commitDistributed("numbers"); + * // or await sql.rollbackDistributed("numbers"); + */ + beginDistributed( + name: string, + fn: SQLTransactionContextCallback, + ): Promise; + /** Alternative method to begin a distributed transaction + * @alias beginDistributed + */ + distributed(name: string, fn: SQLTransactionContextCallback): Promise; + /**If you know what you're doing, you can use unsafe to pass any string you'd like. + * Please note that this can lead to SQL injection if you're not careful. + * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. + * @example + * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) + */ + unsafe(string: string, values?: any[]): SQLQuery; + /** + * Reads a file and uses the contents as a query. + * Optional parameters can be used if the file includes $1, $2, etc + * @example + * const result = await sql.file("query.sql", [1, 2, 3]); + */ + file(filename: string, values?: any[]): SQLQuery; + + /** Current client options */ + options: SQLOptions; + + [Symbol.asyncDispose](): Promise; + } + + /** + * Represents a reserved connection from the connection pool + * Extends SQL with additional release functionality + */ + interface ReservedSQL extends SQL { + /** Releases the client back to the connection pool */ + release(): void; + [Symbol.dispose](): void; + } + + /** + * Represents a client within a transaction context + * Extends SQL with savepoint functionality + */ + interface TransactionSQL extends SQL { + /** Creates a savepoint within the current transaction */ + savepoint(name: string, fn: SQLSavepointContextCallback): Promise; + savepoint(fn: SQLSavepointContextCallback): Promise; + } + /** + * Represents a savepoint within a transaction + */ + interface SavepointSQL extends SQL {} + + var sql: SQL; + var postgres: SQL; + var SQL: SQL; + + /** + * This lets you use macros as regular imports + * @example + * ``` + * { + * "react-relay": { + * "graphql": "bun-macro-relay/bun-macro-relay.tsx" + * } + * } + * ``` + */ + type MacroMap = Record>; + + /** + * 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; + } + + 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; + 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; + + /** 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; + }; + 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 = () =>
Hello World
; + * 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; + /** + * 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-run" + | "entry-point-build"; + + interface Import { + path: string; + kind: ImportKind; + } + + /** + * @see [Bun.build API docs](https://bun.sh/docs/bundler#api) + */ + interface BuildConfig { + entrypoints: string[]; // list of file path + outdir?: string; // output directory + /** + * @default "browser" + */ + 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?: /** - /** - * 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 + * ECMAScript Module format */ - parse(input: string): object; - } - const TOML: TOML; - - /** - * 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; - - /** - * 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 | S3File | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - 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, maxLength?: number): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - maxLength: number, - asUint8Array: false, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - 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, - ): Promise | 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, - ): Promise | 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; - - /** - * 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, - multipartBoundaryExcludingDashes?: string | NodeJS.TypedArray | ArrayBufferView, - ): Promise; - - /** - * 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; - - /** - * 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; - - /** - * 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(stream: ReadableStream): Promise | T[]; - - /** - * Escape the following characters in a string: - * - * - `"` becomes `"""` - * - `&` becomes `"&"` - * - `'` becomes `"'"` - * - `<` becomes `"<"` - * - `>` becomes `">"` + | "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; + // origin?: string; // e.g. http://mydomain.com + loader?: { [k in string]: Loader }; + /** + * Specifies if and how to generate source maps. + * + * - `"none"` - No source maps are generated + * - `"linked"` - A separate `*.ext.map` file is generated alongside each + * `*.ext` file. A `//# sourceMappingURL` comment is added to the output + * file to link the two. Requires `outdir` to be set. + * - `"inline"` - an inline source map is appended to the output file. + * - `"external"` - Generate a separate source map file for each input file. + * No `//# sourceMappingURL` comment is added to the output file. + * + * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. + * + * @default "none" + * + * @see {@link outdir} required for `"linked"` maps + * @see {@link publicPath} to customize the base url of linked source maps + */ + sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; + /** + * 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; + + /** + * Controls how environment variables are handled during bundling. + * + * Can be one of: + * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` + * references to string literals containing the actual environment variable values + * - `"disable"`: Disables environment variable injection entirely + * - A string ending in `*`: Inlines environment variables that match the given prefix. + * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" + * + * @example + * ```ts + * Bun.build({ + * env: "MY_PUBLIC_*", + * entrypoints: ["src/index.ts"], + * }) + * ``` + */ + env?: "inline" | "disable" | `${string}*`; + /** + * Whether to enable minification. + * + * Use `true`/`false` to enable/disable all minification options. Alternatively, + * you can pass an object for granular control over certain minifications. + * + * @default false + */ + 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; + + /** + * Drop function calls to matching property accesses. + */ + drop?: string[]; + + /** + * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. + * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. + * This defaults to `true`. + */ + throw?: boolean; + } + + 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 password. + * If empty, always returns false + */ + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + * + * If specified and the algorithm does not match the hash, this function + * throws an error. + */ + algorithm?: Password.AlgorithmLabel, + ): Promise; + /** + * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. + * + * @returns A promise that resolves to the hashed password + * + * ## Example with argon2 + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world"); + * console.log(hash); // $argon2id$v=1... + * const verify = await password.verify("hello world", hash); + * ``` + * ## Example with bcrypt + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world", "bcrypt"); + * console.log(hash); // $2b$10$... + * const verify = await password.verify("hello world", hash); + * ``` + */ + hash( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before + */ + algorithm?: + | Password.AlgorithmLabel + | Password.Argon2Algorithm + | Password.BCryptAlgorithm, + ): Promise; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.verify} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + verifySync( + password: Bun.StringOrBuffer, + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + */ + algorithm?: Password.AlgorithmLabel, + ): boolean; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.hash} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + hashSync( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before + */ + algorithm?: + | Password.AlgorithmLabel + | Password.Argon2Algorithm + | Password.BCryptAlgorithm, + ): string; + }; + + interface BuildArtifact extends Blob { + path: string; + loader: Loader; + hash: string | null; + kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; + sourcemap: BuildArtifact | null; + } + + interface BuildOutput { + outputs: BuildArtifact[]; + success: boolean; + logs: Array; + } + + /** + * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. * - * 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. + * @param {Object} config - Build configuration options + * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status + * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) * - * Non-string types will be converted to a string before escaping. - */ - function escapeHTML(input: string | object | number | boolean): string; + * @example Basic usage - Bundle a single entrypoint and check results + ```ts + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist' + }); - /** - * 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 { - (promise: T | Promise): Promise | T; - status(promise: T | Promise): "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"; + if (!result.success) { + console.error('Build failed:', result.logs); + process.exit(1); + } + ``` + * + * @example Set up multiple entrypoints with code splitting enabled + ```ts + await Bun.build({ + entrypoints: ['./src/app.tsx', './src/admin.tsx'], + outdir: './dist', + splitting: true, + sourcemap: "external" + }); + ``` + * + * @example Configure minification and optimization settings + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + minify: { + whitespace: true, + identifiers: true, + syntax: true }, - ): Promise; - - /** - * - * **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; - }; - - ADDRCONFIG: number; - ALL: number; - 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; - } - - /** - * 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; - /** - * Close the file descriptor. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; - - 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; - - /** - * 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; - - /** - * Deletes the file. - */ - unlink(): Promise; - - /** - * Deletes the file. ( same as unlink ) - */ - delete(): Promise; - - /** - * Provides useful information about the file. - */ - stat(): Promise; - } - interface NetworkSink extends FileSink { - /** - * Write a chunk of data to the network. - * - * If the network is not writable yet, the data is buffered. - */ - write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number; - /** - * Flush the internal buffer, committing the data to the network. - */ - flush(): number | Promise; - /** - * Finish the upload. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; + drop: ['console', 'debugger'] + }); + ``` + * + * @example Set up custom loaders and mark packages as external + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + loader: { + '.png': 'dataurl', + '.svg': 'file', + '.txt': 'text', + '.json': 'json' + }, + external: ['react', 'react-dom'] + }); + ``` + * + * @example Configure environment variable handling with different modes + ```ts + // Inline all environment variables + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + env: 'inline' + }); - /** - * Get the stat of the file. - */ - stat(): Promise; - } - - var S3Client: S3Client; - var s3: S3Client; - - /** - * Configuration options for S3 operations - */ - interface S3Options extends BlobPropertyBag { - /** - * The Access Control List (ACL) policy for the file. - * Controls who can access the file and what permissions they have. - * - * @example - * // Setting public read access - * const file = s3("public-file.txt", { - * acl: "public-read", - * bucket: "my-bucket" - * }); - * - * @example - * // Using with presigned URLs - * const url = file.presign({ - * acl: "public-read", - * expiresIn: 3600 - * }); - */ - acl?: - | "private" - | "public-read" - | "public-read-write" - | "aws-exec-read" - | "authenticated-read" - | "bucket-owner-read" - | "bucket-owner-full-control" - | "log-delivery-write"; - - /** - * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. - * - * @example - * // Using explicit bucket - * const file = s3("my-file.txt", { bucket: "my-bucket" }); - * - * @example - * // Using environment variables - * // With S3_BUCKET=my-bucket in .env - * const file = s3("my-file.txt"); - */ - bucket?: string; - - /** - * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. - * - * @example - * const file = s3("my-file.txt", { - * bucket: "my-bucket", - * region: "us-west-2" - * }); - */ - region?: string; + // Only include specific env vars + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + env: 'PUBLIC_*' + }); + ``` + * + * @example Set up custom naming patterns for all output types + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + naming: { + entry: '[dir]/[name]-[hash].[ext]', + chunk: 'chunks/[name]-[hash].[ext]', + asset: 'assets/[name]-[hash].[ext]' + } + }); + ``` + @example Work with build artifacts in different formats + ```ts + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'] + }); - /** - * The access key ID for authentication. - * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. - */ - accessKeyId?: string; - - /** - * The secret access key for authentication. - * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. - */ - secretAccessKey?: string; - - /** - * Optional session token for temporary credentials. - * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. - * - * @example - * // Using temporary credentials - * const file = s3("my-file.txt", { - * accessKeyId: tempAccessKey, - * secretAccessKey: tempSecretKey, - * sessionToken: tempSessionToken - * }); - */ - sessionToken?: string; - - /** - * The S3-compatible service endpoint URL. - * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. - * - * @example - * // AWS S3 - * const file = s3("my-file.txt", { - * endpoint: "https://s3.us-east-1.amazonaws.com" - * }); - * - * @example - * // Cloudflare R2 - * const file = s3("my-file.txt", { - * endpoint: "https://.r2.cloudflarestorage.com" - * }); - * - * @example - * // DigitalOcean Spaces - * const file = s3("my-file.txt", { - * endpoint: "https://.digitaloceanspaces.com" - * }); - * - * @example - * // MinIO (local development) - * const file = s3("my-file.txt", { - * endpoint: "http://localhost:9000" - * }); - */ - endpoint?: string; - - /** - * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` - * - * @example - * // Using virtual hosted style - * const file = s3("my-file.txt", { - * virtualHostedStyle: true, - * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" - * }); - */ - virtualHostedStyle?: boolean; - - /** - * The size of each part in multipart uploads (in bytes). - * - Minimum: 5 MiB - * - Maximum: 5120 MiB - * - Default: 5 MiB - * - * @example - * // Configuring multipart uploads - * const file = s3("large-file.dat", { - * partSize: 10 * 1024 * 1024, // 10 MiB parts - * queueSize: 4 // Upload 4 parts in parallel - * }); - * - * const writer = file.writer(); - * // ... write large file in chunks - */ - partSize?: number; - - /** - * Number of parts to upload in parallel for multipart uploads. - * - Default: 5 - * - Maximum: 255 - * - * Increasing this value can improve upload speeds for large files - * but will use more memory. - */ - queueSize?: number; - - /** - * Number of retry attempts for failed uploads. - * - Default: 3 - * - Maximum: 255 - * - * @example - * // Setting retry attempts - * const file = s3("my-file.txt", { - * retry: 5 // Retry failed uploads up to 5 times - * }); - */ - retry?: number; - - /** - * The Content-Type of the file. - * Automatically set based on file extension when possible. - * - * @example - * // Setting explicit content type - * const file = s3("data.bin", { - * type: "application/octet-stream" - * }); - */ - type?: string; - - /** - * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. - * - * @example - * // Setting explicit Storage class - * const file = s3("my-file.json", { - * storageClass: "STANDARD_IA" - * }); - */ - storageClass?: - | "STANDARD" - | "DEEP_ARCHIVE" - | "EXPRESS_ONEZONE" - | "GLACIER" - | "GLACIER_IR" - | "INTELLIGENT_TIERING" - | "ONEZONE_IA" - | "OUTPOSTS" - | "REDUCED_REDUNDANCY" - | "SNOW" - | "STANDARD_IA"; - - /** - * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. - */ - highWaterMark?: number; - } - - /** - * Options for generating presigned URLs - */ - interface S3FilePresignOptions extends S3Options { - /** - * Number of seconds until the presigned URL expires. - * - Default: 86400 (1 day) - * - * @example - * // Short-lived URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Long-lived public URL - * const url = file.presign({ - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - expiresIn?: number; - - /** - * The HTTP method allowed for the presigned URL. - * - * @example - * // GET URL for downloads - * const downloadUrl = file.presign({ - * method: "GET", - * expiresIn: 3600 - * }); - * - * @example - * // PUT URL for uploads - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "application/json" - * }); - */ - method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; - } - - interface S3Stats { - size: number; - lastModified: Date; - etag: string; - type: string; - } - - /** - * Represents a file in an S3-compatible storage service. - * Extends the Blob interface for compatibility with web APIs. - */ - interface S3File extends Blob { - /** - * The size of the file in bytes. - * This is a Promise because it requires a network request to determine the size. - * - * @example - * // Getting file size - * const size = await file.size; - * console.log(`File size: ${size} bytes`); - * - * @example - * // Check if file is larger than 1MB - * if (await file.size > 1024 * 1024) { - * console.log("Large file detected"); - * } - */ - /** - * TODO: figure out how to get the typescript types to not error for this property. - */ - // size: Promise; - - /** - * Creates a new S3File representing a slice of the original file. - * Uses HTTP Range headers for efficient partial downloads. - * - * @param begin - Starting byte offset - * @param end - Ending byte offset (exclusive) - * @param contentType - Optional MIME type for the slice - * @returns A new S3File representing the specified range - * - * @example - * // Reading file header - * const header = file.slice(0, 1024); - * const headerText = await header.text(); - * - * @example - * // Reading with content type - * const jsonSlice = file.slice(1024, 2048, "application/json"); - * const data = await jsonSlice.json(); - * - * @example - * // Reading from offset to end - * const remainder = file.slice(1024); - * const content = await remainder.text(); - */ - slice(begin?: number, end?: number, contentType?: string): S3File; - slice(begin?: number, contentType?: string): S3File; - slice(contentType?: string): S3File; - - /** - * Creates a writable stream for uploading data. - * Suitable for large files as it uses multipart upload. - * - * @param options - Configuration for the upload - * @returns A NetworkSink for writing data - * - * @example - * // Basic streaming write - * const writer = file.writer({ - * type: "application/json" - * }); - * writer.write('{"hello": '); - * writer.write('"world"}'); - * await writer.end(); - * - * @example - * // Optimized large file upload - * const writer = file.writer({ - * partSize: 10 * 1024 * 1024, // 10MB parts - * queueSize: 4, // Upload 4 parts in parallel - * retry: 3 // Retry failed parts - * }); - * - * // Write large chunks of data efficiently - * for (const chunk of largeDataChunks) { - * writer.write(chunk); - * } - * await writer.end(); - * - * @example - * // Error handling - * const writer = file.writer(); - * try { - * writer.write(data); - * await writer.end(); - * } catch (err) { - * console.error('Upload failed:', err); - * // Writer will automatically abort multipart upload on error - * } - */ - writer(options?: S3Options): NetworkSink; - - /** - * Gets a readable stream of the file's content. - * Useful for processing large files without loading them entirely into memory. - * - * @returns A ReadableStream for the file content - * - * @example - * // Basic streaming read - * const stream = file.stream(); - * for await (const chunk of stream) { - * console.log('Received chunk:', chunk); - * } - * - * @example - * // Piping to response - * const stream = file.stream(); - * return new Response(stream, { - * headers: { 'Content-Type': file.type } - * }); - * - * @example - * // Processing large files - * const stream = file.stream(); - * const textDecoder = new TextDecoder(); - * for await (const chunk of stream) { - * const text = textDecoder.decode(chunk); - * // Process text chunk by chunk - * } - */ - readonly readable: ReadableStream; - stream(): ReadableStream; - - /** - * The name or path of the file in the bucket. - * - * @example - * const file = s3("folder/image.jpg"); - * console.log(file.name); // "folder/image.jpg" - */ - readonly name?: string; - - /** - * The bucket name containing the file. - * - * @example - * const file = s3("s3://my-bucket/file.txt"); - * console.log(file.bucket); // "my-bucket" - */ - readonly bucket?: string; - - /** - * Checks if the file exists in S3. - * Uses HTTP HEAD request to efficiently check existence without downloading. - * - * @returns Promise resolving to true if file exists, false otherwise - * - * @example - * // Basic existence check - * if (await file.exists()) { - * console.log("File exists in S3"); - * } - * - * @example - * // With error handling - * try { - * const exists = await file.exists(); - * if (!exists) { - * console.log("File not found"); - * } - * } catch (err) { - * console.error("Error checking file:", err); - * } - */ - exists(): Promise; - - /** - * Uploads data to S3. - * Supports various input types and automatically handles large files. - * - * @param data - The data to upload - * @param options - Upload configuration options - * @returns Promise resolving to number of bytes written - * - * @example - * // Writing string data - * await file.write("Hello World", { - * type: "text/plain" - * }); - * - * @example - * // Writing JSON - * const data = { hello: "world" }; - * await file.write(JSON.stringify(data), { - * type: "application/json" - * }); - * - * @example - * // Writing from Response - * const response = await fetch("https://example.com/data"); - * await file.write(response); - * - * @example - * // Writing with ACL - * await file.write(data, { - * acl: "public-read", - * type: "application/octet-stream" - * }); - */ - write( - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | Request | Response | BunFile | S3File | Blob, - options?: S3Options, - ): Promise; - - /** - * Generates a presigned URL for the file. - * Allows temporary access to the file without exposing credentials. - * - * @param options - Configuration for the presigned URL - * @returns Presigned URL string - * - * @example - * // Basic download URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Upload URL with specific content type - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * @example - * // URL with custom permissions - * const url = file.presign({ - * method: "GET", - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(options?: S3FilePresignOptions): string; - - /** - * Deletes the file from S3. - * - * @returns Promise that resolves when deletion is complete - * - * @example - * // Basic deletion - * await file.delete(); - * - * @example - * // With error handling - * try { - * await file.delete(); - * console.log("File deleted successfully"); - * } catch (err) { - * console.error("Failed to delete file:", err); - * } - */ - delete(): Promise; - - /** - * Alias for delete() method. - * Provided for compatibility with Node.js fs API naming. - * - * @example - * await file.unlink(); - */ - unlink: S3File["delete"]; - - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @returns Promise resolving to S3Stat - */ - stat(): Promise; - } - - /** - * A configured S3 bucket instance for managing files. - * The instance is callable to create S3File instances and provides methods - * for common operations. - * - * @example - * // Basic bucket setup - * const bucket = new S3Client({ - * bucket: "my-bucket", - * accessKeyId: "key", - * secretAccessKey: "secret" - * }); - * - * // Get file instance - * const file = bucket("image.jpg"); - * - * // Common operations - * await bucket.write("data.json", JSON.stringify({hello: "world"})); - * const url = bucket.presign("file.pdf"); - * await bucket.unlink("old.txt"); - */ - type S3Client = { - /** - * Create a new instance of an S3 bucket so that credentials can be managed - * from a single instance instead of being passed to every method. - * - * @param options The default options to use for the S3 client. Can be - * overriden by passing options to the methods. - * - * ## Keep S3 credentials in a single instance - * - * @example - * const bucket = new Bun.S3Client({ - * accessKeyId: "your-access-key", - * secretAccessKey: "your-secret-key", - * bucket: "my-bucket", - * endpoint: "https://s3.us-east-1.amazonaws.com", - * sessionToken: "your-session-token", - * }); - * - * // S3Client is callable, so you can do this: - * const file = bucket.file("my-file.txt"); - * - * // or this: - * await file.write("Hello Bun!"); - * await file.text(); - * - * // To delete the file: - * await bucket.delete("my-file.txt"); - * - * // To write a file without returning the instance: - * await bucket.write("my-file.txt", "Hello Bun!"); - * - */ - new (options?: S3Options): S3Client; - - /** - * Creates an S3File instance for the given path. - * - * @example - * const file = bucket.file("image.jpg"); - * await file.write(imageData); - * const configFile = bucket("config.json", { - * type: "application/json", - * acl: "private" - * }); - */ - file(path: string, options?: S3Options): S3File; - - /** - * Writes data directly to a path in the bucket. - * Supports strings, buffers, streams, and web API types. - * - * @example - * // Write string - * await bucket.write("hello.txt", "Hello World"); - * - * // Write JSON with type - * await bucket.write( - * "data.json", - * JSON.stringify({hello: "world"}), - * {type: "application/json"} - * ); - * - * // Write from fetch - * const res = await fetch("https://example.com/data"); - * await bucket.write("data.bin", res); - * - * // Write with ACL - * await bucket.write("public.html", html, { - * acl: "public-read", - * type: "text/html" - * }); - */ - write( - path: string, - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob - | File, - options?: S3Options, - ): Promise; - - /** - * Generate a presigned URL for temporary access to a file. - * Useful for generating upload/download URLs without exposing credentials. - * - * @example - * // Download URL - * const downloadUrl = bucket.presign("file.pdf", { - * expiresIn: 3600 // 1 hour - * }); - * - * // Upload URL - * const uploadUrl = bucket.presign("uploads/image.jpg", { - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * // Long-lived public URL - * const publicUrl = bucket.presign("public/doc.pdf", { - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(path: string, options?: S3FilePresignOptions): string; - - /** - * Delete a file from the bucket. - * - * @example - * // Simple delete - * await bucket.unlink("old-file.txt"); - * - * // With error handling - * try { - * await bucket.unlink("file.dat"); - * console.log("File deleted"); - * } catch (err) { - * console.error("Delete failed:", err); - * } - */ - unlink(path: string, options?: S3Options): Promise; - delete: S3Client["unlink"]; - - /** - * Get the size of a file in bytes. - * Uses HEAD request to efficiently get size. - * - * @example - * // Get size - * const bytes = await bucket.size("video.mp4"); - * console.log(`Size: ${bytes} bytes`); - * - * // Check if file is large - * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { - * console.log("File is larger than 100MB"); - * } - */ - size(path: string, options?: S3Options): Promise; - - /** - * Check if a file exists in the bucket. - * Uses HEAD request to check existence. - * - * @example - * // Check existence - * if (await bucket.exists("config.json")) { - * const file = bucket("config.json"); - * const config = await file.json(); - * } - * - * // With error handling - * try { - * if (!await bucket.exists("required.txt")) { - * throw new Error("Required file missing"); - * } - * } catch (err) { - * console.error("Check failed:", err); - * } - */ - exists(path: string, options?: S3Options): Promise; - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @param path The path to the file. - * @param options The options to use for the S3 client. - */ - stat(path: string, options?: S3Options): Promise; - }; - /** - * Configuration options for SQL client connection and behavior - * @example - * const config: SQLOptions = { - * host: 'localhost', - * port: 5432, - * user: 'dbuser', - * password: 'secretpass', - * database: 'myapp', - * idleTimeout: 30000, - * max: 20, - * onconnect: (client) => { - * console.log('Connected to database'); - * } - * }; - */ - type 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); - /** Database password for authentication (alias for password) */ - pass?: string | (() => Promise); - /** 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 extends Promise { - /** Indicates if the query is currently executing */ - active: boolean; - /** Indicates if the query has been cancelled */ - cancelled: boolean; - /** Cancels the executing query */ - cancel(): SQLQuery; - /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ - simple(): SQLQuery; - /** Executes the query */ - execute(): SQLQuery; - /** Returns the raw query result */ - raw(): SQLQuery; - /** Returns only the values from the query result */ - values(): SQLQuery; - } - - /** - * Callback function type for transaction contexts - * @param sql Function to execute SQL queries within the transaction - */ - type SQLTransactionContextCallback = (sql: TransactionSQL) => Promise | Array; - /** - * Callback function type for savepoint contexts - * @param sql Function to execute SQL queries within the savepoint - */ - type SQLSavepointContextCallback = (sql: SavepointSQL) => Promise | Array; - - /** - * Main SQL client interface providing connection and transaction management - */ - interface SQL { - /** Creates a new SQL client instance - * @example - * const sql = new SQL("postgres://localhost:5432/mydb"); - * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); - */ - new (connectionString: string | URL): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); - */ - new (connectionString: string | URL, options: SQLOptions): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); - */ - new (options?: SQLOptions): SQL; - /** Executes a SQL query using template literals - * @example - * const [user] = await sql`select * from users where id = ${1}`; - */ - (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; - /** - * Helper function to allow easy use to insert values into a query - * @example - * const result = await sql`insert into users ${sql(users)} RETURNING *`; - */ - (obj: any): SQLQuery; - /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.commitDistributed("my_distributed_transaction"); - */ - commitDistributed(name: string): Promise; - /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.rollbackDistributed("my_distributed_transaction"); - */ - rollbackDistributed(name: string): Promise; - /** Waits for the database connection to be established - * @example - * await sql.connect(); - */ - connect(): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @example - * await sql.close({ timeout: 1 }); - */ - close(options?: { timeout?: number }): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @alias close - * @example - * await sql.end({ timeout: 1 }); - */ - end(options?: { timeout?: number }): Promise; - /** Flushes any pending operations */ - flush(): void; - /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. - * This can be used for running queries on an isolated connection. - * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). - * @example - * const reserved = await sql.reserve(); - * await reserved`select * from users`; - * await reserved.release(); - * // with in a production scenario would be something more like - * const reserved = await sql.reserve(); - * try { - * // ... queries - * } finally { - * await reserved.release(); - * } - * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose - * { - * // always release after context (safer) - * using reserved = await sql.reserve() - * await reserved`select * from users` - * } - */ - reserve(): Promise; - /** Begins a new transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(fn: SQLTransactionContextCallback): Promise; - /** Begins a new transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(options: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(options: string, fn: SQLTransactionContextCallback): Promise; - /** Begins a distributed transaction - * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. - * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. - * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. - * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. - * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. - * @example - * await sql.beginDistributed("numbers", async sql => { - * await sql`create table if not exists numbers (a int)`; - * await sql`insert into numbers values(1)`; - * }); - * // later you can call - * await sql.commitDistributed("numbers"); - * // or await sql.rollbackDistributed("numbers"); - */ - beginDistributed(name: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a distributed transaction - * @alias beginDistributed - */ - distributed(name: string, fn: SQLTransactionContextCallback): Promise; - /**If you know what you're doing, you can use unsafe to pass any string you'd like. - * Please note that this can lead to SQL injection if you're not careful. - * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. - * @example - * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) - */ - unsafe(string: string, values?: any[]): SQLQuery; - /** - * Reads a file and uses the contents as a query. - * Optional parameters can be used if the file includes $1, $2, etc - * @example - * const result = await sql.file("query.sql", [1, 2, 3]); - */ - file(filename: string, values?: any[]): SQLQuery; - - /** Current client options */ - options: SQLOptions; - - [Symbol.asyncDispose](): Promise; - } - - /** - * Represents a reserved connection from the connection pool - * Extends SQL with additional release functionality - */ - interface ReservedSQL extends SQL { - /** Releases the client back to the connection pool */ - release(): void; - [Symbol.dispose](): void; - } - - /** - * Represents a client within a transaction context - * Extends SQL with savepoint functionality - */ - interface TransactionSQL extends SQL { - /** Creates a savepoint within the current transaction */ - savepoint(name: string, fn: SQLSavepointContextCallback): Promise; - savepoint(fn: SQLSavepointContextCallback): Promise; - } - /** - * Represents a savepoint within a transaction - */ - interface SavepointSQL extends SQL {} - - var sql: SQL; - var postgres: SQL; - var SQL: SQL; - - /** - * This lets you use macros as regular imports - * @example - * ``` - * { - * "react-relay": { - * "graphql": "bun-macro-relay/bun-macro-relay.tsx" - * } - * } - * ``` - */ - type MacroMap = Record>; - - /** - * 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; - } - - 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; - 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; - - /** 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; - }; - 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 = () =>
Hello World
; - * 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; - /** - * 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-run" - | "entry-point-build"; - - interface Import { - path: string; - kind: ImportKind; - } - - /** - * @see [Bun.build API docs](https://bun.sh/docs/bundler#api) - */ - interface BuildConfig { - entrypoints: string[]; // list of file path - outdir?: string; // output directory - /** - * @default "browser" - */ - 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; - // origin?: string; // e.g. http://mydomain.com - loader?: { [k in string]: Loader }; - /** - * Specifies if and how to generate source maps. - * - * - `"none"` - No source maps are generated - * - `"linked"` - A separate `*.ext.map` file is generated alongside each - * `*.ext` file. A `//# sourceMappingURL` comment is added to the output - * file to link the two. Requires `outdir` to be set. - * - `"inline"` - an inline source map is appended to the output file. - * - `"external"` - Generate a separate source map file for each input file. - * No `//# sourceMappingURL` comment is added to the output file. - * - * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. - * - * @default "none" - * - * @see {@link outdir} required for `"linked"` maps - * @see {@link publicPath} to customize the base url of linked source maps - */ - sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; - /** - * 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; - - /** - * Controls how environment variables are handled during bundling. - * - * Can be one of: - * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` - * references to string literals containing the actual environment variable values - * - `"disable"`: Disables environment variable injection entirely - * - A string ending in `*`: Inlines environment variables that match the given prefix. - * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" - * - * @example - * ```ts - * Bun.build({ - * env: "MY_PUBLIC_*", - * entrypoints: ["src/index.ts"], - * }) - * ``` - */ - env?: "inline" | "disable" | `${string}*`; - /** - * Whether to enable minification. - * - * Use `true`/`false` to enable/disable all minification options. Alternatively, - * you can pass an object for granular control over certain minifications. - * - * @default false - */ - 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; - - /** - * Drop function calls to matching property accesses. - */ - drop?: string[]; - - /** - * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. - * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. - * This defaults to `true`. - */ - throw?: boolean; - } - - 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 password. - * If empty, always returns false - */ - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - * - * If specified and the algorithm does not match the hash, this function - * throws an error. - */ - algorithm?: Password.AlgorithmLabel, - ): Promise; - /** - * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. - * - * @returns A promise that resolves to the hashed password - * - * ## Example with argon2 - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world"); - * console.log(hash); // $argon2id$v=1... - * const verify = await password.verify("hello world", hash); - * ``` - * ## Example with bcrypt - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world", "bcrypt"); - * console.log(hash); // $2b$10$... - * const verify = await password.verify("hello world", hash); - * ``` - */ - hash( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before - */ - algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, - ): Promise; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.verify} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - verifySync( - password: Bun.StringOrBuffer, - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - */ - algorithm?: Password.AlgorithmLabel, - ): boolean; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.hash} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - hashSync( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before - */ - algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, - ): string; - }; - - interface BuildArtifact extends Blob { - path: string; - loader: Loader; - hash: string | null; - kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; - sourcemap: BuildArtifact | null; - } - - interface BuildOutput { - outputs: BuildArtifact[]; - success: boolean; - logs: Array; - } - - /** - * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. - * - * @param {Object} config - Build configuration options - * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status - * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) - * - * @example Basic usage - Bundle a single entrypoint and check results - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist' - }); - - if (!result.success) { - console.error('Build failed:', result.logs); - process.exit(1); - } - ``` - * - * @example Set up multiple entrypoints with code splitting enabled - ```ts - await Bun.build({ - entrypoints: ['./src/app.tsx', './src/admin.tsx'], - outdir: './dist', - splitting: true, - sourcemap: "external" - }); - ``` - * - * @example Configure minification and optimization settings - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - minify: { - whitespace: true, - identifiers: true, - syntax: true - }, - drop: ['console', 'debugger'] - }); - ``` - * - * @example Set up custom loaders and mark packages as external - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - loader: { - '.png': 'dataurl', - '.svg': 'file', - '.txt': 'text', - '.json': 'json' - }, - external: ['react', 'react-dom'] - }); - ``` - * - * @example Configure environment variable handling with different modes - ```ts - // Inline all environment variables - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'inline' - }); - - // Only include specific env vars - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'PUBLIC_*' - }); - ``` - * - * @example Set up custom naming patterns for all output types - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - naming: { - entry: '[dir]/[name]-[hash].[ext]', - chunk: 'chunks/[name]-[hash].[ext]', - asset: 'assets/[name]-[hash].[ext]' - } - }); - ``` - @example Work with build artifacts in different formats - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'] - }); - - for (const artifact of result.outputs) { - const text = await artifact.text(); - const buffer = await artifact.arrayBuffer(); - const bytes = await artifact.bytes(); + for (const artifact of result.outputs) { + const text = await artifact.text(); + const buffer = await artifact.arrayBuffer(); + const bytes = await artifact.bytes(); new Response(artifact); await Bun.write(artifact.path, artifact); @@ -3226,1283 +3321,1380 @@ declare module "bun" { }); ``` */ - function build(config: BuildConfig): Promise; - /** - * A status that represents the outcome of a sent message. - * - * - if **0**, the message was **dropped**. - * - if **-1**, there is **backpressure** of messages. - * - if **>0**, it represents the **number of bytes sent**. - * - * @example - * ```js - * const status = ws.send("Hello!"); - * if (status === 0) { - * console.log("Message was dropped"); - * } else if (status === -1) { - * console.log("Backpressure was applied"); - * } else { - * console.log(`Success! Sent ${status} bytes`); - * } - * ``` - */ - type ServerWebSocketSendStatus = number; - - /** - * A state that represents if a WebSocket is connected. - * - * - `WebSocket.CONNECTING` is `0`, the connection is pending. - * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. - * - `WebSocket.CLOSING` is `2`, the connection is closing. - * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState - */ - type WebSocketReadyState = 0 | 1 | 2 | 3; - - /** - * A fast WebSocket designed for servers. - * - * Features: - * - **Message compression** - Messages can be compressed - * - **Backpressure** - If the client is not ready to receive data, the server will tell you. - * - **Dropped messages** - If the client cannot receive data, the server will tell you. - * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics - * - * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. - * - * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). - * - * @example - * import { serve } from "bun"; - * - * serve({ - * websocket: { - * open(ws) { - * console.log("Connected", ws.remoteAddress); - * }, - * message(ws, data) { - * console.log("Received", data); - * ws.send(data); - * }, - * close(ws, code, reason) { - * console.log("Disconnected", code, reason); - * }, - * } - * }); - */ - interface ServerWebSocket { - /** - * Sends a message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - * ws.send(new Uint8Array([1, 2, 3, 4])); - */ - send(data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a text message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - */ - sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send(new TextEncoder().encode("Hello!")); - * ws.send(new Uint8Array([1, 2, 3, 4]), true); - */ - sendBinary(data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Closes the connection. - * - * Here is a list of close codes: - * - `1000` means "normal closure" **(default)** - * - `1009` means a message was too big and was rejected - * - `1011` means the server encountered an error - * - `1012` means the server is restarting - * - `1013` means the server is too busy or the client is rate-limited - * - `4000` through `4999` are reserved for applications (you can use it!) - * - * To close the connection abruptly, use `terminate()`. - * - * @param code The close code to send - * @param reason The close reason to send - */ - close(code?: number, reason?: string): void; - - /** - * Abruptly close the connection. - * - * To gracefully close the connection, use `close()`. - */ - terminate(): void; - - /** - * Sends a ping. - * - * @param data The data to send - */ - ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a pong. - * - * @param data The data to send - */ - pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); - */ - publish(topic: string, data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a text message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - */ - publishText(topic: string, data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", new TextEncoder().encode("Hello!")); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); - */ - publishBinary(topic: string, data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Subscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - */ - subscribe(topic: string): void; - - /** - * Unsubscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.unsubscribe("chat"); - */ - unsubscribe(topic: string): void; - - /** - * Is the client subscribed to a topic? - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - * console.log(ws.isSubscribed("chat")); // true - */ - isSubscribed(topic: string): boolean; - - /** - * Batches `send()` and `publish()` operations, which makes it faster to send data. - * - * The `message`, `open`, and `drain` callbacks are automatically corked, so - * you only need to call this if you are sending messages outside of those - * callbacks or in async functions. - * - * @param callback The callback to run. - * @example - * ws.cork((ctx) => { - * ctx.send("These messages"); - * ctx.sendText("are sent"); - * ctx.sendBinary(new TextEncoder().encode("together!")); - * }); - */ - cork(callback: (ws: ServerWebSocket) => T): T; + function build(config: BuildConfig): Promise; + /** + * A status that represents the outcome of a sent message. + * + * - if **0**, the message was **dropped**. + * - if **-1**, there is **backpressure** of messages. + * - if **>0**, it represents the **number of bytes sent**. + * + * @example + * ```js + * const status = ws.send("Hello!"); + * if (status === 0) { + * console.log("Message was dropped"); + * } else if (status === -1) { + * console.log("Backpressure was applied"); + * } else { + * console.log(`Success! Sent ${status} bytes`); + * } + * ``` + */ + type ServerWebSocketSendStatus = number; + + /** + * A state that represents if a WebSocket is connected. + * + * - `WebSocket.CONNECTING` is `0`, the connection is pending. + * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. + * - `WebSocket.CLOSING` is `2`, the connection is closing. + * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState + */ + type WebSocketReadyState = 0 | 1 | 2 | 3; + + /** + * A fast WebSocket designed for servers. + * + * Features: + * - **Message compression** - Messages can be compressed + * - **Backpressure** - If the client is not ready to receive data, the server will tell you. + * - **Dropped messages** - If the client cannot receive data, the server will tell you. + * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics + * + * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. + * + * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). + * + * @example + * import { serve } from "bun"; + * + * serve({ + * websocket: { + * open(ws) { + * console.log("Connected", ws.remoteAddress); + * }, + * message(ws, data) { + * console.log("Received", data); + * ws.send(data); + * }, + * close(ws, code, reason) { + * console.log("Disconnected", code, reason); + * }, + * } + * }); + */ + interface ServerWebSocket { + /** + * Sends a message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + * ws.send(new Uint8Array([1, 2, 3, 4])); + */ + send( + data: string | Bun.BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a text message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + */ + sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send(new TextEncoder().encode("Hello!")); + * ws.send(new Uint8Array([1, 2, 3, 4]), true); + */ + sendBinary( + data: Bun.BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Closes the connection. + * + * Here is a list of close codes: + * - `1000` means "normal closure" **(default)** + * - `1009` means a message was too big and was rejected + * - `1011` means the server encountered an error + * - `1012` means the server is restarting + * - `1013` means the server is too busy or the client is rate-limited + * - `4000` through `4999` are reserved for applications (you can use it!) + * + * To close the connection abruptly, use `terminate()`. + * + * @param code The close code to send + * @param reason The close reason to send + */ + close(code?: number, reason?: string): void; + + /** + * Abruptly close the connection. + * + * To gracefully close the connection, use `close()`. + */ + terminate(): void; + + /** + * Sends a ping. + * + * @param data The data to send + */ + ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a pong. + * + * @param data The data to send + */ + pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); + */ + publish( + topic: string, + data: string | Bun.BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a text message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + */ + publishText( + topic: string, + data: string, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a binary message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", new TextEncoder().encode("Hello!")); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); + */ + publishBinary( + topic: string, + data: Bun.BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Subscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + */ + subscribe(topic: string): void; + + /** + * Unsubscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.unsubscribe("chat"); + */ + unsubscribe(topic: string): void; + + /** + * Is the client subscribed to a topic? + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + * console.log(ws.isSubscribed("chat")); // true + */ + isSubscribed(topic: string): boolean; + + /** + * Batches `send()` and `publish()` operations, which makes it faster to send data. + * + * The `message`, `open`, and `drain` callbacks are automatically corked, so + * you only need to call this if you are sending messages outside of those + * callbacks or in async functions. + * + * @param callback The callback to run. + * @example + * ws.cork((ctx) => { + * ctx.send("These messages"); + * ctx.sendText("are sent"); + * ctx.sendBinary(new TextEncoder().encode("together!")); + * }); + */ + cork(callback: (ws: ServerWebSocket) => T): T; + + /** + * The IP address of the client. + * + * @example + * console.log(socket.remoteAddress); // "127.0.0.1" + */ + readonly remoteAddress: string; + + /** + * The ready state of the client. + * + * - if `0`, the client is connecting. + * - if `1`, the client is connected. + * - if `2`, the client is closing. + * - if `3`, the client is closed. + * + * @example + * console.log(socket.readyState); // 1 + */ + readonly readyState: WebSocketReadyState; + + /** + * Sets how binary data is returned in events. + * + * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** + * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. + * - if `uint8array`, binary data is returned as `Uint8Array` objects. + * + * @example + * let ws: WebSocket; + * ws.binaryType = "uint8array"; + * ws.addEventListener("message", ({ data }) => { + * console.log(data instanceof Uint8Array); // true + * }); + */ + binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; + + /** + * Custom data that you can assign to a client, can be read and written at any time. + * + * @example + * import { serve } from "bun"; + * + * serve({ + * fetch(request, server) { + * const data = { + * accessToken: request.headers.get("Authorization"), + * }; + * if (server.upgrade(request, { data })) { + * return; + * } + * return new Response(); + * }, + * websocket: { + * open(ws) { + * console.log(ws.data.accessToken); + * } + * } + * }); + */ + data: T; + + getBufferedAmount(): number; + } + + /** + * Compression options for WebSocket messages. + */ + type WebSocketCompressor = + | "disable" + | "shared" + | "dedicated" + | "3KB" + | "4KB" + | "8KB" + | "16KB" + | "32KB" + | "64KB" + | "128KB" + | "256KB"; + + /** + * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} + * + * @example + * ```ts + * import { websocket, serve } from "bun"; + * + * serve<{name: string}>({ + * port: 3000, + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log(`${ws.data.name}: ${message}`); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req, { + * data: { + * name: new URL(req.url).searchParams.get("name"), + * }, + * }); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * return; + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + */ + interface WebSocketHandler { + /** + * Called when the server receives an incoming message. + * + * If the message is not a `string`, its type is based on the value of `binaryType`. + * - if `nodebuffer`, then the message is a `Buffer`. + * - if `arraybuffer`, then the message is an `ArrayBuffer`. + * - if `uint8array`, then the message is a `Uint8Array`. + * + * @param ws The websocket that sent the message + * @param message The message received + */ + message( + ws: ServerWebSocket, + message: string | Buffer, + ): void | Promise; + + /** + * Called when a connection is opened. + * + * @param ws The websocket that was opened + */ + open?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection was previously under backpressure, + * meaning it had too many queued messages, but is now ready to receive more data. + * + * @param ws The websocket that is ready for more data + */ + drain?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection is closed. + * + * @param ws The websocket that was closed + * @param code The close code + * @param message The close message + */ + close?( + ws: ServerWebSocket, + code: number, + reason: string, + ): void | Promise; + + /** + * Called when a ping is sent. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + ping?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Called when a pong is received. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + pong?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Sets the maximum size of messages in bytes. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + maxPayloadLength?: number; + + /** + * Sets the maximum number of bytes that can be buffered on a single connection. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + backpressureLimit?: number; + + /** + * Sets if the connection should be closed if `backpressureLimit` is reached. + * + * Default is `false`. + */ + closeOnBackpressureLimit?: boolean; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to no messages or pings. + * + * Default is 2 minutes, or `120` in seconds. + */ + idleTimeout?: number; + + /** + * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? + * + * Default is `false`. + */ + publishToSelf?: boolean; + + /** + * Should the server automatically send and respond to pings to clients? + * + * Default is `true`. + */ + sendPings?: boolean; + + /** + * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. + * + * Default is `false`. + */ + perMessageDeflate?: + | boolean + | { + /** + * Sets the compression level. + */ + compress?: WebSocketCompressor | boolean; + /** + * Sets the decompression level. + */ + decompress?: WebSocketCompressor | boolean; + }; + } + + namespace RouterTypes { + type ExtractRouteParams = + T extends `${string}:${infer Param}/${infer Rest}` + ? { [K in Param]: string } & ExtractRouteParams + : T extends `${string}:${infer Param}` + ? { [K in Param]: string } + : T extends `${string}*` + ? {} + : {}; + + type RouteHandler = ( + req: BunRequest, + server: Server, + ) => Response | Promise; + + type HTTPMethod = + | "GET" + | "POST" + | "PUT" + | "DELETE" + | "PATCH" + | "HEAD" + | "OPTIONS"; + + type RouteHandlerObject = { + [K in HTTPMethod]?: RouteHandler; + }; + + type RouteValue = + | Response + | false + | RouteHandler + | RouteHandlerObject; + } + + interface BunRequest extends Request { + params: RouterTypes.ExtractRouteParams; + } + + interface GenericServeOptions { + /** + * What URI should be used to make {@link Request.url} absolute? + * + * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one + * + * @example + * ```js + * "http://my-app.com" + * ``` + * + * @example + * ```js + * "https://wongmjane.com/" + * ``` + * + * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. + * + * @example + * "http://localhost:3000" + */ + // baseURI?: string; + + /** + * What is the maximum size of a request body? (in bytes) + * @default 1024 * 1024 * 128 // 128MB + */ + maxRequestBodySize?: number; + + /** + * Render contextual errors? This enables bun's error page + * @default process.env.NODE_ENV !== 'production' + */ + development?: + | boolean + | { + /** + * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) + * + * @default true if process.env.NODE_ENV !== 'production' + * + */ + hmr?: boolean; + }; + + error?: ( + this: Server, + error: ErrorLike, + ) => Response | Promise | undefined | Promise; + + /** + * Uniquely identify a server instance with an ID + * + * ### When bun is started with the `--hot` flag + * + * This string will be used to hot reload the server without interrupting + * pending requests or websockets. If not provided, a value will be + * generated. To disable hot reloading, set this value to `null`. + * + * ### When bun is not started with the `--hot` flag + * + * This string will currently do nothing. But in the future it could be useful for logs or metrics. + */ + id?: string | null; + } + + interface ServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * Whether the `SO_REUSEPORT` flag should be set. + * + * This allows multiple processes to bind to the same port, which is useful for load balancing. + * + * @default false + */ + reusePort?: boolean; + + /** + * Whether the `IPV6_V6ONLY` flag should be set. + * @default false + */ + ipv6Only?: boolean; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix?: never; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to inactivity. + * + * Default is `10` seconds. + */ + idleTimeout?: number; + + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | Promise; + } + + interface UnixServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | Promise; + } + + interface WebSocketServeOptions + extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | void | Promise; + } + + interface UnixWebSocketServeOptions + extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | Promise; + } + + interface TLSWebSocketServeOptions + extends WebSocketServeOptions, + TLSOptionsAsDeprecated { + unix?: never; + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSWebSocketServeOptions + extends UnixWebSocketServeOptions, + TLSOptionsAsDeprecated { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + tls?: TLSOptions | TLSOptions[]; + } + + interface ErrorLike extends Error { + code?: string; + errno?: number; + syscall?: string; + } + + interface TLSOptions { + /** + * Passphrase for the TLS key + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + // Note for contributors: TLSOptionsAsDeprecated should be considered immutable + // and new TLS option keys should only be supported on the `.tls` property (which comes + // from the TLSOptions interface above). + /** + * This exists because Bun.serve() extends the TLSOptions object, but + * they're now considered deprecated. You should be passing the + * options on `.tls` instead. + * + * @example + * ```ts + * //// OLD //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * passphrase: "secret", + * }); + * + * //// NEW //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * tls: { + * passphrase: "secret", + * }, + * }); + * ``` + */ + interface TLSOptionsAsDeprecated { + /** + * Passphrase for the TLS key + * + * @deprecated Use `.tls.passphrase` instead + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + * + * @deprecated Use `.tls.dhParamsFile` instead + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + * + * @deprecated Use `.tls.serverName` instead + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + * + * @deprecated Use `.tls.lowMemoryMode` instead + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + * + * @deprecated Use `.tls.rejectUnauthorized` instead + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + * + * @deprecated Use `.tls.requestCert` instead + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + * + * @deprecated Use `.tls.ca` instead + */ + ca?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + * + * @deprecated Use `.tls.cert` instead + */ + cert?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + * + * @deprecated Use `.tls.key` instead + */ + key?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + * + * @deprecated `Use .tls.secureOptions` instead + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSServeOptions + extends UnixServeOptions, + TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface SocketAddress { + /** + * The IP address of the client. + */ + address: string; + /** + * The port of the client. + */ + port: number; + /** + * The IP family ("IPv4" or "IPv6"). + */ + family: "IPv4" | "IPv6"; + } + + /** + * HTTP & HTTPS Server + * + * To start the server, see {@link serve} + * + * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. + * That means starting a new server allocates about 500 KB of memory. Try to + * avoid starting and stopping the server often (unless it's a new instance of bun). + * + * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. + */ + interface Server extends Disposable { + /** + * Stop listening to prevent new connections from being accepted. + * + * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. + * + * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. + * @default false + */ + stop(closeActiveConnections?: boolean): Promise; + + /** + * Update the `fetch` and `error` handlers without restarting the server. + * + * This is useful if you want to change the behavior of your server without + * restarting it or for hot reloading. + * + * @example + * + * ```js + * // create the server + * const server = Bun.serve({ + * fetch(request) { + * return new Response("Hello World v1") + * } + * }); + * + * // Update the server to return a different response + * server.reload({ + * fetch(request) { + * return new Response("Hello World v2") + * } + * }); + * ``` + * + * Passing other options such as `port` or `hostname` won't do anything. + */ + reload }>( + options: ( + | (Omit & { + routes: R; + fetch?: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | (Omit & { + routes?: never; + fetch: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. + */ + static?: R; + }, + ): Server; + + /** + * Mock the fetch handler for a running server. + * + * This feature is not fully implemented yet. It doesn't normalize URLs + * consistently in all cases and it doesn't yet call the `error` handler + * consistently. This needs to be fixed + */ + fetch(request: Request | string): Response | Promise; + + /** + * Upgrade a {@link Request} to a {@link ServerWebSocket} + * + * @param request The {@link Request} to upgrade + * @param options Pass headers or attach data to the {@link ServerWebSocket} + * + * @returns `true` if the upgrade was successful and `false` if it failed + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * What you pass to `data` is available on the {@link ServerWebSocket.data} property + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + upgrade( + request: Request, + options?: { + /** + * Send any additional headers while upgrading, like cookies + */ + headers?: Bun.HeadersInit; + /** + * This value is passed to the {@link ServerWebSocket.data} property + */ + data?: T; + }, + ): boolean; + + /** + * Send a message to all connected {@link ServerWebSocket} subscribed to a topic + * + * @param topic The topic to publish to + * @param data The data to send + * @param compress Should the data be compressed? Ignored if the client does not support compression. + * + * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. + * + * @example + * + * ```js + * server.publish("chat", "Hello World"); + * ``` + * + * @example + * ```js + * server.publish("chat", new Uint8Array([1, 2, 3, 4])); + * ``` + * + * @example + * ```js + * server.publish("chat", new ArrayBuffer(4), true); + * ``` + * + * @example + * ```js + * server.publish("chat", new DataView(new ArrayBuffer(4))); + * ``` + */ + publish( + topic: string, + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * A count of connections subscribed to a given topic + * + * This operation will loop through each topic internally to get the count. + * + * @param topic the websocket topic to check how many subscribers are connected to + * @returns the number of subscribers + */ + subscriberCount(topic: string): number; + + /** + * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * return new Response(server.requestIP(request)); + * } + * } + * ``` + */ + requestIP(request: Request): SocketAddress | null; + + /** + * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * server.timeout(request, 60); + * await Bun.sleep(30000); + * return new Response("30 seconds have passed"); + * } + * } + * ``` + */ + timeout(request: Request, seconds: number): void; + /** + * Undo a call to {@link Server.unref} + * + * If the Server has already been stopped, this does nothing. + * + * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. + */ + ref(): void; + + /** + * Don't keep the process alive if this server is the only thing left. + * Active connections may continue to keep the process alive. + * + * By default, the server is ref'd. + * + * To prevent new connections from being accepted, use {@link Server.stop} + */ + unref(): void; + + /** + * How many requests are in-flight right now? + */ + readonly pendingRequests: number; + + /** + * How many {@link ServerWebSocket}s are in-flight right now? + */ + readonly pendingWebSockets: number; + + readonly url: URL; + + readonly port: number; + /** + * The hostname the server is listening on. Does not include the port + * @example + * ```js + * "localhost" + * ``` + */ + readonly hostname: string; + /** + * Is the server running in development mode? + * + * In development mode, `Bun.serve()` returns rendered error messages with + * stack traces instead of a generic 500 error. This makes debugging easier, + * but development mode shouldn't be used in production or you will risk + * leaking sensitive information. + */ + readonly development: boolean; + + /** + * An identifier of the server instance + * + * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. + * + * When bun is not started with the `--hot` flag, this ID is currently unused. + */ + readonly id: string; + } + + type Serve = + | ServeOptions + | TLSServeOptions + | UnixServeOptions + | UnixTLSServeOptions + | WebSocketServeOptions + | TLSWebSocketServeOptions + | UnixWebSocketServeOptions + | UnixTLSWebSocketServeOptions; + + /** + Bun.serve provides a high-performance HTTP server with built-in routing support. + It enables both function-based and object-based route handlers with type-safe + parameters and method-specific handling. - /** - * The IP address of the client. - * - * @example - * console.log(socket.remoteAddress); // "127.0.0.1" - */ - readonly remoteAddress: string; - - /** - * The ready state of the client. - * - * - if `0`, the client is connecting. - * - if `1`, the client is connected. - * - if `2`, the client is closing. - * - if `3`, the client is closed. - * - * @example - * console.log(socket.readyState); // 1 - */ - readonly readyState: WebSocketReadyState; - - /** - * Sets how binary data is returned in events. - * - * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** - * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. - * - if `uint8array`, binary data is returned as `Uint8Array` objects. - * - * @example - * let ws: WebSocket; - * ws.binaryType = "uint8array"; - * ws.addEventListener("message", ({ data }) => { - * console.log(data instanceof Uint8Array); // true - * }); - */ - binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; - - /** - * Custom data that you can assign to a client, can be read and written at any time. - * - * @example - * import { serve } from "bun"; - * - * serve({ - * fetch(request, server) { - * const data = { - * accessToken: request.headers.get("Authorization"), - * }; - * if (server.upgrade(request, { data })) { - * return; - * } - * return new Response(); - * }, - * websocket: { - * open(ws) { - * console.log(ws.data.accessToken); - * } - * } - * }); - */ - data: T; - - getBufferedAmount(): number; - } - - /** - * Compression options for WebSocket messages. - */ - type WebSocketCompressor = - | "disable" - | "shared" - | "dedicated" - | "3KB" - | "4KB" - | "8KB" - | "16KB" - | "32KB" - | "64KB" - | "128KB" - | "256KB"; - - /** - * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} - * - * @example - * ```ts - * import { websocket, serve } from "bun"; - * - * serve<{name: string}>({ - * port: 3000, - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log(`${ws.data.name}: ${message}`); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req, { - * data: { - * name: new URL(req.url).searchParams.get("name"), - * }, - * }); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * return; - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - */ - interface WebSocketHandler { - /** - * Called when the server receives an incoming message. - * - * If the message is not a `string`, its type is based on the value of `binaryType`. - * - if `nodebuffer`, then the message is a `Buffer`. - * - if `arraybuffer`, then the message is an `ArrayBuffer`. - * - if `uint8array`, then the message is a `Uint8Array`. - * - * @param ws The websocket that sent the message - * @param message The message received - */ - message(ws: ServerWebSocket, message: string | Buffer): void | Promise; - - /** - * Called when a connection is opened. - * - * @param ws The websocket that was opened - */ - open?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection was previously under backpressure, - * meaning it had too many queued messages, but is now ready to receive more data. - * - * @param ws The websocket that is ready for more data - */ - drain?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection is closed. - * - * @param ws The websocket that was closed - * @param code The close code - * @param message The close message - */ - close?(ws: ServerWebSocket, code: number, reason: string): void | Promise; - - /** - * Called when a ping is sent. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - ping?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Called when a pong is received. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - pong?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Sets the maximum size of messages in bytes. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - maxPayloadLength?: number; - - /** - * Sets the maximum number of bytes that can be buffered on a single connection. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - backpressureLimit?: number; - - /** - * Sets if the connection should be closed if `backpressureLimit` is reached. - * - * Default is `false`. - */ - closeOnBackpressureLimit?: boolean; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to no messages or pings. - * - * Default is 2 minutes, or `120` in seconds. - */ - idleTimeout?: number; - - /** - * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? - * - * Default is `false`. - */ - publishToSelf?: boolean; - - /** - * Should the server automatically send and respond to pings to clients? - * - * Default is `true`. - */ - sendPings?: boolean; - - /** - * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. - * - * Default is `false`. - */ - perMessageDeflate?: - | boolean - | { - /** - * Sets the compression level. - */ - compress?: WebSocketCompressor | boolean; - /** - * Sets the decompression level. - */ - decompress?: WebSocketCompressor | boolean; - }; - } - - namespace RouterTypes { - type ExtractRouteParams = T extends `${string}:${infer Param}/${infer Rest}` - ? { [K in Param]: string } & ExtractRouteParams - : T extends `${string}:${infer Param}` - ? { [K in Param]: string } - : T extends `${string}*` - ? {} - : {}; - - type RouteHandler = (req: BunRequest, server: Server) => Response | Promise; - - type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; - - type RouteHandlerObject = { - [K in HTTPMethod]?: RouteHandler; - }; - - type RouteValue = Response | false | RouteHandler | RouteHandlerObject; - } - - interface BunRequest extends Request { - params: RouterTypes.ExtractRouteParams; - } - - interface GenericServeOptions { - /** - * What URI should be used to make {@link Request.url} absolute? - * - * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one - * - * @example - * ```js - * "http://my-app.com" - * ``` - * - * @example - * ```js - * "https://wongmjane.com/" - * ``` - * - * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. - * - * @example - * "http://localhost:3000" - */ - // baseURI?: string; - - /** - * What is the maximum size of a request body? (in bytes) - * @default 1024 * 1024 * 128 // 128MB - */ - maxRequestBodySize?: number; - - /** - * Render contextual errors? This enables bun's error page - * @default process.env.NODE_ENV !== 'production' - */ - development?: - | boolean - | { - /** - * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) - * - * @default true if process.env.NODE_ENV !== 'production' - * - */ - hmr?: boolean; - }; - - error?: (this: Server, error: ErrorLike) => Response | Promise | undefined | Promise; - - /** - * Uniquely identify a server instance with an ID - * - * ### When bun is started with the `--hot` flag - * - * This string will be used to hot reload the server without interrupting - * pending requests or websockets. If not provided, a value will be - * generated. To disable hot reloading, set this value to `null`. - * - * ### When bun is not started with the `--hot` flag - * - * This string will currently do nothing. But in the future it could be useful for logs or metrics. - */ - id?: string | null; - } - - interface ServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * Whether the `SO_REUSEPORT` flag should be set. - * - * This allows multiple processes to bind to the same port, which is useful for load balancing. - * - * @default false - */ - reusePort?: boolean; - - /** - * Whether the `IPV6_V6ONLY` flag should be set. - * @default false - */ - ipv6Only?: boolean; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix?: never; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to inactivity. - * - * Default is `10` seconds. - */ - idleTimeout?: number; - - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | Promise; - } - - interface UnixServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | Promise; - } - - interface WebSocketServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | void | Promise; - } - - interface UnixWebSocketServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | undefined | Promise; - } - - interface TLSWebSocketServeOptions - extends WebSocketServeOptions, - TLSOptionsAsDeprecated { - unix?: never; - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSWebSocketServeOptions - extends UnixWebSocketServeOptions, - TLSOptionsAsDeprecated { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - tls?: TLSOptions | TLSOptions[]; - } - - interface ErrorLike extends Error { - code?: string; - errno?: number; - syscall?: string; - } - - interface TLSOptions { - /** - * Passphrase for the TLS key - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: string | Buffer | BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: string | Buffer | BunFile | Array | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: string | Buffer | BunFile | Array | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - // Note for contributors: TLSOptionsAsDeprecated should be considered immutable - // and new TLS option keys should only be supported on the `.tls` property (which comes - // from the TLSOptions interface above). - /** - * This exists because Bun.serve() extends the TLSOptions object, but - * they're now considered deprecated. You should be passing the - * options on `.tls` instead. - * - * @example - * ```ts - * //// OLD //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * passphrase: "secret", - * }); - * - * //// NEW //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * tls: { - * passphrase: "secret", - * }, - * }); - * ``` - */ - interface TLSOptionsAsDeprecated { - /** - * Passphrase for the TLS key - * - * @deprecated Use `.tls.passphrase` instead - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - * - * @deprecated Use `.tls.dhParamsFile` instead - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - * - * @deprecated Use `.tls.serverName` instead - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - * - * @deprecated Use `.tls.lowMemoryMode` instead - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - * - * @deprecated Use `.tls.rejectUnauthorized` instead - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - * - * @deprecated Use `.tls.requestCert` instead - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - * - * @deprecated Use `.tls.ca` instead - */ - ca?: string | Buffer | BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - * - * @deprecated Use `.tls.cert` instead - */ - cert?: string | Buffer | BunFile | Array | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - * - * @deprecated Use `.tls.key` instead - */ - key?: string | Buffer | BunFile | Array | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - * - * @deprecated `Use .tls.secureOptions` instead - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSServeOptions extends UnixServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface SocketAddress { - /** - * The IP address of the client. - */ - address: string; - /** - * The port of the client. - */ - port: number; - /** - * The IP family ("IPv4" or "IPv6"). - */ - family: "IPv4" | "IPv6"; - } - - /** - * HTTP & HTTPS Server - * - * To start the server, see {@link serve} - * - * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. - * That means starting a new server allocates about 500 KB of memory. Try to - * avoid starting and stopping the server often (unless it's a new instance of bun). - * - * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. - */ - interface Server extends Disposable { - /** - * Stop listening to prevent new connections from being accepted. - * - * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. - * - * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. - * @default false - */ - stop(closeActiveConnections?: boolean): Promise; - - /** - * Update the `fetch` and `error` handlers without restarting the server. - * - * This is useful if you want to change the behavior of your server without - * restarting it or for hot reloading. - * - * @example - * - * ```js - * // create the server - * const server = Bun.serve({ - * fetch(request) { - * return new Response("Hello World v1") - * } - * }); - * - * // Update the server to return a different response - * server.reload({ - * fetch(request) { - * return new Response("Hello World v2") - * } - * }); - * ``` - * - * Passing other options such as `port` or `hostname` won't do anything. - */ - reload }>( - options: ( - | (Omit & { - routes: R; - fetch?: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | (Omit & { - routes?: never; - fetch: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. - */ - static?: R; - }, - ): Server; - - /** - * Mock the fetch handler for a running server. - * - * This feature is not fully implemented yet. It doesn't normalize URLs - * consistently in all cases and it doesn't yet call the `error` handler - * consistently. This needs to be fixed - */ - fetch(request: Request | string): Response | Promise; - - /** - * Upgrade a {@link Request} to a {@link ServerWebSocket} - * - * @param request The {@link Request} to upgrade - * @param options Pass headers or attach data to the {@link ServerWebSocket} - * - * @returns `true` if the upgrade was successful and `false` if it failed - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * What you pass to `data` is available on the {@link ServerWebSocket.data} property - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - upgrade( - request: Request, - options?: { - /** - * Send any additional headers while upgrading, like cookies - */ - headers?: Bun.HeadersInit; - /** - * This value is passed to the {@link ServerWebSocket.data} property - */ - data?: T; - }, - ): boolean; - - /** - * Send a message to all connected {@link ServerWebSocket} subscribed to a topic - * - * @param topic The topic to publish to - * @param data The data to send - * @param compress Should the data be compressed? Ignored if the client does not support compression. - * - * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. - * - * @example - * - * ```js - * server.publish("chat", "Hello World"); - * ``` - * - * @example - * ```js - * server.publish("chat", new Uint8Array([1, 2, 3, 4])); - * ``` - * - * @example - * ```js - * server.publish("chat", new ArrayBuffer(4), true); - * ``` - * - * @example - * ```js - * server.publish("chat", new DataView(new ArrayBuffer(4))); - * ``` - */ - publish( - topic: string, - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * A count of connections subscribed to a given topic - * - * This operation will loop through each topic internally to get the count. - * - * @param topic the websocket topic to check how many subscribers are connected to - * @returns the number of subscribers - */ - subscriberCount(topic: string): number; - - /** - * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * return new Response(server.requestIP(request)); - * } - * } - * ``` - */ - requestIP(request: Request): SocketAddress | null; - - /** - * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * server.timeout(request, 60); - * await Bun.sleep(30000); - * return new Response("30 seconds have passed"); - * } - * } - * ``` - */ - timeout(request: Request, seconds: number): void; - /** - * Undo a call to {@link Server.unref} - * - * If the Server has already been stopped, this does nothing. - * - * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. - */ - ref(): void; - - /** - * Don't keep the process alive if this server is the only thing left. - * Active connections may continue to keep the process alive. - * - * By default, the server is ref'd. - * - * To prevent new connections from being accepted, use {@link Server.stop} - */ - unref(): void; - - /** - * How many requests are in-flight right now? - */ - readonly pendingRequests: number; - - /** - * How many {@link ServerWebSocket}s are in-flight right now? - */ - readonly pendingWebSockets: number; - - readonly url: URL; - - readonly port: number; - /** - * The hostname the server is listening on. Does not include the port - * @example - * ```js - * "localhost" - * ``` - */ - readonly hostname: string; - /** - * Is the server running in development mode? - * - * In development mode, `Bun.serve()` returns rendered error messages with - * stack traces instead of a generic 500 error. This makes debugging easier, - * but development mode shouldn't be used in production or you will risk - * leaking sensitive information. - */ - readonly development: boolean; - - /** - * An identifier of the server instance - * - * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. - * - * When bun is not started with the `--hot` flag, this ID is currently unused. - */ - readonly id: string; - } - - type Serve = - | ServeOptions - | TLSServeOptions - | UnixServeOptions - | UnixTLSServeOptions - | WebSocketServeOptions - | TLSWebSocketServeOptions - | UnixWebSocketServeOptions - | UnixTLSWebSocketServeOptions; - - /** - Bun.serve provides a high-performance HTTP server with built-in routing support. - It enables both function-based and object-based route handlers with type-safe - parameters and method-specific handling. - - @example Basic Usage - ```ts - Bun.serve({ - port: 3000, - fetch(req) { - return new Response("Hello World"); - } - }); - ``` + @example Basic Usage + ```ts + Bun.serve({ + port: 3000, + fetch(req) { + return new Response("Hello World"); + } + }); + ``` @example Route-based Handlers ```ts @@ -4652,2781 +4844,2911 @@ declare module "bun" { @param options - Server configuration options @param options.routes - Route definitions mapping paths to handlers */ - function serve }>( - options: ( - | (DistributedOmit & { - routes: R; - fetch?: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | (DistributedOmit & { - routes?: never; - fetch: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for a while though. - */ - static?: R; - }, - ): Server; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - `type` is auto-set based on the file extension when possible - * - * @example - * ```js - * const file = Bun.file("./hello.json"); - * console.log(file.type); // "application/json" - * console.log(await file.json()); // { hello: "world" } - * ``` - * - * @example - * ```js - * await Bun.write( - * Bun.file("./hello.txt"), - * "Hello, world!" - * ); - * ``` - * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file(path: string | URL, options?: BlobPropertyBag): BunFile; - - /** - * A list of files embedded into the standalone executable. Lexigraphically sorted by name. - * - * If the process is not a standalone executable, this returns an empty array. - */ - const embeddedFiles: ReadonlyArray; - - /** - * `Blob` that leverages the fastest system calls available to operate on files. - * - * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. - * - * `Blob.size` will not be valid until the contents of the file are read at least once. - * `Blob.type` will have a default set based on the file extension - * - * @example - * ```js - * const file = Bun.file(new TextEncoder.encode("./hello.json")); - * console.log(file.type); // "application/json" - * ``` - * - * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - * @example - * ```js - * const file = Bun.file(fd); - * ``` - * - * @param fileDescriptor The file descriptor of the file - */ - // tslint:disable-next-line:unified-signatures - function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; - - /** - * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. - * - * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. - */ - function allocUnsafe(size: number): Uint8Array; - - interface BunInspectOptions { - colors?: boolean; - depth?: number; - sorted?: boolean; - compact?: boolean; - } - - /** - * Pretty-print an object the same as {@link console.log} to a `string` - * - * Supports JSX - * - * @param args - */ - function inspect(arg: any, options?: BunInspectOptions): string; - namespace inspect { - /** - * That can be used to declare custom inspect functions. - */ - const custom: typeof import("util").inspect.custom; - - /** - * Pretty-print an object or array as a table - * - * Like {@link console.table}, except it returns a string - */ - function table(tabularData: object | unknown[], properties?: string[], options?: { colors?: boolean }): string; - function table(tabularData: object | unknown[], options?: { colors?: boolean }): string; - } - - interface MMapOptions { - /** - * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. - */ - sync?: boolean; - /** - * Allow other processes to see results instantly? - * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. - * @default true - */ - shared?: boolean; - } - /** - * Open a file as a live-updating `Uint8Array` without copying memory - * - Writing to the array writes to the file. - * - Reading from the array reads from the file. - * - * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. - * - * --- - * - * This API inherently has some rough edges: - * - It does not support empty files. It will throw a `SystemError` with `EINVAL` - * - Usage on shared/networked filesystems is discouraged. It will be very slow. - * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. - * - * --- - * - * To close the file, set the array to `null` and it will be garbage collected eventually. - */ - function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; - - /** Write to stdout */ - const stdout: BunFile; - /** Write to stderr */ - const stderr: BunFile; - /** - * Read from stdin - * - * This is read-only - */ - const stdin: BunFile; - - type StringLike = string | { toString(): string }; - - type ColorInput = - | { r: number; g: number; b: number; a?: number } - | [number, number, number] - | [number, number, number, number] - | Uint8Array - | Uint8ClampedArray - | Float32Array - | Float64Array - | string - | number - | { toString(): string }; - - function color( - input: ColorInput, - outputFormat?: /** - * True color ANSI color string, for use in terminals - * @example \x1b[38;2;100;200;200m - */ - | "ansi" - | "ansi-16" - | "ansi-16m" - /** - * 256 color ANSI color string, for use in terminals which don't support true color - * - * Tries to match closest 24-bit color to 256 color palette - */ - | "ansi-256" - /** - * Picks the format that produces the shortest output - */ - | "css" - /** - * Lowercase hex color string without alpha - * @example #ff9800 - */ - | "hex" - /** - * Uppercase hex color string without alpha - * @example #FF9800 - */ - | "HEX" - /** - * @example hsl(35.764706, 1, 0.5) - */ - | "hsl" - /** - * @example lab(0.72732764, 33.938198, -25.311619) - */ - | "lab" - /** - * @example 16750592 - */ - | "number" - /** - * RGB color string without alpha - * @example rgb(255, 152, 0) - */ - | "rgb" - /** - * RGB color string with alpha - * @example rgba(255, 152, 0, 1) - */ - | "rgba", - ): string | null; - - function color( - input: ColorInput, - /** - * An array of numbers representing the RGB color - * @example [100, 200, 200] - */ - outputFormat: "[rgb]", - ): [number, number, number] | null; - function color( - input: ColorInput, - /** - * An array of numbers representing the RGBA color - * @example [100, 200, 200, 255] - */ - outputFormat: "[rgba]", - ): [number, number, number, number] | null; - function color( - input: ColorInput, - /** - * An object representing the RGB color - * @example { r: 100, g: 200, b: 200 } - */ - outputFormat: "{rgb}", - ): { r: number; g: number; b: number } | null; - function color( - input: ColorInput, - /** - * An object representing the RGBA color - * @example { r: 100, g: 200, b: 200, a: 0.5 } - */ - outputFormat: "{rgba}", - ): { r: number; g: number; b: number; a: number } | null; - function color(input: ColorInput, outputFormat: "number"): number | null; - - interface Semver { - /** - * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. - */ - satisfies(version: StringLike, range: StringLike): boolean; - - /** - * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. - * Throws an error if either version is invalid. - */ - order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; - } - var semver: Semver; - - interface Unsafe { - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. - * - * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; - - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` - * - * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - // tslint:disable-next-line:unified-signatures - arrayBufferToString(buffer: Uint16Array): string; - - /** Mock bun's segfault handler. You probably don't want to use this */ - segfault(): void; - - /** - * Force the garbage collector to run extremely often, - * especially inside `bun:test`. - * - * - `0`: default, disable - * - `1`: asynchronously call the garbage collector more often - * - `2`: synchronously call the garbage collector more often. - * - * This is a global setting. It's useful for debugging seemingly random crashes. - * - * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. - * - * @param level - * @returns The previous level - */ - gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; - } - const unsafe: Unsafe; - - type DigestEncoding = "utf8" | "ucs2" | "utf16le" | "latin1" | "ascii" | "base64" | "base64url" | "hex"; - - /** - * Are ANSI colors enabled for stdin and stdout? - * - * Used for {@link console.log} - */ - const enableANSIColors: boolean; - - /** - * What script launched bun? - * - * Absolute file path - * - * @example "/never-gonna-give-you-up.js" - */ - const main: string; - - /** - * Manually trigger the garbage collector - * - * This does two things: - * 1. It tells JavaScriptCore to run the garbage collector - * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. - * - * @param force Synchronously run the garbage collector - */ - function gc(force: boolean): void; - - /** - * JavaScriptCore engine's internal heap snapshot - * - * I don't know how to make this something Chrome or Safari can read. - * - * If you have any ideas, please file an issue https://github.com/oven-sh/bun - */ - interface HeapSnapshot { - /** 2 */ - version: number; - - /** "Inspector" */ - type: string; - - nodes: number[]; - - nodeClassNames: string[]; - edges: number[]; - edgeTypes: string[]; - edgeNames: string[]; - } - - /** - * Returns the number of nanoseconds since the process was started. - * - * This function uses a high-resolution monotonic system timer to provide precise time measurements. - * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), - * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). - * - * Due to this limitation, while the internal counter may continue beyond this point, - * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond - * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but - * with reduced precision, which might affect time calculations and comparisons in long-running applications. - * - * @returns {number} The number of nanoseconds since the process was started, with precise values up to - * Number.MAX_SAFE_INTEGER. - */ - function nanoseconds(): number; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector - */ - function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code - * - * This is a JSON string that can be saved to a file. - * ```ts - * const snapshot = Bun.generateHeapSnapshot("v8"); - * await Bun.write("heap.heapsnapshot", snapshot); - * ``` - */ - function generateHeapSnapshot(format: "v8"): string; - - /** - * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. - */ - function shrink(): void; - - /** - * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` - * - * @param path path to open - */ - function openInEditor(path: string, options?: EditorOptions): void; - - var fetch: typeof globalThis.fetch & { - preconnect(url: string): void; - }; - - interface EditorOptions { - editor?: "vscode" | "subl"; - line?: number; - column?: number; - } - - /** - * This class only exists in types - */ - abstract class CryptoHashInterface { - /** - * Update the hash with data - * - * @param data - */ - update(data: Bun.BlobOrStringOrBuffer): T; - - /** - * Finalize the hash - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash(input: Bun.BlobOrStringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash(input: Bun.BlobOrStringOrBuffer, encoding: DigestEncoding): string; - } - - type SupportedCryptoAlgorithms = - | "blake2b256" - | "blake2b512" - | "md4" - | "md5" - | "ripemd160" - | "sha1" - | "sha224" - | "sha256" - | "sha384" - | "sha512" - | "sha512-224" - | "sha512-256" - | "sha3-224" - | "sha3-256" - | "sha3-384" - | "sha3-512" - | "shake128" - | "shake256"; - - /** - * Hardware-accelerated cryptographic hash functions - * - * Used for `crypto.createHash()` - */ - class CryptoHasher { - /** - * The algorithm chosen to hash the data - */ - readonly algorithm: SupportedCryptoAlgorithms; - - /** - * The length of the output hash in bytes - */ - readonly byteLength: number; - - /** - * Create a new hasher - * - * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms - * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. - */ - constructor(algorithm: SupportedCryptoAlgorithms, hmacKey?: string | NodeJS.TypedArray); - - /** - * Update the hash with data - * - * @param input - */ - update(input: Bun.BlobOrStringOrBuffer, inputEncoding?: CryptoEncoding): CryptoHasher; - - /** - * Perform a deep copy of the hasher - */ - copy(): CryptoHasher; - - /** - * Finalize the hash. Resets the CryptoHasher so it can be reused. - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(): Buffer; - digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash(algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer): Buffer; - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - hashInto: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - - /** - * List of supported hash algorithms - * - * These are hardware accelerated with BoringSSL - */ - static readonly algorithms: SupportedCryptoAlgorithms[]; - } - - /** - * Resolve a `Promise` after milliseconds. This is like - * {@link setTimeout} except it returns a `Promise`. - * - * @param ms milliseconds to delay resolving the promise. This is a minimum - * number. It may take longer. If a {@link Date} is passed, it will sleep until the - * {@link Date} is reached. - * - * @example - * ## Sleep for 1 second - * ```ts - * import { sleep } from "bun"; - * - * await sleep(1000); - * ``` - * ## Sleep for 10 milliseconds - * ```ts - * await Bun.sleep(10); - * ``` - * ## Sleep until `Date` - * - * ```ts - * const target = new Date(); - * target.setSeconds(target.getSeconds() + 1); - * await Bun.sleep(target); - * ``` - * Internally, `Bun.sleep` is the equivalent of - * ```ts - * await new Promise((resolve) => setTimeout(resolve, ms)); - * ``` - * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. - */ - function sleep(ms: number | Date): Promise; - - /** - * Sleep the thread for a given number of milliseconds - * - * This is a blocking function. - * - * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) - */ - function sleepSync(ms: number): void; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param encoding `DigestEncoding` to return the hash in - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; - - /** - * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} - * - * Consider using the ugly-named {@link SHA512_256} instead - */ - class SHA1 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 20; - } - class MD5 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class MD4 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class SHA224 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 28; - } - class SHA512 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 64; - } - class SHA384 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 48; - } - class SHA256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - /** - * See also {@link sha} - */ - class SHA512_256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - - /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ - interface ZlibCompressionOptions { - /** - * The compression level to use. Must be between `-1` and `9`. - * - A value of `-1` uses the default compression level (Currently `6`) - * - A value of `0` gives no compression - * - A value of `1` gives least compression, fastest speed - * - A value of `9` gives best compression, slowest speed - */ - level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * How much memory should be allocated for the internal compression state. - * - * A value of `1` uses minimum memory but is slow and reduces compression ratio. - * - * A value of `9` uses maximum memory for optimal speed. The default is `8`. - */ - memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * The base 2 logarithm of the window size (the size of the history buffer). - * - * Larger values of this parameter result in better compression at the expense of memory usage. - * - * The following value ranges are supported: - * - `9..15`: The output will have a zlib header and footer (Deflate) - * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) - * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) - * - * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. - */ - windowBits?: - | -9 - | -10 - | -11 - | -12 - | -13 - | -14 - | -15 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 25 - | 26 - | 27 - | 28 - | 29 - | 30 - | 31; - /** - * Tunes the compression algorithm. - * - * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** - * - `Z_FILTERED`: For data produced by a filter or predictor - * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) - * - `Z_RLE`: Limit match distances to one (run-length encoding) - * - `Z_FIXED` prevents the use of dynamic Huffman codes - * - * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. - * - * `Z_FILTERED` forces more Huffman coding and less string matching, it is - * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. - * Filtered data consists mostly of small values with a somewhat random distribution. - */ - strategy?: number; - - library?: "zlib"; - } - - interface LibdeflateCompressionOptions { - level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; - library?: "libdeflate"; - } - - /** - * Compresses a chunk of data with `zlib` DEFLATE algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function deflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Compresses a chunk of data with `zlib` GZIP algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function gzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` INFLATE algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function inflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` GUNZIP algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function gunzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - - type Target = - /** - * For generating bundles that are intended to be run by the Bun runtime. In many cases, - * it isn't necessary to bundle server-side code; you can directly execute the source code - * without modification. However, bundling your server code can reduce startup times and - * improve running performance. - * - * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which - * indicates to the Bun runtime that there's no need to re-transpile the file before execution. - */ - | "bun" - /** - * The plugin will be applied to Node.js builds - */ - | "node" - /** - * The plugin will be applied to browser builds - */ - | "browser"; - - /** https://bun.sh/docs/bundler/loaders */ - type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "file" | "napi" | "wasm" | "text" | "css" | "html"; - - interface PluginConstraints { - /** - * Only apply the plugin when the import specifier matches this regular expression - * - * @example - * ```ts - * // Only apply the plugin when the import specifier matches the regex - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { - * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; - * }); - * } - * }) - * ``` - */ - filter: RegExp; - - /** - * Only apply the plugin when the import specifier has a namespace matching - * this string - * - * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` - * has the namespace `"bun"`. - * - * The default namespace is `"file"` and it can be omitted from import - * specifiers. - */ - namespace?: string; - } - - interface OnLoadResultSourceCode { - /** - * The source code of the module - */ - contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; - /** - * The loader to use for this file - * - * "css" will be added in a future version of Bun. - */ - loader?: Loader; - } - - interface OnLoadResultObject { - /** - * The object to use as the module - * @example - * ```ts - * // In your loader - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * - * // In your script - * import {foo} from "hello:world"; - * console.log(foo); // "bar" - * ``` - */ - exports: Record; - /** - * The loader to use for this file - */ - loader: "object"; - } - - interface OnLoadArgs { - /** - * The resolved import specifier of the module being loaded - * @example - * ```ts - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * console.log(args.path); // "hello:world" - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * ``` - */ - path: string; - /** - * The namespace of the module being loaded - */ - namespace: string; - /** - * The default loader for this file extension - */ - loader: Loader; - /** - * Defer the execution of this callback until all other modules have been parsed. - * - * @returns Promise which will be resolved when all modules have been parsed - */ - defer: () => Promise; - } - - type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject | undefined | void; - type OnLoadCallback = (args: OnLoadArgs) => OnLoadResult | Promise; - type OnStartCallback = () => void | Promise; - - interface OnResolveArgs { - /** - * The import specifier of the module being loaded - */ - path: string; - /** - * The module that imported the module being resolved - */ - importer: string; - /** - * The namespace of the importer. - */ - namespace: string; - /** - * The directory to perform file-based resolutions in. - */ - resolveDir: string; - /** - * The kind of import this resolve is for. - */ - kind: ImportKind; - // resolveDir: string; - // pluginData: any; - } - - interface OnResolveResult { - /** - * The destination of the import - */ - path: string; - /** - * The namespace of the destination - * It will be concatenated with `path` to form the final import specifier - * @example - * ```ts - * "foo" // "foo:bar" - * ``` - */ - namespace?: string; - external?: boolean; - } - - type OnResolveCallback = ( - args: OnResolveArgs, - ) => OnResolveResult | Promise | undefined | null; - - type FFIFunctionCallable = Function & { - // Making a nominally typed function so that the user must get it from dlopen - readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - - interface PluginBuilder { - /** - * Register a callback which will be invoked when bundling starts. When - * using hot module reloading, this is called at the start of each - * incremental rebuild. - * - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onStart(() => { - * console.log("bundle just started!!") - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onStart(callback: OnStartCallback): this; - onBeforeParse( - constraints: PluginConstraints, - callback: { - napiModule: unknown; - symbol: string; - external?: unknown | undefined; - }, - ): this; - /** - * Register a callback to load imports with a specific import specifier - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; - /** - * Register a callback to resolve imports matching a filter and/or namespace - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onResolve({ filter: /^wat$/ }, (args) => { - * return { path: "/tmp/woah.js" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onResolve(constraints: PluginConstraints, callback: OnResolveCallback): this; - /** - * The config object passed to `Bun.build` as is. Can be mutated. - */ - config: BuildConfig & { plugins: BunPlugin[] }; - - /** - * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules - * - * @param specifier The module specifier to register the callback for - * @param callback The function to run when the module is imported or required - * - * ### Example - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.module("hello:world", () => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * - * // sometime later - * const { foo } = await import("hello:world"); - * console.log(foo); // "bar" - * - * // or - * const { foo } = require("hello:world"); - * console.log(foo); // "bar" - * ``` - * - * @returns `this` for method chaining - */ - module(specifier: string, callback: () => OnLoadResult | Promise): this; - } - - interface BunPlugin { - /** - * Human-readable name of the plugin - * - * In a future version of Bun, this will be used in error messages. - */ - name: string; - - /** - * The target JavaScript environment the plugin should be applied to. - * - `bun`: The default environment when using `bun run` or `bun` to load a script - * - `browser`: The plugin will be applied to browser builds - * - `node`: The plugin will be applied to Node.js builds - * - * If unspecified, it is assumed that the plugin is compatible with all targets. - * - * This field is not read by {@link Bun.plugin} - */ - target?: Target; - /** - * A function that will be called when the plugin is loaded. - * - * This function may be called in the same tick that it is registered, or it - * may be called later. It could potentially be called multiple times for - * different targets. - */ - setup( - /** - * A builder object that can be used to register plugin hooks - * @example - * ```ts - * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), - * })); - * ``` - */ - build: PluginBuilder, - ): void | Promise; - } - - /** - * Extend Bun's module resolution and loading behavior - * - * Plugins are applied in the order they are defined. - * - * Today, there are two kinds of hooks: - * - `onLoad` lets you return source code or an object that will become the module's exports - * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. - * - * Plugin hooks must define a `filter` RegExp and will only be matched if the - * import specifier contains a "." or a ":". - * - * ES Module resolution semantics mean that plugins may be initialized _after_ - * a module is resolved. You might need to load plugins at the very beginning - * of the application and then use a dynamic import to load the rest of the - * application. A future version of Bun may also support specifying plugins - * via `bunfig.toml`. - * - * @example - * A YAML loader plugin - * - * ```js - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) - * })); - * }); - * - * // You can use require() - * const {foo} = require("./file.yaml"); - * - * // Or import - * await import("./file.yaml"); - * - * ``` - */ - interface BunRegisterPlugin { - (options: T): ReturnType; - - /** - * Deactivate all plugins - * - * This prevents registered plugins from being applied to future builds. - */ - clearAll(): void; - } - - const plugin: BunRegisterPlugin; - - /** - * Is the current global scope the main thread? - */ - const isMainThread: boolean; - - /** - * Used when importing an HTML file at runtime. - * - * @example - * - * ```ts - * import app from "./index.html"; - * ``` - * - * Bun.build support for this isn't imlpemented yet. - */ - interface HTMLBundle { - index: string; - } - - interface Socket extends Disposable { - /** - * Write `data` to the socket - * - * @param data The data to write to the socket - * @param byteOffset The offset in the buffer to start writing from (defaults to 0) - * @param byteLength The number of bytes to write (defaults to the length of the buffer) - * - * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. - * - * This is unbuffered as of Bun v0.2.2. That means individual write() calls - * will be slow. In the future, Bun will buffer writes and flush them at the - * end of the tick, when the event loop is idle, or sooner if the buffer is full. - */ - write(data: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; - - /** - * The data context for the socket. - */ - data: Data; - - /** - * Like {@link Socket.write} except it includes a TCP FIN packet - * - * Use it to send your last message and close the connection. - */ - end(data?: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; - - /** - * Close the socket immediately - */ - end(): void; - - /** - * Keep Bun's process alive at least until this socket is closed - * - * After the socket has closed, the socket is unref'd, the process may exit, - * and this becomes a no-op - */ - ref(): void; - - /** - * Set a timeout until the socket automatically closes. - * - * To reset the timeout, call this function again. - * - * When a timeout happens, the `timeout` callback is called and the socket is closed. - */ - timeout(seconds: number): void; - - /** - * Forcefully close the socket. The other end may not receive all data, and - * the socket will be closed immediately. - * - * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to - * `0` and then calls `close(2)`. - */ - terminate(): void; - - /** - * Shutdown writes to a socket - * - * This makes the socket a half-closed socket. It can still receive data. - * - * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally - */ - shutdown(halfClose?: boolean): void; - - readonly readyState: "open" | "closing" | "closed"; - - /** - * Allow Bun's process to exit even if this socket is still open - * - * After the socket has closed, this function does nothing. - */ - unref(): void; - - /** - * Flush any buffered data to the socket - */ - flush(): void; - - /** - * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. - * - * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. - */ - reload(handler: SocketHandler): void; - - /** - * Get the server that created this socket - * - * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. - */ - readonly listener?: SocketListener; - - /** - * Remote IP address connected to the socket - */ - readonly remoteAddress: string; - - /** - * local port connected to the socket - */ - readonly localPort: number; - - /** - * This property is `true` if the peer certificate was signed by one of the CAs - * specified when creating the `Socket` instance, otherwise `false`. - */ - readonly authorized: boolean; - - /** - * String containing the selected ALPN protocol. - * Before a handshake has completed, this value is always null. - * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. - */ - readonly alpnProtocol: string | false | null; - - /** - * Disables TLS renegotiation for this `Socket` instance. Once called, attempts - * to renegotiate will trigger an `error` handler on the `Socket`. - * - * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) - */ - disableRenegotiation(): void; - - /** - * Keying material is used for validations to prevent different kind of attacks in - * network protocols, for example in the specifications of IEEE 802.1X. - * - * Example - * - * ```js - * const keyingMaterial = socket.exportKeyingMaterial( - * 128, - * 'client finished'); - * - * /* - * Example return value of keyingMaterial: - * - * - * ``` - * - * @param length number of bytes to retrieve from keying material - * @param label an application specific label, typically this will be a value from the [IANA Exporter Label - * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). - * @param context Optionally provide a context. - * @return requested bytes of the keying material - */ - exportKeyingMaterial(length: number, label: string, context: Buffer): Buffer; - - /** - * Returns the reason why the peer's certificate was not been verified. This - * property is set only when `socket.authorized === false`. - */ - getAuthorizationError(): Error | null; - - /** - * Returns an object representing the local certificate. The returned object has - * some properties corresponding to the fields of the certificate. - * - * If there is no local certificate, an empty object will be returned. If the - * socket has been destroyed, `null` will be returned. - */ - getCertificate(): PeerCertificate | object | null; - getX509Certificate(): X509Certificate | undefined; - - /** - * Returns an object containing information on the negotiated cipher suite. - * - * For example, a TLSv1.2 protocol with AES256-SHA cipher: - * - * ```json - * { - * "name": "AES256-SHA", - * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", - * "version": "SSLv3" - * } - * ``` - * - */ - getCipher(): CipherNameAndProtocol; - - /** - * Returns an object representing the type, name, and size of parameter of - * an ephemeral key exchange in `perfect forward secrecy` on a client - * connection. It returns an empty object when the key exchange is not - * ephemeral. As this is only supported on a client socket; `null` is returned - * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. - * - * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. - */ - getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; - - /** - * Returns an object representing the peer's certificate. If the peer does not - * provide a certificate, an empty object will be returned. If the socket has been - * destroyed, `null` will be returned. - * - * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's - * certificate. - * @return A certificate object. - */ - getPeerCertificate(): PeerCertificate; - getPeerX509Certificate(): X509Certificate; - - /** - * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. - * @since v12.11.0 - * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. - */ - getSharedSigalgs(): string[]; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. - */ - getTLSFinishedMessage(): Buffer | undefined; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so - * far. - */ - getTLSPeerFinishedMessage(): Buffer | undefined; - - /** - * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. - * - * It may be useful for debugging. - * - * See `Session Resumption` for more information. - */ - getTLSTicket(): Buffer | undefined; - - /** - * Returns a string containing the negotiated SSL/TLS protocol version of the - * current connection. The value `'unknown'` will be returned for connected - * sockets that have not completed the handshaking process. The value `null` will - * be returned for server sockets or disconnected client sockets. - * - * Protocol versions are: - * - * * `'SSLv3'` - * * `'TLSv1'` - * * `'TLSv1.1'` - * * `'TLSv1.2'` - * * `'TLSv1.3'` - * - */ - getTLSVersion(): string; - - /** - * See `Session Resumption` for more information. - * @return `true` if the session was reused, `false` otherwise. - */ - isSessionReused(): boolean; - - /** - * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. - * Returns `true` if setting the limit succeeded; `false` otherwise. - * - * Smaller fragment sizes decrease the buffering latency on the client: larger - * fragments are buffered by the TLS layer until the entire fragment is received - * and its integrity is verified; large fragments can span multiple roundtrips - * and their processing can be delayed due to packet loss or reordering. However, - * smaller fragments add extra TLS framing bytes and CPU overhead, which may - * decrease overall server throughput. - * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. - */ - setMaxSendFragment(size: number): boolean; - - /** - * Enable/disable the use of Nagle's algorithm. - * Only available for already connected sockets, will return false otherwise - * @param noDelay Default: `true` - * @returns true if is able to setNoDelay and false if it fails. - */ - setNoDelay(noDelay?: boolean): boolean; - - /** - * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. - * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. - * Only available for already connected sockets, will return false otherwise. - * - * Enabling the keep-alive functionality will set the following socket options: - * SO_KEEPALIVE=1 - * TCP_KEEPIDLE=initialDelay - * TCP_KEEPCNT=10 - * TCP_KEEPINTVL=1 - * @param enable Default: `false` - * @param initialDelay Default: `0` - * @returns true if is able to setNoDelay and false if it fails. - */ - setKeepAlive(enable?: boolean, initialDelay?: number): boolean; - - /** - * The number of bytes written to the socket. - */ - readonly bytesWritten: number; - } - - interface SocketListener extends Disposable { - stop(closeActiveConnections?: boolean): void; - ref(): void; - unref(): void; - reload(options: Pick, "socket">): void; - data: Data; - } - interface TCPSocketListener extends SocketListener { - readonly port: number; - readonly hostname: string; - } - interface UnixSocketListener extends SocketListener { - readonly unix: string; - } - - interface TCPSocket extends Socket {} - interface TLSSocket extends Socket {} - - interface BinaryTypeList { - arraybuffer: ArrayBuffer; - buffer: Buffer; - uint8array: Uint8Array; - // TODO: DataView - // dataview: DataView; - } - type BinaryType = keyof BinaryTypeList; - - interface SocketHandler { - /** - * Is called when the socket connects, or in case of TLS if no handshake is provided - * this will be called only after handshake - * @param socket - */ - open?(socket: Socket): void | Promise; - close?(socket: Socket): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - data?(socket: Socket, data: BinaryTypeList[DataBinaryType]): void | Promise; - drain?(socket: Socket): void | Promise; - - /** - * When handshake is completed, this functions is called. - * @param socket - * @param success Indicates if the server authorized despite the authorizationError. - * @param authorizationError Certificate Authorization Error or null. - */ - handshake?(socket: Socket, success: boolean, authorizationError: Error | null): void; - - /** - * When the socket has been shutdown from the other end, this function is - * called. This is a TCP FIN packet. - */ - end?(socket: Socket): void | Promise; - - /** - * When the socket fails to be created, this function is called. - * - * The promise returned by `Bun.connect` rejects **after** this function is - * called. - * - * When `connectError` is specified, the rejected promise will not be - * added to the promise rejection queue (so it won't be reported as an - * unhandled promise rejection, since connectError handles it). - * - * When `connectError` is not specified, the rejected promise will be added - * to the promise rejection queue. - */ - connectError?(socket: Socket, error: Error): void | Promise; - - /** - * Called when a message times out. - */ - timeout?(socket: Socket): void | Promise; - /** - * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. - * - * @default "buffer" - * - * @remarks - * This lets you select the desired binary type for the `data` callback. - * It's a small performance optimization to let you avoid creating extra - * ArrayBufferView objects when possible. - * - * Bun originally defaulted to `Uint8Array` but when dealing with network - * data, it's more useful to be able to directly read from the bytes which - * `Buffer` allows. - */ - binaryType?: BinaryType; - } - - interface SocketOptions { - socket: SocketHandler; - data?: Data; - } - // interface TCPSocketOptions extends SocketOptions { - // hostname: string; - // port: number; - // } - - interface TCPSocketListenOptions extends SocketOptions { - hostname: string; - port: number; - tls?: TLSOptions; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface TCPSocketConnectOptions extends SocketOptions { - hostname: string; - port: number; - tls?: boolean; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface UnixSocketOptions extends SocketOptions { - tls?: TLSOptions; - unix: string; - } - - interface FdSocketOptions extends SocketOptions { - tls?: TLSOptions; - fd: number; - } - - /** - * Create a TCP client that connects to a server - * - * @param options The options to use when creating the client - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function connect(options: TCPSocketConnectOptions): Promise>; - function connect(options: UnixSocketOptions): Promise>; - - /** - * Create a TCP server that listens on a port - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function listen(options: TCPSocketListenOptions): TCPSocketListener; - function listen(options: UnixSocketOptions): UnixSocketListener; - - namespace udp { - type Data = string | ArrayBufferView | ArrayBufferLike; - - export interface SocketHandler { - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: Socket): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - } - - export interface ConnectedSocketHandler { - data?( - socket: ConnectedSocket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: ConnectedSocket): void | Promise; - error?(socket: ConnectedSocket, error: Error): void | Promise; - } - - export interface SocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: SocketHandler; - } - - export interface ConnectSocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: ConnectedSocketHandler; - connect: { - hostname: string; - port: number; - }; - } - - export interface BaseUDPSocket { - readonly hostname: string; - readonly port: number; - readonly address: SocketAddress; - readonly binaryType: BinaryType; - readonly closed: boolean; - ref(): void; - unref(): void; - close(): void; - } - - export interface ConnectedSocket extends BaseUDPSocket { - readonly remoteAddress: SocketAddress; - sendMany(packets: readonly Data[]): number; - send(data: Data): boolean; - reload(handler: ConnectedSocketHandler): void; - } - - export interface Socket extends BaseUDPSocket { - sendMany(packets: readonly (Data | string | number)[]): number; - send(data: Data, port: number, address: string): boolean; - reload(handler: SocketHandler): void; - } - } - - /** - * Create a UDP socket - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.hostname The hostname to listen on - * @param options.port The port to listen on - * @param options.binaryType The binary type to use for the socket - * @param options.connect The hostname and port to connect to - */ - export function udpSocket( - options: udp.SocketOptions, - ): Promise>; - export function udpSocket( - options: udp.ConnectSocketOptions, - ): Promise>; - - namespace SpawnOptions { - /** - * Option for stdout/stderr - */ - type Readable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number; - - /** - * Option for stdin - */ - type Writable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number - | ReadableStream - | Blob - | Response - | Request; - - interface OptionsObject< - In extends Writable = Writable, - Out extends Readable = Readable, - Err extends Readable = Readable, - > { - /** - * The current working directory of the process - * - * Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * The environment variables of the process - * - * Defaults to `process.env` as it was when the current Bun process launched. - * - * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. - */ - env?: Record; - - /** - * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. - * This overrides the `stdin`, `stdout`, and `stderr` properties. - * - * For stdin you may pass: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. - * - `number`: The process will read from the file descriptor - * - * For stdout and stdin you may pass: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default ["ignore", "pipe", "inherit"] for `spawn` - * ["ignore", "pipe", "pipe"] for `spawnSync` - */ - stdio?: [In, Out, Err]; - /** - * The file descriptor for the standard input. It may be: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`: The process will read from the buffer - * - `number`: The process will read from the file descriptor - * - * @default "ignore" - */ - stdin?: In; - /** - * The file descriptor for the standard output. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "pipe" - */ - stdout?: Out; - /** - * The file descriptor for the standard error. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "inherit" for `spawn` - * "pipe" for `spawnSync` - */ - stderr?: Err; - - /** - * Callback that runs when the {@link Subprocess} exits - * - * This is called even if the process exits with a non-zero exit code. - * - * Warning: this may run before the `Bun.spawn` function returns. - * - * A simple alternative is `await subprocess.exited`. - * - * @example - * - * ```ts - * const subprocess = spawn({ - * cmd: ["echo", "hello"], - * onExit: (subprocess, code) => { - * console.log(`Process exited with code ${code}`); - * }, - * }); - * ``` - */ - onExit?( - subprocess: Subprocess, - exitCode: number | null, - signalCode: number | null, - /** - * If an error occurred in the call to waitpid2, this will be the error. - */ - error?: ErrorLike, - ): void | Promise; - - /** - * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for - * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized - * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - * - * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, - * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. - * - * Currently, this is only compatible with processes that are other `bun` instances. - */ - ipc?( - message: any, - /** - * The {@link Subprocess} that sent the message - */ - subprocess: Subprocess, - ): void; - - /** - * The serialization format to use for IPC messages. Defaults to `"advanced"`. - * - * To communicate with Node.js processes, use `"json"`. - * - * When `ipc` is not specified, this is ignored. - */ - serialization?: "json" | "advanced"; - - /** - * If true, the subprocess will have a hidden window. - */ - windowsHide?: boolean; - - /** - * If true, no quoting or escaping of arguments is done on Windows. - */ - windowsVerbatimArguments?: boolean; - - /** - * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. - * - * One use-case for this is for applications which wrap other applications or to simulate a symlink. - * - * @default cmds[0] - */ - argv0?: string; - - /** - * An {@link AbortSignal} that can be used to abort the subprocess. - * - * This is useful for aborting a subprocess when some other part of the - * program is aborted, such as a `fetch` response. - * - * Internally, this works by calling `subprocess.kill(1)`. - * - * @example - * ```ts - * const controller = new AbortController(); - * const { signal } = controller; - * const start = performance.now(); - * const subprocess = Bun.spawn({ - * cmd: ["sleep", "100"], - * signal, - * }); - * await Bun.sleep(1); - * controller.abort(); - * await subprocess.exited; - * const end = performance.now(); - * console.log(end - start); // 1ms instead of 101ms - * ``` - */ - signal?: AbortSignal; - } - - type OptionsToSubprocess = - Opts extends OptionsObject - ? Subprocess< - // "Writable extends In" means "if In === Writable", - // aka if true that means the user didn't specify anything - Writable extends In ? "ignore" : In, - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "inherit" : Err - > - : Subprocess; - - type OptionsToSyncSubprocess = - Opts extends OptionsObject - ? SyncSubprocess - : SyncSubprocess; - - type ReadableIO = ReadableStream | number | undefined; - - type ReadableToIO = X extends "pipe" | undefined - ? ReadableStream - : X extends BunFile | ArrayBufferView | number - ? number - : undefined; - - type ReadableToSyncIO = X extends "pipe" | undefined ? Buffer : undefined; - - type WritableIO = FileSink | number | undefined; - - type WritableToIO = X extends "pipe" - ? FileSink - : X extends BunFile | ArrayBufferView | Blob | Request | Response | number - ? number - : undefined; - } - - interface ResourceUsage { - /** - * The number of voluntary and involuntary context switches that the process made. - */ - contextSwitches: { - /** - * Voluntary context switches (context switches that the process initiated). - */ - voluntary: number; - /** - * Involuntary context switches (context switches initiated by the system scheduler). - */ - involuntary: number; - }; - - /** - * The amount of CPU time used by the process, in microseconds. - */ - cpuTime: { - /** - * User CPU time used by the process, in microseconds. - */ - user: number; - /** - * System CPU time used by the process, in microseconds. - */ - system: number; - /** - * Total CPU time used by the process, in microseconds. - */ - total: number; - }; - /** - * The maximum amount of resident set size (in bytes) used by the process during its lifetime. - */ - maxRSS: number; - - /** - * IPC messages sent and received by the process. - */ - messages: { - /** - * The number of IPC messages sent. - */ - sent: number; - /** - * The number of IPC messages received. - */ - received: number; - }; - /** - * The number of IO operations done by the process. - */ - ops: { - /** - * The number of input operations via the file system. - */ - in: number; - /** - * The number of output operations via the file system. - */ - out: number; - }; - /** - * The amount of shared memory that the process used. - */ - shmSize: number; - /** - * The number of signals delivered to the process. - */ - signalCount: number; - /** - * The number of times the process was swapped out of main memory. - */ - swapCount: number; - } - - /** - * A process created by {@link Bun.spawn}. - * - * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSubprocess} (any, pipe, pipe) - * - {@link WritableSubprocess} (pipe, any, any) - * - {@link PipedSubprocess} (pipe, pipe, pipe) - * - {@link NullSubprocess} (ignore, ignore, ignore) - */ - interface Subprocess< - In extends SpawnOptions.Writable = SpawnOptions.Writable, - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > extends AsyncDisposable { - readonly stdin: SpawnOptions.WritableToIO; - readonly stdout: SpawnOptions.ReadableToIO; - readonly stderr: SpawnOptions.ReadableToIO; - - /** - * This returns the same value as {@link Subprocess.stdout} - * - * It exists for compatibility with {@link ReadableStream.pipeThrough} - */ - readonly readable: SpawnOptions.ReadableToIO; - - /** - * The process ID of the child process - * @example - * ```ts - * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); - * console.log(pid); // 1234 - * ``` - */ - readonly pid: number; - /** - * The exit code of the process - * - * The promise will resolve when the process exits - */ - readonly exited: Promise; - - /** - * Synchronously get the exit code of the process - * - * If the process hasn't exited yet, this will return `null` - */ - readonly exitCode: number | null; - - /** - * Synchronously get the signal code of the process - * - * If the process never sent a signal code, this will return `null` - * - * To receive signal code changes, use the `onExit` callback. - * - * If the signal code is unknown, it will return the original signal code - * number, but that case should essentially never happen. - */ - readonly signalCode: NodeJS.Signals | null; - - /** - * Has the process exited? - */ - readonly killed: boolean; - - /** - * Kill the process - * @param exitCode The exitCode to send to the process - */ - kill(exitCode?: number | NodeJS.Signals): void; - - /** - * This method will tell Bun to wait for this process to exit after you already - * called `unref()`. - * - * Before shutting down, Bun will wait for all subprocesses to exit by default - */ - ref(): void; - - /** - * Before shutting down, Bun will wait for all subprocesses to exit by default - * - * This method will tell Bun to not wait for this process to exit before shutting down. - */ - unref(): void; - - /** - * Send a message to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option, and is another instance of `bun`. - * - * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - */ - send(message: any): void; - - /** - * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option. - */ - disconnect(): void; - - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - * - * Only available after the process has exited - * - * If the process hasn't exited yet, this will return `undefined` - */ - resourceUsage(): ResourceUsage | undefined; - } - - /** - * A process created by {@link Bun.spawnSync}. - * - * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSyncSubprocess} (pipe, pipe) - * - {@link NullSyncSubprocess} (ignore, ignore) - */ - interface SyncSubprocess< - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > { - stdout: SpawnOptions.ReadableToSyncIO; - stderr: SpawnOptions.ReadableToSyncIO; - exitCode: number; - success: boolean; - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - */ - resourceUsage: ResourceUsage; - - signalCode?: string; - } - - /** - * Spawn a new process - * - * ```js - * const subprocess = Bun.spawn({ - * cmd: ["echo", "hello"], - * stdout: "pipe", - * }); - * const text = await readableStreamToText(subprocess.stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmd: string[]; // to support dynamically constructed commands - }, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawn(["echo", "hello"]); - * const text = await readableStreamToText(stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync({ - * cmd: ["echo", "hello"], - * }); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); - * ``` - */ - cmd: string[]; - - onExit?: never; - }, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** - * Synchronously spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync(["echo", "hello"]); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ - type ReadableSubprocess = Subprocess; - /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ - type WritableSubprocess = Subprocess<"pipe", any, any>; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ - type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ - type NullSubprocess = Subprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ - type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ - type NullSyncSubprocess = SyncSubprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - - // Blocked on https://github.com/oven-sh/bun/issues/8329 - // /** - // * - // * Count the visible width of a string, as it would be displayed in a terminal. - // * - // * By default, strips ANSI escape codes before measuring the string. This is - // * because ANSI escape codes are not visible characters. If passed a non-string, - // * it will return 0. - // * - // * @param str The string to measure - // * @param options - // */ - // function stringWidth( - // str: string, - // options?: { - // /** - // * Whether to include ANSI escape codes in the width calculation - // * - // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. - // * @default false - // */ - // countAnsiEscapeCodes?: boolean; - // }, - // ): number; - - class FileSystemRouter { - /** - * Create a new {@link FileSystemRouter}. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: process.cwd() + "/pages", - * style: "nextjs", - * }); - * - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} - * ``` - * @param options The options to use when creating the router - * @param options.dir The root directory containing the files to route - * @param options.style The style of router to use (only "nextjs" supported - * for now) - */ - constructor(options: { - /** - * The root directory containing the files to route - * - * There is no default value for this option. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: - */ - dir: string; - style: "nextjs"; - - /** The base path to use when routing */ - assetPrefix?: string; - origin?: string; - /** Limit the pages to those with particular file extensions. */ - fileExtensions?: string[]; - }); - - // todo: URL - match(input: string | Request | Response): MatchedRoute | null; - - readonly assetPrefix: string; - readonly origin: string; - readonly style: string; - readonly routes: Record; - - reload(): void; - } - - interface MatchedRoute { - /** - * A map of the parameters from the route - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: "/path/to/files", - * style: "nextjs", - * }); - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params.year); // "2020" - * console.log(params.month); // "01" - * console.log(params.day); // "01" - * console.log(params.slug); // "hello-world" - * ``` - */ - readonly params: Record; - readonly filePath: string; - readonly pathname: string; - readonly query: Record; - readonly name: string; - readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; - readonly src: string; - } - - /** - * The current version of Bun - * @example - * "0.2.0" - */ - const version: string; - - /** - * The current version of Bun with the shortened commit sha of the build - * @example "v1.1.30 (d09df1af)" - */ - const version_with_sha: string; - - /** - * The git sha at the time the currently-running version of Bun was compiled - * @example - * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" - */ - const revision: string; - - /** - * Find the index of a newline character in potentially ill-formed UTF-8 text. - * - * This is sort of like readline() except without the IO. - */ - function indexOfLine(buffer: ArrayBufferView | ArrayBufferLike, offset?: number): number; - - interface GlobScanOptions { - /** - * The root directory to start matching from. Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * Allow patterns to match entries that begin with a period (`.`). - * - * @default false - */ - dot?: boolean; - - /** - * Return the absolute path for entries. - * - * @default false - */ - absolute?: boolean; - - /** - * Indicates whether to traverse descendants of symbolic link directories. - * - * @default false - */ - followSymlinks?: boolean; - - /** - * Throw an error when symbolic link is broken - * - * @default false - */ - throwErrorOnBrokenSymlink?: boolean; - - /** - * Return only files. - * - * @default true - */ - onlyFiles?: boolean; - } - - /** - * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). - * - * The supported pattern syntax for is: - * - * - `?` - * Matches any single character. - * - `*` - * Matches zero or more characters, except for path separators ('/' or '\'). - * - `**` - * Matches zero or more characters, including path separators. - * Must match a complete path segment, i.e. followed by a path separator or - * at the end of the pattern. - * - `[ab]` - * Matches one of the characters contained in the brackets. - * Character ranges (e.g. "[a-z]") are also supported. - * Use "[!ab]" or "[^ab]" to match any character *except* those contained - * in the brackets. - * - `{a,b}` - * Match one of the patterns contained in the braces. - * Any of the wildcards listed above can be used in the sub patterns. - * Braces may be nested up to 10 levels deep. - * - `!` - * Negates the result when at the start of the pattern. - * Multiple "!" characters negate the pattern multiple times. - * - `\` - * Used to escape any of the special characters above. - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - */ - export class Glob { - constructor(pattern: string); - - /** - * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for await (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scan(optionsOrCwd?: string | GlobScanOptions): AsyncIterableIterator; - - /** - * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; - - /** - * Match the glob against a string - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * expect(glob.match('foo.ts')).toBeTrue(); - * ``` - */ - match(str: string): boolean; - } - - /** - * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. - * - * When the same timestamp is used multiple times, a monotonically increasing - * counter is appended to allow sorting. The final 8 bytes are - * cryptographically random. When the timestamp changes, the counter resets to - * a psuedo-random integer. - * - * @param encoding "hex" | "base64" | "base64url" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - * - * @example - * ```js - * import { randomUUIDv7 } from "bun"; - * const array = [ - * randomUUIDv7(), - * randomUUIDv7(), - * randomUUIDv7(), - * ] - * [ - * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", - * "0192ce07-8c4f-7d67-805f-0f71581b5622", - * "0192ce07-8c4f-7d68-8170-6816e4451a58" - * ] - * ``` - */ - function randomUUIDv7( - /** - * @default "hex" - */ - encoding?: "hex" | "base64" | "base64url", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): string; - - /** - * Generate a UUIDv7 as a Buffer - * - * @param encoding "buffer" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - */ - function randomUUIDv7( - encoding: "buffer", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): Buffer; - - /** - * Types for `bun.lock` - */ - type BunLockFile = { - lockfileVersion: 0 | 1; - workspaces: { - [workspace: string]: BunLockFileWorkspacePackage; - }; - overrides?: Record; - patchedDependencies?: Record; - trustedDependencies?: string[]; - - /** - * ``` - * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } - * - * // first index is resolution for each type of package - * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] - * symlink -> [ "name@link:path", INFO ] - * folder -> [ "name@file:path", INFO ] - * workspace -> [ "name@workspace:path" ] // workspace is only path - * tarball -> [ "name@tarball", INFO ] - * root -> [ "name@root:", { bin, binDir } ] - * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] - * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] - * ``` - * */ - packages: { - [pkg: string]: BunLockFilePackageArray; - }; - }; - - type BunLockFileBasePackageInfo = { - dependencies?: Record; - devDependencies?: Record; - optionalDependencies?: Record; - peerDependencies?: Record; - optionalPeers?: string[]; - bin?: string | Record; - binDir?: string; - }; - - type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { - name?: string; - version?: string; - }; - - type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { - os?: string | string[]; - cpu?: string | string[]; - bundled?: true; - }; - - /** @see {@link BunLockFile.packages} for more info */ - type BunLockFilePackageArray = - /** npm */ - | [pkg: string, registry: string, info: BunLockFilePackageInfo, integrity: string] - /** symlink, folder, tarball */ - | [pkg: string, info: BunLockFilePackageInfo] - /** workspace */ - | [pkg: string] - /** git, github */ - | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] - /** root */ - | [pkg: string, info: Pick]; + function serve< + T, + R extends { [K in keyof R]: RouterTypes.RouteValue }, + >( + options: ( + | (DistributedOmit & { + routes: R; + fetch?: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | (DistributedOmit & { + routes?: never; + fetch: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for a while though. + */ + static?: R; + }, + ): Server; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * - `type` is auto-set based on the file extension when possible + * + * @example + * ```js + * const file = Bun.file("./hello.json"); + * console.log(file.type); // "application/json" + * console.log(await file.json()); // { hello: "world" } + * ``` + * + * @example + * ```js + * await Bun.write( + * Bun.file("./hello.txt"), + * "Hello, world!" + * ); + * ``` + * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: string | URL, options?: BlobPropertyBag): BunFile; + + /** + * A list of files embedded into the standalone executable. Lexigraphically sorted by name. + * + * If the process is not a standalone executable, this returns an empty array. + */ + const embeddedFiles: ReadonlyArray; + + /** + * `Blob` that leverages the fastest system calls available to operate on files. + * + * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. + * + * `Blob.size` will not be valid until the contents of the file are read at least once. + * `Blob.type` will have a default set based on the file extension + * + * @example + * ```js + * const file = Bun.file(new TextEncoder.encode("./hello.json")); + * console.log(file.type); // "application/json" + * ``` + * + * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file( + path: ArrayBufferLike | Uint8Array, + options?: BlobPropertyBag, + ): BunFile; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * + * @example + * ```js + * const file = Bun.file(fd); + * ``` + * + * @param fileDescriptor The file descriptor of the file + */ + // tslint:disable-next-line:unified-signatures + function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; + + /** + * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. + * + * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. + */ + function allocUnsafe(size: number): Uint8Array; + + interface BunInspectOptions { + colors?: boolean; + depth?: number; + sorted?: boolean; + compact?: boolean; + } + + /** + * Pretty-print an object the same as {@link console.log} to a `string` + * + * Supports JSX + * + * @param args + */ + function inspect(arg: any, options?: BunInspectOptions): string; + namespace inspect { + /** + * That can be used to declare custom inspect functions. + */ + const custom: typeof import("util").inspect.custom; + + /** + * Pretty-print an object or array as a table + * + * Like {@link console.table}, except it returns a string + */ + function table( + tabularData: object | unknown[], + properties?: string[], + options?: { colors?: boolean }, + ): string; + function table( + tabularData: object | unknown[], + options?: { colors?: boolean }, + ): string; + } + + interface MMapOptions { + /** + * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. + */ + sync?: boolean; + /** + * Allow other processes to see results instantly? + * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. + * @default true + */ + shared?: boolean; + } + /** + * Open a file as a live-updating `Uint8Array` without copying memory + * - Writing to the array writes to the file. + * - Reading from the array reads from the file. + * + * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. + * + * --- + * + * This API inherently has some rough edges: + * - It does not support empty files. It will throw a `SystemError` with `EINVAL` + * - Usage on shared/networked filesystems is discouraged. It will be very slow. + * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. + * + * --- + * + * To close the file, set the array to `null` and it will be garbage collected eventually. + */ + function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; + + /** Write to stdout */ + const stdout: BunFile; + /** Write to stderr */ + const stderr: BunFile; + /** + * Read from stdin + * + * This is read-only + */ + const stdin: BunFile; + + type StringLike = string | { toString(): string }; + + type ColorInput = + | { r: number; g: number; b: number; a?: number } + | [number, number, number] + | [number, number, number, number] + | Uint8Array + | Uint8ClampedArray + | Float32Array + | Float64Array + | string + | number + | { toString(): string }; + + function color( + input: ColorInput, + outputFormat?: /** + * True color ANSI color string, for use in terminals + * @example \x1b[38;2;100;200;200m + */ + | "ansi" + | "ansi-16" + | "ansi-16m" + /** + * 256 color ANSI color string, for use in terminals which don't support true color + * + * Tries to match closest 24-bit color to 256 color palette + */ + | "ansi-256" + /** + * Picks the format that produces the shortest output + */ + | "css" + /** + * Lowercase hex color string without alpha + * @example #ff9800 + */ + | "hex" + /** + * Uppercase hex color string without alpha + * @example #FF9800 + */ + | "HEX" + /** + * @example hsl(35.764706, 1, 0.5) + */ + | "hsl" + /** + * @example lab(0.72732764, 33.938198, -25.311619) + */ + | "lab" + /** + * @example 16750592 + */ + | "number" + /** + * RGB color string without alpha + * @example rgb(255, 152, 0) + */ + | "rgb" + /** + * RGB color string with alpha + * @example rgba(255, 152, 0, 1) + */ + | "rgba", + ): string | null; + + function color( + input: ColorInput, + /** + * An array of numbers representing the RGB color + * @example [100, 200, 200] + */ + outputFormat: "[rgb]", + ): [number, number, number] | null; + function color( + input: ColorInput, + /** + * An array of numbers representing the RGBA color + * @example [100, 200, 200, 255] + */ + outputFormat: "[rgba]", + ): [number, number, number, number] | null; + function color( + input: ColorInput, + /** + * An object representing the RGB color + * @example { r: 100, g: 200, b: 200 } + */ + outputFormat: "{rgb}", + ): { r: number; g: number; b: number } | null; + function color( + input: ColorInput, + /** + * An object representing the RGBA color + * @example { r: 100, g: 200, b: 200, a: 0.5 } + */ + outputFormat: "{rgba}", + ): { r: number; g: number; b: number; a: number } | null; + function color(input: ColorInput, outputFormat: "number"): number | null; + + interface Semver { + /** + * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. + */ + satisfies(version: StringLike, range: StringLike): boolean; + + /** + * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. + * Throws an error if either version is invalid. + */ + order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; + } + var semver: Semver; + + interface Unsafe { + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. + * + * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; + + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` + * + * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + // tslint:disable-next-line:unified-signatures + arrayBufferToString(buffer: Uint16Array): string; + + /** Mock bun's segfault handler. You probably don't want to use this */ + segfault(): void; + + /** + * Force the garbage collector to run extremely often, + * especially inside `bun:test`. + * + * - `0`: default, disable + * - `1`: asynchronously call the garbage collector more often + * - `2`: synchronously call the garbage collector more often. + * + * This is a global setting. It's useful for debugging seemingly random crashes. + * + * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. + * + * @param level + * @returns The previous level + */ + gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; + } + const unsafe: Unsafe; + + type DigestEncoding = + | "utf8" + | "ucs2" + | "utf16le" + | "latin1" + | "ascii" + | "base64" + | "base64url" + | "hex"; + + /** + * Are ANSI colors enabled for stdin and stdout? + * + * Used for {@link console.log} + */ + const enableANSIColors: boolean; + + /** + * What script launched bun? + * + * Absolute file path + * + * @example "/never-gonna-give-you-up.js" + */ + const main: string; + + /** + * Manually trigger the garbage collector + * + * This does two things: + * 1. It tells JavaScriptCore to run the garbage collector + * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. + * + * @param force Synchronously run the garbage collector + */ + function gc(force: boolean): void; + + /** + * JavaScriptCore engine's internal heap snapshot + * + * I don't know how to make this something Chrome or Safari can read. + * + * If you have any ideas, please file an issue https://github.com/oven-sh/bun + */ + interface HeapSnapshot { + /** 2 */ + version: number; + + /** "Inspector" */ + type: string; + + nodes: number[]; + + nodeClassNames: string[]; + edges: number[]; + edgeTypes: string[]; + edgeNames: string[]; + } + + /** + * Returns the number of nanoseconds since the process was started. + * + * This function uses a high-resolution monotonic system timer to provide precise time measurements. + * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), + * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). + * + * Due to this limitation, while the internal counter may continue beyond this point, + * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond + * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but + * with reduced precision, which might affect time calculations and comparisons in long-running applications. + * + * @returns {number} The number of nanoseconds since the process was started, with precise values up to + * Number.MAX_SAFE_INTEGER. + */ + function nanoseconds(): number; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector + */ + function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code + * + * This is a JSON string that can be saved to a file. + * ```ts + * const snapshot = Bun.generateHeapSnapshot("v8"); + * await Bun.write("heap.heapsnapshot", snapshot); + * ``` + */ + function generateHeapSnapshot(format: "v8"): string; + + /** + * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. + */ + function shrink(): void; + + /** + * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` + * + * @param path path to open + */ + function openInEditor(path: string, options?: EditorOptions): void; + + var fetch: typeof globalThis.fetch & { + preconnect(url: string): void; + }; + + interface EditorOptions { + editor?: "vscode" | "subl"; + line?: number; + column?: number; + } + + /** + * This class only exists in types + */ + abstract class CryptoHashInterface { + /** + * Update the hash with data + * + * @param data + */ + update(data: Bun.BlobOrStringOrBuffer): T; + + /** + * Finalize the hash + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash( + input: Bun.BlobOrStringOrBuffer, + hashInto?: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + } + + type SupportedCryptoAlgorithms = + | "blake2b256" + | "blake2b512" + | "md4" + | "md5" + | "ripemd160" + | "sha1" + | "sha224" + | "sha256" + | "sha384" + | "sha512" + | "sha512-224" + | "sha512-256" + | "sha3-224" + | "sha3-256" + | "sha3-384" + | "sha3-512" + | "shake128" + | "shake256"; + + /** + * Hardware-accelerated cryptographic hash functions + * + * Used for `crypto.createHash()` + */ + class CryptoHasher { + /** + * The algorithm chosen to hash the data + */ + readonly algorithm: SupportedCryptoAlgorithms; + + /** + * The length of the output hash in bytes + */ + readonly byteLength: number; + + /** + * Create a new hasher + * + * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms + * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. + */ + constructor( + algorithm: SupportedCryptoAlgorithms, + hmacKey?: string | NodeJS.TypedArray, + ); + + /** + * Update the hash with data + * + * @param input + */ + update( + input: Bun.BlobOrStringOrBuffer, + inputEncoding?: CryptoEncoding, + ): CryptoHasher; + + /** + * Perform a deep copy of the hasher + */ + copy(): CryptoHasher; + + /** + * Finalize the hash. Resets the CryptoHasher so it can be reused. + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(): Buffer; + digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + ): Buffer; + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + hashInto: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + + /** + * List of supported hash algorithms + * + * These are hardware accelerated with BoringSSL + */ + static readonly algorithms: SupportedCryptoAlgorithms[]; + } + + /** + * Resolve a `Promise` after milliseconds. This is like + * {@link setTimeout} except it returns a `Promise`. + * + * @param ms milliseconds to delay resolving the promise. This is a minimum + * number. It may take longer. If a {@link Date} is passed, it will sleep until the + * {@link Date} is reached. + * + * @example + * ## Sleep for 1 second + * ```ts + * import { sleep } from "bun"; + * + * await sleep(1000); + * ``` + * ## Sleep for 10 milliseconds + * ```ts + * await Bun.sleep(10); + * ``` + * ## Sleep until `Date` + * + * ```ts + * const target = new Date(); + * target.setSeconds(target.getSeconds() + 1); + * await Bun.sleep(target); + * ``` + * Internally, `Bun.sleep` is the equivalent of + * ```ts + * await new Promise((resolve) => setTimeout(resolve, ms)); + * ``` + * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. + */ + function sleep(ms: number | Date): Promise; + + /** + * Sleep the thread for a given number of milliseconds + * + * This is a blocking function. + * + * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) + */ + function sleepSync(ms: number): void; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha( + input: Bun.StringOrBuffer, + hashInto?: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param encoding `DigestEncoding` to return the hash in + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; + + /** + * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} + * + * Consider using the ugly-named {@link SHA512_256} instead + */ + class SHA1 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 20; + } + class MD5 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class MD4 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class SHA224 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 28; + } + class SHA512 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 64; + } + class SHA384 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 48; + } + class SHA256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + /** + * See also {@link sha} + */ + class SHA512_256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + + /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ + interface ZlibCompressionOptions { + /** + * The compression level to use. Must be between `-1` and `9`. + * - A value of `-1` uses the default compression level (Currently `6`) + * - A value of `0` gives no compression + * - A value of `1` gives least compression, fastest speed + * - A value of `9` gives best compression, slowest speed + */ + level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * How much memory should be allocated for the internal compression state. + * + * A value of `1` uses minimum memory but is slow and reduces compression ratio. + * + * A value of `9` uses maximum memory for optimal speed. The default is `8`. + */ + memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * The base 2 logarithm of the window size (the size of the history buffer). + * + * Larger values of this parameter result in better compression at the expense of memory usage. + * + * The following value ranges are supported: + * - `9..15`: The output will have a zlib header and footer (Deflate) + * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) + * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) + * + * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. + */ + windowBits?: + | -9 + | -10 + | -11 + | -12 + | -13 + | -14 + | -15 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 25 + | 26 + | 27 + | 28 + | 29 + | 30 + | 31; + /** + * Tunes the compression algorithm. + * + * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** + * - `Z_FILTERED`: For data produced by a filter or predictor + * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) + * - `Z_RLE`: Limit match distances to one (run-length encoding) + * - `Z_FIXED` prevents the use of dynamic Huffman codes + * + * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. + * + * `Z_FILTERED` forces more Huffman coding and less string matching, it is + * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. + * Filtered data consists mostly of small values with a somewhat random distribution. + */ + strategy?: number; + + library?: "zlib"; + } + + interface LibdeflateCompressionOptions { + level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; + library?: "libdeflate"; + } + + /** + * Compresses a chunk of data with `zlib` DEFLATE algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function deflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Compresses a chunk of data with `zlib` GZIP algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function gzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` INFLATE algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function inflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` GUNZIP algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function gunzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + + type Target = + /** + * For generating bundles that are intended to be run by the Bun runtime. In many cases, + * it isn't necessary to bundle server-side code; you can directly execute the source code + * without modification. However, bundling your server code can reduce startup times and + * improve running performance. + * + * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which + * indicates to the Bun runtime that there's no need to re-transpile the file before execution. + */ + | "bun" + /** + * The plugin will be applied to Node.js builds + */ + | "node" + /** + * The plugin will be applied to browser builds + */ + | "browser"; + + /** https://bun.sh/docs/bundler/loaders */ + type Loader = + | "js" + | "jsx" + | "ts" + | "tsx" + | "json" + | "toml" + | "file" + | "napi" + | "wasm" + | "text" + | "css" + | "html"; + + interface PluginConstraints { + /** + * Only apply the plugin when the import specifier matches this regular expression + * + * @example + * ```ts + * // Only apply the plugin when the import specifier matches the regex + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { + * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; + * }); + * } + * }) + * ``` + */ + filter: RegExp; + + /** + * Only apply the plugin when the import specifier has a namespace matching + * this string + * + * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` + * has the namespace `"bun"`. + * + * The default namespace is `"file"` and it can be omitted from import + * specifiers. + */ + namespace?: string; + } + + interface OnLoadResultSourceCode { + /** + * The source code of the module + */ + contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; + /** + * The loader to use for this file + * + * "css" will be added in a future version of Bun. + */ + loader?: Loader; + } + + interface OnLoadResultObject { + /** + * The object to use as the module + * @example + * ```ts + * // In your loader + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * + * // In your script + * import {foo} from "hello:world"; + * console.log(foo); // "bar" + * ``` + */ + exports: Record; + /** + * The loader to use for this file + */ + loader: "object"; + } + + interface OnLoadArgs { + /** + * The resolved import specifier of the module being loaded + * @example + * ```ts + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * console.log(args.path); // "hello:world" + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * ``` + */ + path: string; + /** + * The namespace of the module being loaded + */ + namespace: string; + /** + * The default loader for this file extension + */ + loader: Loader; + /** + * Defer the execution of this callback until all other modules have been parsed. + * + * @returns Promise which will be resolved when all modules have been parsed + */ + defer: () => Promise; + } + + type OnLoadResult = + | OnLoadResultSourceCode + | OnLoadResultObject + | undefined + | void; + type OnLoadCallback = ( + args: OnLoadArgs, + ) => OnLoadResult | Promise; + type OnStartCallback = () => void | Promise; + + interface OnResolveArgs { + /** + * The import specifier of the module being loaded + */ + path: string; + /** + * The module that imported the module being resolved + */ + importer: string; + /** + * The namespace of the importer. + */ + namespace: string; + /** + * The directory to perform file-based resolutions in. + */ + resolveDir: string; + /** + * The kind of import this resolve is for. + */ + kind: ImportKind; + // resolveDir: string; + // pluginData: any; + } + + interface OnResolveResult { + /** + * The destination of the import + */ + path: string; + /** + * The namespace of the destination + * It will be concatenated with `path` to form the final import specifier + * @example + * ```ts + * "foo" // "foo:bar" + * ``` + */ + namespace?: string; + external?: boolean; + } + + type OnResolveCallback = ( + args: OnResolveArgs, + ) => + | OnResolveResult + | Promise + | undefined + | null; + + type FFIFunctionCallable = Function & { + // Making a nominally typed function so that the user must get it from dlopen + readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + + interface PluginBuilder { + /** + * Register a callback which will be invoked when bundling starts. When + * using hot module reloading, this is called at the start of each + * incremental rebuild. + * + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onStart(() => { + * console.log("bundle just started!!") + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onStart(callback: OnStartCallback): this; + onBeforeParse( + constraints: PluginConstraints, + callback: { + napiModule: unknown; + symbol: string; + external?: unknown | undefined; + }, + ): this; + /** + * Register a callback to load imports with a specific import specifier + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; + /** + * Register a callback to resolve imports matching a filter and/or namespace + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onResolve({ filter: /^wat$/ }, (args) => { + * return { path: "/tmp/woah.js" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onResolve( + constraints: PluginConstraints, + callback: OnResolveCallback, + ): this; + /** + * The config object passed to `Bun.build` as is. Can be mutated. + */ + config: BuildConfig & { plugins: BunPlugin[] }; + + /** + * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules + * + * @param specifier The module specifier to register the callback for + * @param callback The function to run when the module is imported or required + * + * ### Example + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.module("hello:world", () => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * + * // sometime later + * const { foo } = await import("hello:world"); + * console.log(foo); // "bar" + * + * // or + * const { foo } = require("hello:world"); + * console.log(foo); // "bar" + * ``` + * + * @returns `this` for method chaining + */ + module( + specifier: string, + callback: () => OnLoadResult | Promise, + ): this; + } + + interface BunPlugin { + /** + * Human-readable name of the plugin + * + * In a future version of Bun, this will be used in error messages. + */ + name: string; + + /** + * The target JavaScript environment the plugin should be applied to. + * - `bun`: The default environment when using `bun run` or `bun` to load a script + * - `browser`: The plugin will be applied to browser builds + * - `node`: The plugin will be applied to Node.js builds + * + * If unspecified, it is assumed that the plugin is compatible with all targets. + * + * This field is not read by {@link Bun.plugin} + */ + target?: Target; + /** + * A function that will be called when the plugin is loaded. + * + * This function may be called in the same tick that it is registered, or it + * may be called later. It could potentially be called multiple times for + * different targets. + */ + setup( + /** + * A builder object that can be used to register plugin hooks + * @example + * ```ts + * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), + * })); + * ``` + */ + build: PluginBuilder, + ): void | Promise; + } + + /** + * Extend Bun's module resolution and loading behavior + * + * Plugins are applied in the order they are defined. + * + * Today, there are two kinds of hooks: + * - `onLoad` lets you return source code or an object that will become the module's exports + * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. + * + * Plugin hooks must define a `filter` RegExp and will only be matched if the + * import specifier contains a "." or a ":". + * + * ES Module resolution semantics mean that plugins may be initialized _after_ + * a module is resolved. You might need to load plugins at the very beginning + * of the application and then use a dynamic import to load the rest of the + * application. A future version of Bun may also support specifying plugins + * via `bunfig.toml`. + * + * @example + * A YAML loader plugin + * + * ```js + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) + * })); + * }); + * + * // You can use require() + * const {foo} = require("./file.yaml"); + * + * // Or import + * await import("./file.yaml"); + * + * ``` + */ + interface BunRegisterPlugin { + (options: T): ReturnType; + + /** + * Deactivate all plugins + * + * This prevents registered plugins from being applied to future builds. + */ + clearAll(): void; + } + + const plugin: BunRegisterPlugin; + + /** + * Is the current global scope the main thread? + */ + const isMainThread: boolean; + + /** + * Used when importing an HTML file at runtime. + * + * @example + * + * ```ts + * import app from "./index.html"; + * ``` + * + * Bun.build support for this isn't imlpemented yet. + */ + interface HTMLBundle { + index: string; + } + + interface Socket extends Disposable { + /** + * Write `data` to the socket + * + * @param data The data to write to the socket + * @param byteOffset The offset in the buffer to start writing from (defaults to 0) + * @param byteLength The number of bytes to write (defaults to the length of the buffer) + * + * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. + * + * This is unbuffered as of Bun v0.2.2. That means individual write() calls + * will be slow. In the future, Bun will buffer writes and flush them at the + * end of the tick, when the event loop is idle, or sooner if the buffer is full. + */ + write( + data: string | Bun.BufferSource, + byteOffset?: number, + byteLength?: number, + ): number; + + /** + * The data context for the socket. + */ + data: Data; + + /** + * Like {@link Socket.write} except it includes a TCP FIN packet + * + * Use it to send your last message and close the connection. + */ + end( + data?: string | Bun.BufferSource, + byteOffset?: number, + byteLength?: number, + ): number; + + /** + * Close the socket immediately + */ + end(): void; + + /** + * Keep Bun's process alive at least until this socket is closed + * + * After the socket has closed, the socket is unref'd, the process may exit, + * and this becomes a no-op + */ + ref(): void; + + /** + * Set a timeout until the socket automatically closes. + * + * To reset the timeout, call this function again. + * + * When a timeout happens, the `timeout` callback is called and the socket is closed. + */ + timeout(seconds: number): void; + + /** + * Forcefully close the socket. The other end may not receive all data, and + * the socket will be closed immediately. + * + * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to + * `0` and then calls `close(2)`. + */ + terminate(): void; + + /** + * Shutdown writes to a socket + * + * This makes the socket a half-closed socket. It can still receive data. + * + * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally + */ + shutdown(halfClose?: boolean): void; + + readonly readyState: "open" | "closing" | "closed"; + + /** + * Allow Bun's process to exit even if this socket is still open + * + * After the socket has closed, this function does nothing. + */ + unref(): void; + + /** + * Flush any buffered data to the socket + */ + flush(): void; + + /** + * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. + * + * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. + */ + reload(handler: SocketHandler): void; + + /** + * Get the server that created this socket + * + * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. + */ + readonly listener?: SocketListener; + + /** + * Remote IP address connected to the socket + */ + readonly remoteAddress: string; + + /** + * local port connected to the socket + */ + readonly localPort: number; + + /** + * This property is `true` if the peer certificate was signed by one of the CAs + * specified when creating the `Socket` instance, otherwise `false`. + */ + readonly authorized: boolean; + + /** + * String containing the selected ALPN protocol. + * Before a handshake has completed, this value is always null. + * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. + */ + readonly alpnProtocol: string | false | null; + + /** + * Disables TLS renegotiation for this `Socket` instance. Once called, attempts + * to renegotiate will trigger an `error` handler on the `Socket`. + * + * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) + */ + disableRenegotiation(): void; + + /** + * Keying material is used for validations to prevent different kind of attacks in + * network protocols, for example in the specifications of IEEE 802.1X. + * + * Example + * + * ```js + * const keyingMaterial = socket.exportKeyingMaterial( + * 128, + * 'client finished'); + * + * /* + * Example return value of keyingMaterial: + * + * + * ``` + * + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the [IANA Exporter Label + * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context Optionally provide a context. + * @return requested bytes of the keying material + */ + exportKeyingMaterial( + length: number, + label: string, + context: Buffer, + ): Buffer; + + /** + * Returns the reason why the peer's certificate was not been verified. This + * property is set only when `socket.authorized === false`. + */ + getAuthorizationError(): Error | null; + + /** + * Returns an object representing the local certificate. The returned object has + * some properties corresponding to the fields of the certificate. + * + * If there is no local certificate, an empty object will be returned. If the + * socket has been destroyed, `null` will be returned. + */ + getCertificate(): PeerCertificate | object | null; + getX509Certificate(): X509Certificate | undefined; + + /** + * Returns an object containing information on the negotiated cipher suite. + * + * For example, a TLSv1.2 protocol with AES256-SHA cipher: + * + * ```json + * { + * "name": "AES256-SHA", + * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", + * "version": "SSLv3" + * } + * ``` + * + */ + getCipher(): CipherNameAndProtocol; + + /** + * Returns an object representing the type, name, and size of parameter of + * an ephemeral key exchange in `perfect forward secrecy` on a client + * connection. It returns an empty object when the key exchange is not + * ephemeral. As this is only supported on a client socket; `null` is returned + * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. + * + * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. + */ + getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; + + /** + * Returns an object representing the peer's certificate. If the peer does not + * provide a certificate, an empty object will be returned. If the socket has been + * destroyed, `null` will be returned. + * + * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's + * certificate. + * @return A certificate object. + */ + getPeerCertificate(): PeerCertificate; + getPeerX509Certificate(): X509Certificate; + + /** + * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. + * @since v12.11.0 + * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. + */ + getSharedSigalgs(): string[]; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. + */ + getTLSFinishedMessage(): Buffer | undefined; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so + * far. + */ + getTLSPeerFinishedMessage(): Buffer | undefined; + + /** + * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. + * + * It may be useful for debugging. + * + * See `Session Resumption` for more information. + */ + getTLSTicket(): Buffer | undefined; + + /** + * Returns a string containing the negotiated SSL/TLS protocol version of the + * current connection. The value `'unknown'` will be returned for connected + * sockets that have not completed the handshaking process. The value `null` will + * be returned for server sockets or disconnected client sockets. + * + * Protocol versions are: + * + * * `'SSLv3'` + * * `'TLSv1'` + * * `'TLSv1.1'` + * * `'TLSv1.2'` + * * `'TLSv1.3'` + * + */ + getTLSVersion(): string; + + /** + * See `Session Resumption` for more information. + * @return `true` if the session was reused, `false` otherwise. + */ + isSessionReused(): boolean; + + /** + * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. + * Returns `true` if setting the limit succeeded; `false` otherwise. + * + * Smaller fragment sizes decrease the buffering latency on the client: larger + * fragments are buffered by the TLS layer until the entire fragment is received + * and its integrity is verified; large fragments can span multiple roundtrips + * and their processing can be delayed due to packet loss or reordering. However, + * smaller fragments add extra TLS framing bytes and CPU overhead, which may + * decrease overall server throughput. + * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. + */ + setMaxSendFragment(size: number): boolean; + + /** + * Enable/disable the use of Nagle's algorithm. + * Only available for already connected sockets, will return false otherwise + * @param noDelay Default: `true` + * @returns true if is able to setNoDelay and false if it fails. + */ + setNoDelay(noDelay?: boolean): boolean; + + /** + * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. + * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. + * Only available for already connected sockets, will return false otherwise. + * + * Enabling the keep-alive functionality will set the following socket options: + * SO_KEEPALIVE=1 + * TCP_KEEPIDLE=initialDelay + * TCP_KEEPCNT=10 + * TCP_KEEPINTVL=1 + * @param enable Default: `false` + * @param initialDelay Default: `0` + * @returns true if is able to setNoDelay and false if it fails. + */ + setKeepAlive(enable?: boolean, initialDelay?: number): boolean; + + /** + * The number of bytes written to the socket. + */ + readonly bytesWritten: number; + } + + interface SocketListener extends Disposable { + stop(closeActiveConnections?: boolean): void; + ref(): void; + unref(): void; + reload(options: Pick, "socket">): void; + data: Data; + } + interface TCPSocketListener extends SocketListener { + readonly port: number; + readonly hostname: string; + } + interface UnixSocketListener extends SocketListener { + readonly unix: string; + } + + interface TCPSocket extends Socket {} + interface TLSSocket extends Socket {} + + interface BinaryTypeList { + arraybuffer: ArrayBuffer; + buffer: Buffer; + uint8array: Uint8Array; + // TODO: DataView + // dataview: DataView; + } + type BinaryType = keyof BinaryTypeList; + + interface SocketHandler< + Data = unknown, + DataBinaryType extends BinaryType = "buffer", + > { + /** + * Is called when the socket connects, or in case of TLS if no handshake is provided + * this will be called only after handshake + * @param socket + */ + open?(socket: Socket): void | Promise; + close?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + ): void | Promise; + drain?(socket: Socket): void | Promise; + + /** + * When handshake is completed, this functions is called. + * @param socket + * @param success Indicates if the server authorized despite the authorizationError. + * @param authorizationError Certificate Authorization Error or null. + */ + handshake?( + socket: Socket, + success: boolean, + authorizationError: Error | null, + ): void; + + /** + * When the socket has been shutdown from the other end, this function is + * called. This is a TCP FIN packet. + */ + end?(socket: Socket): void | Promise; + + /** + * When the socket fails to be created, this function is called. + * + * The promise returned by `Bun.connect` rejects **after** this function is + * called. + * + * When `connectError` is specified, the rejected promise will not be + * added to the promise rejection queue (so it won't be reported as an + * unhandled promise rejection, since connectError handles it). + * + * When `connectError` is not specified, the rejected promise will be added + * to the promise rejection queue. + */ + connectError?(socket: Socket, error: Error): void | Promise; + + /** + * Called when a message times out. + */ + timeout?(socket: Socket): void | Promise; + /** + * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. + * + * @default "buffer" + * + * @remarks + * This lets you select the desired binary type for the `data` callback. + * It's a small performance optimization to let you avoid creating extra + * ArrayBufferView objects when possible. + * + * Bun originally defaulted to `Uint8Array` but when dealing with network + * data, it's more useful to be able to directly read from the bytes which + * `Buffer` allows. + */ + binaryType?: BinaryType; + } + + interface SocketOptions { + socket: SocketHandler; + data?: Data; + } + // interface TCPSocketOptions extends SocketOptions { + // hostname: string; + // port: number; + // } + + interface TCPSocketListenOptions + extends SocketOptions { + hostname: string; + port: number; + tls?: TLSOptions; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface TCPSocketConnectOptions + extends SocketOptions { + hostname: string; + port: number; + tls?: boolean; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface UnixSocketOptions extends SocketOptions { + tls?: TLSOptions; + unix: string; + } + + interface FdSocketOptions extends SocketOptions { + tls?: TLSOptions; + fd: number; + } + + /** + * Create a TCP client that connects to a server + * + * @param options The options to use when creating the client + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function connect( + options: TCPSocketConnectOptions, + ): Promise>; + function connect( + options: UnixSocketOptions, + ): Promise>; + + /** + * Create a TCP server that listens on a port + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function listen( + options: TCPSocketListenOptions, + ): TCPSocketListener; + function listen( + options: UnixSocketOptions, + ): UnixSocketListener; + + namespace udp { + type Data = string | ArrayBufferView | ArrayBufferLike; + + export interface SocketHandler { + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: Socket): void | Promise; + error?( + socket: Socket, + error: Error, + ): void | Promise; + } + + export interface ConnectedSocketHandler { + data?( + socket: ConnectedSocket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: ConnectedSocket): void | Promise; + error?( + socket: ConnectedSocket, + error: Error, + ): void | Promise; + } + + export interface SocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: SocketHandler; + } + + export interface ConnectSocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: ConnectedSocketHandler; + connect: { + hostname: string; + port: number; + }; + } + + export interface BaseUDPSocket { + readonly hostname: string; + readonly port: number; + readonly address: SocketAddress; + readonly binaryType: BinaryType; + readonly closed: boolean; + ref(): void; + unref(): void; + close(): void; + } + + export interface ConnectedSocket + extends BaseUDPSocket { + readonly remoteAddress: SocketAddress; + sendMany(packets: readonly Data[]): number; + send(data: Data): boolean; + reload(handler: ConnectedSocketHandler): void; + } + + export interface Socket + extends BaseUDPSocket { + sendMany(packets: readonly (Data | string | number)[]): number; + send(data: Data, port: number, address: string): boolean; + reload(handler: SocketHandler): void; + } + } + + /** + * Create a UDP socket + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.hostname The hostname to listen on + * @param options.port The port to listen on + * @param options.binaryType The binary type to use for the socket + * @param options.connect The hostname and port to connect to + */ + export function udpSocket( + options: udp.SocketOptions, + ): Promise>; + export function udpSocket( + options: udp.ConnectSocketOptions, + ): Promise>; + + namespace SpawnOptions { + /** + * Option for stdout/stderr + */ + type Readable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number; + + /** + * Option for stdin + */ + type Writable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number + | ReadableStream + | Blob + | Response + | Request; + + interface OptionsObject< + In extends Writable = Writable, + Out extends Readable = Readable, + Err extends Readable = Readable, + > { + /** + * The current working directory of the process + * + * Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * The environment variables of the process + * + * Defaults to `process.env` as it was when the current Bun process launched. + * + * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. + */ + env?: Record; + + /** + * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. + * This overrides the `stdin`, `stdout`, and `stderr` properties. + * + * For stdin you may pass: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. + * - `number`: The process will read from the file descriptor + * + * For stdout and stdin you may pass: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default ["ignore", "pipe", "inherit"] for `spawn` + * ["ignore", "pipe", "pipe"] for `spawnSync` + */ + stdio?: [In, Out, Err]; + /** + * The file descriptor for the standard input. It may be: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`: The process will read from the buffer + * - `number`: The process will read from the file descriptor + * + * @default "ignore" + */ + stdin?: In; + /** + * The file descriptor for the standard output. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "pipe" + */ + stdout?: Out; + /** + * The file descriptor for the standard error. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "inherit" for `spawn` + * "pipe" for `spawnSync` + */ + stderr?: Err; + + /** + * Callback that runs when the {@link Subprocess} exits + * + * This is called even if the process exits with a non-zero exit code. + * + * Warning: this may run before the `Bun.spawn` function returns. + * + * A simple alternative is `await subprocess.exited`. + * + * @example + * + * ```ts + * const subprocess = spawn({ + * cmd: ["echo", "hello"], + * onExit: (subprocess, code) => { + * console.log(`Process exited with code ${code}`); + * }, + * }); + * ``` + */ + onExit?( + subprocess: Subprocess, + exitCode: number | null, + signalCode: number | null, + /** + * If an error occurred in the call to waitpid2, this will be the error. + */ + error?: ErrorLike, + ): void | Promise; + + /** + * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for + * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized + * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + * + * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, + * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. + * + * Currently, this is only compatible with processes that are other `bun` instances. + */ + ipc?( + message: any, + /** + * The {@link Subprocess} that sent the message + */ + subprocess: Subprocess, + ): void; + + /** + * The serialization format to use for IPC messages. Defaults to `"advanced"`. + * + * To communicate with Node.js processes, use `"json"`. + * + * When `ipc` is not specified, this is ignored. + */ + serialization?: "json" | "advanced"; + + /** + * If true, the subprocess will have a hidden window. + */ + windowsHide?: boolean; + + /** + * If true, no quoting or escaping of arguments is done on Windows. + */ + windowsVerbatimArguments?: boolean; + + /** + * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. + * + * One use-case for this is for applications which wrap other applications or to simulate a symlink. + * + * @default cmds[0] + */ + argv0?: string; + + /** + * An {@link AbortSignal} that can be used to abort the subprocess. + * + * This is useful for aborting a subprocess when some other part of the + * program is aborted, such as a `fetch` response. + * + * Internally, this works by calling `subprocess.kill(1)`. + * + * @example + * ```ts + * const controller = new AbortController(); + * const { signal } = controller; + * const start = performance.now(); + * const subprocess = Bun.spawn({ + * cmd: ["sleep", "100"], + * signal, + * }); + * await Bun.sleep(1); + * controller.abort(); + * await subprocess.exited; + * const end = performance.now(); + * console.log(end - start); // 1ms instead of 101ms + * ``` + */ + signal?: AbortSignal; + } + + type OptionsToSubprocess = + Opts extends OptionsObject + ? Subprocess< + // "Writable extends In" means "if In === Writable", + // aka if true that means the user didn't specify anything + Writable extends In ? "ignore" : In, + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "inherit" : Err + > + : Subprocess; + + type OptionsToSyncSubprocess = + Opts extends OptionsObject + ? SyncSubprocess< + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "pipe" : Err + > + : SyncSubprocess; + + type ReadableIO = ReadableStream | number | undefined; + + type ReadableToIO = X extends "pipe" | undefined + ? ReadableStream + : X extends BunFile | ArrayBufferView | number + ? number + : undefined; + + type ReadableToSyncIO = X extends "pipe" | undefined + ? Buffer + : undefined; + + type WritableIO = FileSink | number | undefined; + + type WritableToIO = X extends "pipe" + ? FileSink + : X extends BunFile | ArrayBufferView | Blob | Request | Response | number + ? number + : undefined; + } + + interface ResourceUsage { + /** + * The number of voluntary and involuntary context switches that the process made. + */ + contextSwitches: { + /** + * Voluntary context switches (context switches that the process initiated). + */ + voluntary: number; + /** + * Involuntary context switches (context switches initiated by the system scheduler). + */ + involuntary: number; + }; + + /** + * The amount of CPU time used by the process, in microseconds. + */ + cpuTime: { + /** + * User CPU time used by the process, in microseconds. + */ + user: number; + /** + * System CPU time used by the process, in microseconds. + */ + system: number; + /** + * Total CPU time used by the process, in microseconds. + */ + total: number; + }; + /** + * The maximum amount of resident set size (in bytes) used by the process during its lifetime. + */ + maxRSS: number; + + /** + * IPC messages sent and received by the process. + */ + messages: { + /** + * The number of IPC messages sent. + */ + sent: number; + /** + * The number of IPC messages received. + */ + received: number; + }; + /** + * The number of IO operations done by the process. + */ + ops: { + /** + * The number of input operations via the file system. + */ + in: number; + /** + * The number of output operations via the file system. + */ + out: number; + }; + /** + * The amount of shared memory that the process used. + */ + shmSize: number; + /** + * The number of signals delivered to the process. + */ + signalCount: number; + /** + * The number of times the process was swapped out of main memory. + */ + swapCount: number; + } + + /** + * A process created by {@link Bun.spawn}. + * + * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSubprocess} (any, pipe, pipe) + * - {@link WritableSubprocess} (pipe, any, any) + * - {@link PipedSubprocess} (pipe, pipe, pipe) + * - {@link NullSubprocess} (ignore, ignore, ignore) + */ + interface Subprocess< + In extends SpawnOptions.Writable = SpawnOptions.Writable, + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > extends AsyncDisposable { + readonly stdin: SpawnOptions.WritableToIO; + readonly stdout: SpawnOptions.ReadableToIO; + readonly stderr: SpawnOptions.ReadableToIO; + + /** + * This returns the same value as {@link Subprocess.stdout} + * + * It exists for compatibility with {@link ReadableStream.pipeThrough} + */ + readonly readable: SpawnOptions.ReadableToIO; + + /** + * The process ID of the child process + * @example + * ```ts + * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); + * console.log(pid); // 1234 + * ``` + */ + readonly pid: number; + /** + * The exit code of the process + * + * The promise will resolve when the process exits + */ + readonly exited: Promise; + + /** + * Synchronously get the exit code of the process + * + * If the process hasn't exited yet, this will return `null` + */ + readonly exitCode: number | null; + + /** + * Synchronously get the signal code of the process + * + * If the process never sent a signal code, this will return `null` + * + * To receive signal code changes, use the `onExit` callback. + * + * If the signal code is unknown, it will return the original signal code + * number, but that case should essentially never happen. + */ + readonly signalCode: NodeJS.Signals | null; + + /** + * Has the process exited? + */ + readonly killed: boolean; + + /** + * Kill the process + * @param exitCode The exitCode to send to the process + */ + kill(exitCode?: number | NodeJS.Signals): void; + + /** + * This method will tell Bun to wait for this process to exit after you already + * called `unref()`. + * + * Before shutting down, Bun will wait for all subprocesses to exit by default + */ + ref(): void; + + /** + * Before shutting down, Bun will wait for all subprocesses to exit by default + * + * This method will tell Bun to not wait for this process to exit before shutting down. + */ + unref(): void; + + /** + * Send a message to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option, and is another instance of `bun`. + * + * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + */ + send(message: any): void; + + /** + * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option. + */ + disconnect(): void; + + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + * + * Only available after the process has exited + * + * If the process hasn't exited yet, this will return `undefined` + */ + resourceUsage(): ResourceUsage | undefined; + } + + /** + * A process created by {@link Bun.spawnSync}. + * + * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSyncSubprocess} (pipe, pipe) + * - {@link NullSyncSubprocess} (ignore, ignore) + */ + interface SyncSubprocess< + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > { + stdout: SpawnOptions.ReadableToSyncIO; + stderr: SpawnOptions.ReadableToSyncIO; + exitCode: number; + success: boolean; + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + */ + resourceUsage: ResourceUsage; + + signalCode?: string; + } + + /** + * Spawn a new process + * + * ```js + * const subprocess = Bun.spawn({ + * cmd: ["echo", "hello"], + * stdout: "pipe", + * }); + * const text = await readableStreamToText(subprocess.stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmd: string[]; // to support dynamically constructed commands + }, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawn(["echo", "hello"]); + * const text = await readableStreamToText(stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync({ + * cmd: ["echo", "hello"], + * }); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); + * ``` + */ + cmd: string[]; + + onExit?: never; + }, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** + * Synchronously spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync(["echo", "hello"]); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ + type ReadableSubprocess = Subprocess; + /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ + type WritableSubprocess = Subprocess<"pipe", any, any>; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ + type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ + type NullSubprocess = Subprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ + type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ + type NullSyncSubprocess = SyncSubprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + + // Blocked on https://github.com/oven-sh/bun/issues/8329 + // /** + // * + // * Count the visible width of a string, as it would be displayed in a terminal. + // * + // * By default, strips ANSI escape codes before measuring the string. This is + // * because ANSI escape codes are not visible characters. If passed a non-string, + // * it will return 0. + // * + // * @param str The string to measure + // * @param options + // */ + // function stringWidth( + // str: string, + // options?: { + // /** + // * Whether to include ANSI escape codes in the width calculation + // * + // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. + // * @default false + // */ + // countAnsiEscapeCodes?: boolean; + // }, + // ): number; + + class FileSystemRouter { + /** + * Create a new {@link FileSystemRouter}. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: process.cwd() + "/pages", + * style: "nextjs", + * }); + * + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} + * ``` + * @param options The options to use when creating the router + * @param options.dir The root directory containing the files to route + * @param options.style The style of router to use (only "nextjs" supported + * for now) + */ + constructor(options: { + /** + * The root directory containing the files to route + * + * There is no default value for this option. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: + */ + dir: string; + style: "nextjs"; + + /** The base path to use when routing */ + assetPrefix?: string; + origin?: string; + /** Limit the pages to those with particular file extensions. */ + fileExtensions?: string[]; + }); + + // todo: URL + match(input: string | Request | Response): MatchedRoute | null; + + readonly assetPrefix: string; + readonly origin: string; + readonly style: string; + readonly routes: Record; + + reload(): void; + } + + interface MatchedRoute { + /** + * A map of the parameters from the route + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: "/path/to/files", + * style: "nextjs", + * }); + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params.year); // "2020" + * console.log(params.month); // "01" + * console.log(params.day); // "01" + * console.log(params.slug); // "hello-world" + * ``` + */ + readonly params: Record; + readonly filePath: string; + readonly pathname: string; + readonly query: Record; + readonly name: string; + readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; + readonly src: string; + } + + /** + * The current version of Bun + * @example + * "0.2.0" + */ + const version: string; + + /** + * The current version of Bun with the shortened commit sha of the build + * @example "v1.1.30 (d09df1af)" + */ + const version_with_sha: string; + + /** + * The git sha at the time the currently-running version of Bun was compiled + * @example + * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" + */ + const revision: string; + + /** + * Find the index of a newline character in potentially ill-formed UTF-8 text. + * + * This is sort of like readline() except without the IO. + */ + function indexOfLine( + buffer: ArrayBufferView | ArrayBufferLike, + offset?: number, + ): number; + + interface GlobScanOptions { + /** + * The root directory to start matching from. Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * Allow patterns to match entries that begin with a period (`.`). + * + * @default false + */ + dot?: boolean; + + /** + * Return the absolute path for entries. + * + * @default false + */ + absolute?: boolean; + + /** + * Indicates whether to traverse descendants of symbolic link directories. + * + * @default false + */ + followSymlinks?: boolean; + + /** + * Throw an error when symbolic link is broken + * + * @default false + */ + throwErrorOnBrokenSymlink?: boolean; + + /** + * Return only files. + * + * @default true + */ + onlyFiles?: boolean; + } + + /** + * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). + * + * The supported pattern syntax for is: + * + * - `?` + * Matches any single character. + * - `*` + * Matches zero or more characters, except for path separators ('/' or '\'). + * - `**` + * Matches zero or more characters, including path separators. + * Must match a complete path segment, i.e. followed by a path separator or + * at the end of the pattern. + * - `[ab]` + * Matches one of the characters contained in the brackets. + * Character ranges (e.g. "[a-z]") are also supported. + * Use "[!ab]" or "[^ab]" to match any character *except* those contained + * in the brackets. + * - `{a,b}` + * Match one of the patterns contained in the braces. + * Any of the wildcards listed above can be used in the sub patterns. + * Braces may be nested up to 10 levels deep. + * - `!` + * Negates the result when at the start of the pattern. + * Multiple "!" characters negate the pattern multiple times. + * - `\` + * Used to escape any of the special characters above. + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + */ + export class Glob { + constructor(pattern: string); + + /** + * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for await (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scan( + optionsOrCwd?: string | GlobScanOptions, + ): AsyncIterableIterator; + + /** + * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; + + /** + * Match the glob against a string + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * expect(glob.match('foo.ts')).toBeTrue(); + * ``` + */ + match(str: string): boolean; + } + + /** + * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. + * + * When the same timestamp is used multiple times, a monotonically increasing + * counter is appended to allow sorting. The final 8 bytes are + * cryptographically random. When the timestamp changes, the counter resets to + * a psuedo-random integer. + * + * @param encoding "hex" | "base64" | "base64url" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + * + * @example + * ```js + * import { randomUUIDv7 } from "bun"; + * const array = [ + * randomUUIDv7(), + * randomUUIDv7(), + * randomUUIDv7(), + * ] + * [ + * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", + * "0192ce07-8c4f-7d67-805f-0f71581b5622", + * "0192ce07-8c4f-7d68-8170-6816e4451a58" + * ] + * ``` + */ + function randomUUIDv7( + /** + * @default "hex" + */ + encoding?: "hex" | "base64" | "base64url", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): string; + + /** + * Generate a UUIDv7 as a Buffer + * + * @param encoding "buffer" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + */ + function randomUUIDv7( + encoding: "buffer", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): Buffer; + + /** + * Types for `bun.lock` + */ + type BunLockFile = { + lockfileVersion: 0 | 1; + workspaces: { + [workspace: string]: BunLockFileWorkspacePackage; + }; + overrides?: Record; + patchedDependencies?: Record; + trustedDependencies?: string[]; + + /** + * ``` + * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } + * + * // first index is resolution for each type of package + * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] + * symlink -> [ "name@link:path", INFO ] + * folder -> [ "name@file:path", INFO ] + * workspace -> [ "name@workspace:path" ] // workspace is only path + * tarball -> [ "name@tarball", INFO ] + * root -> [ "name@root:", { bin, binDir } ] + * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] + * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] + * ``` + * */ + packages: { + [pkg: string]: BunLockFilePackageArray; + }; + }; + + type BunLockFileBasePackageInfo = { + dependencies?: Record; + devDependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; + optionalPeers?: string[]; + bin?: string | Record; + binDir?: string; + }; + + type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { + name?: string; + version?: string; + }; + + type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { + os?: string | string[]; + cpu?: string | string[]; + bundled?: true; + }; + + /** @see {@link BunLockFile.packages} for more info */ + type BunLockFilePackageArray = + /** npm */ + | [ + pkg: string, + registry: string, + info: BunLockFilePackageInfo, + integrity: string, + ] + /** symlink, folder, tarball */ + | [pkg: string, info: BunLockFilePackageInfo] + /** workspace */ + | [pkg: string] + /** git, github */ + | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] + /** root */ + | [pkg: string, info: Pick]; } diff --git a/packages/bun-types/deprecated.d.ts b/packages/bun-types/deprecated.d.ts index 5a90164689ded8..3eb174db4ded5a 100644 --- a/packages/bun-types/deprecated.d.ts +++ b/packages/bun-types/deprecated.d.ts @@ -1,66 +1,71 @@ declare module "bun" { - /** - * @deprecated Renamed to `ErrorLike` - */ - type Errorlike = ErrorLike; - interface TLSOptions { - /** - * File path to a TLS key - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. - */ - keyFile?: string; - /** - * File path to a TLS certificate - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. - */ - certFile?: string; - /** - * File path to a .pem file for a custom root CA - * - * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. - */ - caFile?: string; - } + /** + * @deprecated Renamed to `ErrorLike` + */ + type Errorlike = ErrorLike; + interface TLSOptions { + /** + * File path to a TLS key + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. + */ + keyFile?: string; + /** + * File path to a TLS certificate + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. + */ + certFile?: string; + /** + * File path to a .pem file for a custom root CA + * + * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. + */ + caFile?: string; + } } declare namespace NodeJS { - interface Process { - /** - * @deprecated This is deprecated; use the "node:assert" module instead. - */ - assert(value: unknown, message?: string | Error): asserts value; - } + interface Process { + /** + * @deprecated This is deprecated; use the "node:assert" module instead. + */ + assert(value: unknown, message?: string | Error): asserts value; + } } declare namespace Bun { - interface MessageEvent { - /** @deprecated */ - initMessageEvent( - type: string, - bubbles?: boolean, - cancelable?: boolean, - data?: any, - origin?: string, - lastEventId?: string, - source?: null, - ): void; - } + interface MessageEvent { + /** @deprecated */ + initMessageEvent( + type: string, + bubbles?: boolean, + cancelable?: boolean, + data?: any, + origin?: string, + lastEventId?: string, + source?: null, + ): void; + } } interface CustomEvent { - /** @deprecated */ - initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void; + /** @deprecated */ + initCustomEvent( + type: string, + bubbles?: boolean, + cancelable?: boolean, + detail?: T, + ): void; } interface DOMException { - /** @deprecated */ - readonly code: number; + /** @deprecated */ + readonly code: number; } /** diff --git a/packages/bun-types/devserver.d.ts b/packages/bun-types/devserver.d.ts index a6ff7d1437b34b..e6b44c040f7127 100644 --- a/packages/bun-types/devserver.d.ts +++ b/packages/bun-types/devserver.d.ts @@ -1,24 +1,24 @@ export {}; declare global { - interface ImportMeta { - /** - * Hot module replacement - * - * https://bun.sh/docs/bundler/fullstack - */ - hot: { - /** - * import.meta.hot.data maintains state between module instances during hot replacement, enabling data transfer from previous to new versions. - * - * @example - * ```ts - * import.meta.hot.data = { - * bun: 'is cool', - * }; - * ``` - */ - data: any; - }; - } + interface ImportMeta { + /** + * Hot module replacement + * + * https://bun.sh/docs/bundler/fullstack + */ + hot: { + /** + * import.meta.hot.data maintains state between module instances during hot replacement, enabling data transfer from previous to new versions. + * + * @example + * ```ts + * import.meta.hot.data = { + * bun: 'is cool', + * }; + * ``` + */ + data: any; + }; + } } diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 58e138bbad8c93..599ffa198190b9 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,114 +1,119 @@ interface Headers { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; } var Headers: { - prototype: Headers; - new (init?: Bun.HeadersInit): Headers; + prototype: Headers; + new (init?: Bun.HeadersInit): Headers; }; interface Request { - headers: Headers; + headers: Headers; } var Request: { - prototype: Request; - new (requestInfo: string, requestInit?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, requestInit?: RequestInit): Request; + prototype: Request; + new (requestInfo: string, requestInit?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, requestInit?: RequestInit): Request; }; var Response: { - new (body?: Bun.BodyInit | null | undefined, init?: Bun.ResponseInit | undefined): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: Bun.ResponseInit | number): Response; + new ( + body?: Bun.BodyInit | null | undefined, + init?: Bun.ResponseInit | undefined, + ): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, options?: Bun.ResponseInit | number): Response; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, status?: number): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, status?: number): Response; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, options?: Bun.ResponseInit): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, options?: Bun.ResponseInit): Response; - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; }; type _BunTLSOptions = import("bun").TLSOptions; interface BunFetchRequestInitTLS extends _BunTLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable; + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable< + import("node:tls").ConnectionOptions["checkServerIdentity"] + >; } /** @@ -119,43 +124,46 @@ interface BunFetchRequestInitTLS extends _BunTLSOptions { * if passed to `new Request()`. This is why it's a separate type. */ interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; + /** + * Override the default TLS options + */ + tls?: BunFetchRequestInitTLS; } var fetch: { - /** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ - (request: Request, init?: BunFetchRequestInit): Promise; + /** + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ + (request: Request, init?: BunFetchRequestInit): Promise; - /** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ - (url: string | URL | Request, init?: BunFetchRequestInit): Promise; + /** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ + (url: string | URL | Request, init?: BunFetchRequestInit): Promise; - (input: string | URL | globalThis.Request, init?: BunFetchRequestInit): Promise; + ( + input: string | URL | globalThis.Request, + init?: BunFetchRequestInit, + ): Promise; - /** - * Start the DNS resolution, TCP connection, and TLS handshake for a request - * before the request is actually sent. - * - * This can reduce the latency of a request when you know there's some - * long-running task that will delay the request starting. - * - * This is a bun-specific API and is not part of the Fetch API specification. - */ - preconnect(url: string | URL): void; + /** + * Start the DNS resolution, TCP connection, and TLS handshake for a request + * before the request is actually sent. + * + * This can reduce the latency of a request when you know there's some + * long-running task that will delay the request starting. + * + * This is a bun-specific API and is not part of the Fetch API specification. + */ + preconnect(url: string | URL): void; }; diff --git a/packages/bun-types/ffi.d.ts b/packages/bun-types/ffi.d.ts index 1f0c1ffdfe8b78..c705348c8298bf 100644 --- a/packages/bun-types/ffi.d.ts +++ b/packages/bun-types/ffi.d.ts @@ -15,1144 +15,1162 @@ * goes to Fabrice Bellard and TinyCC maintainers for making this possible. */ declare module "bun:ffi" { - enum FFIType { - char = 0, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int8_t = 1, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i8 = 1, + enum FFIType { + char = 0, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int8_t = 1, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i8 = 1, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint8_t = 2, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u8 = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint8_t = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u8 = 2, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int16_t = 3, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i16 = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int16_t = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i16 = 3, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint16_t = 4, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u16 = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint16_t = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u16 = 4, - /** - * 32-bit signed integer - */ - int32_t = 5, + /** + * 32-bit signed integer + */ + int32_t = 5, - /** - * 32-bit signed integer - * - * Alias of {@link FFIType.int32_t} - */ - i32 = 5, - /** - * 32-bit signed integer - * - * The same as `int` in C - * - * ```c - * int - * ``` - */ - int = 5, + /** + * 32-bit signed integer + * + * Alias of {@link FFIType.int32_t} + */ + i32 = 5, + /** + * 32-bit signed integer + * + * The same as `int` in C + * + * ```c + * int + * ``` + */ + int = 5, - /** - * 32-bit unsigned integer - * - * The same as `unsigned int` in C (on x64 & arm64) - * - * C: - * ```c - * unsigned int - * ``` - * JavaScript: - * ```js - * ptr(new Uint32Array(1)) - * ``` - */ - uint32_t = 6, - /** - * 32-bit unsigned integer - * - * Alias of {@link FFIType.uint32_t} - */ - u32 = 6, + /** + * 32-bit unsigned integer + * + * The same as `unsigned int` in C (on x64 & arm64) + * + * C: + * ```c + * unsigned int + * ``` + * JavaScript: + * ```js + * ptr(new Uint32Array(1)) + * ``` + */ + uint32_t = 6, + /** + * 32-bit unsigned integer + * + * Alias of {@link FFIType.uint32_t} + */ + u32 = 6, - /** - * int64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - int64_t = 7, - /** - * i64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - i64 = 7, + /** + * int64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + int64_t = 7, + /** + * i64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + i64 = 7, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - uint64_t = 8, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - u64 = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + uint64_t = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + u64 = 8, - /** - * Doubles are not supported yet! - */ - double = 9, - /** - * Doubles are not supported yet! - */ - f64 = 9, - /** - * Floats are not supported yet! - */ - float = 10, - /** - * Floats are not supported yet! - */ - f32 = 10, + /** + * Doubles are not supported yet! + */ + double = 9, + /** + * Doubles are not supported yet! + */ + f64 = 9, + /** + * Floats are not supported yet! + */ + float = 10, + /** + * Floats are not supported yet! + */ + f32 = 10, - /** - * Boolean value - * - * Must be `true` or `false`. `0` and `1` type coercion is not supported. - * - * In C, this corresponds to: - * ```c - * bool - * _Bool - * ``` - */ - bool = 11, + /** + * Boolean value + * + * Must be `true` or `false`. `0` and `1` type coercion is not supported. + * + * In C, this corresponds to: + * ```c + * bool + * _Bool + * ``` + */ + bool = 11, - /** - * Pointer value - * - * See {@link Bun.FFI.ptr} for more information - * - * In C: - * ```c - * void* - * ``` - * - * In JavaScript: - * ```js - * ptr(new Uint8Array(1)) - * ``` - */ - ptr = 12, - /** - * Pointer value - * - * alias of {@link FFIType.ptr} - */ - pointer = 12, + /** + * Pointer value + * + * See {@link Bun.FFI.ptr} for more information + * + * In C: + * ```c + * void* + * ``` + * + * In JavaScript: + * ```js + * ptr(new Uint8Array(1)) + * ``` + */ + ptr = 12, + /** + * Pointer value + * + * alias of {@link FFIType.ptr} + */ + pointer = 12, - /** - * void value - * - * void arguments are not supported - * - * void return type is the default return type - * - * In C: - * ```c - * void - * ``` - */ - void = 13, + /** + * void value + * + * void arguments are not supported + * + * void return type is the default return type + * + * In C: + * ```c + * void + * ``` + */ + void = 13, - /** - * When used as a `returns`, this will automatically become a {@link CString}. - * - * When used in `args` it is equivalent to {@link FFIType.pointer} - */ - cstring = 14, + /** + * When used as a `returns`, this will automatically become a {@link CString}. + * + * When used in `args` it is equivalent to {@link FFIType.pointer} + */ + cstring = 14, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `int64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - i64_fast = 15, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `int64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + i64_fast = 15, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `uint64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - u64_fast = 16, - function = 17, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `uint64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + u64_fast = 16, + function = 17, - napi_env = 18, - napi_value = 19, - buffer = 20, - } + napi_env = 18, + napi_value = 19, + buffer = 20, + } - type Pointer = number & { __pointer__: null }; + type Pointer = number & { __pointer__: null }; - interface FFITypeToArgsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: number | bigint; - [FFIType.i64]: number | bigint; - [FFIType.uint64_t]: number | bigint; - [FFIType.u64]: number | bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.void]: undefined; - [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | JSCallback; // cannot be null - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeToReturnsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: bigint; - [FFIType.i64]: bigint; - [FFIType.uint64_t]: bigint; - [FFIType.u64]: bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: Pointer | null; - [FFIType.pointer]: Pointer | null; - [FFIType.void]: undefined; - [FFIType.cstring]: CString; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | null; - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeStringToType { - ["char"]: FFIType.char; - ["int8_t"]: FFIType.int8_t; - ["i8"]: FFIType.i8; - ["uint8_t"]: FFIType.uint8_t; - ["u8"]: FFIType.u8; - ["int16_t"]: FFIType.int16_t; - ["i16"]: FFIType.i16; - ["uint16_t"]: FFIType.uint16_t; - ["u16"]: FFIType.u16; - ["int32_t"]: FFIType.int32_t; - ["i32"]: FFIType.i32; - ["int"]: FFIType.int; - ["uint32_t"]: FFIType.uint32_t; - ["u32"]: FFIType.u32; - ["int64_t"]: FFIType.int64_t; - ["i64"]: FFIType.i64; - ["uint64_t"]: FFIType.uint64_t; - ["u64"]: FFIType.u64; - ["double"]: FFIType.double; - ["f64"]: FFIType.f64; - ["float"]: FFIType.float; - ["f32"]: FFIType.f32; - ["bool"]: FFIType.bool; - ["ptr"]: FFIType.ptr; - ["pointer"]: FFIType.pointer; - ["void"]: FFIType.void; - ["cstring"]: FFIType.cstring; - ["function"]: FFIType.pointer; // for now - ["usize"]: FFIType.uint64_t; // for now - ["callback"]: FFIType.pointer; // for now - ["napi_env"]: FFIType.napi_env; - ["napi_value"]: FFIType.napi_value; - ["buffer"]: FFIType.buffer; - } + interface FFITypeToArgsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: number | bigint; + [FFIType.i64]: number | bigint; + [FFIType.uint64_t]: number | bigint; + [FFIType.u64]: number | bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.void]: undefined; + [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | JSCallback; // cannot be null + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeToReturnsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: bigint; + [FFIType.i64]: bigint; + [FFIType.uint64_t]: bigint; + [FFIType.u64]: bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: Pointer | null; + [FFIType.pointer]: Pointer | null; + [FFIType.void]: undefined; + [FFIType.cstring]: CString; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | null; + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeStringToType { + ["char"]: FFIType.char; + ["int8_t"]: FFIType.int8_t; + ["i8"]: FFIType.i8; + ["uint8_t"]: FFIType.uint8_t; + ["u8"]: FFIType.u8; + ["int16_t"]: FFIType.int16_t; + ["i16"]: FFIType.i16; + ["uint16_t"]: FFIType.uint16_t; + ["u16"]: FFIType.u16; + ["int32_t"]: FFIType.int32_t; + ["i32"]: FFIType.i32; + ["int"]: FFIType.int; + ["uint32_t"]: FFIType.uint32_t; + ["u32"]: FFIType.u32; + ["int64_t"]: FFIType.int64_t; + ["i64"]: FFIType.i64; + ["uint64_t"]: FFIType.uint64_t; + ["u64"]: FFIType.u64; + ["double"]: FFIType.double; + ["f64"]: FFIType.f64; + ["float"]: FFIType.float; + ["f32"]: FFIType.f32; + ["bool"]: FFIType.bool; + ["ptr"]: FFIType.ptr; + ["pointer"]: FFIType.pointer; + ["void"]: FFIType.void; + ["cstring"]: FFIType.cstring; + ["function"]: FFIType.pointer; // for now + ["usize"]: FFIType.uint64_t; // for now + ["callback"]: FFIType.pointer; // for now + ["napi_env"]: FFIType.napi_env; + ["napi_value"]: FFIType.napi_value; + ["buffer"]: FFIType.buffer; + } - type FFITypeOrString = FFIType | keyof FFITypeStringToType; + type FFITypeOrString = FFIType | keyof FFITypeStringToType; - interface FFIFunction { - /** - * Arguments to a FFI function (C ABI) - * - * Defaults to an empty array, which means no arguments. - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, FFIType, suffix } from "bun:ffi" - * - * const lib = dlopen(`adder.${suffix}`, { - * add: { - * // FFIType can be used or you can pass string labels. - * args: [FFIType.i32, "i32"], - * returns: "i32", - * }, - * }) - * lib.symbols.add(1, 2) - * ``` - * In C: - * ```c - * int add(int a, int b) { - * return a + b; - * } - * ``` - */ - readonly args?: readonly FFITypeOrString[]; - /** - * Return type to a FFI function (C ABI) - * - * Defaults to {@link FFIType.void} - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, CString } from "bun:ffi" - * - * const lib = dlopen('z', { - * version: { - * returns: "ptr", - * } - * }); - * console.log(new CString(lib.symbols.version())); - * ``` - * In C: - * ```c - * char* version() - * { - * return "1.0.0"; - * } - * ``` - */ - readonly returns?: FFITypeOrString; + interface FFIFunction { + /** + * Arguments to a FFI function (C ABI) + * + * Defaults to an empty array, which means no arguments. + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, FFIType, suffix } from "bun:ffi" + * + * const lib = dlopen(`adder.${suffix}`, { + * add: { + * // FFIType can be used or you can pass string labels. + * args: [FFIType.i32, "i32"], + * returns: "i32", + * }, + * }) + * lib.symbols.add(1, 2) + * ``` + * In C: + * ```c + * int add(int a, int b) { + * return a + b; + * } + * ``` + */ + readonly args?: readonly FFITypeOrString[]; + /** + * Return type to a FFI function (C ABI) + * + * Defaults to {@link FFIType.void} + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, CString } from "bun:ffi" + * + * const lib = dlopen('z', { + * version: { + * returns: "ptr", + * } + * }); + * console.log(new CString(lib.symbols.version())); + * ``` + * In C: + * ```c + * char* version() + * { + * return "1.0.0"; + * } + * ``` + */ + readonly returns?: FFITypeOrString; - /** - * Function pointer to the native function - * - * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. - * This pointer should not be null (0). - * - * This is useful if the library has already been loaded - * or if the module is also using Node-API. - */ - readonly ptr?: Pointer | bigint; + /** + * Function pointer to the native function + * + * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. + * This pointer should not be null (0). + * + * This is useful if the library has already been loaded + * or if the module is also using Node-API. + */ + readonly ptr?: Pointer | bigint; - /** - * Can C/FFI code call this function from a separate thread? - * - * Only supported with {@link JSCallback}. - * - * This does not make the function run in a separate thread. It is still up to the application/library - * to run their code in a separate thread. - * - * By default, {@link JSCallback} calls are not thread-safe. Turning this on - * incurs a small performance penalty for every function call. That small - * performance penalty needs to be less than the performance gain from - * running the function in a separate thread. - * - * @default false - */ - readonly threadsafe?: boolean; - } + /** + * Can C/FFI code call this function from a separate thread? + * + * Only supported with {@link JSCallback}. + * + * This does not make the function run in a separate thread. It is still up to the application/library + * to run their code in a separate thread. + * + * By default, {@link JSCallback} calls are not thread-safe. Turning this on + * incurs a small performance penalty for every function call. That small + * performance penalty needs to be less than the performance gain from + * running the function in a separate thread. + * + * @default false + */ + readonly threadsafe?: boolean; + } - type Symbols = Readonly>; + type Symbols = Readonly>; - // /** - // * Compile a callback function - // * - // * Returns a function pointer - // * - // */ - // export function callback(ffi: FFIFunction, cb: Function): number; + // /** + // * Compile a callback function + // * + // * Returns a function pointer + // * + // */ + // export function callback(ffi: FFIFunction, cb: Function): number; - interface Library { - symbols: ConvertFns; + interface Library { + symbols: ConvertFns; - /** - * `dlclose` the library, unloading the symbols and freeing allocated memory. - * - * Once called, the library is no longer usable. - * - * Calling a function from a library that has been closed is undefined behavior. - */ - close(): void; - } + /** + * `dlclose` the library, unloading the symbols and freeing allocated memory. + * + * Once called, the library is no longer usable. + * + * Calling a function from a library that has been closed is undefined behavior. + */ + close(): void; + } - type ToFFIType = T extends FFIType ? T : T extends string ? FFITypeStringToType[T] : never; + type ToFFIType = T extends FFIType + ? T + : T extends string + ? FFITypeStringToType[T] + : never; - const FFIFunctionCallableSymbol: unique symbol; - type ConvertFns = { - [K in keyof Fns]: { - ( - ...args: Fns[K]["args"] extends infer A extends readonly FFITypeOrString[] - ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } - : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [unknown] extends [Fns[K]["args"]] - ? [] - : never - ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - ? undefined - : FFITypeToReturnsType[ToFFIType>]; - __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - }; + const FFIFunctionCallableSymbol: unique symbol; + type ConvertFns = { + [K in keyof Fns]: { + ( + ...args: Fns[K]["args"] extends infer A extends + readonly FFITypeOrString[] + ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } + : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [unknown] extends [Fns[K]["args"]] + ? [] + : never + ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + ? undefined + : FFITypeToReturnsType[ToFFIType>]; + __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + }; - /** - * Open a library using `"bun:ffi"` - * - * @param name The name of the library or file path. This will be passed to `dlopen()` - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import {dlopen} from 'bun:ffi'; - * - * const lib = dlopen("duckdb.dylib", { - * get_version: { - * returns: "cstring", - * args: [], - * }, - * }); - * lib.symbols.get_version(); - * // "1.0.0" - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function dlopen>( - name: string | import("bun").BunFile | URL, - symbols: Fns, - ): Library; + /** + * Open a library using `"bun:ffi"` + * + * @param name The name of the library or file path. This will be passed to `dlopen()` + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import {dlopen} from 'bun:ffi'; + * + * const lib = dlopen("duckdb.dylib", { + * get_version: { + * returns: "cstring", + * args: [], + * }, + * }); + * lib.symbols.get_version(); + * // "1.0.0" + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function dlopen>( + name: string | import("bun").BunFile | URL, + symbols: Fns, + ): Library; - /** - * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. - * - * @param options - * @returns Library - * - * @example - * ## Hello, World! - * - * JavaScript: - * ```js - * import { cc } from "bun:ffi"; - * import hello from "./hello.c" with {type: "file"}; - * const {symbols: {hello}} = cc({ - * source: hello, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * // "Hello, World!" - * console.log(hello()); - * ``` - * - * `./hello.c`: - * ```c - * #include - * const char* hello() { - * return "Hello, World!"; - * } - * ``` - */ - function cc>(options: { - /** - * File path to an ISO C11 source file to compile and link - */ - source: string | import("bun").BunFile | URL; + /** + * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. + * + * @param options + * @returns Library + * + * @example + * ## Hello, World! + * + * JavaScript: + * ```js + * import { cc } from "bun:ffi"; + * import hello from "./hello.c" with {type: "file"}; + * const {symbols: {hello}} = cc({ + * source: hello, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * // "Hello, World!" + * console.log(hello()); + * ``` + * + * `./hello.c`: + * ```c + * #include + * const char* hello() { + * return "Hello, World!"; + * } + * ``` + */ + function cc>(options: { + /** + * File path to an ISO C11 source file to compile and link + */ + source: string | import("bun").BunFile | URL; - /** - * Library names to link against - * - * Equivalent to `-l` option in gcc/clang. - */ - library?: string[] | string; + /** + * Library names to link against + * + * Equivalent to `-l` option in gcc/clang. + */ + library?: string[] | string; - /** - * Include directories to pass to the compiler - * - * Equivalent to `-I` option in gcc/clang. - */ - include?: string[] | string; + /** + * Include directories to pass to the compiler + * + * Equivalent to `-I` option in gcc/clang. + */ + include?: string[] | string; - /** - * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - */ - symbols: Fns; + /** + * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + */ + symbols: Fns; - /** - * Map of symbols to define where the key is the symbol name and the value is the symbol value - * - * Equivalent to `-D` option in gcc/clang. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * define: { - * "NDEBUG": "1", - * }, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - define?: Record; + /** + * Map of symbols to define where the key is the symbol name and the value is the symbol value + * + * Equivalent to `-D` option in gcc/clang. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * define: { + * "NDEBUG": "1", + * }, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + define?: Record; - /** - * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. - * - * @default "-std=c11 -Wl,--export-all-symbols -g -O2" - * - * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * flags: ["-framework CoreFoundation", "-framework Security"], - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - flags?: string | string[]; - }): Library; + /** + * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. + * + * @default "-std=c11 -Wl,--export-all-symbols -g -O2" + * + * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * flags: ["-framework CoreFoundation", "-framework Security"], + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + flags?: string | string[]; + }): Library; - /** - * Turn a native library's function pointer into a JavaScript function - * - * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. - * - * @param fn {@link FFIFunction} declaration. `ptr` is required - * - * @example - * - * ```js - * import {CFunction} from 'bun:ffi'; - * - * const getVersion = new CFunction({ - * returns: "cstring", - * args: [], - * ptr: myNativeLibraryGetVersion, - * }); - * getVersion(); - * getVersion.close(); - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { - /** - * Free the memory allocated by the wrapping function - */ - close(): void; - }; + /** + * Turn a native library's function pointer into a JavaScript function + * + * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. + * + * @param fn {@link FFIFunction} declaration. `ptr` is required + * + * @example + * + * ```js + * import {CFunction} from 'bun:ffi'; + * + * const getVersion = new CFunction({ + * returns: "cstring", + * args: [], + * ptr: myNativeLibraryGetVersion, + * }); + * getVersion(); + * getVersion.close(); + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { + /** + * Free the memory allocated by the wrapping function + */ + close(): void; + }; - /** - * Link a map of symbols to JavaScript functions - * - * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. - * - * You could use this with Node-API to skip loading a second time. - * - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import { linkSymbols } from "bun:ffi"; - * - * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); - * - * const lib = linkSymbols({ - * // Unlike with dlopen(), the names here can be whatever you want - * getMajor: { - * returns: "cstring", - * args: [], - * - * // Since this doesn't use dlsym(), you have to provide a valid ptr - * // That ptr could be a number or a bigint - * // An invalid pointer will crash your program. - * ptr: majorPtr, - * }, - * getMinor: { - * returns: "cstring", - * args: [], - * ptr: minorPtr, - * }, - * getPatch: { - * returns: "cstring", - * args: [], - * ptr: patchPtr, - * }, - * }); - * - * const [major, minor, patch] = [ - * lib.symbols.getMajor(), - * lib.symbols.getMinor(), - * lib.symbols.getPatch(), - * ]; - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function linkSymbols>(symbols: Fns): Library; + /** + * Link a map of symbols to JavaScript functions + * + * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. + * + * You could use this with Node-API to skip loading a second time. + * + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import { linkSymbols } from "bun:ffi"; + * + * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); + * + * const lib = linkSymbols({ + * // Unlike with dlopen(), the names here can be whatever you want + * getMajor: { + * returns: "cstring", + * args: [], + * + * // Since this doesn't use dlsym(), you have to provide a valid ptr + * // That ptr could be a number or a bigint + * // An invalid pointer will crash your program. + * ptr: majorPtr, + * }, + * getMinor: { + * returns: "cstring", + * args: [], + * ptr: minorPtr, + * }, + * getPatch: { + * returns: "cstring", + * args: [], + * ptr: patchPtr, + * }, + * }); + * + * const [major, minor, patch] = [ + * lib.symbols.getMajor(), + * lib.symbols.getMinor(), + * lib.symbols.getPatch(), + * ]; + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function linkSymbols>( + symbols: Fns, + ): Library; - /** - * Read a pointer as a {@link Buffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): Buffer; + /** + * Read a pointer as a {@link Buffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toBuffer( + ptr: Pointer, + byteOffset?: number, + byteLength?: number, + ): Buffer; - /** - * Read a pointer as an {@link ArrayBuffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toArrayBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): ArrayBuffer; + /** + * Read a pointer as an {@link ArrayBuffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toArrayBuffer( + ptr: Pointer, + byteOffset?: number, + byteLength?: number, + ): ArrayBuffer; - namespace read { - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f64(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function ptr(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function intptr(ptr: Pointer, byteOffset?: number): number; - } + namespace read { + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f64(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function ptr(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function intptr(ptr: Pointer, byteOffset?: number): number; + } - /** - * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} - * - * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. - * - * This is for use with FFI functions. For performance reasons, FFI will - * not automatically convert typed arrays to C pointers. - * - * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for - * @param {number} byteOffset optional offset into the view in bytes - * - * @example - * - * From JavaScript: - * ```js - * const array = new Uint8Array(10); - * const rawPtr = ptr(array); - * myFFIFunction(rawPtr); - * ``` - * To C: - * ```c - * void myFFIFunction(char* rawPtr) { - * // Do something with rawPtr - * } - * ``` - */ - function ptr(view: NodeJS.TypedArray | ArrayBufferLike | DataView, byteOffset?: number): Pointer; + /** + * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} + * + * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. + * + * This is for use with FFI functions. For performance reasons, FFI will + * not automatically convert typed arrays to C pointers. + * + * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for + * @param {number} byteOffset optional offset into the view in bytes + * + * @example + * + * From JavaScript: + * ```js + * const array = new Uint8Array(10); + * const rawPtr = ptr(array); + * myFFIFunction(rawPtr); + * ``` + * To C: + * ```c + * void myFFIFunction(char* rawPtr) { + * // Do something with rawPtr + * } + * ``` + */ + function ptr( + view: NodeJS.TypedArray | ArrayBufferLike | DataView, + byteOffset?: number, + ): Pointer; - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ - class CString extends String { - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @param ptr The pointer to the C string - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); + class CString extends String { + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @param ptr The pointer to the C string + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); - /** - * The ptr to the C string - * - * This `CString` instance is a clone of the string, so it - * is safe to continue using this instance after the `ptr` has been - * freed. - */ - ptr: Pointer; - byteOffset?: number; - byteLength?: number; + /** + * The ptr to the C string + * + * This `CString` instance is a clone of the string, so it + * is safe to continue using this instance after the `ptr` has been + * freed. + */ + ptr: Pointer; + byteOffset?: number; + byteLength?: number; - /** - * Get the {@link ptr} as an `ArrayBuffer` - * - * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 - */ - get arrayBuffer(): ArrayBuffer; - } + /** + * Get the {@link ptr} as an `ArrayBuffer` + * + * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 + */ + get arrayBuffer(): ArrayBuffer; + } - /** - * Pass a JavaScript function to FFI (Foreign Function Interface) - */ - class JSCallback { - /** - * Enable a JavaScript callback function to be passed to C with bun:ffi - * - * @param callback The JavaScript function to be called - * @param definition The C function definition - */ - constructor(callback: (...args: any[]) => any, definition: FFIFunction); + /** + * Pass a JavaScript function to FFI (Foreign Function Interface) + */ + class JSCallback { + /** + * Enable a JavaScript callback function to be passed to C with bun:ffi + * + * @param callback The JavaScript function to be called + * @param definition The C function definition + */ + constructor(callback: (...args: any[]) => any, definition: FFIFunction); - /** - * The pointer to the C function - * - * Becomes `null` once {@link JSCallback.prototype.close} is called - */ - readonly ptr: Pointer | null; + /** + * The pointer to the C function + * + * Becomes `null` once {@link JSCallback.prototype.close} is called + */ + readonly ptr: Pointer | null; - /** - * Can the callback be called from a different thread? - */ - readonly threadsafe: boolean; + /** + * Can the callback be called from a different thread? + */ + readonly threadsafe: boolean; - /** - * Free the memory allocated for the callback - * - * If called multiple times, does nothing after the first call. - */ - close(): void; - } + /** + * Free the memory allocated for the callback + * + * If called multiple times, does nothing after the first call. + */ + close(): void; + } - /** - * View the generated C code for FFI bindings - * - * You probably won't need this unless there's a bug in the FFI bindings - * generator or you're just curious. - */ - function viewSource(symbols: Symbols, is_callback?: false): string[]; - function viewSource(callback: FFIFunction, is_callback: true): string; + /** + * View the generated C code for FFI bindings + * + * You probably won't need this unless there's a bug in the FFI bindings + * generator or you're just curious. + */ + function viewSource(symbols: Symbols, is_callback?: false): string[]; + function viewSource(callback: FFIFunction, is_callback: true): string; - /** - * Platform-specific file extension name for dynamic libraries - * - * "." is not included - * - * @example - * ```js - * "dylib" // macOS - * ``` - * - * @example - * ```js - * "so" // linux - * ``` - */ - const suffix: string; + /** + * Platform-specific file extension name for dynamic libraries + * + * "." is not included + * + * @example + * ```js + * "dylib" // macOS + * ``` + * + * @example + * ```js + * "so" // linux + * ``` + */ + const suffix: string; } diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index cade6dc3be4798..f8c1bab554eea7 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1,1770 +1,1875 @@ export {}; type _Event = { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly bubbles: boolean; + /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ + cancelBubble: () => void; + /** True if the event was created with the cancelable option */ + readonly cancelable: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly composed: boolean; + /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ + composedPath(): [EventTarget?]; + /** Alias for event.target. */ + readonly currentTarget: EventTarget | null; + /** Is true if cancelable is true and event.preventDefault() has been called. */ + readonly defaultPrevented: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly eventPhase: 0 | 2; + /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ + readonly isTrusted: boolean; + /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ + preventDefault(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + returnValue: boolean; + /** Alias for event.target. */ + readonly srcElement: EventTarget | null; + /** Stops the invocation of event listeners after the current one completes. */ + stopImmediatePropagation(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + stopPropagation(): void; + /** The `EventTarget` dispatching the event */ + readonly target: EventTarget | null; + /** The millisecond timestamp when the Event object was created. */ + readonly timeStamp: number; + /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ + readonly type: string; }; type _EventTarget = { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; + /** + * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. + * + * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. + * + * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. + * Specifically, the `capture` option is used as part of the key when registering a `listener`. + * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. + */ + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ + dispatchEvent(event: Event): boolean; + /** Removes the event listener in target's event listener list with the same type, callback, and options. */ + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; }; declare global { - var Bun: typeof import("bun"); - - namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - - /** Whether you are using Bun */ - isBun: true; - /** The current git sha of Bun **/ - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - } - - namespace Bun { - type ArrayBufferView = NodeJS.TypedArray | DataView; - type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type PathLike = import("bun").PathLike; - type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; - type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; - type ReadableStreamController = ReadableStreamDefaultController; - type ReadableStreamDefaultReadResult = - | ReadableStreamDefaultReadValueResult - | ReadableStreamDefaultReadDoneResult; - type ReadableStreamReader = ReadableStreamDefaultReader; - type Transferable = ArrayBuffer | import("worker_threads").MessagePort; - type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; - type DOMHighResTimeStamp = number; - type EventListenerOrEventListenerObject = EventListener | EventListenerObject; - - type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob; - - type Platform = - | "aix" - | "android" - | "darwin" - | "freebsd" - | "haiku" - | "linux" - | "openbsd" - | "sunos" - | "win32" - | "cygwin" - | "netbsd"; - type Architecture = "arm" | "arm64" | "ia32" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x" | "x64"; - - 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. - */ - type UnhandledRejectionListener = (reason: unknown, promise: Promise) => void; - - type MultipleResolveListener = (type: MultipleResolveType, promise: Promise, value: unknown) => void; - - type HeadersInit = Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; - - type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; - - type _TextEncoder = import("util").TextEncoder; - interface TextEncoder extends _TextEncoder { - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; - /** - * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object - * containing the read Unicode code units and written UTF-8 bytes. - * - * ```js - * const encoder = new TextEncoder(); - * const src = 'this is some data'; - * const dest = new Uint8Array(10); - * const { read, written } = encoder.encodeInto(src, dest); - * ``` - * @param src The text to encode. - * @param dest The array to hold the encode result. - */ - encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; - } - - type _TextDecoder = import("util").TextDecoder; - interface TextDecoder extends _TextDecoder { - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextDecoder; - } - - 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 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 extends Bun.EventInit { - detail?: T; - } - - /** A message received by a target object. */ - interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; - readonly source: Bun.MessageEventSource | null; - } - - interface ReadableStreamDefaultReadManyResult { - done: boolean; - /** Number of bytes */ - size: number; - value: T[]; - } - - interface ResponseInit { - headers?: HeadersInit; - /** @default 200 */ - status?: number; - - /** @default "OK" */ - statusText?: string; - } - - interface EventSourceEventMap { - error: Event; - message: MessageEvent; - open: Event; - } - - interface EventInit { - bubbles?: boolean; - cancelable?: boolean; - composed?: boolean; - } - - interface EventListenerOptions { - /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ - capture?: boolean; - } - - 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): void; - respondWith(response: Response | Promise): 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( - 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( - 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 { - (controller: TransformStreamDefaultController): void | PromiseLike; - } - - interface TransformerStartCallback { - (controller: TransformStreamDefaultController): any; - } - - interface TransformerTransformCallback { - (chunk: I, controller: TransformStreamDefaultController): void | PromiseLike; - } - - interface UnderlyingSinkAbortCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSinkCloseCallback { - (): void | PromiseLike; - } - - interface UnderlyingSinkStartCallback { - (controller: WritableStreamDefaultController): any; - } - - interface UnderlyingSinkWriteCallback { - (chunk: W, controller: WritableStreamDefaultController): void | PromiseLike; - } - - interface UnderlyingSourceCancelCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSink { - abort?: UnderlyingSinkAbortCallback; - close?: UnderlyingSinkCloseCallback; - start?: UnderlyingSinkStartCallback; - type?: undefined | "default" | "bytes"; - write?: UnderlyingSinkWriteCallback; - } - - interface UnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull?: UnderlyingSourcePullCallback; - start?: UnderlyingSourceStartCallback; - /** - * Mode "bytes" is not currently supported. - */ - type?: undefined; - } - - interface DirectUnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull: (controller: ReadableStreamDirectController) => void | PromiseLike; - type: "direct"; - } - - interface UnderlyingSourcePullCallback { - (controller: ReadableStreamController): void | PromiseLike; - } - - interface UnderlyingSourceStartCallback { - (controller: ReadableStreamController): 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( - type: K, - listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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 | (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( - type: K, - listener: (this: Worker, ev: WorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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; - } - } - - type _ReadableStream = import("stream/web").ReadableStream; - interface ReadableStream extends _ReadableStream {} - var ReadableStream: { - prototype: ReadableStream; - new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - }; - - type _WritableStream = import("stream/web").WritableStream; - interface WritableStream extends _WritableStream {} - var WritableStream: { - prototype: WritableStream; - new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; - }; - - type _Worker = import("worker_threads").Worker; - interface Worker extends _Worker {} - var Worker: { - prototype: Worker; - new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; - }; - - var WebSocket: typeof import("ws").WebSocket; - - type _Crypto = import("crypto").webcrypto.Crypto; - interface Crypto extends _Crypto {} - var Crypto: { - prototype: Crypto; - new (): Crypto; - }; - - var crypto: Crypto; - - /** - * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All - * instances of `TextEncoder` only support UTF-8 encoding. - * - * ```js - * const encoder = new TextEncoder(); - * const uint8array = encoder.encode('this is some data'); - * ``` - */ - interface TextEncoder extends Bun.TextEncoder {} - var TextEncoder: typeof TextEncoder; - - interface TextDecoder extends Bun.TextDecoder {} - var TextDecoder: typeof TextDecoder; - - type _Performance = import("perf_hooks").Performance; - interface Performance extends _Performance {} - var performance: Performance; - - interface Event extends _Event {} - var Event: { - prototype: Event; - new (type: string, eventInitDict?: Bun.EventInit): Event; - }; - - interface EventTarget extends _EventTarget {} - var EventTarget: { - prototype: EventTarget; - new (): EventTarget; - }; - - interface File extends Blob { - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; - readonly lastModified: number; - readonly name: string; - } - - var File: typeof File; - - type _RequestInit = import("undici-types").RequestInit; - interface RequestInit extends _RequestInit { - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: import("bun").S3Options; - } - - /** - * ShadowRealms are a distinct global environment, with its own global object - * containing its own intrinsics and built-ins (standard objects that are not - * bound to global variables, like the initial value of Object.prototype). - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - interface ShadowRealm { - /** - * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; - } - - var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; - }; - - function queueMicrotask(callback: (...args: any[]) => void): void; - /** - * Log an error using the default exception handler - * @param error Error or string - */ - function reportError(error: any): void; - - interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; - - [Symbol.toPrimitive](): number; - } - - /** - * Cancel a repeating timer by its timer ID. - * @param id timer id - */ - function clearInterval(id?: number | Timer): void; - /** - * Cancel a delayed function call by its timer ID. - * @param id timer id - */ - function clearTimeout(id?: number | Timer): void; - /** - * Cancel an immediate function call by its immediate ID. - * @param id immediate id - */ - function clearImmediate(id?: number | Timer): void; - /** - * Run a function immediately after main event loop is vacant - * @param handler function to call - */ - function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; - /** - * Run a function every `interval` milliseconds - * @param handler function to call - * @param interval milliseconds to wait between calls - */ - function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; - /** - * Run a function after `timeout` (milliseconds) - * @param handler function to call - * @param timeout milliseconds to wait between calls - */ - function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; - - function addEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - function addEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - function removeEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | Bun.EventListenerOptions, - ): void; - function removeEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | Bun.EventListenerOptions, - ): void; - - /** - * Events providing information related to errors in scripts or in files. - */ - interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; - } - - var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; - }; - - /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ - interface CloseEvent extends Event { - /** Returns the WebSocket connection close code provided by the server. */ - readonly code: number; - /** Returns the WebSocket connection close reason provided by the server. */ - readonly reason: string; - /** Returns true if the connection closed cleanly; false otherwise. */ - readonly wasClean: boolean; - } - - var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; - }; - - interface MessageEvent extends Bun.MessageEvent {} - var MessageEvent: { - prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; - }; - - interface CustomEvent extends Event { - /** Returns any custom data event was created with. Typically used for synthetic events. */ - readonly detail: T; - } - - var CustomEvent: { - prototype: CustomEvent; - new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; - }; - - // /** - // * The URL interface represents an object providing static methods used for - // * creating object URLs. - // */ - // interface URL extends _URL { - // new (url: string | URL, base?: string | URL): URL; - // /** Not implemented yet */ - // createObjectURL(obj: Blob): string; - // /** Not implemented yet */ - // revokeObjectURL(url: string): void; - - // /** - // * Check if `url` is a valid URL string - // * - // * @param url URL string to parse - // * @param base URL to resolve against - // */ - // canParse(url: string, base?: string): boolean; - // } - - interface EventListener { - (evt: Event): void; - } - - interface EventListenerObject { - handleEvent(object: Event): void; - } - - interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; - - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; - } - - interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; - // exit: Event; - } - - interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; - } - - /** - * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) - * - * Before using this, be aware of a few things: - * - * **Using this incorrectly will crash your application**. - * - * This API may change any time JavaScriptCore is updated. - * - * Bun may rewrite ESM import specifiers to point to bundled code. This will - * be confusing when using this API, as it will return a string like - * "/node_modules.server.bun". - * - * Bun may inject additional imports into your code. This usually has a `bun:` prefix. - */ - var Loader: { - /** - * ESM module registry - * - * This lets you implement live reload in Bun. If you - * delete a module specifier from this map, the next time it's imported, it - * will be re-transpiled and loaded again. - * - * The keys are the module specifiers and the - * values are metadata about the module. - * - * The keys are an implementation detail for Bun that will change between - * versions. - * - * - Userland modules are an absolute file path - * - Virtual modules have a `bun:` prefix or `node:` prefix - * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill - * - If you have a `node_modules.bun` file, many modules will point to that file - * - * Virtual modules and JS polyfills are embedded in bun's binary. They don't - * point to anywhere in your local filesystem. - */ - registry: Map< - string, - { - key: string; - /** - * This refers to the state the ESM module is in - * - * TODO: make an enum for this number - */ - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; - /** - * Your application will probably crash if you mess with this. - */ - module: { - dependenciesMap: (typeof Loader)["registry"]; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - /** - * For an already-evaluated module, return the dependencies as module specifiers - * - * This list is already sorted and uniqued. - * - * @example - * - * For this code: - * ```js - * // /foo.js - * import classNames from 'classnames'; - * import React from 'react'; - * import {createElement} from 'react'; - * ``` - * - * This would return: - * ```js - * Loader.dependencyKeysIfEvaluated("/foo.js") - * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] - * ``` - * - * @param specifier - module specifier as it appears in transpiled source code - */ - dependencyKeysIfEvaluated: (specifier: string) => string[]; - /** - * The function JavaScriptCore internally calls when you use an import statement. - * - * This may return a path to `node_modules.server.bun`, which will be confusing. - * - * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} - * instead. - * - * @param specifier - module specifier as it appears in transpiled source code - * @param referrer - module specifier that is resolving this specifier - */ - resolve: (specifier: string, referrer: string) => string; - }; - - interface QueuingStrategy { - highWaterMark?: number; - size?: QueuingStrategySize; - } - - interface QueuingStrategyInit { - /** - * Creates a new ByteLengthQueuingStrategy with the provided high water mark. - * - * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. - */ - highWaterMark: number; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface ByteLengthQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - // changed from QueuingStrategySize - // to avoid conflict with lib.dom.d.ts - readonly size: QueuingStrategySize; - } - - var ByteLengthQueuingStrategy: { - prototype: ByteLengthQueuingStrategy; - new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; - }; - - interface ReadableStreamDefaultController { - readonly desiredSize: number | null; - close(): void; - enqueue(chunk?: R): void; - error(e?: any): void; - } - - interface ReadableStreamDirectController { - close(error?: Error): void; - write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; - end(): number | Promise; - flush(): number | Promise; - start(): void; - } - - var ReadableStreamDefaultController: { - prototype: ReadableStreamDefaultController; - new (): ReadableStreamDefaultController; - }; - - interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { - read(): Promise>; - /** - * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. - * Will only return a promise if the data is not immediately available. - */ - readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; - releaseLock(): void; - } - - var ReadableStreamDefaultReader: { - prototype: ReadableStreamDefaultReader; - new (stream: ReadableStream): ReadableStreamDefaultReader; - }; - - interface ReadableStreamGenericReader { - readonly closed: Promise; - cancel(reason?: any): Promise; - } - - interface ReadableStreamDefaultReadDoneResult { - done: true; - value?: undefined; - } - - interface ReadableStreamDefaultReadValueResult { - done: false; - value: T; - } - - interface ReadableWritablePair { - readable: ReadableStream; - /** - * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - */ - writable: WritableStream; - } - - interface WritableStreamDefaultController { - error(e?: any): void; - } - - var WritableStreamDefaultController: { - prototype: WritableStreamDefaultController; - new (): WritableStreamDefaultController; - }; - - /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ - interface WritableStreamDefaultWriter { - readonly closed: Promise; - readonly desiredSize: number | null; - readonly ready: Promise; - abort(reason?: any): Promise; - close(): Promise; - releaseLock(): void; - write(chunk?: W): Promise; - } - - var WritableStreamDefaultWriter: { - prototype: WritableStreamDefaultWriter; - new (stream: WritableStream): WritableStreamDefaultWriter; - }; - - interface TransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; - } - - var TransformStream: { - prototype: TransformStream; - new ( - transformer?: Transformer, - writableStrategy?: QueuingStrategy, - readableStrategy?: QueuingStrategy, - ): TransformStream; - }; - - interface TransformStreamDefaultController { - readonly desiredSize: number | null; - enqueue(chunk?: O): void; - error(reason?: any): void; - terminate(): void; - } - - var TransformStreamDefaultController: { - prototype: TransformStreamDefaultController; - new (): TransformStreamDefaultController; - }; - - interface StreamPipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - /** - * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - * - * Errors and closures of the source and destination streams propagate as follows: - * - * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. - * - * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. - * - * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. - * - * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. - * - * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. - */ - preventClose?: boolean; - signal?: AbortSignal; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface CountQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - readonly size: QueuingStrategySize; - } - - var CountQueuingStrategy: { - prototype: CountQueuingStrategy; - new (init: QueuingStrategyInit): CountQueuingStrategy; - }; - - interface QueuingStrategySize { - (chunk?: T): number; - } - - interface Transformer { - flush?: Bun.TransformerFlushCallback; - readableType?: undefined; - start?: Bun.TransformerStartCallback; - transform?: Bun.TransformerTransformCallback; - writableType?: undefined; - } - - interface Dict { - [key: string]: T | undefined; - } - - interface ReadOnlyDict { - readonly [key: string]: T | undefined; - } - - interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; - } - - /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ - interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; - } - - var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; - }; - - function alert(message?: string): void; - function confirm(message?: string): boolean; - function prompt(message?: string, _default?: string): string | null; - - type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; - var SubtleCrypto: { - prototype: _SubtleCrypto; - new (): _SubtleCrypto; - }; - - type _CryptoKey = import("crypto").webcrypto.CryptoKey; - interface CryptoKey extends _CryptoKey {} - var CryptoKey: { - prototype: CryptoKey; - new (): CryptoKey; - }; - - interface Position { - lineText: string; - file: string; - namespace: string; - line: number; - column: number; - length: number; - offset: number; - } - - class ResolveMessage { - readonly name: "ResolveMessage"; - readonly position: Position | null; - readonly code: string; - readonly message: string; - readonly referrer: string; - readonly specifier: string; - readonly importKind: - | "entry_point" - | "stmt" - | "require" - | "import" - | "dynamic" - | "require_resolve" - | "at" - | "at_conditional" - | "url" - | "internal"; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - - toString(): string; - } - - class BuildMessage { - readonly name: "BuildMessage"; - readonly position: Position | null; - readonly message: string; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - } - - // Declare "static" methods in Error - interface ErrorConstructor { - /** Create .stack property on a target object */ - // eslint-disable-next-line @typescript-eslint/ban-types - captureStackTrace(targetObject: object, constructorOpt?: Function): void; - - /** - * Optional override for formatting stack traces - * - * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces - */ - prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; - - stackTraceLimit: number; - } - - interface ArrayBufferConstructor { - new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; - } - - interface ArrayBuffer { - /** - * Read-only. The length of the ArrayBuffer (in bytes). - */ - readonly byteLength: number; - /** - * Resize an ArrayBuffer in-place. - */ - resize(byteLength: number): ArrayBuffer; - - /** - * Returns a section of an ArrayBuffer. - */ - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; - } - - interface SharedArrayBuffer { - /** - * Grow the SharedArrayBuffer in-place. - */ - grow(size: number): SharedArrayBuffer; - } - - interface ArrayConstructor { - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; - - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. Results of the map function are also awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * await Array.fromAsync([1], (n) => n + 1); // [2] - * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. - * @param thisArg - The `this` to which `mapFn` is bound. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; - } - - interface ConsoleOptions { - stdout: import("stream").Writable; - stderr?: import("stream").Writable; - ignoreErrors?: boolean; - colorMode?: boolean | "auto"; - inspectOptions?: import("util").InspectOptions; - groupIndentation?: number; - } - - interface Console { - /** - * Asynchronously read lines from standard input (fd 0) - * - * ```ts - * for await (const line of console) { - * console.log(line); - * } - * ``` - */ - [Symbol.asyncIterator](): AsyncIterableIterator; - - /** - * Write text or bytes to stdout - * - * Unlike {@link console.log}, this does no formatting and doesn't add a - * newline or spaces between arguments. You can pass it strings or bytes or - * any combination of the two. - * - * ```ts - * console.write("hello world!", "\n"); // "hello world\n" - * ``` - * - * @param data - The data to write - * @returns The number of bytes written - * - * This function is not available in the browser. - */ - write(...data: Array): number; - - /** - * Clear the console - */ - clear(): void; - - assert(condition?: boolean, ...data: any[]): void; - - /** - * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) - * @param label label counter - */ - count(label?: string): void; - countReset(label?: string): void; - debug(...data: any[]): void; - dir(item?: any, options?: any): void; - dirxml(...data: any[]): void; - /** - * Log to stderr in your terminal - * - * Appears in red - * - * @param data something to display - */ - error(...data: any[]): void; - /** Does nothing currently */ - group(...data: any[]): void; - /** Does nothing currently */ - groupCollapsed(...data: any[]): void; - /** Does nothing currently */ - groupEnd(): void; - info(...data: any[]): void; - log(...data: any[]): void; - /** - * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just - * logging the argument if it can't be parsed as tabular. - * - * ```js - * // These can't be parsed as tabular data - * console.table(Symbol()); - * // Symbol() - * - * console.table(undefined); - * // undefined - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ b โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * ``` - * @param properties Alternate properties for constructing the table. - */ - table(tabularData?: any, properties?: string[]): void; - /** - * Begin a timer to log with {@link console.timeEnd} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - time(label?: string): void; - /** - * End a timer to log with {@link console.time} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - timeEnd(label?: string): void; - timeLog(label?: string, ...data: any[]): void; - timeStamp(label?: string): void; - trace(...data: any[]): void; - warn(...data: any[]): void; - - /** - * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. - */ - // Console: { - // new (options: ConsoleOptions): Console; - // new ( - // stdout: import("stream").Writable, - // stderr?: import("stream").Writable, - // ignoreErrors?: boolean, - // ): Console; - // }; - } - - var console: Console; - - interface ImportMeta { - /** - * `file://` url string for the current module. - * - * @example - * ```ts - * console.log(import.meta.url); - * "file:///Users/me/projects/my-app/src/my-app.ts" - * ``` - */ - url: string; - /** - * Absolute path to the source file - */ - readonly path: string; - /** - * Absolute path to the directory containing the source file. - * - * Does not have a trailing slash - */ - readonly dir: string; - /** - * Filename of the source file - */ - readonly file: string; - /** - * The environment variables of the process - * - * ```ts - * import.meta.env === process.env - * ``` - */ - readonly env: NodeJS.ProcessEnv; - - /** - * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead - * - * Resolve a module ID the same as if you imported it - * - * The `parent` argument is optional, and defaults to the current module's path. - */ - resolveSync(moduleId: string, parent?: string): string; - - /** - * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all - * calls to `require` with `import.meta.require` when transpiling ES Modules - * for the runtime. - * - * Warning: **This API is not stable** and may change or be removed in the - * future. Use at your own risk. - */ - require: NodeJS.Require; - - /** - * Did the current file start the process? - * - * @example - * ```ts - * if (import.meta.main) { - * console.log("I started the process!"); - * } - * ``` - * - * @example - * ```ts - * console.log( - * import.meta.main === (import.meta.path === Bun.main) - * ) - * ``` - */ - readonly main: boolean; - - /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ - dirname: string; - - /** Alias of `import.meta.path`. Exists for Node.js compatibility */ - filename: string; - } - - /** - * NodeJS-style `require` function - * - * @param moduleId - The module ID to resolve - */ - var require: NodeJS.Require; - - /** Same as module.exports */ - var exports: any; - - interface NodeModule { - exports: any; - } - - var module: NodeModule; - - /** - * Creates a deep clone of an object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) - */ - function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; - - /** - * Post a message to the parent thread. - * - * Only useful in a worker thread; calling this from the main thread does nothing. - */ - function postMessage(message: any, transfer?: Bun.Transferable[]): void; - - interface EventSourceInit { - withCredentials?: boolean; - } - - interface PromiseConstructor { - /** - * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called - * separately. - * - * This is useful when you want to return a Promise and have code outside the Promise - * resolve or reject it. - * - * ## Example - * ```ts - * const { promise, resolve, reject } = Promise.withResolvers(); - * - * setTimeout(() => { - * resolve("Hello world!"); - * }, 1000); - * - * await promise; // "Hello world!" - * ``` - * - * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). - */ - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; - } - - interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; - } - - var navigator: Navigator; - - interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; - } - - interface Blob { - /** - * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - */ - new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; - /** - * Read the data from the blob as a JSON object. - * - * This first decodes the data from UTF-8, then parses it as JSON. - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - json(): Promise; - - /** - * Read the data from the blob as a {@link FormData} object. - * - * This first decodes the data from UTF-8, then parses it as a - * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. - * - * The `type` property of the blob is used to determine the format of the - * body. - * - * This is a non-standard addition to the `Blob` API, to make it conform more - * closely to the `BodyMixin` API. - */ - formData(): Promise; - - arrayBuffer(): Promise; - - /** - * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` - */ - bytes(): Promise; - } - - var Blob: typeof Blob; + var Bun: typeof import("bun"); + + namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; + + /** Whether you are using Bun */ + isBun: true; + /** The current git sha of Bun **/ + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + } + + namespace Bun { + type ArrayBufferView = NodeJS.TypedArray | DataView; + type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; + type PathLike = import("bun").PathLike; + type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; + type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; + type ReadableStreamController = ReadableStreamDefaultController; + type ReadableStreamDefaultReadResult = + | ReadableStreamDefaultReadValueResult + | ReadableStreamDefaultReadDoneResult; + type ReadableStreamReader = ReadableStreamDefaultReader; + type Transferable = ArrayBuffer | import("worker_threads").MessagePort; + type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; + type DOMHighResTimeStamp = number; + type EventListenerOrEventListenerObject = + | EventListener + | EventListenerObject; + + type BlobOrStringOrBuffer = + | string + | NodeJS.TypedArray + | ArrayBufferLike + | Blob; + + type Platform = + | "aix" + | "android" + | "darwin" + | "freebsd" + | "haiku" + | "linux" + | "openbsd" + | "sunos" + | "win32" + | "cygwin" + | "netbsd"; + type Architecture = + | "arm" + | "arm64" + | "ia32" + | "mips" + | "mipsel" + | "ppc" + | "ppc64" + | "s390" + | "s390x" + | "x64"; + + 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. + */ + type UnhandledRejectionListener = ( + reason: unknown, + promise: Promise, + ) => void; + + type MultipleResolveListener = ( + type: MultipleResolveType, + promise: Promise, + value: unknown, + ) => void; + + type HeadersInit = + | Headers + | Record + | Array<[string, string]> + | IterableIterator<[string, string]>; + + type ResponseType = + | "basic" + | "cors" + | "default" + | "error" + | "opaque" + | "opaqueredirect"; + + type _TextEncoder = import("util").TextEncoder; + interface TextEncoder extends _TextEncoder { + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): TextEncoder; + /** + * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object + * containing the read Unicode code units and written UTF-8 bytes. + * + * ```js + * const encoder = new TextEncoder(); + * const src = 'this is some data'; + * const dest = new Uint8Array(10); + * const { read, written } = encoder.encodeInto(src, dest); + * ``` + * @param src The text to encode. + * @param dest The array to hold the encode result. + */ + encodeInto( + src?: string, + dest?: Bun.BufferSource, + ): import("util").EncodeIntoResult; + } + + type _TextDecoder = import("util").TextDecoder; + interface TextDecoder extends _TextDecoder { + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): TextDecoder; + } + + 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 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 extends Bun.EventInit { + detail?: T; + } + + /** A message received by a target object. */ + interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; + readonly source: Bun.MessageEventSource | null; + } + + interface ReadableStreamDefaultReadManyResult { + done: boolean; + /** Number of bytes */ + size: number; + value: T[]; + } + + interface ResponseInit { + headers?: HeadersInit; + /** @default 200 */ + status?: number; + + /** @default "OK" */ + statusText?: string; + } + + interface EventSourceEventMap { + error: Event; + message: MessageEvent; + open: Event; + } + + interface EventInit { + bubbles?: boolean; + cancelable?: boolean; + composed?: boolean; + } + + interface EventListenerOptions { + /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ + capture?: boolean; + } + + 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): void; + respondWith(response: Response | Promise): 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( + 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( + 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 { + ( + controller: TransformStreamDefaultController, + ): void | PromiseLike; + } + + interface TransformerStartCallback { + (controller: TransformStreamDefaultController): any; + } + + interface TransformerTransformCallback { + ( + chunk: I, + controller: TransformStreamDefaultController, + ): void | PromiseLike; + } + + interface UnderlyingSinkAbortCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSinkCloseCallback { + (): void | PromiseLike; + } + + interface UnderlyingSinkStartCallback { + (controller: WritableStreamDefaultController): any; + } + + interface UnderlyingSinkWriteCallback { + ( + chunk: W, + controller: WritableStreamDefaultController, + ): void | PromiseLike; + } + + interface UnderlyingSourceCancelCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSink { + abort?: UnderlyingSinkAbortCallback; + close?: UnderlyingSinkCloseCallback; + start?: UnderlyingSinkStartCallback; + type?: undefined | "default" | "bytes"; + write?: UnderlyingSinkWriteCallback; + } + + interface UnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull?: UnderlyingSourcePullCallback; + start?: UnderlyingSourceStartCallback; + /** + * Mode "bytes" is not currently supported. + */ + type?: undefined; + } + + interface DirectUnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull: ( + controller: ReadableStreamDirectController, + ) => void | PromiseLike; + type: "direct"; + } + + interface UnderlyingSourcePullCallback { + (controller: ReadableStreamController): void | PromiseLike; + } + + interface UnderlyingSourceStartCallback { + (controller: ReadableStreamController): 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( + type: K, + listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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 + | 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( + type: K, + listener: (this: Worker, ev: WorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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; + } + } + + type _ReadableStream = import("stream/web").ReadableStream; + interface ReadableStream extends _ReadableStream {} + var ReadableStream: { + prototype: ReadableStream; + new ( + underlyingSource?: Bun.UnderlyingSource, + strategy?: QueuingStrategy, + ): ReadableStream; + new ( + underlyingSource?: Bun.DirectUnderlyingSource, + strategy?: QueuingStrategy, + ): ReadableStream; + }; + + type _WritableStream = import("stream/web").WritableStream; + interface WritableStream extends _WritableStream {} + var WritableStream: { + prototype: WritableStream; + new ( + underlyingSink?: Bun.UnderlyingSink, + strategy?: QueuingStrategy, + ): WritableStream; + }; + + type _Worker = import("worker_threads").Worker; + interface Worker extends _Worker {} + var Worker: { + prototype: Worker; + new ( + scriptURL: string | URL, + options?: Bun.WorkerOptions | undefined, + ): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; + }; + + var WebSocket: typeof import("ws").WebSocket; + + type _Crypto = import("crypto").webcrypto.Crypto; + interface Crypto extends _Crypto {} + var Crypto: { + prototype: Crypto; + new (): Crypto; + }; + + var crypto: Crypto; + + /** + * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All + * instances of `TextEncoder` only support UTF-8 encoding. + * + * ```js + * const encoder = new TextEncoder(); + * const uint8array = encoder.encode('this is some data'); + * ``` + */ + interface TextEncoder extends Bun.TextEncoder {} + var TextEncoder: typeof TextEncoder; + + interface TextDecoder extends Bun.TextDecoder {} + var TextDecoder: typeof TextDecoder; + + type _Performance = import("perf_hooks").Performance; + interface Performance extends _Performance {} + var performance: Performance; + + interface Event extends _Event {} + var Event: { + prototype: Event; + new (type: string, eventInitDict?: Bun.EventInit): Event; + }; + + interface EventTarget extends _EventTarget {} + var EventTarget: { + prototype: EventTarget; + new (): EventTarget; + }; + + interface File extends Blob { + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new ( + parts: Bun.BlobPart[], + name: string, + options?: BlobPropertyBag & { lastModified?: Date | number }, + ): File; + readonly lastModified: number; + readonly name: string; + } + + var File: typeof File; + + type _RequestInit = import("undici-types").RequestInit; + interface RequestInit extends _RequestInit { + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: import("bun").S3Options; + } + + /** + * ShadowRealms are a distinct global environment, with its own global object + * containing its own intrinsics and built-ins (standard objects that are not + * bound to global variables, like the initial value of Object.prototype). + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + interface ShadowRealm { + /** + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; + } + + var ShadowRealm: { + prototype: ShadowRealm; + new (): ShadowRealm; + }; + + function queueMicrotask(callback: (...args: any[]) => void): void; + /** + * Log an error using the default exception handler + * @param error Error or string + */ + function reportError(error: any): void; + + interface Timer { + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; + + [Symbol.toPrimitive](): number; + } + + /** + * Cancel a repeating timer by its timer ID. + * @param id timer id + */ + function clearInterval(id?: number | Timer): void; + /** + * Cancel a delayed function call by its timer ID. + * @param id timer id + */ + function clearTimeout(id?: number | Timer): void; + /** + * Cancel an immediate function call by its immediate ID. + * @param id immediate id + */ + function clearImmediate(id?: number | Timer): void; + /** + * Run a function immediately after main event loop is vacant + * @param handler function to call + */ + function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; + /** + * Run a function every `interval` milliseconds + * @param handler function to call + * @param interval milliseconds to wait between calls + */ + function setInterval( + handler: Bun.TimerHandler, + interval?: number, + ...arguments: any[] + ): Timer; + /** + * Run a function after `timeout` (milliseconds) + * @param handler function to call + * @param timeout milliseconds to wait between calls + */ + function setTimeout( + handler: Bun.TimerHandler, + timeout?: number, + ...arguments: any[] + ): Timer; + + function addEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + function addEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + function removeEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | Bun.EventListenerOptions, + ): void; + function removeEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | Bun.EventListenerOptions, + ): void; + + /** + * Events providing information related to errors in scripts or in files. + */ + interface ErrorEvent extends Event { + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; + } + + var ErrorEvent: { + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; + }; + + /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ + interface CloseEvent extends Event { + /** Returns the WebSocket connection close code provided by the server. */ + readonly code: number; + /** Returns the WebSocket connection close reason provided by the server. */ + readonly reason: string; + /** Returns true if the connection closed cleanly; false otherwise. */ + readonly wasClean: boolean; + } + + var CloseEvent: { + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; + }; + + interface MessageEvent extends Bun.MessageEvent {} + var MessageEvent: { + prototype: MessageEvent; + new ( + type: string, + eventInitDict?: Bun.MessageEventInit, + ): MessageEvent; + }; + + interface CustomEvent extends Event { + /** Returns any custom data event was created with. Typically used for synthetic events. */ + readonly detail: T; + } + + var CustomEvent: { + prototype: CustomEvent; + new ( + type: string, + eventInitDict?: Bun.CustomEventInit, + ): CustomEvent; + }; + + // /** + // * The URL interface represents an object providing static methods used for + // * creating object URLs. + // */ + // interface URL extends _URL { + // new (url: string | URL, base?: string | URL): URL; + // /** Not implemented yet */ + // createObjectURL(obj: Blob): string; + // /** Not implemented yet */ + // revokeObjectURL(url: string): void; + + // /** + // * Check if `url` is a valid URL string + // * + // * @param url URL string to parse + // * @param base URL to resolve against + // */ + // canParse(url: string, base?: string): boolean; + // } + + interface EventListener { + (evt: Event): void; + } + + interface EventListenerObject { + handleEvent(object: Event): void; + } + + interface FetchEvent extends Event { + readonly request: Request; + readonly url: string; + + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; + } + + interface EventMap { + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; + // exit: Event; + } + + interface AddEventListenerOptions extends Bun.EventListenerOptions { + once?: boolean; + passive?: boolean; + signal?: AbortSignal; + } + + /** + * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) + * + * Before using this, be aware of a few things: + * + * **Using this incorrectly will crash your application**. + * + * This API may change any time JavaScriptCore is updated. + * + * Bun may rewrite ESM import specifiers to point to bundled code. This will + * be confusing when using this API, as it will return a string like + * "/node_modules.server.bun". + * + * Bun may inject additional imports into your code. This usually has a `bun:` prefix. + */ + var Loader: { + /** + * ESM module registry + * + * This lets you implement live reload in Bun. If you + * delete a module specifier from this map, the next time it's imported, it + * will be re-transpiled and loaded again. + * + * The keys are the module specifiers and the + * values are metadata about the module. + * + * The keys are an implementation detail for Bun that will change between + * versions. + * + * - Userland modules are an absolute file path + * - Virtual modules have a `bun:` prefix or `node:` prefix + * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill + * - If you have a `node_modules.bun` file, many modules will point to that file + * + * Virtual modules and JS polyfills are embedded in bun's binary. They don't + * point to anywhere in your local filesystem. + */ + registry: Map< + string, + { + key: string; + /** + * This refers to the state the ESM module is in + * + * TODO: make an enum for this number + */ + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array< + (typeof Loader)["registry"] extends Map ? V : any + >; + /** + * Your application will probably crash if you mess with this. + */ + module: { + dependenciesMap: (typeof Loader)["registry"]; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; + /** + * For an already-evaluated module, return the dependencies as module specifiers + * + * This list is already sorted and uniqued. + * + * @example + * + * For this code: + * ```js + * // /foo.js + * import classNames from 'classnames'; + * import React from 'react'; + * import {createElement} from 'react'; + * ``` + * + * This would return: + * ```js + * Loader.dependencyKeysIfEvaluated("/foo.js") + * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] + * ``` + * + * @param specifier - module specifier as it appears in transpiled source code + */ + dependencyKeysIfEvaluated: (specifier: string) => string[]; + /** + * The function JavaScriptCore internally calls when you use an import statement. + * + * This may return a path to `node_modules.server.bun`, which will be confusing. + * + * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} + * instead. + * + * @param specifier - module specifier as it appears in transpiled source code + * @param referrer - module specifier that is resolving this specifier + */ + resolve: (specifier: string, referrer: string) => string; + }; + + interface QueuingStrategy { + highWaterMark?: number; + size?: QueuingStrategySize; + } + + interface QueuingStrategyInit { + /** + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. + */ + highWaterMark: number; + } + + /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ + interface ByteLengthQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + // changed from QueuingStrategySize + // to avoid conflict with lib.dom.d.ts + readonly size: QueuingStrategySize; + } + + var ByteLengthQueuingStrategy: { + prototype: ByteLengthQueuingStrategy; + new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; + }; + + interface ReadableStreamDefaultController { + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; + } + + interface ReadableStreamDirectController { + close(error?: Error): void; + write( + data: Bun.BufferSource | ArrayBuffer | string, + ): number | Promise; + end(): number | Promise; + flush(): number | Promise; + start(): void; + } + + var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; + }; + + interface ReadableStreamDefaultReader + extends ReadableStreamGenericReader { + read(): Promise>; + /** + * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. + * Will only return a promise if the data is not immediately available. + */ + readMany(): + | Promise> + | Bun.ReadableStreamDefaultReadManyResult; + releaseLock(): void; + } + + var ReadableStreamDefaultReader: { + prototype: ReadableStreamDefaultReader; + new (stream: ReadableStream): ReadableStreamDefaultReader; + }; + + interface ReadableStreamGenericReader { + readonly closed: Promise; + cancel(reason?: any): Promise; + } + + interface ReadableStreamDefaultReadDoneResult { + done: true; + value?: undefined; + } + + interface ReadableStreamDefaultReadValueResult { + done: false; + value: T; + } + + interface ReadableWritablePair { + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; + } + + interface WritableStreamDefaultController { + error(e?: any): void; + } + + var WritableStreamDefaultController: { + prototype: WritableStreamDefaultController; + new (): WritableStreamDefaultController; + }; + + /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ + interface WritableStreamDefaultWriter { + readonly closed: Promise; + readonly desiredSize: number | null; + readonly ready: Promise; + abort(reason?: any): Promise; + close(): Promise; + releaseLock(): void; + write(chunk?: W): Promise; + } + + var WritableStreamDefaultWriter: { + prototype: WritableStreamDefaultWriter; + new (stream: WritableStream): WritableStreamDefaultWriter; + }; + + interface TransformStream { + readonly readable: ReadableStream; + readonly writable: WritableStream; + } + + var TransformStream: { + prototype: TransformStream; + new ( + transformer?: Transformer, + writableStrategy?: QueuingStrategy, + readableStrategy?: QueuingStrategy, + ): TransformStream; + }; + + interface TransformStreamDefaultController { + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; + } + + var TransformStreamDefaultController: { + prototype: TransformStreamDefaultController; + new (): TransformStreamDefaultController; + }; + + interface StreamPipeOptions { + preventAbort?: boolean; + preventCancel?: boolean; + /** + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + * + * Errors and closures of the source and destination streams propagate as follows: + * + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. + * + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. + * + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. + * + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. + */ + preventClose?: boolean; + signal?: AbortSignal; + } + + /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ + interface CountQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + readonly size: QueuingStrategySize; + } + + var CountQueuingStrategy: { + prototype: CountQueuingStrategy; + new (init: QueuingStrategyInit): CountQueuingStrategy; + }; + + interface QueuingStrategySize { + (chunk?: T): number; + } + + interface Transformer { + flush?: Bun.TransformerFlushCallback; + readableType?: undefined; + start?: Bun.TransformerStartCallback; + transform?: Bun.TransformerTransformCallback; + writableType?: undefined; + } + + interface Dict { + [key: string]: T | undefined; + } + + interface ReadOnlyDict { + readonly [key: string]: T | undefined; + } + + interface ErrnoException extends Error { + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; + } + + /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ + interface DOMException extends Error { + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; + } + + var DOMException: { + prototype: DOMException; + new (message?: string, name?: string): DOMException; + }; + + function alert(message?: string): void; + function confirm(message?: string): boolean; + function prompt(message?: string, _default?: string): string | null; + + type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; + var SubtleCrypto: { + prototype: _SubtleCrypto; + new (): _SubtleCrypto; + }; + + type _CryptoKey = import("crypto").webcrypto.CryptoKey; + interface CryptoKey extends _CryptoKey {} + var CryptoKey: { + prototype: CryptoKey; + new (): CryptoKey; + }; + + interface Position { + lineText: string; + file: string; + namespace: string; + line: number; + column: number; + length: number; + offset: number; + } + + class ResolveMessage { + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; + } + + class BuildMessage { + readonly name: "BuildMessage"; + readonly position: Position | null; + readonly message: string; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + } + + // Declare "static" methods in Error + interface ErrorConstructor { + /** Create .stack property on a target object */ + // eslint-disable-next-line @typescript-eslint/ban-types + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: + | ((err: Error, stackTraces: NodeJS.CallSite[]) => any) + | undefined; + + stackTraceLimit: number; + } + + interface ArrayBufferConstructor { + new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; + } + + interface ArrayBuffer { + /** + * Read-only. The length of the ArrayBuffer (in bytes). + */ + readonly byteLength: number; + /** + * Resize an ArrayBuffer in-place. + */ + resize(byteLength: number): ArrayBuffer; + + /** + * Returns a section of an ArrayBuffer. + */ + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; + } + + interface SharedArrayBuffer { + /** + * Grow the SharedArrayBuffer in-place. + */ + grow(size: number): SharedArrayBuffer; + } + + interface ArrayConstructor { + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + ): Promise[]>; + + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. Results of the map function are also awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * await Array.fromAsync([1], (n) => n + 1); // [2] + * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. + * @param thisArg - The `this` to which `mapFn` is bound. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; + } + + interface ConsoleOptions { + stdout: import("stream").Writable; + stderr?: import("stream").Writable; + ignoreErrors?: boolean; + colorMode?: boolean | "auto"; + inspectOptions?: import("util").InspectOptions; + groupIndentation?: number; + } + + interface Console { + /** + * Asynchronously read lines from standard input (fd 0) + * + * ```ts + * for await (const line of console) { + * console.log(line); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterableIterator; + + /** + * Write text or bytes to stdout + * + * Unlike {@link console.log}, this does no formatting and doesn't add a + * newline or spaces between arguments. You can pass it strings or bytes or + * any combination of the two. + * + * ```ts + * console.write("hello world!", "\n"); // "hello world\n" + * ``` + * + * @param data - The data to write + * @returns The number of bytes written + * + * This function is not available in the browser. + */ + write(...data: Array): number; + + /** + * Clear the console + */ + clear(): void; + + assert(condition?: boolean, ...data: any[]): void; + + /** + * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) + * @param label label counter + */ + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: any): void; + dirxml(...data: any[]): void; + /** + * Log to stderr in your terminal + * + * Appears in red + * + * @param data something to display + */ + error(...data: any[]): void; + /** Does nothing currently */ + group(...data: any[]): void; + /** Does nothing currently */ + groupCollapsed(...data: any[]): void; + /** Does nothing currently */ + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + /** + * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just + * logging the argument if it can't be parsed as tabular. + * + * ```js + * // These can't be parsed as tabular data + * console.table(Symbol()); + * // Symbol() + * + * console.table(undefined); + * // undefined + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ b โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * ``` + * @param properties Alternate properties for constructing the table. + */ + table(tabularData?: any, properties?: string[]): void; + /** + * Begin a timer to log with {@link console.timeEnd} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + time(label?: string): void; + /** + * End a timer to log with {@link console.time} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + timeStamp(label?: string): void; + trace(...data: any[]): void; + warn(...data: any[]): void; + + /** + * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. + */ + // Console: { + // new (options: ConsoleOptions): Console; + // new ( + // stdout: import("stream").Writable, + // stderr?: import("stream").Writable, + // ignoreErrors?: boolean, + // ): Console; + // }; + } + + var console: Console; + + interface ImportMeta { + /** + * `file://` url string for the current module. + * + * @example + * ```ts + * console.log(import.meta.url); + * "file:///Users/me/projects/my-app/src/my-app.ts" + * ``` + */ + url: string; + /** + * Absolute path to the source file + */ + readonly path: string; + /** + * Absolute path to the directory containing the source file. + * + * Does not have a trailing slash + */ + readonly dir: string; + /** + * Filename of the source file + */ + readonly file: string; + /** + * The environment variables of the process + * + * ```ts + * import.meta.env === process.env + * ``` + */ + readonly env: NodeJS.ProcessEnv; + + /** + * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead + * + * Resolve a module ID the same as if you imported it + * + * The `parent` argument is optional, and defaults to the current module's path. + */ + resolveSync(moduleId: string, parent?: string): string; + + /** + * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all + * calls to `require` with `import.meta.require` when transpiling ES Modules + * for the runtime. + * + * Warning: **This API is not stable** and may change or be removed in the + * future. Use at your own risk. + */ + require: NodeJS.Require; + + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; + + /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ + dirname: string; + + /** Alias of `import.meta.path`. Exists for Node.js compatibility */ + filename: string; + } + + /** + * NodeJS-style `require` function + * + * @param moduleId - The module ID to resolve + */ + var require: NodeJS.Require; + + /** Same as module.exports */ + var exports: any; + + interface NodeModule { + exports: any; + } + + var module: NodeModule; + + /** + * Creates a deep clone of an object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) + */ + function structuredClone( + value: T, + options?: Bun.StructuredSerializeOptions, + ): T; + + /** + * Post a message to the parent thread. + * + * Only useful in a worker thread; calling this from the main thread does nothing. + */ + function postMessage(message: any, transfer?: Bun.Transferable[]): void; + + interface EventSourceInit { + withCredentials?: boolean; + } + + interface PromiseConstructor { + /** + * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called + * separately. + * + * This is useful when you want to return a Promise and have code outside the Promise + * resolve or reject it. + * + * ## Example + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); + * + * setTimeout(() => { + * resolve("Hello world!"); + * }, 1000); + * + * await promise; // "Hello world!" + * ``` + * + * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). + */ + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; + } + + interface Navigator { + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; + } + + var navigator: Navigator; + + interface BlobPropertyBag { + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; + } + + interface Blob { + /** + * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + */ + new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; + /** + * Read the data from the blob as a JSON object. + * + * This first decodes the data from UTF-8, then parses it as JSON. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + json(): Promise; + + /** + * Read the data from the blob as a {@link FormData} object. + * + * This first decodes the data from UTF-8, then parses it as a + * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. + * + * The `type` property of the blob is used to determine the format of the + * body. + * + * This is a non-standard addition to the `Blob` API, to make it conform more + * closely to the `BodyMixin` API. + */ + formData(): Promise; + + arrayBuffer(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + */ + bytes(): Promise; + } + + var Blob: typeof Blob; } diff --git a/packages/bun-types/html-rewriter.d.ts b/packages/bun-types/html-rewriter.d.ts index 4b2b2954cff397..6bec7fea979ab2 100644 --- a/packages/bun-types/html-rewriter.d.ts +++ b/packages/bun-types/html-rewriter.d.ts @@ -1,129 +1,129 @@ declare namespace HTMLRewriterTypes { - interface HTMLRewriterElementContentHandlers { - element?(element: Element): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - } + interface HTMLRewriterElementContentHandlers { + element?(element: Element): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + } - interface HTMLRewriterDocumentContentHandlers { - doctype?(doctype: Doctype): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - end?(end: DocumentEnd): void | Promise; - } + interface HTMLRewriterDocumentContentHandlers { + doctype?(doctype: Doctype): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + end?(end: DocumentEnd): void | Promise; + } - interface Text { - /** The text content */ - readonly text: string; - /** Whether this chunk is the last piece of text in a text node */ - readonly lastInTextNode: boolean; - /** Whether this chunk was removed */ - readonly removed: boolean; - /** Insert content before this chunk */ - before(content: Content, options?: ContentOptions): Text; - /** Insert content after this chunk */ - after(content: Content, options?: ContentOptions): Text; - /** Replace this chunk with new content */ - replace(content: Content, options?: ContentOptions): Text; - /** Remove this chunk */ - remove(): Text; - } + interface Text { + /** The text content */ + readonly text: string; + /** Whether this chunk is the last piece of text in a text node */ + readonly lastInTextNode: boolean; + /** Whether this chunk was removed */ + readonly removed: boolean; + /** Insert content before this chunk */ + before(content: Content, options?: ContentOptions): Text; + /** Insert content after this chunk */ + after(content: Content, options?: ContentOptions): Text; + /** Replace this chunk with new content */ + replace(content: Content, options?: ContentOptions): Text; + /** Remove this chunk */ + remove(): Text; + } - interface Doctype { - /** The doctype name (e.g. "html" for ) */ - readonly name: string | null; - /** The doctype public identifier */ - readonly publicId: string | null; - /** The doctype system identifier */ - readonly systemId: string | null; - /** Whether this doctype was removed */ - readonly removed: boolean; - /** Remove this doctype */ - remove(): Doctype; - } + interface Doctype { + /** The doctype name (e.g. "html" for ) */ + readonly name: string | null; + /** The doctype public identifier */ + readonly publicId: string | null; + /** The doctype system identifier */ + readonly systemId: string | null; + /** Whether this doctype was removed */ + readonly removed: boolean; + /** Remove this doctype */ + remove(): Doctype; + } - interface DocumentEnd { - /** Append content at the end of the document */ - append(content: Content, options?: ContentOptions): DocumentEnd; - } + interface DocumentEnd { + /** Append content at the end of the document */ + append(content: Content, options?: ContentOptions): DocumentEnd; + } - interface ContentOptions { - /** Whether to parse the content as HTML */ - html?: boolean; - } + interface ContentOptions { + /** Whether to parse the content as HTML */ + html?: boolean; + } - type Content = string; + type Content = string; - interface Comment { - /** The comment text */ - text: string; - /** Whether this comment was removed */ - readonly removed: boolean; - /** Insert content before this comment */ - before(content: Content, options?: ContentOptions): Comment; - /** Insert content after this comment */ - after(content: Content, options?: ContentOptions): Comment; - /** Replace this comment with new content */ - replace(content: Content, options?: ContentOptions): Comment; - /** Remove this comment */ - remove(): Comment; - } + interface Comment { + /** The comment text */ + text: string; + /** Whether this comment was removed */ + readonly removed: boolean; + /** Insert content before this comment */ + before(content: Content, options?: ContentOptions): Comment; + /** Insert content after this comment */ + after(content: Content, options?: ContentOptions): Comment; + /** Replace this comment with new content */ + replace(content: Content, options?: ContentOptions): Comment; + /** Remove this comment */ + remove(): Comment; + } - interface Element { - /** The tag name in lowercase (e.g. "div", "span") */ - tagName: string; - /** Iterator for the element's attributes */ - readonly attributes: IterableIterator<[string, string]>; - /** Whether this element was removed */ - readonly removed: boolean; - /** Whether the element is explicitly self-closing, e.g. */ - readonly selfClosing: boolean; - /** - * Whether the element can have inner content. Returns `true` unless - * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) - * - or it's self-closing in a foreign context (eg. in SVG, MathML). - */ - readonly canHaveContent: boolean; - /** The element's namespace URI */ - readonly namespaceURI: string; - /** Get an attribute value by name */ - getAttribute(name: string): string | null; - /** Check if an attribute exists */ - hasAttribute(name: string): boolean; - /** Set an attribute value */ - setAttribute(name: string, value: string): Element; - /** Remove an attribute */ - removeAttribute(name: string): Element; - /** Insert content before this element */ - before(content: Content, options?: ContentOptions): Element; - /** Insert content after this element */ - after(content: Content, options?: ContentOptions): Element; - /** Insert content at the start of this element */ - prepend(content: Content, options?: ContentOptions): Element; - /** Insert content at the end of this element */ - append(content: Content, options?: ContentOptions): Element; - /** Replace this element with new content */ - replace(content: Content, options?: ContentOptions): Element; - /** Remove this element and its contents */ - remove(): Element; - /** Remove this element but keep its contents */ - removeAndKeepContent(): Element; - /** Set the inner content of this element */ - setInnerContent(content: Content, options?: ContentOptions): Element; - /** Add a handler for the end tag of this element */ - onEndTag(handler: (tag: EndTag) => void | Promise): void; - } + interface Element { + /** The tag name in lowercase (e.g. "div", "span") */ + tagName: string; + /** Iterator for the element's attributes */ + readonly attributes: IterableIterator<[string, string]>; + /** Whether this element was removed */ + readonly removed: boolean; + /** Whether the element is explicitly self-closing, e.g. */ + readonly selfClosing: boolean; + /** + * Whether the element can have inner content. Returns `true` unless + * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) + * - or it's self-closing in a foreign context (eg. in SVG, MathML). + */ + readonly canHaveContent: boolean; + /** The element's namespace URI */ + readonly namespaceURI: string; + /** Get an attribute value by name */ + getAttribute(name: string): string | null; + /** Check if an attribute exists */ + hasAttribute(name: string): boolean; + /** Set an attribute value */ + setAttribute(name: string, value: string): Element; + /** Remove an attribute */ + removeAttribute(name: string): Element; + /** Insert content before this element */ + before(content: Content, options?: ContentOptions): Element; + /** Insert content after this element */ + after(content: Content, options?: ContentOptions): Element; + /** Insert content at the start of this element */ + prepend(content: Content, options?: ContentOptions): Element; + /** Insert content at the end of this element */ + append(content: Content, options?: ContentOptions): Element; + /** Replace this element with new content */ + replace(content: Content, options?: ContentOptions): Element; + /** Remove this element and its contents */ + remove(): Element; + /** Remove this element but keep its contents */ + removeAndKeepContent(): Element; + /** Set the inner content of this element */ + setInnerContent(content: Content, options?: ContentOptions): Element; + /** Add a handler for the end tag of this element */ + onEndTag(handler: (tag: EndTag) => void | Promise): void; + } - interface EndTag { - /** The tag name in lowercase */ - name: string; - /** Insert content before this end tag */ - before(content: Content, options?: ContentOptions): EndTag; - /** Insert content after this end tag */ - after(content: Content, options?: ContentOptions): EndTag; - /** Remove this end tag */ - remove(): EndTag; - } + interface EndTag { + /** The tag name in lowercase */ + name: string; + /** Insert content before this end tag */ + before(content: Content, options?: ContentOptions): EndTag; + /** Insert content after this end tag */ + after(content: Content, options?: ContentOptions): EndTag; + /** Remove this end tag */ + remove(): EndTag; + } } /** @@ -149,36 +149,41 @@ declare namespace HTMLRewriterTypes { * ``` */ declare class HTMLRewriter { - constructor(); - /** - * Add handlers for elements matching a CSS selector - * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") - * @param handlers - Object containing handler functions for elements, comments, and text nodes - */ - on(selector: string, handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers): HTMLRewriter; + constructor(); + /** + * Add handlers for elements matching a CSS selector + * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") + * @param handlers - Object containing handler functions for elements, comments, and text nodes + */ + on( + selector: string, + handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers, + ): HTMLRewriter; - /** - * Add handlers for document-level events - * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end - */ - onDocument(handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers): HTMLRewriter; + /** + * Add handlers for document-level events + * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end + */ + onDocument( + handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers, + ): HTMLRewriter; - /** - * Transform HTML content - * @param input - The HTML to transform - * @returns A new {@link Response} with the transformed HTML - */ - transform(input: Response | Blob | Bun.BufferSource): Response; - /** - * Transform HTML content - * @param input - The HTML string to transform - * @returns A new {@link String} containing the transformed HTML - */ - transform(input: string): string; - /** - * Transform HTML content - * @param input - The HTML to transform as a {@link ArrayBuffer} - * @returns A new {@link ArrayBuffer} with the transformed HTML - */ - transform(input: ArrayBuffer): ArrayBuffer; + /** + * Transform HTML content + * @param input - The HTML to transform + * @returns A new {@link Response} with the transformed HTML + */ + transform(input: Response | Blob | Bun.BufferSource): Response; + /** + * Transform HTML content + * @param input - The HTML string to transform + * @returns A new {@link String} containing the transformed HTML + */ + transform(input: string): string; + /** + * Transform HTML content + * @param input - The HTML to transform as a {@link ArrayBuffer} + * @returns A new {@link ArrayBuffer} with the transformed HTML + */ + transform(input: ArrayBuffer): ArrayBuffer; } diff --git a/packages/bun-types/jsc.d.ts b/packages/bun-types/jsc.d.ts index 2a07534586516c..c5942da2813fb5 100644 --- a/packages/bun-types/jsc.d.ts +++ b/packages/bun-types/jsc.d.ts @@ -1,229 +1,243 @@ declare module "bun:jsc" { - /** - * This used to be called "describe" but it could be confused with the test runner. - */ - function jscDescribe(value: any): string; - function jscDescribeArray(args: any[]): string; - function gcAndSweep(): number; - function fullGC(): number; - function edenGC(): number; - function heapSize(): number; - function heapStats(): { - heapSize: number; - heapCapacity: number; - extraMemorySize: number; - objectCount: number; - protectedObjectCount: number; - globalObjectCount: number; - protectedGlobalObjectCount: number; - objectTypeCounts: Record; - protectedObjectTypeCounts: Record; - }; - function memoryUsage(): { - current: number; - peak: number; - currentCommit: number; - peakCommit: number; - pageFaults: number; - }; - function getRandomSeed(): number; - function setRandomSeed(value: number): void; - function isRope(input: string): boolean; - function callerSourceOrigin(): string; - function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; - function noOSRExitFuzzing(func: (...args: any[]) => any): (...args: any[]) => any; - function optimizeNextInvocation(func: (...args: any[]) => any): void; - function numberOfDFGCompiles(func: (...args: any[]) => any): number; - function releaseWeakRefs(): void; - function totalCompileTime(func: (...args: any[]) => any): number; - function reoptimizationRetryCount(func: (...args: any[]) => any): number; - function drainMicrotasks(): void; + /** + * This used to be called "describe" but it could be confused with the test runner. + */ + function jscDescribe(value: any): string; + function jscDescribeArray(args: any[]): string; + function gcAndSweep(): number; + function fullGC(): number; + function edenGC(): number; + function heapSize(): number; + function heapStats(): { + heapSize: number; + heapCapacity: number; + extraMemorySize: number; + objectCount: number; + protectedObjectCount: number; + globalObjectCount: number; + protectedGlobalObjectCount: number; + objectTypeCounts: Record; + protectedObjectTypeCounts: Record; + }; + function memoryUsage(): { + current: number; + peak: number; + currentCommit: number; + peakCommit: number; + pageFaults: number; + }; + function getRandomSeed(): number; + function setRandomSeed(value: number): void; + function isRope(input: string): boolean; + function callerSourceOrigin(): string; + function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; + function noOSRExitFuzzing( + func: (...args: any[]) => any, + ): (...args: any[]) => any; + function optimizeNextInvocation(func: (...args: any[]) => any): void; + function numberOfDFGCompiles(func: (...args: any[]) => any): number; + function releaseWeakRefs(): void; + function totalCompileTime(func: (...args: any[]) => any): number; + function reoptimizationRetryCount(func: (...args: any[]) => any): number; + function drainMicrotasks(): void; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A SharedArrayBuffer that can be sent to another Bun instance. - */ - function serialize(value: any, options?: { binaryType?: "arraybuffer" }): SharedArrayBuffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A SharedArrayBuffer that can be sent to another Bun instance. + */ + function serialize( + value: any, + options?: { binaryType?: "arraybuffer" }, + ): SharedArrayBuffer; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A Buffer that can be sent to another Bun instance. - */ - function serialize(value: any, options?: { binaryType: "nodebuffer" }): Buffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A Buffer that can be sent to another Bun instance. + */ + function serialize( + value: any, + options?: { binaryType: "nodebuffer" }, + ): Buffer; - /** - * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. - * - * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. - */ - function deserialize(value: ArrayBufferLike | NodeJS.TypedArray | Buffer): any; + /** + * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. + * + * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. + */ + function deserialize( + value: ArrayBufferLike | NodeJS.TypedArray | Buffer, + ): any; - /** - * Set the timezone used by Intl, Date, etc. - * - * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" - * - * @returns The normalized time zone string - * - * You can also set process.env.TZ to the time zone you want to use. - * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` - */ - function setTimeZone(timeZone: string): string; + /** + * Set the timezone used by Intl, Date, etc. + * + * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" + * + * @returns The normalized time zone string + * + * You can also set process.env.TZ to the time zone you want to use. + * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` + */ + function setTimeZone(timeZone: string): string; - interface SamplingProfile { - /** - * A formatted summary of the top functions - * - * Example output: - * ```js - * - * Sampling rate: 100.000000 microseconds. Total samples: 6858 - * Top functions as - * 2948 '#:8' - * 393 'visit#:8' - * 263 'push#:8' - * 164 'scan_ref_scoped#:8' - * 164 'walk#:8' - * 144 'pop#:8' - * 107 'extract_candidates#:8' - * 94 'get#:8' - * 82 'Function#:4294967295' - * 79 'set#:8' - * 67 'forEach#:5' - * 58 'collapse#:8' - * ``` - */ - functions: string; - /** - * A formatted summary of the top bytecodes - * - * Example output: - * ```js - * Tier breakdown: - * ----------------------------------- - * LLInt: 106 (1.545640%) - * Baseline: 2355 (34.339458%) - * DFG: 3290 (47.973170%) - * FTL: 833 (12.146398%) - * js builtin: 132 (1.924759%) - * Wasm: 0 (0.000000%) - * Host: 111 (1.618548%) - * RegExp: 15 (0.218723%) - * C/C++: 0 (0.000000%) - * Unknown Executable: 148 (2.158064%) - * - * Hottest bytecodes as - * 273 'visit#:DFG:bc#63' - * 121 'walk#:DFG:bc#7' - * 119 '#:Baseline:bc#1' - * 82 'Function#:None:' - * 66 '#:DFG:bc#11' - * 65 '#:DFG:bc#33' - * 58 '#:Baseline:bc#7' - * 53 '#:Baseline:bc#23' - * 50 'forEach#:DFG:bc#83' - * 49 'pop#:FTL:bc#65' - * 47 '#:DFG:bc#99' - * 45 '#:DFG:bc#16' - * 44 '#:DFG:bc#7' - * 44 '#:Baseline:bc#30' - * 44 'push#:FTL:bc#214' - * 41 '#:DFG:bc#50' - * 39 'get#:DFG:bc#27' - * 39 '#:Baseline:bc#0' - * 36 '#:DFG:bc#27' - * 36 'Dictionary#:DFG:bc#41' - * 36 'visit#:DFG:bc#81' - * 36 'get#:FTL:bc#11' - * 32 'push#:FTL:bc#49' - * 31 '#:DFG:bc#76' - * 31 '#:DFG:bc#10' - * 31 '#:DFG:bc#73' - * 29 'set#:DFG:bc#28' - * 28 'in_boolean_context#:DFG:bc#104' - * 28 '#:Baseline:' - * 28 'regExpSplitFast#:None:' - * 26 'visit#:DFG:bc#95' - * 26 'pop#:FTL:bc#120' - * 25 '#:DFG:bc#23' - * 25 'push#:FTL:bc#152' - * 24 'push#:FTL:bc#262' - * 24 '#:FTL:bc#10' - * 23 'is_identifier_char#:DFG:bc#22' - * 23 'visit#:DFG:bc#22' - * 22 '#:FTL:bc#27' - * 22 'indexOf#:None:' - * ``` - */ - bytecodes: string; + interface SamplingProfile { + /** + * A formatted summary of the top functions + * + * Example output: + * ```js + * + * Sampling rate: 100.000000 microseconds. Total samples: 6858 + * Top functions as + * 2948 '#:8' + * 393 'visit#:8' + * 263 'push#:8' + * 164 'scan_ref_scoped#:8' + * 164 'walk#:8' + * 144 'pop#:8' + * 107 'extract_candidates#:8' + * 94 'get#:8' + * 82 'Function#:4294967295' + * 79 'set#:8' + * 67 'forEach#:5' + * 58 'collapse#:8' + * ``` + */ + functions: string; + /** + * A formatted summary of the top bytecodes + * + * Example output: + * ```js + * Tier breakdown: + * ----------------------------------- + * LLInt: 106 (1.545640%) + * Baseline: 2355 (34.339458%) + * DFG: 3290 (47.973170%) + * FTL: 833 (12.146398%) + * js builtin: 132 (1.924759%) + * Wasm: 0 (0.000000%) + * Host: 111 (1.618548%) + * RegExp: 15 (0.218723%) + * C/C++: 0 (0.000000%) + * Unknown Executable: 148 (2.158064%) + * + * Hottest bytecodes as + * 273 'visit#:DFG:bc#63' + * 121 'walk#:DFG:bc#7' + * 119 '#:Baseline:bc#1' + * 82 'Function#:None:' + * 66 '#:DFG:bc#11' + * 65 '#:DFG:bc#33' + * 58 '#:Baseline:bc#7' + * 53 '#:Baseline:bc#23' + * 50 'forEach#:DFG:bc#83' + * 49 'pop#:FTL:bc#65' + * 47 '#:DFG:bc#99' + * 45 '#:DFG:bc#16' + * 44 '#:DFG:bc#7' + * 44 '#:Baseline:bc#30' + * 44 'push#:FTL:bc#214' + * 41 '#:DFG:bc#50' + * 39 'get#:DFG:bc#27' + * 39 '#:Baseline:bc#0' + * 36 '#:DFG:bc#27' + * 36 'Dictionary#:DFG:bc#41' + * 36 'visit#:DFG:bc#81' + * 36 'get#:FTL:bc#11' + * 32 'push#:FTL:bc#49' + * 31 '#:DFG:bc#76' + * 31 '#:DFG:bc#10' + * 31 '#:DFG:bc#73' + * 29 'set#:DFG:bc#28' + * 28 'in_boolean_context#:DFG:bc#104' + * 28 '#:Baseline:' + * 28 'regExpSplitFast#:None:' + * 26 'visit#:DFG:bc#95' + * 26 'pop#:FTL:bc#120' + * 25 '#:DFG:bc#23' + * 25 'push#:FTL:bc#152' + * 24 'push#:FTL:bc#262' + * 24 '#:FTL:bc#10' + * 23 'is_identifier_char#:DFG:bc#22' + * 23 'visit#:DFG:bc#22' + * 22 '#:FTL:bc#27' + * 22 'indexOf#:None:' + * ``` + */ + bytecodes: string; - /** - * Stack traces of the top functions - */ - stackTraces: string[]; - } + /** + * Stack traces of the top functions + */ + stackTraces: string[]; + } - /** - * Run JavaScriptCore's sampling profiler for a particular function - * - * This is pretty low-level. - * - * Things to know: - * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation - * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile - * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile - * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile - */ - function profile any>( - callback: T, - sampleInterval?: number, - ...args: Parameters - ): ReturnType extends Promise ? Promise : SamplingProfile; + /** + * Run JavaScriptCore's sampling profiler for a particular function + * + * This is pretty low-level. + * + * Things to know: + * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation + * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile + * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile + * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile + */ + function profile any>( + callback: T, + sampleInterval?: number, + ...args: Parameters + ): ReturnType extends Promise + ? Promise + : SamplingProfile; - /** - * This returns objects which native code has explicitly protected from being - * garbage collected - * - * By calling this function you create another reference to the object, which - * will further prevent it from being garbage collected - * - * This function is mostly a debugging tool for bun itself. - * - * Warning: not all objects returned are supposed to be observable from JavaScript - */ - function getProtectedObjects(): any[]; + /** + * This returns objects which native code has explicitly protected from being + * garbage collected + * + * By calling this function you create another reference to the object, which + * will further prevent it from being garbage collected + * + * This function is mostly a debugging tool for bun itself. + * + * Warning: not all objects returned are supposed to be observable from JavaScript + */ + function getProtectedObjects(): any[]; - /** - * Start a remote debugging socket server on the given port. - * - * This exposes JavaScriptCore's built-in debugging server. - * - * This is untested. May not be supported yet on macOS - */ - function startRemoteDebugger(host?: string, port?: number): void; + /** + * Start a remote debugging socket server on the given port. + * + * This exposes JavaScriptCore's built-in debugging server. + * + * This is untested. May not be supported yet on macOS + */ + function startRemoteDebugger(host?: string, port?: number): void; - /** - * Run JavaScriptCore's sampling profiler - */ - function startSamplingProfiler(optionalDirectory?: string): void; + /** + * Run JavaScriptCore's sampling profiler + */ + function startSamplingProfiler(optionalDirectory?: string): void; - /** - * Non-recursively estimate the memory usage of an object, excluding the memory usage of - * properties or other objects it references. For more accurate per-object - * memory usage, use {@link Bun.generateHeapSnapshot}. - * - * This is a best-effort estimate. It may not be 100% accurate. When it's - * wrong, it may mean the memory is non-contiguous (such as a large array). - * - * Passing a primitive type that isn't heap allocated returns 0. - */ - function estimateShallowMemoryUsageOf(value: object | CallableFunction | bigint | symbol | string): number; + /** + * Non-recursively estimate the memory usage of an object, excluding the memory usage of + * properties or other objects it references. For more accurate per-object + * memory usage, use {@link Bun.generateHeapSnapshot}. + * + * This is a best-effort estimate. It may not be 100% accurate. When it's + * wrong, it may mean the memory is non-contiguous (such as a large array). + * + * Passing a primitive type that isn't heap allocated returns 0. + */ + function estimateShallowMemoryUsageOf( + value: object | CallableFunction | bigint | symbol | string, + ): number; } diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index 56b6e74a791b6c..88237b34673619 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -1,4 +1,3 @@ -export {}; declare var onmessage: never; declare var Bun: typeof import("bun"); @@ -119,9 +118,28 @@ declare interface Event { } declare module "bun" { - export function fetch(request: Request, init?: RequestInit): Promise; - export function fetch(url: string | URL | Request, init?: RequestInit): Promise; - export function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise; + interface Env { + [key: string]: string | undefined; + } + + interface ProcessEnv extends Env {} + + export var env: Env; + + export var fetch: { + (request: Request, init?: RequestInit): Promise; + (url: string | URL | Request, init?: RequestInit): Promise; + (input: string | URL | globalThis.Request, init?: RequestInit): Promise; + preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; + }; } declare namespace Bun { @@ -194,6 +212,8 @@ declare interface FetchEvent extends Event { respondWith(response: Response | Promise): void; } +declare var fetch: typeof import("bun").fetch; + declare interface EventMap { fetch: FetchEvent; message: MessageEvent; @@ -246,25 +266,14 @@ declare interface ImportMeta { }; } -declare function fetch(request: Request, init?: RequestInit): Promise; -declare function fetch(url: string | URL | Request, init?: RequestInit): Promise; -declare function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise; - -declare namespace Bun { - interface Env { - [key: string]: string | undefined; - } - - interface ProcessEnv extends Env {} - - export const env: Env; - export const fetch: typeof globalThis.fetch; -} - declare interface NodeModule { exports: any; } +declare interface Headers { + toJSON(): Record; +} + declare namespace NodeJS { interface Process { readonly version: string; @@ -444,6 +453,6 @@ declare interface ArrayConstructor { } declare module "*.svg" { - const content: string; + const content: `${string}.svg`; export = content; } diff --git a/packages/bun-types/overrides.d.ts b/packages/bun-types/overrides.d.ts index 2c9563224342e2..e679e20ae30824 100644 --- a/packages/bun-types/overrides.d.ts +++ b/packages/bun-types/overrides.d.ts @@ -3,62 +3,72 @@ export {}; import type { BunFile, Env, PathLike } from "bun"; declare global { - namespace NodeJS { - interface ProcessVersions extends Dict { - bun: string; - } - interface ProcessEnv extends Env {} - } + namespace NodeJS { + interface ProcessVersions extends Dict { + bun: string; + } + interface ProcessEnv extends Env {} + } } declare module "fs/promises" { - function exists(path: PathLike): Promise; + function exists(path: PathLike): Promise; } declare module "tls" { - interface BunConnectionOptions extends Omit { - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: string | Buffer | NodeJS.TypedArray | BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: - | string - | Buffer - | NodeJS.TypedArray - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: - | string - | Buffer - | BunFile - | NodeJS.TypedArray - | Array - | undefined; - } + interface BunConnectionOptions + extends Omit { + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: + | string + | Buffer + | NodeJS.TypedArray + | BunFile + | Array + | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: + | string + | Buffer + | NodeJS.TypedArray + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: + | string + | Buffer + | BunFile + | NodeJS.TypedArray + | Array + | undefined; + } - function connect(options: BunConnectionOptions, secureConnectListener?: () => void): TLSSocket; + function connect( + options: BunConnectionOptions, + secureConnectListener?: () => void, + ): TLSSocket; } diff --git a/packages/bun-types/sqlite.d.ts b/packages/bun-types/sqlite.d.ts index dd370d3f46bcc2..303469772cb98c 100644 --- a/packages/bun-types/sqlite.d.ts +++ b/packages/bun-types/sqlite.d.ts @@ -24,1118 +24,1143 @@ * | `null` | `NULL` | */ declare module "bun:sqlite" { - export class Database implements Disposable { - /** - * Open or create a SQLite3 database - * - * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. - * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. - * - * @example - * - * ```ts - * const db = new Database("mydb.sqlite"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open an in-memory database - * - * ```ts - * const db = new Database(":memory:"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open read-only - * - * ```ts - * const db = new Database("mydb.sqlite", {readonly: true}); - * ``` - */ - constructor( - filename?: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; + export class Database implements Disposable { + /** + * Open or create a SQLite3 database + * + * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. + * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. + * + * @example + * + * ```ts + * const db = new Database("mydb.sqlite"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open an in-memory database + * + * ```ts + * const db = new Database(":memory:"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open read-only + * + * ```ts + * const db = new Database("mydb.sqlite", {readonly: true}); + * ``` + */ + constructor( + filename?: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; - /** - * When set to `true`, integers are returned as `bigint` types. - * - * When set to `false`, integers are returned as `number` types and truncated to 52 bits. - * - * @default false - * @since v1.1.14 - */ - safeIntegers?: boolean; + /** + * When set to `true`, integers are returned as `bigint` types. + * + * When set to `false`, integers are returned as `number` types and truncated to 52 bits. + * + * @default false + * @since v1.1.14 + */ + safeIntegers?: boolean; - /** - * When set to `false` or `undefined`: - * - Queries missing bound parameters will NOT throw an error - * - Bound named parameters in JavaScript need to exactly match the SQL query. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: false }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); - * ``` - * - * When set to `true`: - * - Queries missing bound parameters will throw an error - * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: true }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); - * ``` - * @since v1.1.14 - */ - strict?: boolean; - }, - ); + /** + * When set to `false` or `undefined`: + * - Queries missing bound parameters will NOT throw an error + * - Bound named parameters in JavaScript need to exactly match the SQL query. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: false }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); + * ``` + * + * When set to `true`: + * - Queries missing bound parameters will throw an error + * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: true }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); + * ``` + * @since v1.1.14 + */ + strict?: boolean; + }, + ); - /** - * This is an alias of `new Database()` - * - * See {@link Database} - */ - static open( - filename: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; - }, - ): Database; + /** + * This is an alias of `new Database()` + * + * See {@link Database} + */ + static open( + filename: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; + }, + ): Database; - /** - * Execute a SQL query **without returning any results**. - * - * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * ``` - * - * Useful for queries like: - * - `CREATE TABLE` - * - `INSERT INTO` - * - `UPDATE` - * - `DELETE FROM` - * - `DROP TABLE` - * - `PRAGMA` - * - `ATTACH DATABASE` - * - `DETACH DATABASE` - * - `REINDEX` - * - `VACUUM` - * - `EXPLAIN ANALYZE` - * - `CREATE INDEX` - * - `CREATE TRIGGER` - * - `CREATE VIEW` - * - `CREATE VIRTUAL TABLE` - * - `CREATE TEMPORARY TABLE` - * - * @param sql The SQL query to run - * - * @param bindings Optional bindings for the query - * - * @returns `Database` instance - * - * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. - * - * * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(sqlQuery: string, ...bindings: ParamsType[]): Changes; - /** + /** + * Execute a SQL query **without returning any results**. + * + * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * ``` + * + * Useful for queries like: + * - `CREATE TABLE` + * - `INSERT INTO` + * - `UPDATE` + * - `DELETE FROM` + * - `DROP TABLE` + * - `PRAGMA` + * - `ATTACH DATABASE` + * - `DETACH DATABASE` + * - `REINDEX` + * - `VACUUM` + * - `EXPLAIN ANALYZE` + * - `CREATE INDEX` + * - `CREATE TRIGGER` + * - `CREATE VIEW` + * - `CREATE VIRTUAL TABLE` + * - `CREATE TEMPORARY TABLE` + * + * @param sql The SQL query to run + * + * @param bindings Optional bindings for the query + * + * @returns `Database` instance + * + * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. + * + * * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run( + sqlQuery: string, + ...bindings: ParamsType[] + ): Changes; + /** This is an alias of {@link Database.prototype.run} */ - exec(sqlQuery: string, ...bindings: ParamsType[]): Changes; + exec( + sqlQuery: string, + ...bindings: ParamsType[] + ): Changes; - /** - * Compile a SQL query and return a {@link Statement} object. This is the - * same as {@link prepare} except that it caches the compiled query. - * - * This **does not execute** the query, but instead prepares it for later - * execution and caches the compiled query if possible. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * - * // run the query again - * stmt.all(); - * ``` - * - * @param sql The SQL query to compile - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - query( - sqlQuery: string, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. This is the + * same as {@link prepare} except that it caches the compiled query. + * + * This **does not execute** the query, but instead prepares it for later + * execution and caches the compiled query if possible. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * + * // run the query again + * stmt.all(); + * ``` + * + * @param sql The SQL query to compile + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + query( + sqlQuery: string, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Compile a SQL query and return a {@link Statement} object. - * - * This does not cache the compiled query and does not execute the query. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * ``` - * - * @param sql The SQL query to compile - * @param params Optional bindings for the query - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - prepare( - sqlQuery: string, - params?: ParamsType, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. + * + * This does not cache the compiled query and does not execute the query. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * ``` + * + * @param sql The SQL query to compile + * @param params Optional bindings for the query + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + prepare< + ReturnType, + ParamsType extends SQLQueryBindings | SQLQueryBindings[], + >( + sqlQuery: string, + params?: ParamsType, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Is the database in a transaction? - * - * @returns `true` if the database is in a transaction, `false` otherwise - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * db.run("BEGIN"); - * db.run("INSERT INTO foo VALUES (?)", ["qux"]); - * console.log(db.inTransaction()); - * ``` - */ - get inTransaction(): boolean; + /** + * Is the database in a transaction? + * + * @returns `true` if the database is in a transaction, `false` otherwise + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * db.run("BEGIN"); + * db.run("INSERT INTO foo VALUES (?)", ["qux"]); + * console.log(db.inTransaction()); + * ``` + */ + get inTransaction(): boolean; - /** - * Close the database connection. - * - * It is safe to call this method multiple times. If the database is already - * closed, this is a no-op. Running queries after the database has been - * closed will throw an error. - * - * @example - * ```ts - * db.close(); - * ``` - * This is called automatically when the database instance is garbage collected. - * - * Internally, this calls `sqlite3_close_v2`. - */ - close( - /** - * If `true`, then the database will throw an error if it is in use - * @default false - * - * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. - * - * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). - * - * Bun will automatically call close by default when the database instance is garbage collected. - * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. - */ - throwOnError?: boolean, - ): void; + /** + * Close the database connection. + * + * It is safe to call this method multiple times. If the database is already + * closed, this is a no-op. Running queries after the database has been + * closed will throw an error. + * + * @example + * ```ts + * db.close(); + * ``` + * This is called automatically when the database instance is garbage collected. + * + * Internally, this calls `sqlite3_close_v2`. + */ + close( + /** + * If `true`, then the database will throw an error if it is in use + * @default false + * + * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. + * + * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). + * + * Bun will automatically call close by default when the database instance is garbage collected. + * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. + */ + throwOnError?: boolean, + ): void; - /** - * The filename passed when `new Database()` was called - * @example - * ```ts - * const db = new Database("mydb.sqlite"); - * console.log(db.filename); - * // => "mydb.sqlite" - * ``` - */ - readonly filename: string; + /** + * The filename passed when `new Database()` was called + * @example + * ```ts + * const db = new Database("mydb.sqlite"); + * console.log(db.filename); + * // => "mydb.sqlite" + * ``` + */ + readonly filename: string; - /** - * The underlying `sqlite3` database handle - * - * In native code, this is not a file descriptor, but an index into an array of database handles - */ - readonly handle: number; + /** + * The underlying `sqlite3` database handle + * + * In native code, this is not a file descriptor, but an index into an array of database handles + */ + readonly handle: number; - /** - * Load a SQLite3 extension - * - * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} - * - * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. - * - * @param extension name/path of the extension to load - * @param entryPoint optional entry point of the extension - */ - loadExtension(extension: string, entryPoint?: string): void; + /** + * Load a SQLite3 extension + * + * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} + * + * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. + * + * @param extension name/path of the extension to load + * @param entryPoint optional entry point of the extension + */ + loadExtension(extension: string, entryPoint?: string): void; - /** - * Change the dynamic library path to SQLite - * - * @note macOS-only - * - * This only works before SQLite is loaded, so - * that's before you call `new Database()`. - * - * It can only be run once because this will load - * the SQLite library into the process. - * - * @param path The path to the SQLite library - */ - static setCustomSQLite(path: string): boolean; + /** + * Change the dynamic library path to SQLite + * + * @note macOS-only + * + * This only works before SQLite is loaded, so + * that's before you call `new Database()`. + * + * It can only be run once because this will load + * the SQLite library into the process. + * + * @param path The path to the SQLite library + */ + static setCustomSQLite(path: string): boolean; - [Symbol.dispose](): void; + [Symbol.dispose](): void; - /** - * Creates a function that always runs inside a transaction. When the - * function is invoked, it will begin a new transaction. When the function - * returns, the transaction will be committed. If an exception is thrown, - * the transaction will be rolled back (and the exception will propagate as - * usual). - * - * @param insideTransaction The callback which runs inside a transaction - * - * @example - * ```ts - * // setup - * import { Database } from "bun:sqlite"; - * const db = Database.open(":memory:"); - * db.exec( - * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" - * ); - * - * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); - * const insertMany = db.transaction((cats) => { - * for (const cat of cats) insert.run(cat); - * }); - * - * insertMany([ - * { $name: "Joey", $age: 2 }, - * { $name: "Sally", $age: 4 }, - * { $name: "Junior", $age: 1 }, - * ]); - * ``` - */ - transaction(insideTransaction: (...args: any) => void): CallableFunction & { - /** - * uses "BEGIN DEFERRED" - */ - deferred: (...args: any) => void; - /** - * uses "BEGIN IMMEDIATE" - */ - immediate: (...args: any) => void; - /** - * uses "BEGIN EXCLUSIVE" - */ - exclusive: (...args: any) => void; - }; + /** + * Creates a function that always runs inside a transaction. When the + * function is invoked, it will begin a new transaction. When the function + * returns, the transaction will be committed. If an exception is thrown, + * the transaction will be rolled back (and the exception will propagate as + * usual). + * + * @param insideTransaction The callback which runs inside a transaction + * + * @example + * ```ts + * // setup + * import { Database } from "bun:sqlite"; + * const db = Database.open(":memory:"); + * db.exec( + * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" + * ); + * + * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); + * const insertMany = db.transaction((cats) => { + * for (const cat of cats) insert.run(cat); + * }); + * + * insertMany([ + * { $name: "Joey", $age: 2 }, + * { $name: "Sally", $age: 4 }, + * { $name: "Junior", $age: 1 }, + * ]); + * ``` + */ + transaction(insideTransaction: (...args: any) => void): CallableFunction & { + /** + * uses "BEGIN DEFERRED" + */ + deferred: (...args: any) => void; + /** + * uses "BEGIN IMMEDIATE" + */ + immediate: (...args: any) => void; + /** + * uses "BEGIN EXCLUSIVE" + */ + exclusive: (...args: any) => void; + }; - /** - * Save the database to an in-memory {@link Buffer} object. - * - * Internally, this calls `sqlite3_serialize`. - * - * @param name Name to save the database as @default "main" - * @returns Buffer containing the serialized database - */ - serialize(name?: string): Buffer; + /** + * Save the database to an in-memory {@link Buffer} object. + * + * Internally, this calls `sqlite3_serialize`. + * + * @param name Name to save the database as @default "main" + * @returns Buffer containing the serialized database + */ + serialize(name?: string): Buffer; - /** - * Load a serialized SQLite3 database - * - * Internally, this calls `sqlite3_deserialize`. - * - * @param serialized Data to load - * @returns `Database` instance - * - * @example - * ```ts - * test("supports serialize/deserialize", () => { - * const db = Database.open(":memory:"); - * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); - * db.exec('INSERT INTO test (name) VALUES ("Hello")'); - * db.exec('INSERT INTO test (name) VALUES ("World")'); - * - * const input = db.serialize(); - * const db2 = new Database(input); - * - * const stmt = db2.prepare("SELECT * FROM test"); - * expect(JSON.stringify(stmt.get())).toBe( - * JSON.stringify({ - * id: 1, - * name: "Hello", - * }), - * ); - * - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * ]), - * ); - * db2.exec("insert into test (name) values ('foo')"); - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * { - * id: 3, - * name: "foo", - * }, - * ]), - * ); - * - * const db3 = Database.deserialize(input, true); - * try { - * db3.exec("insert into test (name) values ('foo')"); - * throw new Error("Expected error"); - * } catch (e) { - * expect(e.message).toBe("attempt to write a readonly database"); - * } - * }); - * ``` - */ - static deserialize(serialized: NodeJS.TypedArray | ArrayBufferLike, isReadOnly?: boolean): Database; + /** + * Load a serialized SQLite3 database + * + * Internally, this calls `sqlite3_deserialize`. + * + * @param serialized Data to load + * @returns `Database` instance + * + * @example + * ```ts + * test("supports serialize/deserialize", () => { + * const db = Database.open(":memory:"); + * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); + * db.exec('INSERT INTO test (name) VALUES ("Hello")'); + * db.exec('INSERT INTO test (name) VALUES ("World")'); + * + * const input = db.serialize(); + * const db2 = new Database(input); + * + * const stmt = db2.prepare("SELECT * FROM test"); + * expect(JSON.stringify(stmt.get())).toBe( + * JSON.stringify({ + * id: 1, + * name: "Hello", + * }), + * ); + * + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * ]), + * ); + * db2.exec("insert into test (name) values ('foo')"); + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * { + * id: 3, + * name: "foo", + * }, + * ]), + * ); + * + * const db3 = Database.deserialize(input, true); + * try { + * db3.exec("insert into test (name) values ('foo')"); + * throw new Error("Expected error"); + * } catch (e) { + * expect(e.message).toBe("attempt to write a readonly database"); + * } + * }); + * ``` + */ + static deserialize( + serialized: NodeJS.TypedArray | ArrayBufferLike, + isReadOnly?: boolean, + ): Database; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(op: number, arg?: ArrayBufferView | number): number; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(zDbName: string, op: number, arg?: ArrayBufferView | number): number; - } + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(op: number, arg?: ArrayBufferView | number): number; + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl( + zDbName: string, + op: number, + arg?: ArrayBufferView | number, + ): number; + } - /** - * A prepared statement. - * - * This is returned by {@link Database.prepare} and {@link Database.query}. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.all("baz"); - * // => [{bar: "baz"}] - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.get("baz"); - * // => {bar: "baz"} - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.run("baz"); - * // => undefined - * ``` - */ - export class Statement implements Disposable { - /** - * Creates a new prepared statement from native code. - * - * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. - */ - constructor(nativeHandle: any); + /** + * A prepared statement. + * + * This is returned by {@link Database.prepare} and {@link Database.query}. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.all("baz"); + * // => [{bar: "baz"}] + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.get("baz"); + * // => {bar: "baz"} + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.run("baz"); + * // => undefined + * ``` + */ + export class Statement< + ReturnType = unknown, + ParamsType extends SQLQueryBindings[] = any[], + > implements Disposable + { + /** + * Creates a new prepared statement from native code. + * + * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. + */ + constructor(nativeHandle: any); - /** - * Execute the prepared statement and return all results as objects. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.all("baz"); - * // => [{bar: "baz"}] - * - * stmt.all(); - * // => [] - * - * stmt.all("foo"); - * // => [{bar: "foo"}] - * ``` - */ - all(...params: ParamsType): ReturnType[]; + /** + * Execute the prepared statement and return all results as objects. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.all("baz"); + * // => [{bar: "baz"}] + * + * stmt.all(); + * // => [] + * + * stmt.all("foo"); + * // => [{bar: "foo"}] + * ``` + */ + all(...params: ParamsType): ReturnType[]; - /** - * Execute the prepared statement and return **the first** result. - * - * If no result is returned, this returns `null`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.get("baz"); - * // => {bar: "baz"} - * - * stmt.get(); - * // => null - * - * stmt.get("foo"); - * // => {bar: "foo"} - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - get(...params: ParamsType): ReturnType | null; + /** + * Execute the prepared statement and return **the first** result. + * + * If no result is returned, this returns `null`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.get("baz"); + * // => {bar: "baz"} + * + * stmt.get(); + * // => null + * + * stmt.get("foo"); + * // => {bar: "foo"} + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + get(...params: ParamsType): ReturnType | null; - /** - * Execute the prepared statement and return an - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - */ - iterate(...params: ParamsType): IterableIterator; - [Symbol.iterator](): IterableIterator; + /** + * Execute the prepared statement and return an + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + */ + iterate(...params: ParamsType): IterableIterator; + [Symbol.iterator](): IterableIterator; - /** - * Execute the prepared statement. This returns `undefined`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("UPDATE foo SET bar = ?"); - * stmt.run("baz"); - * // => undefined - * - * stmt.run(); - * // => undefined - * - * stmt.run("foo"); - * // => undefined - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(...params: ParamsType): Changes; + /** + * Execute the prepared statement. This returns `undefined`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("UPDATE foo SET bar = ?"); + * stmt.run("baz"); + * // => undefined + * + * stmt.run(); + * // => undefined + * + * stmt.run("foo"); + * // => undefined + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(...params: ParamsType): Changes; - /** - * Execute the prepared statement and return the results as an array of arrays. - * - * In Bun v0.6.7 and earlier, this method returned `null` if there were no - * results instead of `[]`. This was changed in v0.6.8 to align - * more with what people expect. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.values("baz"); - * // => [['baz']] - * - * stmt.values(); - * // => [['baz']] - * - * stmt.values("foo"); - * // => [['foo']] - * - * stmt.values("not-found"); - * // => [] - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | ---------------|-------------| - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - values(...params: ParamsType): Array>; + /** + * Execute the prepared statement and return the results as an array of arrays. + * + * In Bun v0.6.7 and earlier, this method returned `null` if there were no + * results instead of `[]`. This was changed in v0.6.8 to align + * more with what people expect. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.values("baz"); + * // => [['baz']] + * + * stmt.values(); + * // => [['baz']] + * + * stmt.values("foo"); + * // => [['foo']] + * + * stmt.values("not-found"); + * // => [] + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | ---------------|-------------| + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + values( + ...params: ParamsType + ): Array>; - /** - * The names of the columns returned by the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); - * - * console.log(stmt.columnNames); - * // => ["bar"] - * ``` - */ - readonly columnNames: string[]; + /** + * The names of the columns returned by the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); + * + * console.log(stmt.columnNames); + * // => ["bar"] + * ``` + */ + readonly columnNames: string[]; - /** - * The number of parameters expected in the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * console.log(stmt.paramsCount); - * // => 1 - * ``` - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); - * console.log(stmt.paramsCount); - * // => 2 - * ``` - */ - readonly paramsCount: number; + /** + * The number of parameters expected in the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * console.log(stmt.paramsCount); + * // => 1 + * ``` + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); + * console.log(stmt.paramsCount); + * // => 2 + * ``` + */ + readonly paramsCount: number; - /** - * Finalize the prepared statement, freeing the resources used by the - * statement and preventing it from being executed again. - * - * This is called automatically when the prepared statement is garbage collected. - * - * It is safe to call this multiple times. Calling this on a finalized - * statement has no effect. - * - * Internally, this calls `sqlite3_finalize`. - */ - finalize(): void; + /** + * Finalize the prepared statement, freeing the resources used by the + * statement and preventing it from being executed again. + * + * This is called automatically when the prepared statement is garbage collected. + * + * It is safe to call this multiple times. Calling this on a finalized + * statement has no effect. + * + * Internally, this calls `sqlite3_finalize`. + */ + finalize(): void; - /** - * Calls {@link finalize} if it wasn't already called. - */ - [Symbol.dispose](): void; + /** + * Calls {@link finalize} if it wasn't already called. + */ + [Symbol.dispose](): void; - /** - * Return the expanded SQL string for the prepared statement. - * - * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); - * console.log(stmt.toString()); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * console.log(stmt); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * ``` - */ - toString(): string; + /** + * Return the expanded SQL string for the prepared statement. + * + * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); + * console.log(stmt.toString()); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * console.log(stmt); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * ``` + */ + toString(): string; - /** - * - * Make {@link get} and {@link all} return an instance of the provided - * `Class` instead of the default `Object`. - * - * @param Class A class to use - * @returns The same statement instance, modified to return an instance of `Class` - * - * This lets you attach methods, getters, and setters to the returned - * objects. - * - * For performance reasons, constructors for classes are not called, which means - * initializers will not be called and private fields will not be - * accessible. - * - * @example - * - * ## Custom class - * ```ts - * class User { - * rawBirthdate: string; - * get birthdate() { - * return new Date(this.rawBirthdate); - * } - * } - * - * const db = new Database(":memory:"); - * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); - * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); - * const query = db.query("SELECT * FROM users"); - * query.as(User); - * const user = query.get(); - * console.log(user.birthdate); - * // => Date(1995, 12, 19) - * ``` - */ - as(Class: new (...args: any[]) => T): Statement; + /** + * + * Make {@link get} and {@link all} return an instance of the provided + * `Class` instead of the default `Object`. + * + * @param Class A class to use + * @returns The same statement instance, modified to return an instance of `Class` + * + * This lets you attach methods, getters, and setters to the returned + * objects. + * + * For performance reasons, constructors for classes are not called, which means + * initializers will not be called and private fields will not be + * accessible. + * + * @example + * + * ## Custom class + * ```ts + * class User { + * rawBirthdate: string; + * get birthdate() { + * return new Date(this.rawBirthdate); + * } + * } + * + * const db = new Database(":memory:"); + * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); + * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); + * const query = db.query("SELECT * FROM users"); + * query.as(User); + * const user = query.get(); + * console.log(user.birthdate); + * // => Date(1995, 12, 19) + * ``` + */ + as(Class: new (...args: any[]) => T): Statement; - /** - * Native object representing the underlying `sqlite3_stmt` - * - * This is left untyped because the ABI of the native bindings may change at any time. - */ - readonly native: any; - } + /** + * Native object representing the underlying `sqlite3_stmt` + * + * This is left untyped because the ABI of the native bindings may change at any time. + */ + readonly native: any; + } - /** - * Constants from `sqlite3.h` - * - * This list isn't exhaustive, but some of the ones which are relevant - */ - export const constants: { - /** - * Open the database as read-only (no write operations, no create). - * @constant 0x00000001 - */ - SQLITE_OPEN_READONLY: number; - /** - * Open the database for reading and writing - * @constant 0x00000002 - */ - SQLITE_OPEN_READWRITE: number; - /** - * Allow creating a new database - * @constant 0x00000004 - */ - SQLITE_OPEN_CREATE: number; - /** - * @constant 0x00000008 - */ - SQLITE_OPEN_DELETEONCLOSE: number; - /** - * @constant 0x00000010 - */ - SQLITE_OPEN_EXCLUSIVE: number; - /** - * @constant 0x00000020 - */ - SQLITE_OPEN_AUTOPROXY: number; - /** - * @constant 0x00000040 - */ - SQLITE_OPEN_URI: number; - /** - * @constant 0x00000080 - */ - SQLITE_OPEN_MEMORY: number; - /** - * @constant 0x00000100 - */ - SQLITE_OPEN_MAIN_DB: number; - /** - * @constant 0x00000200 - */ - SQLITE_OPEN_TEMP_DB: number; - /** - * @constant 0x00000400 - */ - SQLITE_OPEN_TRANSIENT_DB: number; - /** - * @constant 0x00000800 - */ - SQLITE_OPEN_MAIN_JOURNAL: number; - /** - * @constant 0x00001000 - */ - SQLITE_OPEN_TEMP_JOURNAL: number; - /** - * @constant 0x00002000 - */ - SQLITE_OPEN_SUBJOURNAL: number; - /** - * @constant 0x00004000 - */ - SQLITE_OPEN_SUPER_JOURNAL: number; - /** - * @constant 0x00008000 - */ - SQLITE_OPEN_NOMUTEX: number; - /** - * @constant 0x00010000 - */ - SQLITE_OPEN_FULLMUTEX: number; - /** - * @constant 0x00020000 - */ - SQLITE_OPEN_SHAREDCACHE: number; - /** - * @constant 0x00040000 - */ - SQLITE_OPEN_PRIVATECACHE: number; - /** - * @constant 0x00080000 - */ - SQLITE_OPEN_WAL: number; - /** - * @constant 0x01000000 - */ - SQLITE_OPEN_NOFOLLOW: number; - /** - * @constant 0x02000000 - */ - SQLITE_OPEN_EXRESCODE: number; - /** - * @constant 0x01 - */ - SQLITE_PREPARE_PERSISTENT: number; - /** - * @constant 0x02 - */ - SQLITE_PREPARE_NORMALIZE: number; - /** - * @constant 0x04 - */ - SQLITE_PREPARE_NO_VTAB: number; + /** + * Constants from `sqlite3.h` + * + * This list isn't exhaustive, but some of the ones which are relevant + */ + export const constants: { + /** + * Open the database as read-only (no write operations, no create). + * @constant 0x00000001 + */ + SQLITE_OPEN_READONLY: number; + /** + * Open the database for reading and writing + * @constant 0x00000002 + */ + SQLITE_OPEN_READWRITE: number; + /** + * Allow creating a new database + * @constant 0x00000004 + */ + SQLITE_OPEN_CREATE: number; + /** + * @constant 0x00000008 + */ + SQLITE_OPEN_DELETEONCLOSE: number; + /** + * @constant 0x00000010 + */ + SQLITE_OPEN_EXCLUSIVE: number; + /** + * @constant 0x00000020 + */ + SQLITE_OPEN_AUTOPROXY: number; + /** + * @constant 0x00000040 + */ + SQLITE_OPEN_URI: number; + /** + * @constant 0x00000080 + */ + SQLITE_OPEN_MEMORY: number; + /** + * @constant 0x00000100 + */ + SQLITE_OPEN_MAIN_DB: number; + /** + * @constant 0x00000200 + */ + SQLITE_OPEN_TEMP_DB: number; + /** + * @constant 0x00000400 + */ + SQLITE_OPEN_TRANSIENT_DB: number; + /** + * @constant 0x00000800 + */ + SQLITE_OPEN_MAIN_JOURNAL: number; + /** + * @constant 0x00001000 + */ + SQLITE_OPEN_TEMP_JOURNAL: number; + /** + * @constant 0x00002000 + */ + SQLITE_OPEN_SUBJOURNAL: number; + /** + * @constant 0x00004000 + */ + SQLITE_OPEN_SUPER_JOURNAL: number; + /** + * @constant 0x00008000 + */ + SQLITE_OPEN_NOMUTEX: number; + /** + * @constant 0x00010000 + */ + SQLITE_OPEN_FULLMUTEX: number; + /** + * @constant 0x00020000 + */ + SQLITE_OPEN_SHAREDCACHE: number; + /** + * @constant 0x00040000 + */ + SQLITE_OPEN_PRIVATECACHE: number; + /** + * @constant 0x00080000 + */ + SQLITE_OPEN_WAL: number; + /** + * @constant 0x01000000 + */ + SQLITE_OPEN_NOFOLLOW: number; + /** + * @constant 0x02000000 + */ + SQLITE_OPEN_EXRESCODE: number; + /** + * @constant 0x01 + */ + SQLITE_PREPARE_PERSISTENT: number; + /** + * @constant 0x02 + */ + SQLITE_PREPARE_NORMALIZE: number; + /** + * @constant 0x04 + */ + SQLITE_PREPARE_NO_VTAB: number; - /** - * @constant 1 - */ - SQLITE_FCNTL_LOCKSTATE: number; - /** - * @constant 2 - */ - SQLITE_FCNTL_GET_LOCKPROXYFILE: number; - /** - * @constant 3 - */ - SQLITE_FCNTL_SET_LOCKPROXYFILE: number; - /** - * @constant 4 - */ - SQLITE_FCNTL_LAST_ERRNO: number; - /** - * @constant 5 - */ - SQLITE_FCNTL_SIZE_HINT: number; - /** - * @constant 6 - */ - SQLITE_FCNTL_CHUNK_SIZE: number; - /** - * @constant 7 - */ - SQLITE_FCNTL_FILE_POINTER: number; - /** - * @constant 8 - */ - SQLITE_FCNTL_SYNC_OMITTED: number; - /** - * @constant 9 - */ - SQLITE_FCNTL_WIN32_AV_RETRY: number; - /** - * @constant 10 - * - * Control whether or not the WAL is persisted - * Some versions of macOS configure WAL to be persistent by default. - * - * You can change this with code like the below: - * ```ts - * import { Database } from "bun:sqlite"; - * - * const db = Database.open("mydb.sqlite"); - * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); - * // enable WAL - * db.exec("PRAGMA journal_mode = WAL"); - * // .. do some work - * db.close(); - * ``` - * - */ - SQLITE_FCNTL_PERSIST_WAL: number; - /** - * @constant 11 - */ - SQLITE_FCNTL_OVERWRITE: number; - /** - * @constant 12 - */ - SQLITE_FCNTL_VFSNAME: number; - /** - * @constant 13 - */ - SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; - /** - * @constant 14 - */ - SQLITE_FCNTL_PRAGMA: number; - /** - * @constant 15 - */ - SQLITE_FCNTL_BUSYHANDLER: number; - /** - * @constant 16 - */ - SQLITE_FCNTL_TEMPFILENAME: number; - /** - * @constant 18 - */ - SQLITE_FCNTL_MMAP_SIZE: number; - /** - * @constant 19 - */ - SQLITE_FCNTL_TRACE: number; - /** - * @constant 20 - */ - SQLITE_FCNTL_HAS_MOVED: number; - /** - * @constant 21 - */ - SQLITE_FCNTL_SYNC: number; - /** - * @constant 22 - */ - SQLITE_FCNTL_COMMIT_PHASETWO: number; - /** - * @constant 23 - */ - SQLITE_FCNTL_WIN32_SET_HANDLE: number; - /** - * @constant 24 - */ - SQLITE_FCNTL_WAL_BLOCK: number; - /** - * @constant 25 - */ - SQLITE_FCNTL_ZIPVFS: number; - /** - * @constant 26 - */ - SQLITE_FCNTL_RBU: number; - /** - * @constant 27 - */ - SQLITE_FCNTL_VFS_POINTER: number; - /** - * @constant 28 - */ - SQLITE_FCNTL_JOURNAL_POINTER: number; - /** - * @constant 29 - */ - SQLITE_FCNTL_WIN32_GET_HANDLE: number; - /** - * @constant 30 - */ - SQLITE_FCNTL_PDB: number; - /** - * @constant 31 - */ - SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; - /** - * @constant 32 - */ - SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; - /** - * @constant 33 - */ - SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; - /** - * @constant 34 - */ - SQLITE_FCNTL_LOCK_TIMEOUT: number; - /** - * @constant 35 - */ - SQLITE_FCNTL_DATA_VERSION: number; - /** - * @constant 36 - */ - SQLITE_FCNTL_SIZE_LIMIT: number; - /** - * @constant 37 - */ - SQLITE_FCNTL_CKPT_DONE: number; - /** - * @constant 38 - */ - SQLITE_FCNTL_RESERVE_BYTES: number; - /** - * @constant 39 - */ - SQLITE_FCNTL_CKPT_START: number; - /** - * @constant 40 - */ - SQLITE_FCNTL_EXTERNAL_READER: number; - /** - * @constant 41 - */ - SQLITE_FCNTL_CKSM_FILE: number; - /** - * @constant 42 - */ - SQLITE_FCNTL_RESET_CACHE: number; - }; + /** + * @constant 1 + */ + SQLITE_FCNTL_LOCKSTATE: number; + /** + * @constant 2 + */ + SQLITE_FCNTL_GET_LOCKPROXYFILE: number; + /** + * @constant 3 + */ + SQLITE_FCNTL_SET_LOCKPROXYFILE: number; + /** + * @constant 4 + */ + SQLITE_FCNTL_LAST_ERRNO: number; + /** + * @constant 5 + */ + SQLITE_FCNTL_SIZE_HINT: number; + /** + * @constant 6 + */ + SQLITE_FCNTL_CHUNK_SIZE: number; + /** + * @constant 7 + */ + SQLITE_FCNTL_FILE_POINTER: number; + /** + * @constant 8 + */ + SQLITE_FCNTL_SYNC_OMITTED: number; + /** + * @constant 9 + */ + SQLITE_FCNTL_WIN32_AV_RETRY: number; + /** + * @constant 10 + * + * Control whether or not the WAL is persisted + * Some versions of macOS configure WAL to be persistent by default. + * + * You can change this with code like the below: + * ```ts + * import { Database } from "bun:sqlite"; + * + * const db = Database.open("mydb.sqlite"); + * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); + * // enable WAL + * db.exec("PRAGMA journal_mode = WAL"); + * // .. do some work + * db.close(); + * ``` + * + */ + SQLITE_FCNTL_PERSIST_WAL: number; + /** + * @constant 11 + */ + SQLITE_FCNTL_OVERWRITE: number; + /** + * @constant 12 + */ + SQLITE_FCNTL_VFSNAME: number; + /** + * @constant 13 + */ + SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; + /** + * @constant 14 + */ + SQLITE_FCNTL_PRAGMA: number; + /** + * @constant 15 + */ + SQLITE_FCNTL_BUSYHANDLER: number; + /** + * @constant 16 + */ + SQLITE_FCNTL_TEMPFILENAME: number; + /** + * @constant 18 + */ + SQLITE_FCNTL_MMAP_SIZE: number; + /** + * @constant 19 + */ + SQLITE_FCNTL_TRACE: number; + /** + * @constant 20 + */ + SQLITE_FCNTL_HAS_MOVED: number; + /** + * @constant 21 + */ + SQLITE_FCNTL_SYNC: number; + /** + * @constant 22 + */ + SQLITE_FCNTL_COMMIT_PHASETWO: number; + /** + * @constant 23 + */ + SQLITE_FCNTL_WIN32_SET_HANDLE: number; + /** + * @constant 24 + */ + SQLITE_FCNTL_WAL_BLOCK: number; + /** + * @constant 25 + */ + SQLITE_FCNTL_ZIPVFS: number; + /** + * @constant 26 + */ + SQLITE_FCNTL_RBU: number; + /** + * @constant 27 + */ + SQLITE_FCNTL_VFS_POINTER: number; + /** + * @constant 28 + */ + SQLITE_FCNTL_JOURNAL_POINTER: number; + /** + * @constant 29 + */ + SQLITE_FCNTL_WIN32_GET_HANDLE: number; + /** + * @constant 30 + */ + SQLITE_FCNTL_PDB: number; + /** + * @constant 31 + */ + SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; + /** + * @constant 32 + */ + SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; + /** + * @constant 33 + */ + SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; + /** + * @constant 34 + */ + SQLITE_FCNTL_LOCK_TIMEOUT: number; + /** + * @constant 35 + */ + SQLITE_FCNTL_DATA_VERSION: number; + /** + * @constant 36 + */ + SQLITE_FCNTL_SIZE_LIMIT: number; + /** + * @constant 37 + */ + SQLITE_FCNTL_CKPT_DONE: number; + /** + * @constant 38 + */ + SQLITE_FCNTL_RESERVE_BYTES: number; + /** + * @constant 39 + */ + SQLITE_FCNTL_CKPT_START: number; + /** + * @constant 40 + */ + SQLITE_FCNTL_EXTERNAL_READER: number; + /** + * @constant 41 + */ + SQLITE_FCNTL_CKSM_FILE: number; + /** + * @constant 42 + */ + SQLITE_FCNTL_RESET_CACHE: number; + }; - /** - * The native module implementing the sqlite3 C bindings - * - * It is lazily-initialized, so this will return `undefined` until the first - * call to new Database(). - * - * The native module makes no gurantees about ABI stability, so it is left - * untyped - * - * If you need to use it directly for some reason, please let us know because - * that probably points to a deficiency in this API. - */ - export var native: any; + /** + * The native module implementing the sqlite3 C bindings + * + * It is lazily-initialized, so this will return `undefined` until the first + * call to new Database(). + * + * The native module makes no gurantees about ABI stability, so it is left + * untyped + * + * If you need to use it directly for some reason, please let us know because + * that probably points to a deficiency in this API. + */ + export var native: any; - export type SQLQueryBindings = - | string - | bigint - | NodeJS.TypedArray - | number - | boolean - | null - | Record; + export type SQLQueryBindings = + | string + | bigint + | NodeJS.TypedArray + | number + | boolean + | null + | Record< + string, + string | bigint | NodeJS.TypedArray | number | boolean | null + >; - export default Database; + export default Database; - /** - * Errors from SQLite have a name `SQLiteError`. - * - */ - export class SQLiteError extends Error { - readonly name: "SQLiteError"; + /** + * Errors from SQLite have a name `SQLiteError`. + * + */ + export class SQLiteError extends Error { + readonly name: "SQLiteError"; - /** - * The SQLite3 extended error code - * - * This corresponds to `sqlite3_extended_errcode`. - * - * @since v1.0.21 - */ - errno: number; + /** + * The SQLite3 extended error code + * + * This corresponds to `sqlite3_extended_errcode`. + * + * @since v1.0.21 + */ + errno: number; - /** - * The name of the SQLite3 error code - * - * @example - * "SQLITE_CONSTRAINT_UNIQUE" - * - * @since v1.0.21 - */ - code?: string; + /** + * The name of the SQLite3 error code + * + * @example + * "SQLITE_CONSTRAINT_UNIQUE" + * + * @since v1.0.21 + */ + code?: string; - /** - * The UTF-8 byte offset of the sqlite3 query that failed, if known - * - * This corresponds to `sqlite3_error_offset`. - * - * @since v1.0.21 - */ - readonly byteOffset: number; - } + /** + * The UTF-8 byte offset of the sqlite3 query that failed, if known + * + * This corresponds to `sqlite3_error_offset`. + * + * @since v1.0.21 + */ + readonly byteOffset: number; + } - /** - * An object representing the changes made to the database since the last `run` or `exec` call. - * - * @since Bun v1.1.14 - */ - export interface Changes { - /** - * The number of rows changed by the last `run` or `exec` call. - */ - changes: number; + /** + * An object representing the changes made to the database since the last `run` or `exec` call. + * + * @since Bun v1.1.14 + */ + export interface Changes { + /** + * The number of rows changed by the last `run` or `exec` call. + */ + changes: number; - /** - * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. - */ - lastInsertRowid: number | bigint; - } + /** + * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. + */ + lastInsertRowid: number | bigint; + } } diff --git a/packages/bun-types/test.d.ts b/packages/bun-types/test.d.ts index 9c5ef1a2da6670..e2d4a01871c381 100644 --- a/packages/bun-types/test.d.ts +++ b/packages/bun-types/test.d.ts @@ -14,995 +14,1060 @@ * ``` */ declare module "bun:test" { - /** - * -- Mocks -- - */ - export type Mock any> = JestMock.Mock; - - export const mock: { - any>(Function?: T): Mock; - - /** - * Replace the module `id` with the return value of `factory`. - * - * This is useful for mocking modules. - * - * @param id module ID to mock - * @param factory a function returning an object that will be used as the exports of the mocked module - * - * @example - * ## Example - * ```ts - * import { mock } from "bun:test"; - * - * mock.module("fs/promises", () => { - * return { - * readFile: () => Promise.resolve("hello world"), - * }; - * }); - * - * import { readFile } from "fs/promises"; - * - * console.log(await readFile("hello.txt", "utf8")); // hello world - * ``` - * - * ## More notes - * - * If the module is already loaded, exports are overwritten with the return - * value of `factory`. If the export didn't exist before, it will not be - * added to existing import statements. This is due to how ESM works. - */ - module(id: string, factory: () => any): void | Promise; - /** - * Restore the previous value of mocks. - */ - restore(): void; - }; - - /** - * Control the system time used by: - * - `Date.now()` - * - `new Date()` - * - `Intl.DateTimeFormat().format()` - * - * In the future, we may add support for more functions, but we haven't done that yet. - * - * @param now The time to set the system time to. If not provided, the system time will be reset. - * @returns `this` - * @since v0.6.13 - * - * ## Set Date to a specific time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); - * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z - * ``` - * ## Reset Date to the current time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(); - * ``` - */ - export function setSystemTime(now?: Date | number): ThisType; - - interface Jest { - restoreAllMocks(): void; - clearAllMocks(): void; - fn any>(func?: T): Mock; - setSystemTime(now?: number | Date): void; - setTimeout(milliseconds: number): void; - } - export const jest: Jest; - export namespace jest { - /** - * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. - */ - type Mock any = (...args: any[]) => any> = JestMock.Mock; - /** - * Wraps a class, function or object type with Jest mock type definitions. - */ - // type Mocked = JestMock.Mocked; - /** - * Wraps a class type with Jest mock type definitions. - */ - // type MockedClass = JestMock.MockedClass; - /** - * Wraps a function type with Jest mock type definitions. - */ - // type MockedFunction any> = JestMock.MockedFunction; - /** - * Wraps an object type with Jest mock type definitions. - */ - // type MockedObject = JestMock.MockedObject; - /** - * Constructs the type of a replaced property. - */ - type Replaced = JestMock.Replaced; - /** - * Constructs the type of a spied class or function. - */ - type Spied any)> = JestMock.Spied; - /** - * Constructs the type of a spied class. - */ - type SpiedClass = JestMock.SpiedClass; - /** - * Constructs the type of a spied function. - */ - type SpiedFunction any> = JestMock.SpiedFunction; - /** - * Constructs the type of a spied getter. - */ - type SpiedGetter = JestMock.SpiedGetter; - /** - * Constructs the type of a spied setter. - */ - type SpiedSetter = JestMock.SpiedSetter; - } - - export function spyOn( - obj: T, - methodOrPropertyValue: K, - ): Mock any ? T[K] : never>; - - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export interface Describe { - (label: string, fn: () => void): void; - /** - * Skips all other tests, except this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - only(label: string, fn: () => void): void; - /** - * Skips this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - skip(label: string, fn: () => void): void; - /** - * Marks this group of tests as to be written or to be fixed. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - todo(label: string, fn?: () => void): void; - /** - * Runs this group of tests, only if `condition` is true. - * - * This is the opposite of `describe.skipIf()`. - * - * @param condition if these tests should run - */ - if(condition: boolean): (label: string, fn: () => void) => void; - /** - * Skips this group of tests, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - skipIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Marks this group of tests as to be written or to be fixed, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - todoIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; - each( - table: readonly T[], - ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; - each( - table: T[], - ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; - } - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export const describe: Describe; - /** - * Runs a function, once, before all the tests. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, tests will not run in this file. - * - * @example - * let database; - * beforeAll(async () => { - * database = await connect("localhost"); - * }); - * - * @param fn the function to run - */ - export function beforeAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function before each test. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, the test will not run. - * - * @param fn the function to run - */ - export function beforeEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function, once, after all the tests. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @example - * let database; - * afterAll(async () => { - * if (database) { - * await database.close(); - * } - * }); - * - * @param fn the function to run - */ - export function afterAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function after each test. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @param fn the function to run - */ - export function afterEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will - * override this value. The default timeout is 5000ms (5 seconds). - * - * @param milliseconds the number of milliseconds for the default timeout - */ - export function setDefaultTimeout(milliseconds: number): void; - export interface TestOptions { - /** - * Sets the timeout for the test in milliseconds. - * - * If the test does not complete within this time, the test will fail with: - * ```ts - * 'Timeout: test {name} timed out after 5000ms' - * ``` - * - * @default 5000 // 5 seconds - */ - timeout?: number; - /** - * Sets the number of times to retry the test if it fails. - * - * @default 0 - */ - retry?: number; - /** - * Sets the number of times to repeat the test, regardless of whether it passed or failed. - * - * @default 0 - */ - repeats?: number; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * test("can set a timeout", async () => { - * await Bun.sleep(100); - * }, 50); // or { timeout: 50 } - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - export interface Test { - ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - /** - * - If a `number`, sets the timeout for the test in milliseconds. - * - If an `object`, sets the options for the test. - * - `timeout` sets the timeout for the test in milliseconds. - * - `retry` sets the number of times to retry the test if it fails. - * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. - */ - options?: number | TestOptions, - ): void; - /** - * Skips all other tests, except this test when run with the `--only` option. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - only( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Skips this test. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - skip( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as to be written or to be fixed. - * - * These tests will not be executed unless the `--todo` flag is passed. With the flag, - * if the test passes, the test will be marked as `fail` in the results; you will have to - * remove the `.todo` or check that your test - * is implemented correctly. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - todo( - label: string, - fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as failing. - * - * Use `test.failing` when you are writing a test and expecting it to fail. - * These tests will behave the other way normal tests do. If failing test - * will throw any errors then it will pass. If it does not throw it will - * fail. - * - * `test.failing` is very similar to {@link test.todo} except that it always - * runs, regardless of the `--todo` flag. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - failing(label: string, fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs this test, if `condition` is true. - * - * This is the opposite of `test.skipIf()`. - * - * @param condition if the test should run - */ - if( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Skips this test, if `condition` is true. - * - * @param condition if the test should be skipped - */ - skipIf( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Marks this test as to be written or to be fixed, if `condition` is true. - * - * @param condition if the test should be marked TODO - */ - todoIf( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; - each( - table: readonly T[], - ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; - each( - table: T[], - ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * @param label the label for the test - * @param fn the test function - */ - export const test: Test; - export { test as it }; - - /** - * Asserts that a value matches some criteria. - * - * @link https://jestjs.io/docs/expect#reference - * @example - * expect(1 + 1).toBe(2); - * expect([1,2,3]).toContain(2); - * expect(null).toBeNull(); - * - * @param actual The actual (received) value - */ - export const expect: Expect; - - type ExpectNot = Omit & AsymmetricMatchersBuiltinNegated; - - export interface Expect extends AsymmetricMatchers { - // the `expect()` callable signature - /** - * @param actual the actual value - * @param customFailMessage an optional custom message to display if the test fails. - * */ - - (actual?: T, customFailMessage?: string): Matchers; - - /** - * Access to negated asymmetric matchers. - * - * @example - * expect("abc").toEqual(expect.stringContaining("abc")); // will pass - * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail - */ - not: ExpectNot; - - /** - * Create an asymmetric matcher for a promise resolved value. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass - * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail - * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail - */ - resolvesTo: AsymmetricMatchers; - - /** - * Create an asymmetric matcher for a promise rejected value. - * - * @example - * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass - * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail - * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail - */ - rejectsTo: AsymmetricMatchers; - - /** - * Register new custom matchers. - * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. - * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` - * - * @example - * expect.extend({ - * toBeWithinRange(actual, min, max) { - * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') - * throw new Error('Invalid usage'); - * const pass = actual >= min && actual <= max; - * return { - * pass: pass, - * message: () => `expected ${this.utils.printReceived(actual)} ` + - * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, - * }; - * }, - * }); - * - * test('some test', () => { - * expect(50).toBeWithinRange(0, 100); // will pass - * expect(50).toBeWithinRange(100, 200); // will fail - * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass - * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass - * }); - */ - extend(matchers: ExpectExtendMatchers): void; - - /** - * Throw an error if this function is called. - * - * @param msg Optional message to display if the test fails - * @returns never - * - * @example - * ## Example - * - * ```ts - * import { expect, test } from "bun:test"; - * - * test("!!abc!! is not a module", () => { - * try { - * require("!!abc!!"); - * expect.unreachable(); - * } catch(e) { - * expect(e.name).not.toBe("UnreachableError"); - * } - * }); - * ``` - */ - unreachable(msg?: string | Error): never; - - /** - * Ensures that an assertion is made - */ - hasAssertions(): void; - - /** - * Ensures that a specific number of assertions are made - */ - assertions(neededAssertions: number): void; - } - - /** - * You can extend this interface with declaration merging, in order to add type support for custom matchers. - * @template T Type of the actual value - * - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface Matchers extends MatchersBuiltin {} - - /** - * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} - - export interface AsymmetricMatchersBuiltin { - /** - * Matches anything that was created with the given constructor. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * @example - * - * function randocall(fn) { - * return fn(Math.floor(Math.random() * 6 + 1)); - * } - * - * test('randocall calls its callback with a number', () => { - * const mock = jest.fn(); - * randocall(mock); - * expect(mock).toBeCalledWith(expect.any(Number)); - * }); - */ - any(constructor: ((...args: any[]) => any) | { new (...args: any[]): any }): AsymmetricMatcher; - /** - * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead - * of a literal value. For example, if you want to check that a mock function is called with a - * non-null argument: - * - * @example - * - * test('map calls its argument with a non-null argument', () => { - * const mock = jest.fn(); - * [1].map(x => mock(x)); - * expect(mock).toBeCalledWith(expect.anything()); - * }); - */ - anything(): AsymmetricMatcher; - /** - * Matches any array made up entirely of elements in the provided array. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - /** - * Matches any object that recursively matches the provided keys. - * This is often handy in conjunction with other asymmetric matchers. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - /** - * Matches any received string that contains the exact expected string - */ - stringContaining(str: string | String): AsymmetricMatcher; - /** - * Matches any string that contains the exact provided string - */ - stringMatching(regex: string | String | RegExp): AsymmetricMatcher; - /** - * Useful when comparing floating point numbers in object properties or array item. - * If you need to compare a number, use `.toBeCloseTo` instead. - * - * The optional `numDigits` argument limits the number of digits to check after the decimal point. - * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - interface AsymmetricMatchersBuiltinNegated { - /** - * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail - * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - */ - resolvesTo: ExpectNot; - - /** - * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. - * - * @example - * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail - * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - */ - rejectsTo: ExpectNot; - - /** - * `expect.not.arrayContaining(array)` matches a received array which - * does not contain all of the elements in the expected array. That is, - * the expected array is not a subset of the received array. It is the - * inverse of `expect.arrayContaining`. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - - /** - * `expect.not.objectContaining(object)` matches any received object - * that does not recursively match the expected properties. That is, the - * expected object is not a subset of the received object. Therefore, - * it matches a received object which contains properties that are not - * in the expected object. It is the inverse of `expect.objectContaining`. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - - /** - * `expect.not.stringContaining(string)` matches the received string - * that does not contain the exact expected string. It is the inverse of - * `expect.stringContaining`. - */ - stringContaining(str: string | String): AsymmetricMatcher; - - /** - * `expect.not.stringMatching(string | regexp)` matches the received - * string that does not match the expected regexp. It is the inverse of - * `expect.stringMatching`. - */ - stringMatching(str: string | String | RegExp): AsymmetricMatcher; - - /** - * `expect.not.closeTo` matches a number not close to the provided value. - * Useful when comparing floating point numbers in object properties or array item. - * It is the inverse of `expect.closeTo`. - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - export interface MatchersBuiltin { - /** - * Negates the result of a subsequent assertion. - * If you know how to test something, `.not` lets you test its opposite. - * - * @example - * expect(1).not.toBe(0); - * expect(null).not.toBeNull(); - * - * @example - * expect(42).toEqual(42); // will pass - * expect(42).not.toEqual(42); // will fail - */ - not: Matchers; - - /** - * Expects the value to be a promise that resolves. - * - * @example - * expect(Promise.resolve(1)).resolves.toBe(1); - */ - resolves: Matchers>; - - /** - * Expects the value to be a promise that rejects. - * - * @example - * expect(Promise.reject("error")).rejects.toBe("error"); - */ - rejects: Matchers; - - /** - * Assertion which passes. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass - * @example - * expect().pass(); - * expect().pass("message is optional"); - * expect().not.pass(); - * expect().not.pass("hi"); - * - * @param message the message to display if the test fails (optional) - */ - pass: (message?: string) => void; - /** - * Assertion which fails. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail - * @example - * expect().fail(); - * expect().fail("message is optional"); - * expect().not.fail(); - * expect().not.fail("hi"); - */ - fail: (message?: string) => void; - /** - * Asserts that a value equals what is expected. - * - * - For non-primitive values, like objects and arrays, - * use `toEqual()` instead. - * - For floating-point numbers, use `toBeCloseTo()` instead. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([123]).toBe([123]); // fail, use toEqual() - * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() - * - * @param expected the expected value - */ - toBe(expected: T): void; - /** - * Asserts that a number is odd. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd - * @example - * expect(1).toBeOdd(); - * expect(2).not.toBeOdd(); - */ - toBeOdd(): void; - /** - * Asserts that a number is even. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven - * @example - * expect(2).toBeEven(); - * expect(1).not.toBeEven(); - */ - toBeEven(): void; - /** - * Asserts that value is close to the expected by floating point precision. - * - * For example, the following fails because arithmetic on decimal (base 10) - * values often have rounding errors in limited precision binary (base 2) representation. - * - * @example - * expect(0.2 + 0.1).toBe(0.3); // fails - * - * Use `toBeCloseTo` to compare floating point numbers for approximate equality. - * - * @example - * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes - * - * @param expected the expected value - * @param numDigits the number of digits to check after the decimal point. Default is `2` - */ - toBeCloseTo(expected: number, numDigits?: number): void; - /** - * Asserts that a value is deeply equal to what is expected. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([456]).toEqual([456]); - * expect({ value: 1 }).toEqual({ value: 1 }); - * - * @param expected the expected value - */ - toEqual(expected: T): void; - /** - * Asserts that a value is deeply and strictly equal to - * what is expected. - * - * There are two key differences from `toEqual()`: - * 1. It checks that the class is the same. - * 2. It checks that `undefined` values match as well. - * - * @example - * class Dog { - * type = "dog"; - * } - * const actual = new Dog(); - * expect(actual).toStrictEqual(new Dog()); - * expect(actual).toStrictEqual({ type: "dog" }); // fail - * - * @example - * const actual = { value: 1, name: undefined }; - * expect(actual).toEqual({ value: 1 }); - * expect(actual).toStrictEqual({ value: 1 }); // fail - * - * @param expected the expected value - */ - toStrictEqual(expected: T): void; - /** - * Asserts that the value is deep equal to an element in the expected array. - * - * The value must be an array or iterable, which includes strings. - * - * @example - * expect(1).toBeOneOf([1,2,3]); - * expect("foo").toBeOneOf(["foo", "bar"]); - * expect(true).toBeOneOf(new Set([true])); - * - * @param expected the expected value - */ - toBeOneOf(expected: Array | Iterable): void; - /** - * Asserts that a value contains what is expected. - * - * The value must be an array or iterable, which - * includes strings. - * - * @example - * expect([1, 2, 3]).toContain(1); - * expect(new Set([true])).toContain(true); - * expect("hello").toContain("o"); - * - * @param expected the expected value - */ - toContain(expected: unknown): void; - /** - * Asserts that an `object` contains a key. - * - * The value must be an object - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); - * - * @param expected the expected value - */ - toContainKey(expected: unknown): void; - /** - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); - * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); - * - * @param expected the expected value - */ - toContainAllKeys(expected: unknown): void; - /** - * Asserts that an `object` contains at least one of the provided keys. - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); - * - * @param expected the expected value - */ - toContainAnyKeys(expected: unknown): void; - - /** + /** + * -- Mocks -- + */ + export type Mock any> = JestMock.Mock; + + export const mock: { + any>(Function?: T): Mock; + + /** + * Replace the module `id` with the return value of `factory`. + * + * This is useful for mocking modules. + * + * @param id module ID to mock + * @param factory a function returning an object that will be used as the exports of the mocked module + * + * @example + * ## Example + * ```ts + * import { mock } from "bun:test"; + * + * mock.module("fs/promises", () => { + * return { + * readFile: () => Promise.resolve("hello world"), + * }; + * }); + * + * import { readFile } from "fs/promises"; + * + * console.log(await readFile("hello.txt", "utf8")); // hello world + * ``` + * + * ## More notes + * + * If the module is already loaded, exports are overwritten with the return + * value of `factory`. If the export didn't exist before, it will not be + * added to existing import statements. This is due to how ESM works. + */ + module(id: string, factory: () => any): void | Promise; + /** + * Restore the previous value of mocks. + */ + restore(): void; + }; + + /** + * Control the system time used by: + * - `Date.now()` + * - `new Date()` + * - `Intl.DateTimeFormat().format()` + * + * In the future, we may add support for more functions, but we haven't done that yet. + * + * @param now The time to set the system time to. If not provided, the system time will be reset. + * @returns `this` + * @since v0.6.13 + * + * ## Set Date to a specific time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); + * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z + * ``` + * ## Reset Date to the current time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(); + * ``` + */ + export function setSystemTime(now?: Date | number): ThisType; + + interface Jest { + restoreAllMocks(): void; + clearAllMocks(): void; + fn any>(func?: T): Mock; + setSystemTime(now?: number | Date): void; + setTimeout(milliseconds: number): void; + } + export const jest: Jest; + export namespace jest { + /** + * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. + */ + type Mock any = (...args: any[]) => any> = + JestMock.Mock; + /** + * Wraps a class, function or object type with Jest mock type definitions. + */ + // type Mocked = JestMock.Mocked; + /** + * Wraps a class type with Jest mock type definitions. + */ + // type MockedClass = JestMock.MockedClass; + /** + * Wraps a function type with Jest mock type definitions. + */ + // type MockedFunction any> = JestMock.MockedFunction; + /** + * Wraps an object type with Jest mock type definitions. + */ + // type MockedObject = JestMock.MockedObject; + /** + * Constructs the type of a replaced property. + */ + type Replaced = JestMock.Replaced; + /** + * Constructs the type of a spied class or function. + */ + type Spied any)> = + JestMock.Spied; + /** + * Constructs the type of a spied class. + */ + type SpiedClass = JestMock.SpiedClass; + /** + * Constructs the type of a spied function. + */ + type SpiedFunction any> = + JestMock.SpiedFunction; + /** + * Constructs the type of a spied getter. + */ + type SpiedGetter = JestMock.SpiedGetter; + /** + * Constructs the type of a spied setter. + */ + type SpiedSetter = JestMock.SpiedSetter; + } + + export function spyOn( + obj: T, + methodOrPropertyValue: K, + ): Mock any ? T[K] : never>; + + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export interface Describe { + (label: string, fn: () => void): void; + /** + * Skips all other tests, except this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + only(label: string, fn: () => void): void; + /** + * Skips this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + skip(label: string, fn: () => void): void; + /** + * Marks this group of tests as to be written or to be fixed. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + todo(label: string, fn?: () => void): void; + /** + * Runs this group of tests, only if `condition` is true. + * + * This is the opposite of `describe.skipIf()`. + * + * @param condition if these tests should run + */ + if(condition: boolean): (label: string, fn: () => void) => void; + /** + * Skips this group of tests, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + skipIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Marks this group of tests as to be written or to be fixed, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + todoIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): ( + label: string, + fn: (...args: [...T]) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: readonly T[], + ): ( + label: string, + fn: (...args: Readonly) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: T[], + ): ( + label: string, + fn: (...args: T[]) => void | Promise, + options?: number | TestOptions, + ) => void; + } + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export const describe: Describe; + /** + * Runs a function, once, before all the tests. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, tests will not run in this file. + * + * @example + * let database; + * beforeAll(async () => { + * database = await connect("localhost"); + * }); + * + * @param fn the function to run + */ + export function beforeAll( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function before each test. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, the test will not run. + * + * @param fn the function to run + */ + export function beforeEach( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function, once, after all the tests. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @example + * let database; + * afterAll(async () => { + * if (database) { + * await database.close(); + * } + * }); + * + * @param fn the function to run + */ + export function afterAll( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function after each test. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @param fn the function to run + */ + export function afterEach( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will + * override this value. The default timeout is 5000ms (5 seconds). + * + * @param milliseconds the number of milliseconds for the default timeout + */ + export function setDefaultTimeout(milliseconds: number): void; + export interface TestOptions { + /** + * Sets the timeout for the test in milliseconds. + * + * If the test does not complete within this time, the test will fail with: + * ```ts + * 'Timeout: test {name} timed out after 5000ms' + * ``` + * + * @default 5000 // 5 seconds + */ + timeout?: number; + /** + * Sets the number of times to retry the test if it fails. + * + * @default 0 + */ + retry?: number; + /** + * Sets the number of times to repeat the test, regardless of whether it passed or failed. + * + * @default 0 + */ + repeats?: number; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * test("can set a timeout", async () => { + * await Bun.sleep(100); + * }, 50); // or { timeout: 50 } + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + export interface Test { + ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + /** + * - If a `number`, sets the timeout for the test in milliseconds. + * - If an `object`, sets the options for the test. + * - `timeout` sets the timeout for the test in milliseconds. + * - `retry` sets the number of times to retry the test if it fails. + * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. + */ + options?: number | TestOptions, + ): void; + /** + * Skips all other tests, except this test when run with the `--only` option. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + only( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Skips this test. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + skip( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as to be written or to be fixed. + * + * These tests will not be executed unless the `--todo` flag is passed. With the flag, + * if the test passes, the test will be marked as `fail` in the results; you will have to + * remove the `.todo` or check that your test + * is implemented correctly. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + todo( + label: string, + fn?: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as failing. + * + * Use `test.failing` when you are writing a test and expecting it to fail. + * These tests will behave the other way normal tests do. If failing test + * will throw any errors then it will pass. If it does not throw it will + * fail. + * + * `test.failing` is very similar to {@link test.todo} except that it always + * runs, regardless of the `--todo` flag. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + failing( + label: string, + fn?: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs this test, if `condition` is true. + * + * This is the opposite of `test.skipIf()`. + * + * @param condition if the test should run + */ + if( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Skips this test, if `condition` is true. + * + * @param condition if the test should be skipped + */ + skipIf( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Marks this test as to be written or to be fixed, if `condition` is true. + * + * @param condition if the test should be marked TODO + */ + todoIf( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): ( + label: string, + fn: (...args: [...T]) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: readonly T[], + ): ( + label: string, + fn: (...args: Readonly) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: T[], + ): ( + label: string, + fn: (...args: T[]) => void | Promise, + options?: number | TestOptions, + ) => void; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * @param label the label for the test + * @param fn the test function + */ + export const test: Test; + export { test as it }; + + /** + * Asserts that a value matches some criteria. + * + * @link https://jestjs.io/docs/expect#reference + * @example + * expect(1 + 1).toBe(2); + * expect([1,2,3]).toContain(2); + * expect(null).toBeNull(); + * + * @param actual The actual (received) value + */ + export const expect: Expect; + + type ExpectNot = Omit & + AsymmetricMatchersBuiltinNegated; + + export interface Expect extends AsymmetricMatchers { + // the `expect()` callable signature + /** + * @param actual the actual value + * @param customFailMessage an optional custom message to display if the test fails. + * */ + + (actual?: T, customFailMessage?: string): Matchers; + + /** + * Access to negated asymmetric matchers. + * + * @example + * expect("abc").toEqual(expect.stringContaining("abc")); // will pass + * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail + */ + not: ExpectNot; + + /** + * Create an asymmetric matcher for a promise resolved value. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass + * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail + * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail + */ + resolvesTo: AsymmetricMatchers; + + /** + * Create an asymmetric matcher for a promise rejected value. + * + * @example + * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass + * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail + * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail + */ + rejectsTo: AsymmetricMatchers; + + /** + * Register new custom matchers. + * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. + * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` + * + * @example + * expect.extend({ + * toBeWithinRange(actual, min, max) { + * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') + * throw new Error('Invalid usage'); + * const pass = actual >= min && actual <= max; + * return { + * pass: pass, + * message: () => `expected ${this.utils.printReceived(actual)} ` + + * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, + * }; + * }, + * }); + * + * test('some test', () => { + * expect(50).toBeWithinRange(0, 100); // will pass + * expect(50).toBeWithinRange(100, 200); // will fail + * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass + * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass + * }); + */ + extend(matchers: ExpectExtendMatchers): void; + + /** + * Throw an error if this function is called. + * + * @param msg Optional message to display if the test fails + * @returns never + * + * @example + * ## Example + * + * ```ts + * import { expect, test } from "bun:test"; + * + * test("!!abc!! is not a module", () => { + * try { + * require("!!abc!!"); + * expect.unreachable(); + * } catch(e) { + * expect(e.name).not.toBe("UnreachableError"); + * } + * }); + * ``` + */ + unreachable(msg?: string | Error): never; + + /** + * Ensures that an assertion is made + */ + hasAssertions(): void; + + /** + * Ensures that a specific number of assertions are made + */ + assertions(neededAssertions: number): void; + } + + /** + * You can extend this interface with declaration merging, in order to add type support for custom matchers. + * @template T Type of the actual value + * + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface Matchers extends MatchersBuiltin {} + + /** + * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} + + export interface AsymmetricMatchersBuiltin { + /** + * Matches anything that was created with the given constructor. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * @example + * + * function randocall(fn) { + * return fn(Math.floor(Math.random() * 6 + 1)); + * } + * + * test('randocall calls its callback with a number', () => { + * const mock = jest.fn(); + * randocall(mock); + * expect(mock).toBeCalledWith(expect.any(Number)); + * }); + */ + any( + constructor: ((...args: any[]) => any) | { new (...args: any[]): any }, + ): AsymmetricMatcher; + /** + * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead + * of a literal value. For example, if you want to check that a mock function is called with a + * non-null argument: + * + * @example + * + * test('map calls its argument with a non-null argument', () => { + * const mock = jest.fn(); + * [1].map(x => mock(x)); + * expect(mock).toBeCalledWith(expect.anything()); + * }); + */ + anything(): AsymmetricMatcher; + /** + * Matches any array made up entirely of elements in the provided array. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + /** + * Matches any object that recursively matches the provided keys. + * This is often handy in conjunction with other asymmetric matchers. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + /** + * Matches any received string that contains the exact expected string + */ + stringContaining(str: string | String): AsymmetricMatcher; + /** + * Matches any string that contains the exact provided string + */ + stringMatching(regex: string | String | RegExp): AsymmetricMatcher; + /** + * Useful when comparing floating point numbers in object properties or array item. + * If you need to compare a number, use `.toBeCloseTo` instead. + * + * The optional `numDigits` argument limits the number of digits to check after the decimal point. + * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + interface AsymmetricMatchersBuiltinNegated { + /** + * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail + * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + */ + resolvesTo: ExpectNot; + + /** + * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. + * + * @example + * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail + * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + */ + rejectsTo: ExpectNot; + + /** + * `expect.not.arrayContaining(array)` matches a received array which + * does not contain all of the elements in the expected array. That is, + * the expected array is not a subset of the received array. It is the + * inverse of `expect.arrayContaining`. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + + /** + * `expect.not.objectContaining(object)` matches any received object + * that does not recursively match the expected properties. That is, the + * expected object is not a subset of the received object. Therefore, + * it matches a received object which contains properties that are not + * in the expected object. It is the inverse of `expect.objectContaining`. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + + /** + * `expect.not.stringContaining(string)` matches the received string + * that does not contain the exact expected string. It is the inverse of + * `expect.stringContaining`. + */ + stringContaining(str: string | String): AsymmetricMatcher; + + /** + * `expect.not.stringMatching(string | regexp)` matches the received + * string that does not match the expected regexp. It is the inverse of + * `expect.stringMatching`. + */ + stringMatching(str: string | String | RegExp): AsymmetricMatcher; + + /** + * `expect.not.closeTo` matches a number not close to the provided value. + * Useful when comparing floating point numbers in object properties or array item. + * It is the inverse of `expect.closeTo`. + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + export interface MatchersBuiltin { + /** + * Negates the result of a subsequent assertion. + * If you know how to test something, `.not` lets you test its opposite. + * + * @example + * expect(1).not.toBe(0); + * expect(null).not.toBeNull(); + * + * @example + * expect(42).toEqual(42); // will pass + * expect(42).not.toEqual(42); // will fail + */ + not: Matchers; + + /** + * Expects the value to be a promise that resolves. + * + * @example + * expect(Promise.resolve(1)).resolves.toBe(1); + */ + resolves: Matchers>; + + /** + * Expects the value to be a promise that rejects. + * + * @example + * expect(Promise.reject("error")).rejects.toBe("error"); + */ + rejects: Matchers; + + /** + * Assertion which passes. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass + * @example + * expect().pass(); + * expect().pass("message is optional"); + * expect().not.pass(); + * expect().not.pass("hi"); + * + * @param message the message to display if the test fails (optional) + */ + pass: (message?: string) => void; + /** + * Assertion which fails. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail + * @example + * expect().fail(); + * expect().fail("message is optional"); + * expect().not.fail(); + * expect().not.fail("hi"); + */ + fail: (message?: string) => void; + /** + * Asserts that a value equals what is expected. + * + * - For non-primitive values, like objects and arrays, + * use `toEqual()` instead. + * - For floating-point numbers, use `toBeCloseTo()` instead. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([123]).toBe([123]); // fail, use toEqual() + * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() + * + * @param expected the expected value + */ + toBe(expected: T): void; + /** + * Asserts that a number is odd. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd + * @example + * expect(1).toBeOdd(); + * expect(2).not.toBeOdd(); + */ + toBeOdd(): void; + /** + * Asserts that a number is even. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven + * @example + * expect(2).toBeEven(); + * expect(1).not.toBeEven(); + */ + toBeEven(): void; + /** + * Asserts that value is close to the expected by floating point precision. + * + * For example, the following fails because arithmetic on decimal (base 10) + * values often have rounding errors in limited precision binary (base 2) representation. + * + * @example + * expect(0.2 + 0.1).toBe(0.3); // fails + * + * Use `toBeCloseTo` to compare floating point numbers for approximate equality. + * + * @example + * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes + * + * @param expected the expected value + * @param numDigits the number of digits to check after the decimal point. Default is `2` + */ + toBeCloseTo(expected: number, numDigits?: number): void; + /** + * Asserts that a value is deeply equal to what is expected. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([456]).toEqual([456]); + * expect({ value: 1 }).toEqual({ value: 1 }); + * + * @param expected the expected value + */ + toEqual(expected: T): void; + /** + * Asserts that a value is deeply and strictly equal to + * what is expected. + * + * There are two key differences from `toEqual()`: + * 1. It checks that the class is the same. + * 2. It checks that `undefined` values match as well. + * + * @example + * class Dog { + * type = "dog"; + * } + * const actual = new Dog(); + * expect(actual).toStrictEqual(new Dog()); + * expect(actual).toStrictEqual({ type: "dog" }); // fail + * + * @example + * const actual = { value: 1, name: undefined }; + * expect(actual).toEqual({ value: 1 }); + * expect(actual).toStrictEqual({ value: 1 }); // fail + * + * @param expected the expected value + */ + toStrictEqual(expected: T): void; + /** + * Asserts that the value is deep equal to an element in the expected array. + * + * The value must be an array or iterable, which includes strings. + * + * @example + * expect(1).toBeOneOf([1,2,3]); + * expect("foo").toBeOneOf(["foo", "bar"]); + * expect(true).toBeOneOf(new Set([true])); + * + * @param expected the expected value + */ + toBeOneOf(expected: Array | Iterable): void; + /** + * Asserts that a value contains what is expected. + * + * The value must be an array or iterable, which + * includes strings. + * + * @example + * expect([1, 2, 3]).toContain(1); + * expect(new Set([true])).toContain(true); + * expect("hello").toContain("o"); + * + * @param expected the expected value + */ + toContain(expected: unknown): void; + /** + * Asserts that an `object` contains a key. + * + * The value must be an object + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); + * + * @param expected the expected value + */ + toContainKey(expected: unknown): void; + /** + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); + * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); + * + * @param expected the expected value + */ + toContainAllKeys(expected: unknown): void; + /** + * Asserts that an `object` contains at least one of the provided keys. + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); + * + * @param expected the expected value + */ + toContainAnyKeys(expected: unknown): void; + + /** * Asserts that an `object` contain the provided value. * * The value must be an object @@ -1029,1148 +1094,1189 @@ declare module "bun:test" { * * @param expected the expected value */ - toContainValue(expected: unknown): void; - - /** - * Asserts that an `object` contain the provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainValues(['foo']); - * expect(o).toContainValues(['baz', 'bar']); - * expect(o).not.toContainValues(['qux', 'foo']); - * @param expected the expected value - */ - toContainValues(expected: unknown): void; - - /** - * Asserts that an `object` contain all the provided values. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAllValues(['foo', 'bar', 'baz']); - * expect(o).toContainAllValues(['baz', 'bar', 'foo']); - * expect(o).not.toContainAllValues(['bar', 'foo']); - * @param expected the expected value - */ - toContainAllValues(expected: unknown): void; - - /** - * Asserts that an `object` contain any provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAnyValues(['qux', 'foo']); - * expect(o).toContainAnyValues(['qux', 'bar']); - * expect(o).toContainAnyValues(['qux', 'baz']); - * expect(o).not.toContainAnyValues(['qux']); - * @param expected the expected value - */ - toContainAnyValues(expected: unknown): void; - - /** - * Asserts that an `object` contains all the provided keys. - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); - * - * @param expected the expected value - */ - toContainKeys(expected: unknown): void; - /** - * Asserts that a value contains and equals what is expected. - * - * This matcher will perform a deep equality check for members - * of arrays, rather than checking for object identity. - * - * @example - * expect([{ a: 1 }]).toContainEqual({ a: 1 }); - * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); - * - * @param expected the expected value - */ - toContainEqual(expected: unknown): void; - /** - * Asserts that a value has a `.length` property - * that is equal to the expected length. - * - * @example - * expect([]).toHaveLength(0); - * expect("hello").toHaveLength(4); - * - * @param length the expected length - */ - toHaveLength(length: number): void; - /** - * Asserts that a value has a property with the - * expected name, and value if provided. - * - * @example - * expect(new Set()).toHaveProperty("size"); - * expect(new Uint8Array()).toHaveProperty("byteLength", 0); - * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); - * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); - * - * @param keyPath the expected property name or path, or an index - * @param value the expected property value, if provided - */ - toHaveProperty(keyPath: string | number | Array, value?: unknown): void; - /** - * Asserts that a value is "truthy". - * - * To assert that a value equals `true`, use `toBe(true)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeTruthy(): void; - /** - * Asserts that a value is "falsy". - * - * To assert that a value equals `false`, use `toBe(false)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeFalsy(): void; - /** - * Asserts that a value is defined. (e.g. is not `undefined`) - * - * @example - * expect(true).toBeDefined(); - * expect(undefined).toBeDefined(); // fail - */ - toBeDefined(): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that a value is `undefined`. - * - * @example - * expect(undefined).toBeUndefined(); - * expect(null).toBeUndefined(); // fail - */ - toBeUndefined(): void; - /** - * Asserts that a value is `null`. - * - * @example - * expect(null).toBeNull(); - * expect(undefined).toBeNull(); // fail - */ - toBeNull(): void; - /** - * Asserts that a value is `NaN`. - * - * Same as using `Number.isNaN()`. - * - * @example - * expect(NaN).toBeNaN(); - * expect(Infinity).toBeNaN(); // fail - * expect("notanumber").toBeNaN(); // fail - */ - toBeNaN(): void; - /** - * Asserts that a value is a `number` and is greater than the expected value. - * - * @example - * expect(1).toBeGreaterThan(0); - * expect(3.14).toBeGreaterThan(3); - * expect(9).toBeGreaterThan(9); // fail - * - * @param expected the expected number - */ - toBeGreaterThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is greater than or equal to the expected value. - * - * @example - * expect(1).toBeGreaterThanOrEqual(0); - * expect(3.14).toBeGreaterThanOrEqual(3); - * expect(9).toBeGreaterThanOrEqual(9); - * - * @param expected the expected number - */ - toBeGreaterThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than the expected value. - * - * @example - * expect(-1).toBeLessThan(0); - * expect(3).toBeLessThan(3.14); - * expect(9).toBeLessThan(9); // fail - * - * @param expected the expected number - */ - toBeLessThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than or equal to the expected value. - * - * @example - * expect(-1).toBeLessThanOrEqual(0); - * expect(3).toBeLessThanOrEqual(3.14); - * expect(9).toBeLessThanOrEqual(9); - * - * @param expected the expected number - */ - toBeLessThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrow("Oops!"); - * expect(fail).toThrow(/oops/i); - * expect(fail).toThrow(Error); - * expect(fail).toThrow(); - * - * @param expected the expected error, error message, or error pattern - */ - toThrow(expected?: unknown): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowError("Oops!"); - * expect(fail).toThrowError(/oops/i); - * expect(fail).toThrowError(Error); - * expect(fail).toThrowError(); - * - * @param expected the expected error, error message, or error pattern - * @alias toThrow - */ - toThrowError(expected?: unknown): void; - /** - * Asserts that a value matches a regular expression or includes a substring. - * - * @example - * expect("dog").toMatch(/dog/); - * expect("dog").toMatch("og"); - * - * @param expected the expected substring or pattern. - */ - toMatch(expected: string | RegExp): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot('hint message'); - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(hint?: string): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot(); - * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); - * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(propertyMatchers?: object, hint?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect("Hello").toMatchInlineSnapshot(); - * expect("Hello").toMatchInlineSnapshot(`"Hello"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(value?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` - * { - * "v": Any, - * } - * `); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingSnapshot(); - * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingSnapshot(hint?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingInlineSnapshot(); - * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingInlineSnapshot(value?: string): void; - /** - * Asserts that an object matches a subset of properties. - * - * @example - * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); - * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); - * - * @param subset Subset of properties to match with. - */ - toMatchObject(subset: object): void; - /** - * Asserts that a value is empty. - * - * @example - * expect("").toBeEmpty(); - * expect([]).toBeEmpty(); - * expect({}).toBeEmpty(); - * expect(new Set()).toBeEmpty(); - */ - toBeEmpty(): void; - /** - * Asserts that a value is an empty `object`. - * - * @example - * expect({}).toBeEmptyObject(); - * expect({ a: 'hello' }).not.toBeEmptyObject(); - */ - toBeEmptyObject(): void; - /** - * Asserts that a value is `null` or `undefined`. - * - * @example - * expect(null).toBeNil(); - * expect(undefined).toBeNil(); - */ - toBeNil(): void; - /** - * Asserts that a value is a `array`. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray - * @example - * expect([1]).toBeArray(); - * expect(new Array(1)).toBeArray(); - * expect({}).not.toBeArray(); - */ - toBeArray(): void; - /** - * Asserts that a value is a `array` of a certain length. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize - * @example - * expect([]).toBeArrayOfSize(0); - * expect([1]).toBeArrayOfSize(1); - * expect(new Array(1)).toBeArrayOfSize(1); - * expect({}).not.toBeArrayOfSize(0); - */ - toBeArrayOfSize(size: number): void; - /** - * Asserts that a value is a `boolean`. - * - * @example - * expect(true).toBeBoolean(); - * expect(false).toBeBoolean(); - * expect(null).not.toBeBoolean(); - * expect(0).not.toBeBoolean(); - */ - toBeBoolean(): void; - /** - * Asserts that a value is `true`. - * - * @example - * expect(true).toBeTrue(); - * expect(false).not.toBeTrue(); - * expect(1).not.toBeTrue(); - */ - toBeTrue(): void; - /** - * Asserts that a value matches a specific type. - * - * @link https://vitest.dev/api/expect.html#tobetypeof - * @example - * expect(1).toBeTypeOf("number"); - * expect("hello").toBeTypeOf("string"); - * expect([]).not.toBeTypeOf("boolean"); - */ - toBeTypeOf(type: "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"): void; - /** - * Asserts that a value is `false`. - * - * @example - * expect(false).toBeFalse(); - * expect(true).not.toBeFalse(); - * expect(0).not.toBeFalse(); - */ - toBeFalse(): void; - /** - * Asserts that a value is a `number`. - * - * @example - * expect(1).toBeNumber(); - * expect(3.14).toBeNumber(); - * expect(NaN).toBeNumber(); - * expect(BigInt(1)).not.toBeNumber(); - */ - toBeNumber(): void; - /** - * Asserts that a value is a `number`, and is an integer. - * - * @example - * expect(1).toBeInteger(); - * expect(3.14).not.toBeInteger(); - * expect(NaN).not.toBeInteger(); - */ - toBeInteger(): void; - /** - * Asserts that a value is an `object`. - * - * @example - * expect({}).toBeObject(); - * expect("notAnObject").not.toBeObject(); - * expect(NaN).not.toBeObject(); - */ - toBeObject(): void; - /** - * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. - * - * @example - * expect(1).toBeFinite(); - * expect(3.14).toBeFinite(); - * expect(NaN).not.toBeFinite(); - * expect(Infinity).not.toBeFinite(); - */ - toBeFinite(): void; - /** - * Asserts that a value is a positive `number`. - * - * @example - * expect(1).toBePositive(); - * expect(-3.14).not.toBePositive(); - * expect(NaN).not.toBePositive(); - */ - toBePositive(): void; - /** - * Asserts that a value is a negative `number`. - * - * @example - * expect(-3.14).toBeNegative(); - * expect(1).not.toBeNegative(); - * expect(NaN).not.toBeNegative(); - */ - toBeNegative(): void; - /** - * Asserts that a value is a number between a start and end value. - * - * @param start the start number (inclusive) - * @param end the end number (exclusive) - */ - toBeWithin(start: number, end: number): void; - /** - * Asserts that a value is equal to the expected string, ignoring any whitespace. - * - * @example - * expect(" foo ").toEqualIgnoringWhitespace("foo"); - * expect("bar").toEqualIgnoringWhitespace(" bar "); - * - * @param expected the expected string - */ - toEqualIgnoringWhitespace(expected: string): void; - /** - * Asserts that a value is a `symbol`. - * - * @example - * expect(Symbol("foo")).toBeSymbol(); - * expect("foo").not.toBeSymbol(); - */ - toBeSymbol(): void; - /** - * Asserts that a value is a `function`. - * - * @example - * expect(() => {}).toBeFunction(); - */ - toBeFunction(): void; - /** - * Asserts that a value is a `Date` object. - * - * To check if a date is valid, use `toBeValidDate()` instead. - * - * @example - * expect(new Date()).toBeDate(); - * expect(new Date(null)).toBeDate(); - * expect("2020-03-01").not.toBeDate(); - */ - toBeDate(): void; - /** - * Asserts that a value is a valid `Date` object. - * - * @example - * expect(new Date()).toBeValidDate(); - * expect(new Date(null)).not.toBeValidDate(); - * expect("2020-03-01").not.toBeValidDate(); - */ - toBeValidDate(): void; - /** - * Asserts that a value is a `string`. - * - * @example - * expect("foo").toBeString(); - * expect(new String("bar")).toBeString(); - * expect(123).not.toBeString(); - */ - toBeString(): void; - /** - * Asserts that a value includes a `string`. - * - * For non-string values, use `toContain()` instead. - * - * @param expected the expected substring - */ - toInclude(expected: string): void; - /** - * Asserts that a value includes a `string` {times} times. - * @param expected the expected substring - * @param times the number of times the substring should occur - */ - toIncludeRepeated(expected: string, times: number): void; - /** - * Checks whether a value satisfies a custom condition. - * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. - * @example - * expect(1).toSatisfy((val) => val > 0); - * expect("foo").toSatisfy((val) => val === "foo"); - * expect("bar").not.toSatisfy((val) => val === "bun"); - * @link https://vitest.dev/api/expect.html#tosatisfy - * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy - */ - toSatisfy(predicate: (value: T) => boolean): void; - /** - * Asserts that a value starts with a `string`. - * - * @param expected the string to start with - */ - toStartWith(expected: string): void; - /** - * Asserts that a value ends with a `string`. - * - * @param expected the string to end with - */ - toEndWith(expected: string): void; - /** - * Ensures that a mock function has returned successfully at least once. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturned(): void; - - /** - * Ensures that a mock function has returned successfully at `times` times. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturnedTimes(times: number): void; - - /** - * Ensures that a mock function is called. - */ - toHaveBeenCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - * @alias toHaveBeenCalled - */ - toBeCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - */ - toHaveBeenCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledTimes - */ - toBeCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - */ - toHaveBeenCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledWith - */ - toBeCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the last call. - */ - toHaveBeenLastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - lastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - */ - toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - nthCalledWith(n: number, ...expected: unknown[]): void; - } - - /** - * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. - */ - // Defined as an alias of `any` so that it does not trigger any type mismatch - export type AsymmetricMatcher = any; - - export interface MatcherResult { - pass: boolean; - message?: string | (() => string); - } - - export type CustomMatcher = ( - this: MatcherContext, - expected: E, - ...matcherArguments: P - ) => MatcherResult | Promise; - - /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ - export type CustomMatchersDetected = Omit, keyof MatchersBuiltin> & - Omit; - - /** - * If the types has been defined through declaration merging, enforce it. - * Otherwise enforce the generic custom matcher signature. - */ - export type ExpectExtendMatchers = { - [k in keyof M]: k extends keyof CustomMatchersDetected - ? CustomMatcher> - : CustomMatcher; - }; - - /** Custom equality tester */ - export type Tester = (this: TesterContext, a: any, b: any, customTesters: Tester[]) => boolean | undefined; - - export type EqualsFunction = ( - a: unknown, - b: unknown, - //customTesters?: Array, - //strictCheck?: boolean, - ) => boolean; - - export interface TesterContext { - equals: EqualsFunction; - } - - interface MatcherState { - //assertionCalls: number; - //currentConcurrentTestName?: () => string | undefined; - //currentTestName?: string; - //error?: Error; - //expand: boolean; - //expectedAssertionsNumber: number | null; - //expectedAssertionsNumberError?: Error; - //isExpectingAssertions: boolean; - //isExpectingAssertionsError?: Error; - isNot: boolean; - //numPassingAsserts: number; - promise: string; - //suppressedErrors: Array; - //testPath?: string; - } - - type MatcherHintColor = (arg: string) => string; // subset of Chalk type - - interface MatcherUtils { - //customTesters: Array; - //dontThrow(): void; // (internally used by jest snapshot) - equals: EqualsFunction; - utils: Readonly<{ - stringify(value: unknown): string; - printReceived(value: unknown): string; - printExpected(value: unknown): string; - matcherHint( - matcherName: string, - received?: unknown, - expected?: unknown, - options?: { - isNot?: boolean; - promise?: string; - isDirectExpectCall?: boolean; // (internal) - comment?: string; - expectedColor?: MatcherHintColor; - receivedColor?: MatcherHintColor; - secondArgument?: string; - secondArgumentColor?: MatcherHintColor; - }, - ): string; - //iterableEquality: Tester; - //subsetEquality: Tester; - // ... - }>; - } - - type MatcherContext = MatcherUtils & MatcherState; + toContainValue(expected: unknown): void; + + /** + * Asserts that an `object` contain the provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainValues(['foo']); + * expect(o).toContainValues(['baz', 'bar']); + * expect(o).not.toContainValues(['qux', 'foo']); + * @param expected the expected value + */ + toContainValues(expected: unknown): void; + + /** + * Asserts that an `object` contain all the provided values. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAllValues(['foo', 'bar', 'baz']); + * expect(o).toContainAllValues(['baz', 'bar', 'foo']); + * expect(o).not.toContainAllValues(['bar', 'foo']); + * @param expected the expected value + */ + toContainAllValues(expected: unknown): void; + + /** + * Asserts that an `object` contain any provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAnyValues(['qux', 'foo']); + * expect(o).toContainAnyValues(['qux', 'bar']); + * expect(o).toContainAnyValues(['qux', 'baz']); + * expect(o).not.toContainAnyValues(['qux']); + * @param expected the expected value + */ + toContainAnyValues(expected: unknown): void; + + /** + * Asserts that an `object` contains all the provided keys. + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); + * + * @param expected the expected value + */ + toContainKeys(expected: unknown): void; + /** + * Asserts that a value contains and equals what is expected. + * + * This matcher will perform a deep equality check for members + * of arrays, rather than checking for object identity. + * + * @example + * expect([{ a: 1 }]).toContainEqual({ a: 1 }); + * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); + * + * @param expected the expected value + */ + toContainEqual(expected: unknown): void; + /** + * Asserts that a value has a `.length` property + * that is equal to the expected length. + * + * @example + * expect([]).toHaveLength(0); + * expect("hello").toHaveLength(4); + * + * @param length the expected length + */ + toHaveLength(length: number): void; + /** + * Asserts that a value has a property with the + * expected name, and value if provided. + * + * @example + * expect(new Set()).toHaveProperty("size"); + * expect(new Uint8Array()).toHaveProperty("byteLength", 0); + * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); + * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); + * + * @param keyPath the expected property name or path, or an index + * @param value the expected property value, if provided + */ + toHaveProperty( + keyPath: string | number | Array, + value?: unknown, + ): void; + /** + * Asserts that a value is "truthy". + * + * To assert that a value equals `true`, use `toBe(true)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeTruthy(): void; + /** + * Asserts that a value is "falsy". + * + * To assert that a value equals `false`, use `toBe(false)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeFalsy(): void; + /** + * Asserts that a value is defined. (e.g. is not `undefined`) + * + * @example + * expect(true).toBeDefined(); + * expect(undefined).toBeDefined(); // fail + */ + toBeDefined(): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that a value is `undefined`. + * + * @example + * expect(undefined).toBeUndefined(); + * expect(null).toBeUndefined(); // fail + */ + toBeUndefined(): void; + /** + * Asserts that a value is `null`. + * + * @example + * expect(null).toBeNull(); + * expect(undefined).toBeNull(); // fail + */ + toBeNull(): void; + /** + * Asserts that a value is `NaN`. + * + * Same as using `Number.isNaN()`. + * + * @example + * expect(NaN).toBeNaN(); + * expect(Infinity).toBeNaN(); // fail + * expect("notanumber").toBeNaN(); // fail + */ + toBeNaN(): void; + /** + * Asserts that a value is a `number` and is greater than the expected value. + * + * @example + * expect(1).toBeGreaterThan(0); + * expect(3.14).toBeGreaterThan(3); + * expect(9).toBeGreaterThan(9); // fail + * + * @param expected the expected number + */ + toBeGreaterThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is greater than or equal to the expected value. + * + * @example + * expect(1).toBeGreaterThanOrEqual(0); + * expect(3.14).toBeGreaterThanOrEqual(3); + * expect(9).toBeGreaterThanOrEqual(9); + * + * @param expected the expected number + */ + toBeGreaterThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than the expected value. + * + * @example + * expect(-1).toBeLessThan(0); + * expect(3).toBeLessThan(3.14); + * expect(9).toBeLessThan(9); // fail + * + * @param expected the expected number + */ + toBeLessThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than or equal to the expected value. + * + * @example + * expect(-1).toBeLessThanOrEqual(0); + * expect(3).toBeLessThanOrEqual(3.14); + * expect(9).toBeLessThanOrEqual(9); + * + * @param expected the expected number + */ + toBeLessThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrow("Oops!"); + * expect(fail).toThrow(/oops/i); + * expect(fail).toThrow(Error); + * expect(fail).toThrow(); + * + * @param expected the expected error, error message, or error pattern + */ + toThrow(expected?: unknown): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowError("Oops!"); + * expect(fail).toThrowError(/oops/i); + * expect(fail).toThrowError(Error); + * expect(fail).toThrowError(); + * + * @param expected the expected error, error message, or error pattern + * @alias toThrow + */ + toThrowError(expected?: unknown): void; + /** + * Asserts that a value matches a regular expression or includes a substring. + * + * @example + * expect("dog").toMatch(/dog/); + * expect("dog").toMatch("og"); + * + * @param expected the expected substring or pattern. + */ + toMatch(expected: string | RegExp): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot('hint message'); + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(hint?: string): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot(); + * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); + * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(propertyMatchers?: object, hint?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect("Hello").toMatchInlineSnapshot(); + * expect("Hello").toMatchInlineSnapshot(`"Hello"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(value?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` + * { + * "v": Any, + * } + * `); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingSnapshot(); + * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingSnapshot(hint?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingInlineSnapshot(); + * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingInlineSnapshot(value?: string): void; + /** + * Asserts that an object matches a subset of properties. + * + * @example + * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); + * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); + * + * @param subset Subset of properties to match with. + */ + toMatchObject(subset: object): void; + /** + * Asserts that a value is empty. + * + * @example + * expect("").toBeEmpty(); + * expect([]).toBeEmpty(); + * expect({}).toBeEmpty(); + * expect(new Set()).toBeEmpty(); + */ + toBeEmpty(): void; + /** + * Asserts that a value is an empty `object`. + * + * @example + * expect({}).toBeEmptyObject(); + * expect({ a: 'hello' }).not.toBeEmptyObject(); + */ + toBeEmptyObject(): void; + /** + * Asserts that a value is `null` or `undefined`. + * + * @example + * expect(null).toBeNil(); + * expect(undefined).toBeNil(); + */ + toBeNil(): void; + /** + * Asserts that a value is a `array`. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray + * @example + * expect([1]).toBeArray(); + * expect(new Array(1)).toBeArray(); + * expect({}).not.toBeArray(); + */ + toBeArray(): void; + /** + * Asserts that a value is a `array` of a certain length. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize + * @example + * expect([]).toBeArrayOfSize(0); + * expect([1]).toBeArrayOfSize(1); + * expect(new Array(1)).toBeArrayOfSize(1); + * expect({}).not.toBeArrayOfSize(0); + */ + toBeArrayOfSize(size: number): void; + /** + * Asserts that a value is a `boolean`. + * + * @example + * expect(true).toBeBoolean(); + * expect(false).toBeBoolean(); + * expect(null).not.toBeBoolean(); + * expect(0).not.toBeBoolean(); + */ + toBeBoolean(): void; + /** + * Asserts that a value is `true`. + * + * @example + * expect(true).toBeTrue(); + * expect(false).not.toBeTrue(); + * expect(1).not.toBeTrue(); + */ + toBeTrue(): void; + /** + * Asserts that a value matches a specific type. + * + * @link https://vitest.dev/api/expect.html#tobetypeof + * @example + * expect(1).toBeTypeOf("number"); + * expect("hello").toBeTypeOf("string"); + * expect([]).not.toBeTypeOf("boolean"); + */ + toBeTypeOf( + type: + | "bigint" + | "boolean" + | "function" + | "number" + | "object" + | "string" + | "symbol" + | "undefined", + ): void; + /** + * Asserts that a value is `false`. + * + * @example + * expect(false).toBeFalse(); + * expect(true).not.toBeFalse(); + * expect(0).not.toBeFalse(); + */ + toBeFalse(): void; + /** + * Asserts that a value is a `number`. + * + * @example + * expect(1).toBeNumber(); + * expect(3.14).toBeNumber(); + * expect(NaN).toBeNumber(); + * expect(BigInt(1)).not.toBeNumber(); + */ + toBeNumber(): void; + /** + * Asserts that a value is a `number`, and is an integer. + * + * @example + * expect(1).toBeInteger(); + * expect(3.14).not.toBeInteger(); + * expect(NaN).not.toBeInteger(); + */ + toBeInteger(): void; + /** + * Asserts that a value is an `object`. + * + * @example + * expect({}).toBeObject(); + * expect("notAnObject").not.toBeObject(); + * expect(NaN).not.toBeObject(); + */ + toBeObject(): void; + /** + * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. + * + * @example + * expect(1).toBeFinite(); + * expect(3.14).toBeFinite(); + * expect(NaN).not.toBeFinite(); + * expect(Infinity).not.toBeFinite(); + */ + toBeFinite(): void; + /** + * Asserts that a value is a positive `number`. + * + * @example + * expect(1).toBePositive(); + * expect(-3.14).not.toBePositive(); + * expect(NaN).not.toBePositive(); + */ + toBePositive(): void; + /** + * Asserts that a value is a negative `number`. + * + * @example + * expect(-3.14).toBeNegative(); + * expect(1).not.toBeNegative(); + * expect(NaN).not.toBeNegative(); + */ + toBeNegative(): void; + /** + * Asserts that a value is a number between a start and end value. + * + * @param start the start number (inclusive) + * @param end the end number (exclusive) + */ + toBeWithin(start: number, end: number): void; + /** + * Asserts that a value is equal to the expected string, ignoring any whitespace. + * + * @example + * expect(" foo ").toEqualIgnoringWhitespace("foo"); + * expect("bar").toEqualIgnoringWhitespace(" bar "); + * + * @param expected the expected string + */ + toEqualIgnoringWhitespace(expected: string): void; + /** + * Asserts that a value is a `symbol`. + * + * @example + * expect(Symbol("foo")).toBeSymbol(); + * expect("foo").not.toBeSymbol(); + */ + toBeSymbol(): void; + /** + * Asserts that a value is a `function`. + * + * @example + * expect(() => {}).toBeFunction(); + */ + toBeFunction(): void; + /** + * Asserts that a value is a `Date` object. + * + * To check if a date is valid, use `toBeValidDate()` instead. + * + * @example + * expect(new Date()).toBeDate(); + * expect(new Date(null)).toBeDate(); + * expect("2020-03-01").not.toBeDate(); + */ + toBeDate(): void; + /** + * Asserts that a value is a valid `Date` object. + * + * @example + * expect(new Date()).toBeValidDate(); + * expect(new Date(null)).not.toBeValidDate(); + * expect("2020-03-01").not.toBeValidDate(); + */ + toBeValidDate(): void; + /** + * Asserts that a value is a `string`. + * + * @example + * expect("foo").toBeString(); + * expect(new String("bar")).toBeString(); + * expect(123).not.toBeString(); + */ + toBeString(): void; + /** + * Asserts that a value includes a `string`. + * + * For non-string values, use `toContain()` instead. + * + * @param expected the expected substring + */ + toInclude(expected: string): void; + /** + * Asserts that a value includes a `string` {times} times. + * @param expected the expected substring + * @param times the number of times the substring should occur + */ + toIncludeRepeated(expected: string, times: number): void; + /** + * Checks whether a value satisfies a custom condition. + * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. + * @example + * expect(1).toSatisfy((val) => val > 0); + * expect("foo").toSatisfy((val) => val === "foo"); + * expect("bar").not.toSatisfy((val) => val === "bun"); + * @link https://vitest.dev/api/expect.html#tosatisfy + * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy + */ + toSatisfy(predicate: (value: T) => boolean): void; + /** + * Asserts that a value starts with a `string`. + * + * @param expected the string to start with + */ + toStartWith(expected: string): void; + /** + * Asserts that a value ends with a `string`. + * + * @param expected the string to end with + */ + toEndWith(expected: string): void; + /** + * Ensures that a mock function has returned successfully at least once. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturned(): void; + + /** + * Ensures that a mock function has returned successfully at `times` times. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturnedTimes(times: number): void; + + /** + * Ensures that a mock function is called. + */ + toHaveBeenCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + * @alias toHaveBeenCalled + */ + toBeCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + */ + toHaveBeenCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledTimes + */ + toBeCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + */ + toHaveBeenCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledWith + */ + toBeCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the last call. + */ + toHaveBeenLastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + lastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + */ + toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + nthCalledWith(n: number, ...expected: unknown[]): void; + } + + /** + * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. + */ + // Defined as an alias of `any` so that it does not trigger any type mismatch + export type AsymmetricMatcher = any; + + export interface MatcherResult { + pass: boolean; + message?: string | (() => string); + } + + export type CustomMatcher = ( + this: MatcherContext, + expected: E, + ...matcherArguments: P + ) => MatcherResult | Promise; + + /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ + export type CustomMatchersDetected = Omit< + Matchers, + keyof MatchersBuiltin + > & + Omit; + + /** + * If the types has been defined through declaration merging, enforce it. + * Otherwise enforce the generic custom matcher signature. + */ + export type ExpectExtendMatchers = { + [k in keyof M]: k extends keyof CustomMatchersDetected + ? CustomMatcher> + : CustomMatcher; + }; + + /** Custom equality tester */ + export type Tester = ( + this: TesterContext, + a: any, + b: any, + customTesters: Tester[], + ) => boolean | undefined; + + export type EqualsFunction = ( + a: unknown, + b: unknown, + //customTesters?: Array, + //strictCheck?: boolean, + ) => boolean; + + export interface TesterContext { + equals: EqualsFunction; + } + + interface MatcherState { + //assertionCalls: number; + //currentConcurrentTestName?: () => string | undefined; + //currentTestName?: string; + //error?: Error; + //expand: boolean; + //expectedAssertionsNumber: number | null; + //expectedAssertionsNumberError?: Error; + //isExpectingAssertions: boolean; + //isExpectingAssertionsError?: Error; + isNot: boolean; + //numPassingAsserts: number; + promise: string; + //suppressedErrors: Array; + //testPath?: string; + } + + type MatcherHintColor = (arg: string) => string; // subset of Chalk type + + interface MatcherUtils { + //customTesters: Array; + //dontThrow(): void; // (internally used by jest snapshot) + equals: EqualsFunction; + utils: Readonly<{ + stringify(value: unknown): string; + printReceived(value: unknown): string; + printExpected(value: unknown): string; + matcherHint( + matcherName: string, + received?: unknown, + expected?: unknown, + options?: { + isNot?: boolean; + promise?: string; + isDirectExpectCall?: boolean; // (internal) + comment?: string; + expectedColor?: MatcherHintColor; + receivedColor?: MatcherHintColor; + secondArgument?: string; + secondArgumentColor?: MatcherHintColor; + }, + ): string; + //iterableEquality: Tester; + //subsetEquality: Tester; + // ... + }>; + } + + type MatcherContext = MatcherUtils & MatcherState; } declare module "test" { - export type * from "bun:test"; + export type * from "bun:test"; } declare namespace JestMock { - /** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - export interface ClassLike { - new (...args: any): any; - } - - export type ConstructorLikeKeys = keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - }; - - // export const fn: ( - // implementation?: T | undefined, - // ) => Mock; - - export type FunctionLike = (...args: any) => any; - - export type MethodLikeKeys = keyof { - [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; - }; - - export interface Mock any> extends MockInstance { - (...args: Parameters): ReturnType; - } - - /** - * All what the internal typings need is to be sure that we have any-function. - * `FunctionLike` type ensures that and helps to constrain the type as well. - * The default of `UnknownFunction` makes sure that `any`s do not leak to the - * user side. For instance, calling `fn()` without implementation will return - * a mock of `(...args: Array) => unknown` type. If implementation - * is provided, its typings are inferred correctly. - */ - // export interface Mock - // extends Function, - // MockInstance { - // new (...args: Parameters): ReturnType; - // (...args: Parameters): ReturnType; - // } - - // export type Mocked = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunction - // : T extends object - // ? MockedObject - // : T; - - // export const mocked: { - // ( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // ( - // source: T_1, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // }; - - // export type MockedClass = MockInstance< - // (...args: ConstructorParameters) => Mocked> - // > & - // MockedObject; - - // export type MockedFunction = MockInstance & - // MockedObject; - - // type MockedFunctionShallow = MockInstance & T; - - // export type MockedObject = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunction - // : T[K] extends object - // ? MockedObject - // : T[K]; - // } & T; - - // type MockedObjectShallow = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunctionShallow - // : T[K]; - // } & T; - - // export type MockedShallow = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunctionShallow - // : T extends object - // ? MockedObjectShallow - // : T; - - // export type MockFunctionMetadata< - // T = unknown, - // MetadataType = MockMetadataType, - // > = MockMetadata; - - // export type MockFunctionMetadataType = MockMetadataType; - - type MockFunctionResult = - | MockFunctionResultIncomplete - | MockFunctionResultReturn - | MockFunctionResultThrow; - - interface MockFunctionResultIncomplete { - type: "incomplete"; - /** - * Result of a single call to a mock function that has not yet completed. - * This occurs if you test the result from within the mock function itself, - * or from within a function that was called by the mock. - */ - value: undefined; - } - - interface MockFunctionResultReturn { - type: "return"; - /** - * Result of a single call to a mock function that returned. - */ - value: ReturnType; - } - - interface MockFunctionResultThrow { - type: "throw"; - /** - * Result of a single call to a mock function that threw. - */ - value: unknown; - } - - interface MockFunctionState { - /** - * List of the call arguments of all calls that have been made to the mock. - */ - calls: Array>; - /** - * List of all the object instances that have been instantiated from the mock. - */ - instances: Array>; - /** - * List of all the function contexts that have been applied to calls to the mock. - */ - contexts: Array>; - /** - * List of the call order indexes of the mock. Jest is indexing the order of - * invocations of all mocks in a test file. The index is starting with `1`. - */ - invocationCallOrder: number[]; - /** - * List of the call arguments of the last call that was made to the mock. - * If the function was not called, it will return `undefined`. - */ - lastCall?: Parameters; - /** - * List of the results of all calls that have been made to the mock. - */ - results: Array>; - } - - export interface MockInstance { - _isMockFunction: true; - _protoImpl: Function; - getMockImplementation(): T | undefined; - getMockName(): string; - mock: MockFunctionState; - mockClear(): this; - mockReset(): this; - mockRestore(): void; - mockImplementation(fn: T): this; - mockImplementationOnce(fn: T): this; - withImplementation(fn: T, callback: () => Promise): Promise; - withImplementation(fn: T, callback: () => void): void; - mockName(name: string): this; - mockReturnThis(): this; - mockReturnValue(value: ReturnType): this; - mockReturnValueOnce(value: ReturnType): this; - mockResolvedValue(value: ResolveType): this; - mockResolvedValueOnce(value: ResolveType): this; - mockRejectedValue(value: RejectType): this; - mockRejectedValueOnce(value: RejectType): this; - } - - // export type MockMetadata = { - // ref?: number; - // members?: Record>; - // mockImpl?: T; - // name?: string; - // refID?: number; - // type?: MetadataType; - // value?: T; - // length?: number; - // }; - - // export type MockMetadataType = - // | "object" - // | "array" - // | "regexp" - // | "function" - // | "constant" - // | "collection" - // | "null" - // | "undefined"; - - // export class ModuleMocker { - // private readonly _environmentGlobal; - // private _mockState; - // private _mockConfigRegistry; - // private _spyState; - // private _invocationCallCounter; - // /** - // * @see README.md - // * @param global Global object of the test environment, used to create - // * mocks - // */ - // constructor(global: typeof globalThis); - // private _getSlots; - // private _ensureMockConfig; - // private _ensureMockState; - // private _defaultMockConfig; - // private _defaultMockState; - // private _makeComponent; - // private _createMockFunction; - // private _generateMock; - // /** - // * Check whether the given property of an object has been already replaced. - // */ - // private _findReplacedProperty; - // /** - // * @see README.md - // * @param metadata Metadata for the mock in the schema returned by the - // * getMetadata method of this module. - // */ - // generateFromMetadata(metadata: MockMetadata): Mocked; - // /** - // * @see README.md - // * @param component The component for which to retrieve metadata. - // */ - // getMetadata( - // component: T, - // _refs?: Map, - // ): MockMetadata | null; - // isMockFunction( - // fn: MockInstance, - // ): fn is MockInstance; - // isMockFunction

, R>( - // fn: (...args: P) => R, - // ): fn is Mock<(...args: P) => R>; - // isMockFunction(fn: unknown): fn is Mock; - // fn(implementation?: T): Mock; - // private _attachMockImplementation; - // spyOn< - // T extends object, - // K extends PropertyLikeKeys, - // A extends "get" | "set", - // >( - // object: T, - // methodKey: K, - // accessType: A, - // ): A extends "get" - // ? SpiedGetter - // : A extends "set" - // ? SpiedSetter - // : never; - // spyOn< - // T extends object, - // K extends ConstructorLikeKeys | MethodLikeKeys, - // V extends Required[K], - // >( - // object: T, - // methodKey: K, - // ): V extends ClassLike | FunctionLike ? Spied : never; - // private _spyOnProperty; - // replaceProperty< - // T extends object, - // K extends PropertyLikeKeys, - // V extends T[K], - // >(object: T, propertyKey: K, value: V): Replaced; - // clearAllMocks(): void; - // resetAllMocks(): void; - // restoreAllMocks(): void; - // private _typeOf; - // mocked( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // mocked( - // source: T, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // } - - export type PropertyLikeKeys = Exclude | MethodLikeKeys>; - - export type RejectType = ReturnType extends PromiseLike ? unknown : never; - - export interface Replaced { - /** - * Restore property to its original value known at the time of mocking. - */ - restore(): void; - /** - * Change the value of the property. - */ - replaceValue(value: T): this; - } - - export function replaceProperty< - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; - } - >, - V extends T[K_2], - >(object: T, propertyKey: K_2, value: V): Replaced; - - export type ResolveType = ReturnType extends PromiseLike ? U : never; - - export type Spied = T extends ClassLike - ? SpiedClass - : T extends FunctionLike - ? SpiedFunction - : never; - - export type SpiedClass = MockInstance< - (...args: ConstructorParameters) => InstanceType - >; - - export type SpiedFunction = MockInstance< - (...args: Parameters) => ReturnType - >; - - export type SpiedGetter = MockInstance<() => T>; - - export type SpiedSetter = MockInstance<(arg: T) => void>; - - export interface SpyInstance extends MockInstance {} - - export const spyOn: { - < - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; - } - >, - V extends Required[K_2], - A extends "set" | "get", - >( - object: T, - methodKey: K_2, - accessType: A, - ): A extends "get" ? SpiedGetter : A extends "set" ? SpiedSetter : never; - < - T_1 extends object, - K_5 extends - | keyof { - [K_3 in keyof T_1 as Required[K_3] extends ClassLike ? K_3 : never]: T_1[K_3]; - } - | keyof { - [K_4 in keyof T_1 as Required[K_4] extends FunctionLike ? K_4 : never]: T_1[K_4]; - }, - V_1 extends Required[K_5], - >( - object: T_1, - methodKey: K_5, - ): V_1 extends ClassLike | FunctionLike ? Spied : never; - }; - - export interface UnknownClass { - new (...args: unknown[]): unknown; - } - - export type UnknownFunction = (...args: unknown[]) => unknown; + /** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + export interface ClassLike { + new (...args: any): any; + } + + export type ConstructorLikeKeys = keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + }; + + // export const fn: ( + // implementation?: T | undefined, + // ) => Mock; + + export type FunctionLike = (...args: any) => any; + + export type MethodLikeKeys = keyof { + [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; + }; + + export interface Mock any> + extends MockInstance { + (...args: Parameters): ReturnType; + } + + /** + * All what the internal typings need is to be sure that we have any-function. + * `FunctionLike` type ensures that and helps to constrain the type as well. + * The default of `UnknownFunction` makes sure that `any`s do not leak to the + * user side. For instance, calling `fn()` without implementation will return + * a mock of `(...args: Array) => unknown` type. If implementation + * is provided, its typings are inferred correctly. + */ + // export interface Mock + // extends Function, + // MockInstance { + // new (...args: Parameters): ReturnType; + // (...args: Parameters): ReturnType; + // } + + // export type Mocked = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunction + // : T extends object + // ? MockedObject + // : T; + + // export const mocked: { + // ( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // ( + // source: T_1, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // }; + + // export type MockedClass = MockInstance< + // (...args: ConstructorParameters) => Mocked> + // > & + // MockedObject; + + // export type MockedFunction = MockInstance & + // MockedObject; + + // type MockedFunctionShallow = MockInstance & T; + + // export type MockedObject = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunction + // : T[K] extends object + // ? MockedObject + // : T[K]; + // } & T; + + // type MockedObjectShallow = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunctionShallow + // : T[K]; + // } & T; + + // export type MockedShallow = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunctionShallow + // : T extends object + // ? MockedObjectShallow + // : T; + + // export type MockFunctionMetadata< + // T = unknown, + // MetadataType = MockMetadataType, + // > = MockMetadata; + + // export type MockFunctionMetadataType = MockMetadataType; + + type MockFunctionResult = + | MockFunctionResultIncomplete + | MockFunctionResultReturn + | MockFunctionResultThrow; + + interface MockFunctionResultIncomplete { + type: "incomplete"; + /** + * Result of a single call to a mock function that has not yet completed. + * This occurs if you test the result from within the mock function itself, + * or from within a function that was called by the mock. + */ + value: undefined; + } + + interface MockFunctionResultReturn { + type: "return"; + /** + * Result of a single call to a mock function that returned. + */ + value: ReturnType; + } + + interface MockFunctionResultThrow { + type: "throw"; + /** + * Result of a single call to a mock function that threw. + */ + value: unknown; + } + + interface MockFunctionState { + /** + * List of the call arguments of all calls that have been made to the mock. + */ + calls: Array>; + /** + * List of all the object instances that have been instantiated from the mock. + */ + instances: Array>; + /** + * List of all the function contexts that have been applied to calls to the mock. + */ + contexts: Array>; + /** + * List of the call order indexes of the mock. Jest is indexing the order of + * invocations of all mocks in a test file. The index is starting with `1`. + */ + invocationCallOrder: number[]; + /** + * List of the call arguments of the last call that was made to the mock. + * If the function was not called, it will return `undefined`. + */ + lastCall?: Parameters; + /** + * List of the results of all calls that have been made to the mock. + */ + results: Array>; + } + + export interface MockInstance { + _isMockFunction: true; + _protoImpl: Function; + getMockImplementation(): T | undefined; + getMockName(): string; + mock: MockFunctionState; + mockClear(): this; + mockReset(): this; + mockRestore(): void; + mockImplementation(fn: T): this; + mockImplementationOnce(fn: T): this; + withImplementation(fn: T, callback: () => Promise): Promise; + withImplementation(fn: T, callback: () => void): void; + mockName(name: string): this; + mockReturnThis(): this; + mockReturnValue(value: ReturnType): this; + mockReturnValueOnce(value: ReturnType): this; + mockResolvedValue(value: ResolveType): this; + mockResolvedValueOnce(value: ResolveType): this; + mockRejectedValue(value: RejectType): this; + mockRejectedValueOnce(value: RejectType): this; + } + + // export type MockMetadata = { + // ref?: number; + // members?: Record>; + // mockImpl?: T; + // name?: string; + // refID?: number; + // type?: MetadataType; + // value?: T; + // length?: number; + // }; + + // export type MockMetadataType = + // | "object" + // | "array" + // | "regexp" + // | "function" + // | "constant" + // | "collection" + // | "null" + // | "undefined"; + + // export class ModuleMocker { + // private readonly _environmentGlobal; + // private _mockState; + // private _mockConfigRegistry; + // private _spyState; + // private _invocationCallCounter; + // /** + // * @see README.md + // * @param global Global object of the test environment, used to create + // * mocks + // */ + // constructor(global: typeof globalThis); + // private _getSlots; + // private _ensureMockConfig; + // private _ensureMockState; + // private _defaultMockConfig; + // private _defaultMockState; + // private _makeComponent; + // private _createMockFunction; + // private _generateMock; + // /** + // * Check whether the given property of an object has been already replaced. + // */ + // private _findReplacedProperty; + // /** + // * @see README.md + // * @param metadata Metadata for the mock in the schema returned by the + // * getMetadata method of this module. + // */ + // generateFromMetadata(metadata: MockMetadata): Mocked; + // /** + // * @see README.md + // * @param component The component for which to retrieve metadata. + // */ + // getMetadata( + // component: T, + // _refs?: Map, + // ): MockMetadata | null; + // isMockFunction( + // fn: MockInstance, + // ): fn is MockInstance; + // isMockFunction

, R>( + // fn: (...args: P) => R, + // ): fn is Mock<(...args: P) => R>; + // isMockFunction(fn: unknown): fn is Mock; + // fn(implementation?: T): Mock; + // private _attachMockImplementation; + // spyOn< + // T extends object, + // K extends PropertyLikeKeys, + // A extends "get" | "set", + // >( + // object: T, + // methodKey: K, + // accessType: A, + // ): A extends "get" + // ? SpiedGetter + // : A extends "set" + // ? SpiedSetter + // : never; + // spyOn< + // T extends object, + // K extends ConstructorLikeKeys | MethodLikeKeys, + // V extends Required[K], + // >( + // object: T, + // methodKey: K, + // ): V extends ClassLike | FunctionLike ? Spied : never; + // private _spyOnProperty; + // replaceProperty< + // T extends object, + // K extends PropertyLikeKeys, + // V extends T[K], + // >(object: T, propertyKey: K, value: V): Replaced; + // clearAllMocks(): void; + // resetAllMocks(): void; + // restoreAllMocks(): void; + // private _typeOf; + // mocked( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // mocked( + // source: T, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // } + + export type PropertyLikeKeys = Exclude< + keyof T, + ConstructorLikeKeys | MethodLikeKeys + >; + + export type RejectType = + ReturnType extends PromiseLike ? unknown : never; + + export interface Replaced { + /** + * Restore property to its original value known at the time of mocking. + */ + restore(): void; + /** + * Change the value of the property. + */ + replaceValue(value: T): this; + } + + export function replaceProperty< + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike + ? K_1 + : never]: T[K_1]; + } + >, + V extends T[K_2], + >(object: T, propertyKey: K_2, value: V): Replaced; + + export type ResolveType = + ReturnType extends PromiseLike ? U : never; + + export type Spied = T extends ClassLike + ? SpiedClass + : T extends FunctionLike + ? SpiedFunction + : never; + + export type SpiedClass = MockInstance< + (...args: ConstructorParameters) => InstanceType + >; + + export type SpiedFunction = + MockInstance<(...args: Parameters) => ReturnType>; + + export type SpiedGetter = MockInstance<() => T>; + + export type SpiedSetter = MockInstance<(arg: T) => void>; + + export interface SpyInstance + extends MockInstance {} + + export const spyOn: { + < + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike + ? K + : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike + ? K_1 + : never]: T[K_1]; + } + >, + V extends Required[K_2], + A extends "set" | "get", + >( + object: T, + methodKey: K_2, + accessType: A, + ): A extends "get" + ? SpiedGetter + : A extends "set" + ? SpiedSetter + : never; + < + T_1 extends object, + K_5 extends + | keyof { + [K_3 in keyof T_1 as Required[K_3] extends ClassLike + ? K_3 + : never]: T_1[K_3]; + } + | keyof { + [K_4 in keyof T_1 as Required[K_4] extends FunctionLike + ? K_4 + : never]: T_1[K_4]; + }, + V_1 extends Required[K_5], + >( + object: T_1, + methodKey: K_5, + ): V_1 extends ClassLike | FunctionLike ? Spied : never; + }; + + export interface UnknownClass { + new (...args: unknown[]): unknown; + } + + export type UnknownFunction = (...args: unknown[]) => unknown; } diff --git a/packages/bun-types/test/array-buffer.test.ts b/packages/bun-types/test/array-buffer.test.ts index a3253138e308c2..9fd63d35108368 100644 --- a/packages/bun-types/test/array-buffer.test.ts +++ b/packages/bun-types/test/array-buffer.test.ts @@ -1,5 +1,5 @@ const buffer = new ArrayBuffer(1024, { - maxByteLength: 2048, + maxByteLength: 2048, }); console.log(buffer.byteLength); // 1024 diff --git a/packages/bun-types/test/array.test.ts b/packages/bun-types/test/array.test.ts index af57108192d40d..d9fce478c69188 100644 --- a/packages/bun-types/test/array.test.ts +++ b/packages/bun-types/test/array.test.ts @@ -1,16 +1,18 @@ import { expectType } from "./utilities.test"; async function* listReleases() { - for (let page = 1; ; page++) { - const response = await fetch(`https://api.github.com/repos/oven-sh/bun/releases?page=${page}`); - const releases = (await response.json()) as Array<{ data: string }>; - if (!releases.length) { - break; - } - for (const release of releases) { - yield release; - } - } + for (let page = 1; ; page++) { + const response = await fetch( + `https://api.github.com/repos/oven-sh/bun/releases?page=${page}`, + ); + const releases = (await response.json()) as Array<{ data: string }>; + if (!releases.length) { + break; + } + for (const release of releases) { + yield release; + } + } } await Array.fromAsync(listReleases()); @@ -18,12 +20,12 @@ await Array.fromAsync(listReleases()); // Tests from issue #8484 // https://github.com/oven-sh/bun/issues/8484 async function* naturals() { - for (let i = 0; i < 10; i++) { - yield i; - } + for (let i = 0; i < 10; i++) { + yield i; + } } -const test1 = await Array.fromAsync(naturals(), n => Promise.resolve(`${n}`)); +const test1 = await Array.fromAsync(naturals(), (n) => Promise.resolve(`${n}`)); expectType(test1); const test2 = await Array.fromAsync([Promise.resolve(1), Promise.resolve(2)]); diff --git a/packages/bun-types/test/broadcast.test.ts b/packages/bun-types/test/broadcast.test.ts index 1d853f7fec23dc..1458e0c0615365 100644 --- a/packages/bun-types/test/broadcast.test.ts +++ b/packages/bun-types/test/broadcast.test.ts @@ -1,9 +1,9 @@ const channel = new BroadcastChannel("my-channel"); const message = { hello: "world" }; -channel.onmessage = event => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - console.log((event as any).data); // { hello: "world" } +channel.onmessage = (event) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + console.log((event as any).data); // { hello: "world" } }; channel.postMessage(message); diff --git a/packages/bun-types/test/bun.test.ts b/packages/bun-types/test/bun.test.ts index ae642ff6f1e53c..b3cfb1bfeed41b 100644 --- a/packages/bun-types/test/bun.test.ts +++ b/packages/bun-types/test/bun.test.ts @@ -1,51 +1,51 @@ import { BunFile, BunPlugin, FileBlob } from "bun"; import * as tsd from "./utilities.test"; { - const _plugin: BunPlugin = { - name: "asdf", - setup() {}, - }; - _plugin; + const _plugin: BunPlugin = { + name: "asdf", + setup() {}, + }; + _plugin; } { - // tslint:disable-next-line:no-void-expression - const arg = Bun.plugin({ - name: "arg", - setup() {}, - }); + // tslint:disable-next-line:no-void-expression + const arg = Bun.plugin({ + name: "arg", + setup() {}, + }); - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - tsd.expectType(arg); + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + tsd.expectType(arg); } { - // tslint:disable-next-line:no-void-expression - const arg = Bun.plugin({ - name: "arg", - async setup() {}, - }); + // tslint:disable-next-line:no-void-expression + const arg = Bun.plugin({ + name: "arg", + async setup() {}, + }); - tsd.expectType>(arg); + tsd.expectType>(arg); } { - const f = Bun.file("asdf"); - tsd.expectType(f); - tsd.expectType(f); + const f = Bun.file("asdf"); + tsd.expectType(f); + tsd.expectType(f); } { - Bun.spawn(["anything"], { - env: process.env, - }); - Bun.spawn(["anything"], { - env: { ...process.env }, - }); - Bun.spawn(["anything"], { - env: { ...process.env, dummy: "" }, - }); + Bun.spawn(["anything"], { + env: process.env, + }); + Bun.spawn(["anything"], { + env: { ...process.env }, + }); + Bun.spawn(["anything"], { + env: { ...process.env, dummy: "" }, + }); } { - Bun.TOML.parse("asdf = asdf"); + Bun.TOML.parse("asdf = asdf"); } DOMException; diff --git a/packages/bun-types/test/console.test.ts b/packages/bun-types/test/console.test.ts index 779bbab1984711..b00be4b0c7e101 100644 --- a/packages/bun-types/test/console.test.ts +++ b/packages/bun-types/test/console.test.ts @@ -5,19 +5,19 @@ c1.log(); c2.log(); async () => { - // tslint:disable-next-line:await-promise - for await (const line of c1) { - console.log("Received:", line); - } + // tslint:disable-next-line:await-promise + for await (const line of c1) { + console.log("Received:", line); + } - // tslint:disable-next-line:await-promise - for await (const line of c2) { - console.log("Received:", line); - } - // tslint:disable-next-line:await-promise - for await (const line of console) { - console.log("Received:", line); - } + // tslint:disable-next-line:await-promise + for await (const line of c2) { + console.log("Received:", line); + } + // tslint:disable-next-line:await-promise + for await (const line of console) { + console.log("Received:", line); + } - return null; + return null; }; diff --git a/packages/bun-types/test/diag.test.ts b/packages/bun-types/test/diag.test.ts index 35f41ce050664d..df3aef7e3c6e82 100644 --- a/packages/bun-types/test/diag.test.ts +++ b/packages/bun-types/test/diag.test.ts @@ -5,7 +5,7 @@ const channel = diagnostics_channel.channel("my-channel"); // Subscribe to the channel channel.subscribe((message, name) => { - console.log("Received message:", message); + console.log("Received message:", message); }); // Publish a message to the channel diff --git a/packages/bun-types/test/dom.test.ts b/packages/bun-types/test/dom.test.ts index c3d8a4383640e5..804f5cead79e61 100644 --- a/packages/bun-types/test/dom.test.ts +++ b/packages/bun-types/test/dom.test.ts @@ -3,23 +3,23 @@ import { INSPECT_MAX_BYTES } from "buffer"; INSPECT_MAX_BYTES; { - new Blob([]); + new Blob([]); } { - new MessagePort(); + new MessagePort(); } { - new MessageChannel(); + new MessageChannel(); } { - new BroadcastChannel("zxgdfg"); + new BroadcastChannel("zxgdfg"); } { - new Response("asdf"); + new Response("asdf"); } { - Response.json({ asdf: "asdf" }).ok; - const r = Response.json({ hello: "world" }); - r.body; + Response.json({ asdf: "asdf" }).ok; + const r = Response.json({ hello: "world" }); + r.body; } diff --git a/packages/bun-types/test/env.test.ts b/packages/bun-types/test/env.test.ts index f9b1d53be648b4..aa26b9f002ee84 100644 --- a/packages/bun-types/test/env.test.ts +++ b/packages/bun-types/test/env.test.ts @@ -1,19 +1,19 @@ import { expectType } from "./utilities.test"; declare module "bun" { - interface Env { - FOO: "FOO"; - } + interface Env { + FOO: "FOO"; + } } expectType<"FOO">(process.env.FOO); declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace NodeJS { - interface ProcessEnv { - BAR: "BAR"; - } - } + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace NodeJS { + interface ProcessEnv { + BAR: "BAR"; + } + } } expectType<"BAR">(process.env.BAR); diff --git a/packages/bun-types/test/events.test.ts b/packages/bun-types/test/events.test.ts index d774a4b619d0dd..b3404096aa7185 100644 --- a/packages/bun-types/test/events.test.ts +++ b/packages/bun-types/test/events.test.ts @@ -13,8 +13,8 @@ import { expectType } from "./utilities.test"; const e2 = new EventEmitter(); e2.on("qwer", (_: any) => { - _; + _; }); -e2.on("asdf", arg => { - expectType(arg); +e2.on("asdf", (arg) => { + expectType(arg); }); diff --git a/packages/bun-types/test/ffi.test.ts b/packages/bun-types/test/ffi.test.ts index 277c45b5ec57a6..c7a74e0cdb5ff4 100644 --- a/packages/bun-types/test/ffi.test.ts +++ b/packages/bun-types/test/ffi.test.ts @@ -1,4 +1,12 @@ -import { CString, dlopen, FFIType, JSCallback, Pointer, read, suffix } from "bun:ffi"; +import { + CString, + dlopen, + FFIType, + JSCallback, + Pointer, + read, + suffix, +} from "bun:ffi"; import * as tsd from "./utilities.test"; // `suffix` is either "dylib", "so", or "dll" depending on the platform @@ -6,60 +14,60 @@ import * as tsd from "./utilities.test"; const path = `libsqlite3.${suffix}`; const lib = dlopen( - path, // a library name or file path - { - sqlite3_libversion: { - // no arguments, returns a string - args: [], - returns: FFIType.cstring, - }, - add: { - args: [FFIType.i32, FFIType.i32], - returns: FFIType.i32, - }, - ptr_type: { - args: [FFIType.pointer], - returns: FFIType.pointer, - }, - fn_type: { - args: [FFIType.function], - returns: FFIType.function, - }, - allArgs: { - args: [ - FFIType.char, // string - FFIType.int8_t, - FFIType.i8, - FFIType.uint8_t, - FFIType.u8, - FFIType.int16_t, - FFIType.i16, - FFIType.uint16_t, - FFIType.u16, - FFIType.int32_t, - FFIType.i32, - FFIType.int, - FFIType.uint32_t, - FFIType.u32, - FFIType.int64_t, - FFIType.i64, - FFIType.uint64_t, - FFIType.u64, - FFIType.double, - FFIType.f64, - FFIType.float, - FFIType.f32, - FFIType.bool, - FFIType.ptr, - FFIType.pointer, - FFIType.void, - FFIType.cstring, - FFIType.i64_fast, - FFIType.u64_fast, - ], - returns: FFIType.void, - }, - }, + path, // a library name or file path + { + sqlite3_libversion: { + // no arguments, returns a string + args: [], + returns: FFIType.cstring, + }, + add: { + args: [FFIType.i32, FFIType.i32], + returns: FFIType.i32, + }, + ptr_type: { + args: [FFIType.pointer], + returns: FFIType.pointer, + }, + fn_type: { + args: [FFIType.function], + returns: FFIType.function, + }, + allArgs: { + args: [ + FFIType.char, // string + FFIType.int8_t, + FFIType.i8, + FFIType.uint8_t, + FFIType.u8, + FFIType.int16_t, + FFIType.i16, + FFIType.uint16_t, + FFIType.u16, + FFIType.int32_t, + FFIType.i32, + FFIType.int, + FFIType.uint32_t, + FFIType.u32, + FFIType.int64_t, + FFIType.i64, + FFIType.uint64_t, + FFIType.u64, + FFIType.double, + FFIType.f64, + FFIType.float, + FFIType.f32, + FFIType.bool, + FFIType.ptr, + FFIType.pointer, + FFIType.void, + FFIType.cstring, + FFIType.i64_fast, + FFIType.u64_fast, + ], + returns: FFIType.void, + }, + }, ); declare const ptr: Pointer; @@ -69,44 +77,46 @@ tsd.expectType(lib.symbols.add(1, 2)); tsd.expectType(lib.symbols.ptr_type(ptr)); -tsd.expectType(lib.symbols.fn_type(new JSCallback(() => {}, {}))); +tsd.expectType( + lib.symbols.fn_type(new JSCallback(() => {}, {})), +); function _arg( - ...params: [ - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - boolean, - Pointer, - Pointer, - // tslint:disable-next-line: void-return - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - void, - CString, - number | bigint, - number | bigint, - ] + ...params: [ + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + boolean, + Pointer, + Pointer, + // tslint:disable-next-line: void-return + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + void, + CString, + number | bigint, + number | bigint, + ] ) { - console.log("asdf"); + console.log("asdf"); } _arg; @@ -143,20 +153,20 @@ tsd.expectTypeEquals(true); // tslint:disable-next-line:no-object-literal-type-assertion const as_const_test = { - sqlite3_libversion: { - args: [], - returns: FFIType.cstring, - }, - multi_args: { - args: [FFIType.i32, FFIType.f32], - returns: FFIType.void, - }, - no_returns: { - args: [FFIType.i32], - }, - no_args: { - returns: FFIType.i32, - }, + sqlite3_libversion: { + args: [], + returns: FFIType.cstring, + }, + multi_args: { + args: [FFIType.i32, FFIType.f32], + returns: FFIType.void, + }, + no_returns: { + args: [FFIType.i32], + }, + no_args: { + returns: FFIType.i32, + }, } as const; const lib2 = dlopen(path, as_const_test); @@ -165,7 +175,10 @@ tsd.expectType(lib2.symbols.sqlite3_libversion()); // tslint:disable-next-line:no-void-expression // eslint-disable-next-line @typescript-eslint/no-invalid-void-type tsd.expectType(lib2.symbols.multi_args(1, 2)); -tsd.expectTypeEquals, undefined>(true); +tsd.expectTypeEquals< + ReturnType<(typeof lib2)["symbols"]["no_returns"]>, + undefined +>(true); tsd.expectTypeEquals, []>(true); tsd.expectType(read.u8(ptr)); diff --git a/packages/bun-types/test/fs.test.ts b/packages/bun-types/test/fs.test.ts index 863c528d1ba72b..5fe2e4c920835c 100644 --- a/packages/bun-types/test/fs.test.ts +++ b/packages/bun-types/test/fs.test.ts @@ -11,10 +11,10 @@ tsd.expectType>(fs.promises.exists("/etc/passwd")); // file path watch(".", (eventType, filename) => { - console.log(`event type = ${eventType}`); - if (filename) { - console.log(`filename = ${filename}`); - } + console.log(`event type = ${eventType}`); + if (filename) { + console.log(`filename = ${filename}`); + } }); await Bun.file("sdf").exists(); diff --git a/packages/bun-types/test/fsrouter.test.ts b/packages/bun-types/test/fsrouter.test.ts index 1a1b9975560bff..2e26f90bb0e066 100644 --- a/packages/bun-types/test/fsrouter.test.ts +++ b/packages/bun-types/test/fsrouter.test.ts @@ -2,8 +2,8 @@ import { FileSystemRouter } from "bun"; import { expectType } from "./utilities.test"; const router = new FileSystemRouter({ - dir: "/pages", - style: "nextjs", + dir: "/pages", + style: "nextjs", }); const match = router.match("/"); diff --git a/packages/bun-types/test/globals.test.ts b/packages/bun-types/test/globals.test.ts index d2fb69e4c9eb89..3644f515ba4c0d 100644 --- a/packages/bun-types/test/globals.test.ts +++ b/packages/bun-types/test/globals.test.ts @@ -26,14 +26,16 @@ expectType(new Bun.SHA512_256().update("test").digest("hex")); expectType(Bun.deflateSync(new Uint8Array(128))); expectType(Bun.gzipSync(new Uint8Array(128))); expectType( - Bun.deflateSync(new Uint8Array(128), { - level: -1, - memLevel: 8, - strategy: 0, - windowBits: 15, - }), + Bun.deflateSync(new Uint8Array(128), { + level: -1, + memLevel: 8, + strategy: 0, + windowBits: 15, + }), +); +expectType( + Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 }), ); -expectType(Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 })); expectType(Bun.inflateSync(new Uint8Array(64))); // Pretend this is DEFLATE compressed data expectType(Bun.gunzipSync(new Uint8Array(64))); // Pretend this is GZIP compressed data expectAssignable({ windowBits: -11 }); @@ -45,7 +47,9 @@ expectType(Bun.pathToFileURL("/foo/bar.txt")); expectType(Bun.fileURLToPath(new URL("file:///foo/bar.txt"))); // Testing ../fs.d.ts -expectType(fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString()); +expectType( + fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString(), +); expectType(fs.existsSync("./index.d.ts")); // tslint:disable-next-line:no-void-expression // eslint-disable-next-line @typescript-eslint/no-invalid-void-type @@ -58,7 +62,9 @@ expectType(fs.appendFileSync("./index.d.ts", "test")); expectType(fs.mkdirSync("./index.d.ts")); // Testing ^promises.d.ts -expectType((await fsPromises.readFile("./index.d.ts", { encoding: "utf-8" })).toString()); +expectType( + (await fsPromises.readFile("./index.d.ts", { encoding: "utf-8" })).toString(), +); expectType>(fsPromises.access("./index.d.ts")); expectType>(fsPromises.appendFile("./index.d.ts", "test")); expectType>(fsPromises.mkdir("./index.d.ts")); @@ -136,7 +142,7 @@ function stuff(arg: ReadableStreamDefaultReader): any; function stuff(arg: ReadableStreamDefaultController): any; function stuff(arg: WritableStreamDefaultWriter): any; function stuff(arg: any) { - return "asfd"; + return "asfd"; } stuff("asdf" as any as Blob); @@ -157,145 +163,145 @@ const readableStream = new ReadableStream(); const writableStream = new WritableStream(); { - const a = new ByteLengthQueuingStrategy({ highWaterMark: 0 }); - a.highWaterMark; + const a = new ByteLengthQueuingStrategy({ highWaterMark: 0 }); + a.highWaterMark; } { - const a = new ReadableStreamDefaultController(); - a.close(); + const a = new ReadableStreamDefaultController(); + a.close(); } { - const a = new ReadableStreamDefaultReader(readableStream); - await a.cancel(); + const a = new ReadableStreamDefaultReader(readableStream); + await a.cancel(); } { - const a = new WritableStreamDefaultController(); - a.error(); + const a = new WritableStreamDefaultController(); + a.error(); } { - const a = new WritableStreamDefaultWriter(writableStream); - await a.close(); + const a = new WritableStreamDefaultWriter(writableStream); + await a.close(); } { - const a = new TransformStream(); - a.readable; + const a = new TransformStream(); + a.readable; } { - const a = new TransformStreamDefaultController(); - a.enqueue("asdf"); + const a = new TransformStreamDefaultController(); + a.enqueue("asdf"); } { - const a = new CountQueuingStrategy({ highWaterMark: 0 }); - a.highWaterMark; + const a = new CountQueuingStrategy({ highWaterMark: 0 }); + a.highWaterMark; } { - const a = new DOMException(); - a.DATA_CLONE_ERR; + const a = new DOMException(); + a.DATA_CLONE_ERR; } { - const a = new SubtleCrypto(); - await a.decrypt("asdf", new CryptoKey(), new Uint8Array()); + const a = new SubtleCrypto(); + await a.decrypt("asdf", new CryptoKey(), new Uint8Array()); } { - const a = new CryptoKey(); - a.algorithm; + const a = new CryptoKey(); + a.algorithm; } { - const a = new BuildError(); - a.level; + const a = new BuildError(); + a.level; } { - const a = new ResolveError(); - a.level; + const a = new ResolveError(); + a.level; } { - const a = new AbortController(); - a; + const a = new AbortController(); + a; } { - const a = new AbortSignal(); - a.aborted; + const a = new AbortSignal(); + a.aborted; } { - const a = new Request("asdf"); - await a.json(); - a.cache; + const a = new Request("asdf"); + await a.json(); + a.cache; } { - const a = new Response(); - await a.text(); - a.ok; + const a = new Response(); + await a.text(); + a.ok; } { - const a = new FormData(); - a.delete("asdf"); + const a = new FormData(); + a.delete("asdf"); } { - const a = new Headers(); - a.append("asdf", "asdf"); + const a = new Headers(); + a.append("asdf", "asdf"); } { - const a = new EventTarget(); - a.dispatchEvent(new Event("asdf")); + const a = new EventTarget(); + a.dispatchEvent(new Event("asdf")); } { - const a = new Event("asdf"); - a.bubbles; - a.composedPath()[0]; + const a = new Event("asdf"); + a.bubbles; + a.composedPath()[0]; } { - const a = new Blob(); - a.size; + const a = new Blob(); + a.size; } { - const a = new File(["asdf"], "stuff.txt "); - a.name; + const a = new File(["asdf"], "stuff.txt "); + a.name; } { - performance.now(); + performance.now(); } { - const a = new URL("asdf"); - a.host; - a.href; + const a = new URL("asdf"); + a.host; + a.href; } { - const a = new URLSearchParams(); - a; + const a = new URLSearchParams(); + a; } { - const a = new TextDecoder(); - a.decode(new Uint8Array()); + const a = new TextDecoder(); + a.decode(new Uint8Array()); } { - const a = new TextEncoder(); - a.encode("asdf"); + const a = new TextEncoder(); + a.encode("asdf"); } { - const a = new BroadcastChannel("stuff"); - a.close(); + const a = new BroadcastChannel("stuff"); + a.close(); } { - const a = new MessageChannel(); - a.port1; + const a = new MessageChannel(); + a.port1; } { - const a = new MessagePort(); - a.close(); + const a = new MessagePort(); + a.close(); } { - var a!: RequestInit; - a.mode; - a.credentials; + var a!: RequestInit; + a.mode; + a.credentials; } { - var b!: ResponseInit; - b.status; + var b!: ResponseInit; + b.status; } { - const ws = new WebSocket("ws://www.host.com/path"); - ws.send("asdf"); + const ws = new WebSocket("ws://www.host.com/path"); + ws.send("asdf"); } atob("asf"); diff --git a/packages/bun-types/test/http.test.ts b/packages/bun-types/test/http.test.ts index c78ab80c233ce8..49ee1e02c1b9f0 100644 --- a/packages/bun-types/test/http.test.ts +++ b/packages/bun-types/test/http.test.ts @@ -29,7 +29,7 @@ export {}; // URLSearchParams should be iterable const sp = new URLSearchParams("q=foo&bar=baz"); for (const q of sp) { - console.log(q); + console.log(q); } fetch; diff --git a/packages/bun-types/test/jsc.test.ts b/packages/bun-types/test/jsc.test.ts index c1a531f1153af3..181c5d84179a69 100644 --- a/packages/bun-types/test/jsc.test.ts +++ b/packages/bun-types/test/jsc.test.ts @@ -6,5 +6,5 @@ const buffer = serialize(obj); const clone = deserialize(buffer); if (deepEquals(obj, clone)) { - console.log("They are equal!"); + console.log("They are equal!"); } diff --git a/packages/bun-types/test/mocks.test.ts b/packages/bun-types/test/mocks.test.ts index 8c891743356fcc..87eb74dcea59db 100644 --- a/packages/bun-types/test/mocks.test.ts +++ b/packages/bun-types/test/mocks.test.ts @@ -2,7 +2,7 @@ import { jest, mock } from "bun:test"; import { expectType } from "./utilities.test"; const mock1 = mock((arg: string) => { - return arg.length; + return arg.length; }); const arg1 = mock1("1"); diff --git a/packages/bun-types/test/net.test.ts b/packages/bun-types/test/net.test.ts index 76ad4b01516fe9..2756dd4d1dd7d4 100644 --- a/packages/bun-types/test/net.test.ts +++ b/packages/bun-types/test/net.test.ts @@ -1,11 +1,11 @@ import * as net from "node:net"; const socket = net.connect({ - port: 80, - host: "localhost", + port: 80, + host: "localhost", }); socket.connect({ - port: 80, - host: "localhost", + port: 80, + host: "localhost", }); diff --git a/packages/bun-types/test/process.test.ts b/packages/bun-types/test/process.test.ts index 6ea7cf043d902c..04c8d17b249856 100644 --- a/packages/bun-types/test/process.test.ts +++ b/packages/bun-types/test/process.test.ts @@ -2,15 +2,15 @@ process.memoryUsage(); process.cpuUsage().system; process.cpuUsage().user; process.on("SIGINT", () => { - console.log("Interrupt from keyboard"); + console.log("Interrupt from keyboard"); }); -process.on("beforeExit", code => { - console.log("Event loop is empty and no work is left to schedule.", code); +process.on("beforeExit", (code) => { + console.log("Event loop is empty and no work is left to schedule.", code); }); -process.on("exit", code => { - console.log("Exiting with code:", code); +process.on("exit", (code) => { + console.log("Exiting with code:", code); }); process.kill(123, "SIGTERM"); @@ -21,7 +21,7 @@ process.getgroups!(); process.getuid!(); process.once("SIGINT", () => { - console.log("Interrupt from keyboard"); + console.log("Interrupt from keyboard"); }); // commented methods are not yet implemented diff --git a/packages/bun-types/test/readline.test.ts b/packages/bun-types/test/readline.test.ts index 967d9b06d5db79..7b4be00a01a201 100644 --- a/packages/bun-types/test/readline.test.ts +++ b/packages/bun-types/test/readline.test.ts @@ -1,10 +1,10 @@ import * as readline from "node:readline/promises"; const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: true, + input: process.stdin, + output: process.stdout, + terminal: true, }); -await rl.question("What is your age?\n").then(answer => { - console.log("Your age is: " + answer); +await rl.question("What is your age?\n").then((answer) => { + console.log("Your age is: " + answer); }); diff --git a/packages/bun-types/test/serve.test.ts b/packages/bun-types/test/serve.test.ts index 1ddd23a0c6dff3..60903bf71fc7fc 100644 --- a/packages/bun-types/test/serve.test.ts +++ b/packages/bun-types/test/serve.test.ts @@ -1,160 +1,160 @@ Bun.serve({ - fetch(req) { - console.log(req.url); // => http://localhost:3000/ - return new Response("Hello World"); - }, + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, }); Bun.serve({ - fetch(req) { - console.log(req.url); // => http://localhost:3000/ - return new Response("Hello World"); - }, - keyFile: "ca.pem", - certFile: "cert.pem", + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, + keyFile: "ca.pem", + certFile: "cert.pem", }); Bun.serve({ - websocket: { - message(ws, message) { - ws.send(message); - }, - }, - - fetch(req, server) { - // Upgrade to a ServerWebSocket if we can - // This automatically checks for the `Sec-WebSocket-Key` header - // meaning you don't have to check headers, you can just call `upgrade()` - if (server.upgrade(req)) { - // When upgrading, we return undefined since we don't want to send a Response - return; - } - - return new Response("Regular HTTP response"); - }, + websocket: { + message(ws, message) { + ws.send(message); + }, + }, + + fetch(req, server) { + // Upgrade to a ServerWebSocket if we can + // This automatically checks for the `Sec-WebSocket-Key` header + // meaning you don't have to check headers, you can just call `upgrade()` + if (server.upgrade(req)) { + // When upgrading, we return undefined since we don't want to send a Response + return; + } + + return new Response("Regular HTTP response"); + }, }); Bun.serve<{ - name: string; + name: string; }>({ - fetch(req, server) { - const url = new URL(req.url); - if (url.pathname === "/chat") { - if ( - server.upgrade(req, { - data: { - name: new URL(req.url).searchParams.get("name") || "Friend", - }, - headers: { - "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), - }, - }) - ) { - return; - } - } - - return new Response("Expected a websocket connection", { status: 400 }); - }, - - websocket: { - open(ws) { - console.log("WebSocket opened"); - ws.subscribe("the-group-chat"); - }, - - message(ws, message) { - ws.publish("the-group-chat", `${ws.data.name}: ${message.toString()}`); - }, - - close(ws, code, reason) { - ws.publish("the-group-chat", `${ws.data.name} left the chat`); - }, - - drain(ws) { - console.log("Please send me data. I am ready to receive it."); - }, - - perMessageDeflate: true, - }, + fetch(req, server) { + const url = new URL(req.url); + if (url.pathname === "/chat") { + if ( + server.upgrade(req, { + data: { + name: new URL(req.url).searchParams.get("name") || "Friend", + }, + headers: { + "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), + }, + }) + ) { + return; + } + } + + return new Response("Expected a websocket connection", { status: 400 }); + }, + + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("the-group-chat"); + }, + + message(ws, message) { + ws.publish("the-group-chat", `${ws.data.name}: ${message.toString()}`); + }, + + close(ws, code, reason) { + ws.publish("the-group-chat", `${ws.data.name} left the chat`); + }, + + drain(ws) { + console.log("Please send me data. I am ready to receive it."); + }, + + perMessageDeflate: true, + }, }); Bun.serve({ - fetch(req) { - throw new Error("woops!"); - }, - error(error) { - return new Response(`

${error.message}\n${error.stack}
`, { - headers: { - "Content-Type": "text/html", - }, - }); - }, + fetch(req) { + throw new Error("woops!"); + }, + error(error) { + return new Response(`
${error.message}\n${error.stack}
`, { + headers: { + "Content-Type": "text/html", + }, + }); + }, }); export {}; Bun.serve({ - port: 1234, - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, + port: 1234, + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch() { - return new Response(); - }, + unix: "/tmp/bun.sock", + fetch() { + return new Response(); + }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, + unix: "/tmp/bun.sock", + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch() { - return new Response(); - }, - tls: {}, + unix: "/tmp/bun.sock", + fetch() { + return new Response(); + }, + tls: {}, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, - tls: {}, + unix: "/tmp/bun.sock", + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, + tls: {}, }); Bun.serve({ - fetch(req, server) { - server.upgrade(req); - }, - websocket: { - open(ws) { - console.log("WebSocket opened"); - ws.subscribe("test-channel"); - }, - - message(ws, message) { - ws.publish("test-channel", `${message.toString()}`); - }, - perMessageDeflate: true, - }, + fetch(req, server) { + server.upgrade(req); + }, + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("test-channel"); + }, + + message(ws, message) { + ws.publish("test-channel", `${message.toString()}`); + }, + perMessageDeflate: true, + }, }); // Bun.serve({ // unix: "/tmp/bun.sock", diff --git a/packages/bun-types/test/spawn.test.ts b/packages/bun-types/test/spawn.test.ts index a6c8fddff15b5d..9dbfef61bf9264 100644 --- a/packages/bun-types/test/spawn.test.ts +++ b/packages/bun-types/test/spawn.test.ts @@ -1,145 +1,176 @@ -import { FileSink, NullSubprocess, PipedSubprocess, ReadableSubprocess, SyncSubprocess, WritableSubprocess } from "bun"; +import { + FileSink, + NullSubprocess, + PipedSubprocess, + ReadableSubprocess, + SyncSubprocess, + WritableSubprocess, +} from "bun"; import * as tsd from "./utilities.test"; Bun.spawn(["echo", "hello"]); function depromise(_promise: Promise): T { - return "asdf" as any as T; + return "asdf" as any as T; } { - const proc = Bun.spawn(["echo", "hello"], { - cwd: "./path/to/subdir", // specify a working direcory - env: { ...process.env, FOO: "bar" }, // specify environment variables - onExit(proc, exitCode, signalCode, error) { - // exit handler - }, - }); - - proc.pid; // process ID of subprocess - - tsd.expectType>(proc.stdout); - tsd.expectType(proc.stderr); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + cwd: "./path/to/subdir", // specify a working direcory + env: { ...process.env, FOO: "bar" }, // specify environment variables + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + proc.pid; // process ID of subprocess + + tsd.expectType>(proc.stdout); + tsd.expectType(proc.stderr); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["cat"], { - stdin: depromise(fetch("https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js")), - }); - - const text = depromise(new Response(proc.stdout).text()); - console.log(text); // "const input = "hello world".repeat(400); ..." + const proc = Bun.spawn(["cat"], { + stdin: depromise( + fetch( + "https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js", + ), + ), + }); + + const text = depromise(new Response(proc.stdout).text()); + console.log(text); // "const input = "hello world".repeat(400); ..." } { - const proc = Bun.spawn(["cat"], { - stdin: "pipe", // return a FileSink for writing - }); - - // enqueue string data - proc.stdin.write("hello"); - - // enqueue binary data - const enc = new TextEncoder(); - proc.stdin.write(enc.encode(" world!")); - enc.encodeInto(" world!", {} as any as Uint8Array); - // Bun-specific overloads - // these fail when lib.dom.d.ts is present - enc.encodeInto(" world!", new Uint32Array(124)); - enc.encodeInto(" world!", {} as any as DataView); - - // send buffered data - await proc.stdin.flush(); - - // close the input stream - await proc.stdin.end(); + const proc = Bun.spawn(["cat"], { + stdin: "pipe", // return a FileSink for writing + }); + + // enqueue string data + proc.stdin.write("hello"); + + // enqueue binary data + const enc = new TextEncoder(); + proc.stdin.write(enc.encode(" world!")); + enc.encodeInto(" world!", {} as any as Uint8Array); + // Bun-specific overloads + // these fail when lib.dom.d.ts is present + enc.encodeInto(" world!", new Uint32Array(124)); + enc.encodeInto(" world!", {} as any as DataView); + + // send buffered data + await proc.stdin.flush(); + + // close the input stream + await proc.stdin.end(); } { - const proc = Bun.spawn(["echo", "hello"]); - const text = depromise(new Response(proc.stdout).text()); - console.log(text); // => "hello" + const proc = Bun.spawn(["echo", "hello"]); + const text = depromise(new Response(proc.stdout).text()); + console.log(text); // => "hello" } { - const proc = Bun.spawn(["echo", "hello"], { - onExit(proc, exitCode, signalCode, error) { - // exit handler - }, - }); - - await proc.exited; // resolves when process exit - proc.killed; // boolean โ€” was the process killed? - proc.exitCode; // null | number - proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... - proc.kill(); - proc.killed; // true - - proc.kill(); // specify an exit code - proc.unref(); + const proc = Bun.spawn(["echo", "hello"], { + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + await proc.exited; // resolves when process exit + proc.killed; // boolean โ€” was the process killed? + proc.exitCode; // null | number + proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... + proc.kill(); + proc.killed; // true + + proc.kill(); // specify an exit code + proc.unref(); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["pipe", "pipe", "pipe"], - }); - tsd.expectType(proc.stdin); - tsd.expectType>(proc.stdout); - tsd.expectType>(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["pipe", "pipe", "pipe"], + }); + tsd.expectType(proc.stdin); + tsd.expectType>(proc.stdout); + tsd.expectType>(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["inherit", "inherit", "inherit"], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["inherit", "inherit", "inherit"], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["ignore", "ignore", "ignore"], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["ignore", "ignore", "ignore"], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [null, null, null], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [null, null, null], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Request("1"), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Request("1"), null, null], + }); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Response("1"), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Response("1"), null, null], + }); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Uint8Array([]), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Uint8Array([]), null, null], + }); + tsd.expectType(proc.stdin); } -tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); -tsd.expectNotAssignable(Bun.spawn([], { stdio: ["inherit", "inherit", "inherit"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); -tsd.expectNotAssignable(Bun.spawn([], { stdio: ["pipe", "ignore", "pipe"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "ignore", "inherit"] })); -tsd.expectNotAssignable(Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: ["ignore", "inherit", "ignore"] })); -tsd.expectAssignable(Bun.spawn([], { stdio: [null, null, null] })); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), +); +tsd.expectNotAssignable( + Bun.spawn([], { stdio: ["inherit", "inherit", "inherit"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), +); +tsd.expectNotAssignable( + Bun.spawn([], { stdio: ["pipe", "ignore", "pipe"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["pipe", "ignore", "inherit"] }), +); +tsd.expectNotAssignable( + Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: ["ignore", "inherit", "ignore"] }), +); +tsd.expectAssignable( + Bun.spawn([], { stdio: [null, null, null] }), +); tsd.expectNotAssignable(Bun.spawn([], {})); tsd.expectNotAssignable(Bun.spawn([], {})); diff --git a/packages/bun-types/test/sqlite.test.ts b/packages/bun-types/test/sqlite.test.ts index 32cd98057e3d7a..7cb261f571f397 100644 --- a/packages/bun-types/test/sqlite.test.ts +++ b/packages/bun-types/test/sqlite.test.ts @@ -3,14 +3,14 @@ import { expectType } from "./utilities.test"; const db = new Database(":memory:"); const query1 = db.query< - { name: string; dob: number }, // return type first - { $id: string } + { name: string; dob: number }, // return type first + { $id: string } >("select name, dob from users where id = $id"); query1.all({ $id: "asdf" }); // => {name: string; dob:string}[] const query2 = db.query< - { name: string; dob: number }, - [string, number] // pass tuple for positional params + { name: string; dob: number }, + [string, number] // pass tuple for positional params >("select ?1 as name, ?2 as dob"); const allResults = query2.all("Shaq", 50); // => {name: string; dob:string}[] const getResults = query2.get("Shaq", 50); // => {name: string; dob:string}[] @@ -25,9 +25,9 @@ expectType<{ name: string; dob: number } | null>(getResults); expectType(runResults); const query3 = db.prepare< - { name: string; dob: number }, // return type first - // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [{ $id: string }] + { name: string; dob: number }, // return type first + // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [{ $id: string }] >("select name, dob from users where id = $id"); const allResults3 = query3.all({ $id: "asdf" }); expectType>(allResults3); diff --git a/packages/bun-types/test/streams.test.ts b/packages/bun-types/test/streams.test.ts index 50c6fdeb65dd6f..3a303a618b8bc9 100644 --- a/packages/bun-types/test/streams.test.ts +++ b/packages/bun-types/test/streams.test.ts @@ -1,23 +1,23 @@ new ReadableStream({ - start(controller) { - controller.enqueue("hello"); - controller.enqueue("world"); - controller.close(); - }, + start(controller) { + controller.enqueue("hello"); + controller.enqueue("world"); + controller.close(); + }, }); // this will have type errors when lib.dom.d.ts is present // afaik this isn't fixable new ReadableStream({ - type: "direct", - pull(controller) { - // eslint-disable-next-line - controller.write("hello"); - // eslint-disable-next-line - controller.write("world"); - controller.close(); - }, - cancel() { - // called if stream.cancel() is called - }, + type: "direct", + pull(controller) { + // eslint-disable-next-line + controller.write("hello"); + // eslint-disable-next-line + controller.write("world"); + controller.close(); + }, + cancel() { + // called if stream.cancel() is called + }, }); diff --git a/packages/bun-types/test/tcp.test.ts b/packages/bun-types/test/tcp.test.ts index fe1b66a64880c5..f9f1038f2fbb43 100644 --- a/packages/bun-types/test/tcp.test.ts +++ b/packages/bun-types/test/tcp.test.ts @@ -1,134 +1,134 @@ import * as Bun from "bun"; await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLocaleLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLocaleLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, - tls: { - certFile: "asdf", - keyFile: "adsf", - }, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, + tls: { + certFile: "asdf", + keyFile: "adsf", + }, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, - tls: { - cert: "asdf", - key: Bun.file("adsf"), - ca: Buffer.from("asdf"), - }, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, + tls: { + cert: "asdf", + key: Bun.file("adsf"), + ca: Buffer.from("asdf"), + }, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); const listener = Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); listener.data.arg = "asdf"; @@ -140,8 +140,8 @@ listener.data.arg = 234; // }); listener.reload({ - socket: { - open() {}, - // ...listener. - }, + socket: { + open() {}, + // ...listener. + }, }); diff --git a/packages/bun-types/test/test.test.ts b/packages/bun-types/test/test.test.ts index 31a580aba2cfd5..6f7d1a4951dab3 100644 --- a/packages/bun-types/test/test.test.ts +++ b/packages/bun-types/test/test.test.ts @@ -1,4 +1,13 @@ -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, spyOn, test } from "bun:test"; +import { + afterAll, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + spyOn, + test, +} from "bun:test"; import { expectType } from "./utilities.test"; const spy = spyOn(console, "log"); @@ -7,119 +16,119 @@ expectType(spy.mock.calls); const hooks = [beforeAll, beforeEach, afterAll, afterEach]; for (const hook of hooks) { - hook(() => { - // ... - }); - // eslint-disable-next-line - hook(async () => { - // ... - return; - }); - hook((done: (err?: unknown) => void) => { - done(); - done(new Error()); - done("Error"); - }); + hook(() => { + // ... + }); + // eslint-disable-next-line + hook(async () => { + // ... + return; + }); + hook((done: (err?: unknown) => void) => { + done(); + done(new Error()); + done("Error"); + }); } describe("bun:test", () => { - describe("expect()", () => { - test("toThrow()", () => { - function fail() { - throw new Error("Bad"); - } - expect(fail).toThrow(); - expect(fail).toThrow("Bad"); - expect(fail).toThrow(/bad/i); - expect(fail).toThrow(Error); - expect(fail).toThrow(new Error("Bad")); - }); - }); - test("expect()", () => { - expect(1).toBe(1); - expect(1).not.toBe(2); - // @ts-expect-error - expect({ a: 1 }).toEqual({ a: 1, b: undefined }); - expect({ a: 1 }).toStrictEqual({ a: 1 }); - expect(new Set()).toHaveProperty("size"); - expect(new Uint8Array()).toHaveProperty("byteLength", 0); - expect([]).toHaveLength(0); - expect(["bun"]).toContain("bun"); - expect(true).toBeTruthy(); - expect(false).toBeFalsy(); - expect(Math.PI).toBeGreaterThan(3.14); - expect(Math.PI).toBeGreaterThan(3n); - expect(Math.PI).toBeGreaterThanOrEqual(3.14); - expect(Math.PI).toBeGreaterThanOrEqual(3n); - expect(NaN).toBeNaN(); - expect(null).toBeNull(); - expect(undefined).toBeUndefined(); - expect(undefined).not.toBeDefined(); - }); + describe("expect()", () => { + test("toThrow()", () => { + function fail() { + throw new Error("Bad"); + } + expect(fail).toThrow(); + expect(fail).toThrow("Bad"); + expect(fail).toThrow(/bad/i); + expect(fail).toThrow(Error); + expect(fail).toThrow(new Error("Bad")); + }); + }); + test("expect()", () => { + expect(1).toBe(1); + expect(1).not.toBe(2); + // @ts-expect-error + expect({ a: 1 }).toEqual({ a: 1, b: undefined }); + expect({ a: 1 }).toStrictEqual({ a: 1 }); + expect(new Set()).toHaveProperty("size"); + expect(new Uint8Array()).toHaveProperty("byteLength", 0); + expect([]).toHaveLength(0); + expect(["bun"]).toContain("bun"); + expect(true).toBeTruthy(); + expect(false).toBeFalsy(); + expect(Math.PI).toBeGreaterThan(3.14); + expect(Math.PI).toBeGreaterThan(3n); + expect(Math.PI).toBeGreaterThanOrEqual(3.14); + expect(Math.PI).toBeGreaterThanOrEqual(3n); + expect(NaN).toBeNaN(); + expect(null).toBeNull(); + expect(undefined).toBeUndefined(); + expect(undefined).not.toBeDefined(); + }); }); // inference should work when data is passed directly in test.each([ - ["a", true, 5], - ["b", false, 1234], + ["a", true, 5], + ["b", false, 1234], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([ - ["a", true, 5], - ["b", false, 5], + ["a", true, 5], + ["b", false, 5], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([{ asdf: "asdf" }, { asdf: "asdf" }])("test.each", (a, b, c) => { - expectType<{ asdf: string }>(a); - expectType<{ asdf: string }>(c); + expectType<{ asdf: string }>(a); + expectType<{ asdf: string }>(c); }); // no inference on data const data = [ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ]; test.each(data)("test.each", (...args) => { - expectType(args[0]); + expectType(args[0]); }); describe.each(data)("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); // as const const dataAsConst = [ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ] as const; test.each(dataAsConst)("test.each", (...args) => { - expectType(args[0]); - expectType(args[1]); - expectType(args[2]); + expectType(args[0]); + expectType(args[1]); + expectType(args[2]); }); describe.each(dataAsConst)("test.each", (...args) => { - expectType(args[0]); - expectType(args[1]); - expectType(args[2]); + expectType(args[0]); + expectType(args[1]); + expectType(args[2]); }); describe.each(dataAsConst)("test.each", (a, b, c) => { - expectType<"a" | "b">(a); - expectType(b); - expectType<5 | "asdf">(c); + expectType<"a" | "b">(a); + expectType(b); + expectType<5 | "asdf">(c); }); diff --git a/packages/bun-types/test/tls.test.ts b/packages/bun-types/test/tls.test.ts index fb2aa7d9b885a1..df6f1979c53b95 100644 --- a/packages/bun-types/test/tls.test.ts +++ b/packages/bun-types/test/tls.test.ts @@ -3,30 +3,30 @@ import tls from "node:tls"; tls.getCiphers()[0]; tls.connect({ - host: "localhost", - port: 80, - ca: "asdf", - cert: "path to cert", + host: "localhost", + port: 80, + ca: "asdf", + cert: "path to cert", }); tls.connect({ - host: "localhost", - port: 80, - ca: Bun.file("asdf"), - cert: Bun.file("path to cert"), - ciphers: "adsf", + host: "localhost", + port: 80, + ca: Bun.file("asdf"), + cert: Bun.file("path to cert"), + ciphers: "adsf", }); tls.connect({ - host: "localhost", - port: 80, - ca: Buffer.from("asdf"), - cert: Buffer.from("asdf"), + host: "localhost", + port: 80, + ca: Buffer.from("asdf"), + cert: Buffer.from("asdf"), }); tls.connect({ - host: "localhost", - port: 80, - ca: new Uint8Array([1, 2, 3]), - cert: new Uint8Array([1, 2, 3]), + host: "localhost", + port: 80, + ca: new Uint8Array([1, 2, 3]), + cert: new Uint8Array([1, 2, 3]), }); diff --git a/packages/bun-types/test/tty.test.ts b/packages/bun-types/test/tty.test.ts index 7e9f45115c731f..f6aff4b61e7e52 100644 --- a/packages/bun-types/test/tty.test.ts +++ b/packages/bun-types/test/tty.test.ts @@ -1,10 +1,10 @@ import * as tty from "tty"; const rs = new tty.ReadStream(234, { - allowHalfOpen: true, - readable: true, - signal: new AbortSignal(), - writable: true, + allowHalfOpen: true, + readable: true, + signal: new AbortSignal(), + writable: true, }); const ws = new tty.WriteStream(234); diff --git a/packages/bun-types/test/utilities.test.ts b/packages/bun-types/test/utilities.test.ts index 9fb6f411160b93..ef198a27614e3d 100644 --- a/packages/bun-types/test/utilities.test.ts +++ b/packages/bun-types/test/utilities.test.ts @@ -5,4 +5,6 @@ export declare const expectAssignable: (expression: T) => void; // eslint-disable-next-line @definitelytyped/no-unnecessary-generics export declare const expectNotAssignable: (expression: any) => void; // eslint-disable-next-line @definitelytyped/no-unnecessary-generics -export declare const expectTypeEquals: (expression: T extends S ? (S extends T ? true : false) : false) => void; +export declare const expectTypeEquals: ( + expression: T extends S ? (S extends T ? true : false) : false, +) => void; diff --git a/packages/bun-types/test/wasm.test.ts b/packages/bun-types/test/wasm.test.ts index 3b8785ec732709..f745fbe84e94ec 100644 --- a/packages/bun-types/test/wasm.test.ts +++ b/packages/bun-types/test/wasm.test.ts @@ -1,42 +1,42 @@ async () => { - // Fetch and compile a WebAssembly module - const response = await fetch("module.wasm"); - const buffer = await response.arrayBuffer(); - const module = await WebAssembly.compile(buffer); - - // Create a WebAssembly Memory object - const memory = new WebAssembly.Memory({ initial: 1 }); - - // Create a WebAssembly Table object - const table = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); - - // Instantiate the WebAssembly module - const instance = await WebAssembly.instantiate(module, { - js: { - log: (arg: any) => console.log("Logging from WASM:", arg), - tableFunc: () => console.log("Table function called"), - }, - env: { - memory: memory, - table: table, - }, - }); - - // Exported WebAssembly functions - const { exportedFunction } = instance.exports; - exportedFunction; - - // Call an exported WebAssembly function - // exportedFunction(); - - // Interact with WebAssembly memory - const uint8Array = new Uint8Array(memory.buffer); - uint8Array[0] = 1; // Modify memory - - // Use the WebAssembly Table - table.set(0, instance.exports.exportedTableFunction); - // eslint-disable-next-line - table.get(0)(); // Call a function stored in the table - - // Additional operations with instance, memory, and table can be performed here + // Fetch and compile a WebAssembly module + const response = await fetch("module.wasm"); + const buffer = await response.arrayBuffer(); + const module = await WebAssembly.compile(buffer); + + // Create a WebAssembly Memory object + const memory = new WebAssembly.Memory({ initial: 1 }); + + // Create a WebAssembly Table object + const table = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); + + // Instantiate the WebAssembly module + const instance = await WebAssembly.instantiate(module, { + js: { + log: (arg: any) => console.log("Logging from WASM:", arg), + tableFunc: () => console.log("Table function called"), + }, + env: { + memory: memory, + table: table, + }, + }); + + // Exported WebAssembly functions + const { exportedFunction } = instance.exports; + exportedFunction; + + // Call an exported WebAssembly function + // exportedFunction(); + + // Interact with WebAssembly memory + const uint8Array = new Uint8Array(memory.buffer); + uint8Array[0] = 1; // Modify memory + + // Use the WebAssembly Table + table.set(0, instance.exports.exportedTableFunction); + // eslint-disable-next-line + table.get(0)(); // Call a function stored in the table + + // Additional operations with instance, memory, and table can be performed here }; diff --git a/packages/bun-types/test/worker.test.ts b/packages/bun-types/test/worker.test.ts index 335f2652a9fe23..a6a32787b4a99e 100644 --- a/packages/bun-types/test/worker.test.ts +++ b/packages/bun-types/test/worker.test.ts @@ -3,17 +3,17 @@ import * as tsd from "./utilities.test"; const webWorker = new Worker("./worker.js"); -webWorker.addEventListener("message", event => { - tsd.expectType(event); +webWorker.addEventListener("message", (event) => { + tsd.expectType(event); }); -webWorker.addEventListener("error", event => { - tsd.expectType(event); +webWorker.addEventListener("error", (event) => { + tsd.expectType(event); }); -webWorker.addEventListener("messageerror", event => { - tsd.expectType(event); +webWorker.addEventListener("messageerror", (event) => { + tsd.expectType(event); }); -webWorker.onmessage = ev => "asdf"; -webWorker.onmessageerror = ev => "asdf"; +webWorker.onmessage = (ev) => "asdf"; +webWorker.onmessageerror = (ev) => "asdf"; webWorker.postMessage("asdf", []); webWorker.terminate(); webWorker.addEventListener("close", () => {}); @@ -24,8 +24,8 @@ webWorker.unref(); webWorker.threadId; const nodeWorker = new NodeWorker("./worker.ts"); -nodeWorker.on("message", event => { - console.log("Message from worker:", event); +nodeWorker.on("message", (event) => { + console.log("Message from worker:", event); }); nodeWorker.postMessage("Hello from main thread!"); @@ -33,8 +33,8 @@ const workerURL = new URL("worker.ts", "/path/to/").href; const _worker2 = new Worker(workerURL); nodeWorker.postMessage("hello"); -webWorker.onmessage = event => { - console.log(event.data); +webWorker.onmessage = (event) => { + console.log(event.data); }; // On the worker thread, `postMessage` is automatically "routed" to the parent thread. @@ -49,13 +49,13 @@ await nodeWorker.terminate(); // Bun.pathToFileURL const _worker3 = new Worker(new URL("worker.ts", "/path/to/").href, { - ref: true, - smol: true, - credentials: "same-origin", - name: "a name", - env: { - envValue: "hello", - }, + ref: true, + smol: true, + credentials: "same-origin", + name: "a name", + env: { + envValue: "hello", + }, }); export { _worker2, _worker3, nodeWorker as worker }; diff --git a/packages/bun-types/test/ws.test.ts b/packages/bun-types/test/ws.test.ts index fdc4072af2403f..83bfd0e4723b43 100644 --- a/packages/bun-types/test/ws.test.ts +++ b/packages/bun-types/test/ws.test.ts @@ -5,7 +5,7 @@ const ws = new WebSocket("ws://www.host.com/path"); ws.send("asdf"); const wss = new WebSocketServer({ - port: 8080, - perMessageDeflate: false, + port: 8080, + perMessageDeflate: false, }); wss; diff --git a/packages/bun-types/wasm.d.ts b/packages/bun-types/wasm.d.ts index b4975f140a94e2..ccbc0d1ef97d21 100644 --- a/packages/bun-types/wasm.d.ts +++ b/packages/bun-types/wasm.d.ts @@ -1,270 +1,291 @@ export {}; -type _Global = typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; -} - ? T - : Bun.WebAssembly.Global; +type _Global = + typeof globalThis extends { + onerror: any; + WebAssembly: { Global: infer T }; + } + ? T + : Bun.WebAssembly.Global; type _CompileError = typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; + onerror: any; + WebAssembly: { CompileError: infer T }; } - ? T - : Bun.WebAssembly.CompileError; + ? T + : Bun.WebAssembly.CompileError; type _LinkError = typeof globalThis extends { - onerror: any; - WebAssembly: { LinkError: infer T }; + onerror: any; + WebAssembly: { LinkError: infer T }; } - ? T - : Bun.WebAssembly.LinkError; + ? T + : Bun.WebAssembly.LinkError; type _RuntimeError = typeof globalThis extends { - onerror: any; - WebAssembly: { RuntimeError: infer T }; + onerror: any; + WebAssembly: { RuntimeError: infer T }; } - ? T - : Bun.WebAssembly.RuntimeError; + ? T + : Bun.WebAssembly.RuntimeError; type _Memory = typeof globalThis extends { - onerror: any; - WebAssembly: { Memory: infer T }; + onerror: any; + WebAssembly: { Memory: infer T }; } - ? T - : Bun.WebAssembly.Memory; + ? T + : Bun.WebAssembly.Memory; type _Instance = typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; + onerror: any; + WebAssembly: { Instance: infer T }; } - ? T - : Bun.WebAssembly.Instance; + ? T + : Bun.WebAssembly.Instance; type _Module = typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; + onerror: any; + WebAssembly: { Module: infer T }; } - ? T - : Bun.WebAssembly.Module; + ? T + : Bun.WebAssembly.Module; type _Table = typeof globalThis extends { - onerror: any; - WebAssembly: { Table: infer T }; + onerror: any; + WebAssembly: { Table: infer T }; } - ? T - : Bun.WebAssembly.Table; + ? T + : Bun.WebAssembly.Table; declare global { - namespace Bun { - namespace WebAssembly { - type ImportExportKind = "function" | "global" | "memory" | "table"; - type TableKind = "anyfunc" | "externref"; - // eslint-disable-next-line @typescript-eslint/ban-types - type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table; - type Exports = Record; - type ImportValue = ExportValue | number; - type Imports = Record; - type ModuleImports = Record; - - interface ValueTypeMap { - // eslint-disable-next-line @typescript-eslint/ban-types - anyfunc: Function; - externref: any; - f32: number; - f64: number; - i32: number; - i64: bigint; - v128: never; - } - - type ValueType = keyof ValueTypeMap; - - interface GlobalDescriptor { - mutable?: boolean; - value: T; - } - - interface Global { - // { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ - value: ValueTypeMap[T]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ - valueOf(): ValueTypeMap[T]; - } - - interface CompileError extends Error {} - - interface LinkError extends Error {} - - interface RuntimeError extends Error {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ - interface Instance { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ - readonly exports: Exports; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ - interface Memory { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ - readonly buffer: ArrayBuffer; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ - grow(delta: number): number; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ - interface Module {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ - interface Table { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ - readonly length: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ - get(index: number): any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ - grow(delta: number, value?: any): number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ - set(index: number, value?: any): void; - } - - interface MemoryDescriptor { - initial: number; - maximum?: number; - shared?: boolean; - } - - interface ModuleExportDescriptor { - kind: ImportExportKind; - name: string; - } - - interface ModuleImportDescriptor { - kind: ImportExportKind; - module: string; - name: string; - } - - interface TableDescriptor { - element: TableKind; - initial: number; - maximum?: number; - } - - interface WebAssemblyInstantiatedSource { - instance: Instance; - module: Module; - } - } - } - - namespace WebAssembly { - interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} - interface GlobalDescriptor - extends Bun.WebAssembly.GlobalDescriptor {} - interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} - interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} - interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} - interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} - interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} - - interface LinkError extends _LinkError {} - var LinkError: { - prototype: LinkError; - new (message?: string): LinkError; - (message?: string): LinkError; - }; - - interface CompileError extends _CompileError {} - var CompileError: typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; - } - ? T - : { - prototype: CompileError; - new (message?: string): CompileError; - (message?: string): CompileError; - }; - - interface RuntimeError extends _RuntimeError {} - var RuntimeError: { - prototype: RuntimeError; - new (message?: string): RuntimeError; - (message?: string): RuntimeError; - }; - - interface Global extends _Global {} - var Global: typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; - } - ? T - : { - prototype: Global; - new ( - descriptor: GlobalDescriptor, - v?: ValueTypeMap[T], - ): Global; - }; - - interface Instance extends _Instance {} - var Instance: typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; - } - ? T - : { - prototype: Instance; - new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; - }; - - interface Memory extends _Memory {} - var Memory: { - prototype: Memory; - new (descriptor: MemoryDescriptor): Memory; - }; - - interface Module extends _Module {} - var Module: typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; - } - ? T - : { - prototype: Module; - new (bytes: Bun.BufferSource): Module; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ - customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ - exports(moduleObject: Module): ModuleExportDescriptor[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ - imports(moduleObject: Module): ModuleImportDescriptor[]; - }; - - interface Table extends _Table {} - var Table: { - prototype: Table; - new (descriptor: TableDescriptor, value?: any): Table; - }; - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ - function compile(bytes: Bun.BufferSource): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ - function compileStreaming(source: Response | PromiseLike): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ - function instantiate( - bytes: Bun.BufferSource, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ - function instantiateStreaming( - source: Response | PromiseLike, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ - function validate(bytes: Bun.BufferSource): boolean; - } + namespace Bun { + namespace WebAssembly { + type ImportExportKind = "function" | "global" | "memory" | "table"; + type TableKind = "anyfunc" | "externref"; + // eslint-disable-next-line @typescript-eslint/ban-types + type ExportValue = + | Function + | Global + | WebAssembly.Memory + | WebAssembly.Table; + type Exports = Record; + type ImportValue = ExportValue | number; + type Imports = Record; + type ModuleImports = Record; + + interface ValueTypeMap { + // eslint-disable-next-line @typescript-eslint/ban-types + anyfunc: Function; + externref: any; + f32: number; + f64: number; + i32: number; + i64: bigint; + v128: never; + } + + type ValueType = keyof ValueTypeMap; + + interface GlobalDescriptor { + mutable?: boolean; + value: T; + } + + interface Global { + // { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ + value: ValueTypeMap[T]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ + valueOf(): ValueTypeMap[T]; + } + + interface CompileError extends Error {} + + interface LinkError extends Error {} + + interface RuntimeError extends Error {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ + interface Instance { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ + readonly exports: Exports; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ + interface Memory { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ + readonly buffer: ArrayBuffer; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ + grow(delta: number): number; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ + interface Module {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ + interface Table { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ + readonly length: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ + get(index: number): any; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ + grow(delta: number, value?: any): number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ + set(index: number, value?: any): void; + } + + interface MemoryDescriptor { + initial: number; + maximum?: number; + shared?: boolean; + } + + interface ModuleExportDescriptor { + kind: ImportExportKind; + name: string; + } + + interface ModuleImportDescriptor { + kind: ImportExportKind; + module: string; + name: string; + } + + interface TableDescriptor { + element: TableKind; + initial: number; + maximum?: number; + } + + interface WebAssemblyInstantiatedSource { + instance: Instance; + module: Module; + } + } + } + + namespace WebAssembly { + interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} + interface GlobalDescriptor< + T extends keyof ValueTypeMap = keyof ValueTypeMap, + > extends Bun.WebAssembly.GlobalDescriptor {} + interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} + interface ModuleExportDescriptor + extends Bun.WebAssembly.ModuleExportDescriptor {} + interface ModuleImportDescriptor + extends Bun.WebAssembly.ModuleImportDescriptor {} + interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} + interface WebAssemblyInstantiatedSource + extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} + + interface LinkError extends _LinkError {} + var LinkError: { + prototype: LinkError; + new (message?: string): LinkError; + (message?: string): LinkError; + }; + + interface CompileError extends _CompileError {} + var CompileError: typeof globalThis extends { + onerror: any; + WebAssembly: { CompileError: infer T }; + } + ? T + : { + prototype: CompileError; + new (message?: string): CompileError; + (message?: string): CompileError; + }; + + interface RuntimeError extends _RuntimeError {} + var RuntimeError: { + prototype: RuntimeError; + new (message?: string): RuntimeError; + (message?: string): RuntimeError; + }; + + interface Global + extends _Global {} + var Global: typeof globalThis extends { + onerror: any; + WebAssembly: { Global: infer T }; + } + ? T + : { + prototype: Global; + new ( + descriptor: GlobalDescriptor, + v?: ValueTypeMap[T], + ): Global; + }; + + interface Instance extends _Instance {} + var Instance: typeof globalThis extends { + onerror: any; + WebAssembly: { Instance: infer T }; + } + ? T + : { + prototype: Instance; + new ( + module: Module, + importObject?: Bun.WebAssembly.Imports, + ): Instance; + }; + + interface Memory extends _Memory {} + var Memory: { + prototype: Memory; + new (descriptor: MemoryDescriptor): Memory; + }; + + interface Module extends _Module {} + var Module: typeof globalThis extends { + onerror: any; + WebAssembly: { Module: infer T }; + } + ? T + : { + prototype: Module; + new (bytes: Bun.BufferSource): Module; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ + customSections( + moduleObject: Module, + sectionName: string, + ): ArrayBuffer[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ + exports(moduleObject: Module): ModuleExportDescriptor[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + + interface Table extends _Table {} + var Table: { + prototype: Table; + new (descriptor: TableDescriptor, value?: any): Table; + }; + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ + function compile(bytes: Bun.BufferSource): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ + function compileStreaming( + source: Response | PromiseLike, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ + function instantiate( + bytes: Bun.BufferSource, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + function instantiate( + moduleObject: Module, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ + function instantiateStreaming( + source: Response | PromiseLike, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ + function validate(bytes: Bun.BufferSource): boolean; + } } diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 02ad2d0156a5e1..0689dd87b489f8 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -87,8 +87,13 @@ new ReadableStream({}); const body = await fetch(req1); +Bun.fetch satisfies typeof fetch; +Bun.fetch.preconnect satisfies typeof fetch.preconnect; + await body.text(); +fetch; + fetch.preconnect(new URL("")); Bun.serve({ From f476d88a498af0cdc72e14cbf1a469c92993cd35 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 6 Mar 2025 04:24:17 +0000 Subject: [PATCH 04/72] some changes --- packages/bun-types/new/index.d.ts | 522 +++----------------- packages/bun-types/new/s3.d.ts | 204 ++++++++ test/integration/bun-types/fixture/index.ts | 10 +- 3 files changed, 289 insertions(+), 447 deletions(-) create mode 100644 packages/bun-types/new/s3.d.ts diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index 88237b34673619..52974937249eab 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -1,458 +1,90 @@ +/// + declare var onmessage: never; declare var Bun: typeof import("bun"); -declare var TextEncoder: typeof TextEncoder; -declare var TextDecoder: typeof TextDecoder; -declare var crypto: Crypto; -declare var performance: Performance; -declare var Event: { - prototype: Event; - new (type: string, eventInitDict?: Bun.EventInit): Event; -}; -declare var EventTarget: { - prototype: EventTarget; - new (): EventTarget; -}; -declare var File: typeof File; -declare var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; -}; -declare var queueMicrotask: (callback: (...args: any[]) => void) => void; -declare var reportError: (error: any) => void; -declare var clearInterval: (id?: number | Timer) => void; -declare var clearTimeout: (id?: number | Timer) => void; -declare var clearImmediate: (id?: number | Timer) => void; -declare var setImmediate: (handler: Bun.TimerHandler, ...arguments: any[]) => Timer; -declare var setInterval: (handler: Bun.TimerHandler, interval?: number, ...arguments: any[]) => Timer; -declare var setTimeout: (handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]) => Timer; -declare var addEventListener: typeof addEventListener; -declare var removeEventListener: typeof removeEventListener; -declare var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; -}; -declare var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; -}; -declare var MessageEvent: { - prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; -}; -declare var CustomEvent: { - prototype: CustomEvent; - new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; -}; -declare var Loader: { - registry: Map< - string, - { - key: string; - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array; - module: { - dependenciesMap: Map; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - dependencyKeysIfEvaluated: (specifier: string) => string[]; - resolve: (specifier: string, referrer: string) => string; -}; -declare var Blob: typeof Blob; -declare var WebSocket: typeof import("ws").WebSocket; -declare var navigator: Navigator; -declare var console: Console; -declare var require: NodeJS.Require; -declare var exports: any; -declare var module: NodeModule; -declare function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; -declare function postMessage(message: any, transfer?: Bun.Transferable[]): void; -declare function alert(message?: string): void; -declare function confirm(message?: string): boolean; -declare function prompt(message?: string, _default?: string): string | null; - -declare interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; - [Symbol.toPrimitive](): number; -} - -declare interface ReadableStream extends import("stream/web").ReadableStream {} -declare interface WritableStream extends import("stream/web").WritableStream {} -declare interface Worker extends import("worker_threads").Worker {} - -declare interface ShadowRealm { - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; -} - -declare interface Event { - readonly bubbles: boolean; - cancelBubble: () => void; - readonly cancelable: boolean; - readonly composed: boolean; - composedPath(): [EventTarget?]; - readonly currentTarget: EventTarget | null; - readonly defaultPrevented: boolean; - readonly eventPhase: 0 | 2; - readonly isTrusted: boolean; - preventDefault(): void; - returnValue: boolean; - readonly srcElement: EventTarget | null; - stopImmediatePropagation(): void; - stopPropagation(): void; - readonly target: EventTarget | null; - readonly timeStamp: number; - readonly type: string; -} declare module "bun" { - interface Env { - [key: string]: string | undefined; - } - - interface ProcessEnv extends Env {} - - export var env: Env; - - export var fetch: { - (request: Request, init?: RequestInit): Promise; - (url: string | URL | Request, init?: RequestInit): Promise; - (input: string | URL | globalThis.Request, init?: RequestInit): Promise; - preconnect( - url: string | URL, - options?: { - dns?: boolean; - tcp?: boolean; - http?: boolean; - https?: boolean; - }, - ): void; - }; -} - -declare namespace Bun { - export * from "bun"; -} - -declare interface EventTarget { - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - dispatchEvent(event: Event): boolean; - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; -} - -declare interface File extends Blob { - readonly lastModified: number; - readonly name: string; -} - -declare interface RequestInit extends import("undici-types").RequestInit { - verbose?: boolean; - proxy?: string; - s3?: import("bun").S3Options; -} - -declare interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; -} - -declare interface CloseEvent extends Event { - readonly code: number; - readonly reason: string; - readonly wasClean: boolean; -} - -declare interface MessageEvent extends Event { - readonly data: T; - readonly lastEventId: string; - readonly origin: string; - readonly ports: readonly (typeof MessagePort)[]; - readonly source: Bun.MessageEventSource | null; -} - -declare interface CustomEvent extends Event { - readonly detail: T; -} - -declare interface EventListener { - (evt: Event): void; -} - -declare interface EventListenerObject { - handleEvent(object: Event): void; -} - -declare interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; -} - -declare var fetch: typeof import("bun").fetch; - -declare interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; -} - -declare interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; -} - -declare interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; -} - -declare interface Blob { - json(): Promise; - formData(): Promise; - arrayBuffer(): Promise; - bytes(): Promise; -} - -declare interface ArrayBuffer { - readonly byteLength: number; - resize(byteLength: number): ArrayBuffer; - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; -} - -declare interface SharedArrayBuffer { - grow(size: number): SharedArrayBuffer; -} - -declare interface ImportMeta { - url: string; - readonly path: string; - readonly dir: string; - readonly file: string; - readonly env: NodeJS.ProcessEnv; - resolveSync(moduleId: string, parent?: string): string; - require: NodeJS.Require; - readonly main: boolean; - dirname: string; - filename: string; - hot?: { - data: any; - }; -} - -declare interface NodeModule { - exports: any; -} - -declare interface Headers { - toJSON(): Record; + interface Env { + [key: string]: string | undefined; + } + + export var env: Env; + + export var fetch: { + (request: Request, init?: RequestInit): Promise; + (url: string | URL | Request, init?: RequestInit): Promise; + ( + input: string | URL | globalThis.Request, + init?: RequestInit, + ): Promise; + preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; + }; +} + +interface RequestInit { + verbose?: boolean; + proxy?: string; + s3?: import("bun").S3Options; +} + +declare namespace fetch { + export function preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; +} + +interface ImportMeta { + url: string; + readonly path: string; + readonly dir: string; + readonly file: string; + readonly env: NodeJS.ProcessEnv; + resolveSync(moduleId: string, parent?: string): string; + require: NodeJS.Require; + readonly main: boolean; + dirname: string; + filename: string; + + hot?: { + data: any; + }; +} + +interface Headers { + toJSON(): Record; } declare namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - isBun: true; - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - - interface ProcessVersions extends Dict { - bun: string; - } - - interface ProcessEnv extends Env {} -} - -declare namespace WebAssembly { - interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} - interface GlobalDescriptor - extends Bun.WebAssembly.GlobalDescriptor {} - interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} - interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} - interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} - interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} - interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} - - interface LinkError extends Error {} - var LinkError: { - prototype: LinkError; - new (message?: string): LinkError; - (message?: string): LinkError; - }; - - interface CompileError extends Error {} - var CompileError: { - prototype: CompileError; - new (message?: string): CompileError; - (message?: string): CompileError; - }; - - interface RuntimeError extends Error {} - var RuntimeError: { - prototype: RuntimeError; - new (message?: string): RuntimeError; - (message?: string): RuntimeError; - }; - - interface Global { - value: ValueTypeMap[T]; - valueOf(): ValueTypeMap[T]; - } - var Global: { - prototype: Global; - new ( - descriptor: GlobalDescriptor, - v?: ValueTypeMap[T], - ): Global; - }; - - interface Instance { - readonly exports: Bun.WebAssembly.Exports; - } - var Instance: { - prototype: Instance; - new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; - }; - - interface Memory { - readonly buffer: ArrayBuffer; - grow(delta: number): number; - } - var Memory: { - prototype: Memory; - new (descriptor: MemoryDescriptor): Memory; - }; - - interface Module {} - var Module: { - prototype: Module; - new (bytes: Bun.BufferSource): Module; - customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; - exports(moduleObject: Module): ModuleExportDescriptor[]; - imports(moduleObject: Module): ModuleImportDescriptor[]; - }; - - interface Table { - readonly length: number; - get(index: number): any; - grow(delta: number, value?: any): number; - set(index: number, value?: any): void; - } - var Table: { - prototype: Table; - new (descriptor: TableDescriptor, value?: any): Table; - }; - - function compile(bytes: Bun.BufferSource): Promise; - function compileStreaming(source: Response | PromiseLike): Promise; - function instantiate( - bytes: Bun.BufferSource, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; - function instantiateStreaming( - source: Response | PromiseLike, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - function validate(bytes: Bun.BufferSource): boolean; -} - -declare interface Dict { - [key: string]: T | undefined; -} - -declare interface ReadOnlyDict { - readonly [key: string]: T | undefined; -} - -declare interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; -} - -declare interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; -} - -declare var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; -}; - -declare interface PromiseConstructor { - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; -} + interface Process { + readonly version: string; + browser: boolean; + isBun: true; + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } -declare interface ArrayConstructor { - fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; + interface ProcessVersions extends Dict { + bun: string; + } } declare module "*.svg" { - const content: `${string}.svg`; - export = content; + const content: `${string}.svg`; + export = content; } diff --git a/packages/bun-types/new/s3.d.ts b/packages/bun-types/new/s3.d.ts new file mode 100644 index 00000000000000..31591aca89dca7 --- /dev/null +++ b/packages/bun-types/new/s3.d.ts @@ -0,0 +1,204 @@ +declare module "bun" { + interface S3Options extends BlobPropertyBag { + /** + * The Access Control List (ACL) policy for the file. + * Controls who can access the file and what permissions they have. + * + * @example + * // Setting public read access + * const file = s3("public-file.txt", { + * acl: "public-read", + * bucket: "my-bucket" + * }); + * + * @example + * // Using with presigned URLs + * const url = file.presign({ + * acl: "public-read", + * expiresIn: 3600 + * }); + */ + acl?: + | "private" + | "public-read" + | "public-read-write" + | "aws-exec-read" + | "authenticated-read" + | "bucket-owner-read" + | "bucket-owner-full-control" + | "log-delivery-write"; + + /** + * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. + * + * @example + * // Using explicit bucket + * const file = s3("my-file.txt", { bucket: "my-bucket" }); + * + * @example + * // Using environment variables + * // With S3_BUCKET=my-bucket in .env + * const file = s3("my-file.txt"); + */ + bucket?: string; + + /** + * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. + * + * @example + * const file = s3("my-file.txt", { + * bucket: "my-bucket", + * region: "us-west-2" + * }); + */ + region?: string; + + /** + * The access key ID for authentication. + * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. + */ + accessKeyId?: string; + + /** + * The secret access key for authentication. + * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. + */ + secretAccessKey?: string; + + /** + * Optional session token for temporary credentials. + * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. + * + * @example + * // Using temporary credentials + * const file = s3("my-file.txt", { + * accessKeyId: tempAccessKey, + * secretAccessKey: tempSecretKey, + * sessionToken: tempSessionToken + * }); + */ + sessionToken?: string; + + /** + * The S3-compatible service endpoint URL. + * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. + * + * @example + * // AWS S3 + * const file = s3("my-file.txt", { + * endpoint: "https://s3.us-east-1.amazonaws.com" + * }); + * + * @example + * // Cloudflare R2 + * const file = s3("my-file.txt", { + * endpoint: "https://.r2.cloudflarestorage.com" + * }); + * + * @example + * // DigitalOcean Spaces + * const file = s3("my-file.txt", { + * endpoint: "https://.digitaloceanspaces.com" + * }); + * + * @example + * // MinIO (local development) + * const file = s3("my-file.txt", { + * endpoint: "http://localhost:9000" + * }); + */ + endpoint?: string; + + /** + * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` + * + * @example + * // Using virtual hosted style + * const file = s3("my-file.txt", { + * virtualHostedStyle: true, + * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" + * }); + */ + virtualHostedStyle?: boolean; + + /** + * The size of each part in multipart uploads (in bytes). + * - Minimum: 5 MiB + * - Maximum: 5120 MiB + * - Default: 5 MiB + * + * @example + * // Configuring multipart uploads + * const file = s3("large-file.dat", { + * partSize: 10 * 1024 * 1024, // 10 MiB parts + * queueSize: 4 // Upload 4 parts in parallel + * }); + * + * const writer = file.writer(); + * // ... write large file in chunks + */ + partSize?: number; + + /** + * Number of parts to upload in parallel for multipart uploads. + * - Default: 5 + * - Maximum: 255 + * + * Increasing this value can improve upload speeds for large files + * but will use more memory. + */ + queueSize?: number; + + /** + * Number of retry attempts for failed uploads. + * - Default: 3 + * - Maximum: 255 + * + * @example + * // Setting retry attempts + * const file = s3("my-file.txt", { + * retry: 5 // Retry failed uploads up to 5 times + * }); + */ + retry?: number; + + /** + * The Content-Type of the file. + * Automatically set based on file extension when possible. + * + * @example + * // Setting explicit content type + * const file = s3("data.bin", { + * type: "application/octet-stream" + * }); + */ + type?: string; + + /** + * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. + * + * @example + * // Setting explicit Storage class + * const file = s3("my-file.json", { + * storageClass: "STANDARD_IA" + * }); + */ + storageClass?: + | "STANDARD" + | "DEEP_ARCHIVE" + | "EXPRESS_ONEZONE" + | "GLACIER" + | "GLACIER_IR" + | "INTELLIGENT_TIERING" + | "ONEZONE_IA" + | "OUTPOSTS" + | "REDUCED_REDUNDANCY" + | "SNOW" + | "STANDARD_IA"; + + /** + * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. + */ + highWaterMark?: number; + } +} diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 0689dd87b489f8..9ad92a479353ab 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -21,6 +21,10 @@ fetch("url", { proxy: "", }); +Bun.fetch("", { + proxy: "", +}); + new Bun.$.ShellError(); new Promise(resolve => { @@ -132,7 +136,9 @@ Bun.fetch.preconnect; Bun.fetch("", { proxy: "", - s3: {}, + s3: { + acl: "public-read", + }, }); Bun.serve({ @@ -149,7 +155,7 @@ Bun.serve({ }, }); -import.meta.hot.data; +import.meta.hot?.data; import { serve } from "bun"; From dde397c35175361c89bb2eb936cfdd6585bd2936 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 6 Mar 2025 15:13:08 +0000 Subject: [PATCH 05/72] YES!! --- packages/bun-types/new/bun.d.ts | 7 + packages/bun-types/new/fetch.d.ts | 181 ++++++++++++++++++++ packages/bun-types/new/index.d.ts | 110 +++++------- test/integration/bun-types/fixture/index.ts | 26 +-- 4 files changed, 244 insertions(+), 80 deletions(-) create mode 100644 packages/bun-types/new/bun.d.ts create mode 100644 packages/bun-types/new/fetch.d.ts diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts new file mode 100644 index 00000000000000..2159a7c0e36afe --- /dev/null +++ b/packages/bun-types/new/bun.d.ts @@ -0,0 +1,7 @@ +export {}; + +import * as BunModule from "bun"; + +declare global { + export import Bun = BunModule; +} diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts new file mode 100644 index 00000000000000..b2bf3489c49167 --- /dev/null +++ b/packages/bun-types/new/fetch.d.ts @@ -0,0 +1,181 @@ +interface Headers { + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; +} + +declare var Headers: { + prototype: Headers; + new (init?: Bun.HeadersInit): Headers; +}; + +interface Request { + headers: Headers; +} + +declare var Request: { + prototype: Request; + new (requestInfo: string, requestInit?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, requestInit?: RequestInit): Request; +}; + +declare var Response: { + new ( + body?: Bun.BodyInit | null | undefined, + init?: Bun.ResponseInit | undefined, + ): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, options?: Bun.ResponseInit | number): Response; + + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, status?: number): Response; + + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, options?: Bun.ResponseInit): Response; + + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; +}; + +type _BunTLSOptions = import("bun").TLSOptions; +interface BunFetchRequestInitTLS extends _BunTLSOptions { + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable< + import("node:tls").ConnectionOptions["checkServerIdentity"] + >; +} + +/** + * BunFetchRequestInit represents additional options that Bun supports in `fetch()` only. + * + * Bun extends the `fetch` API with some additional options, except + * this interface is not quite a `RequestInit`, because they won't work + * if passed to `new Request()`. This is why it's a separate type. + */ +interface BunFetchRequestInit extends RequestInit { + /** + * Override the default TLS options + */ + tls?: BunFetchRequestInitTLS; +} + +/** + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch( + request: Request, + init?: BunFetchRequestInit, +): Promise; +/** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch( + url: string | URL | Request, + init?: BunFetchRequestInit, +): Promise; + +/** + * Send a HTTP(s) request + * + * @param input URL string or Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch( + input: string | URL | globalThis.Request, + init?: BunFetchRequestInit, +): Promise; + +declare namespace fetch { + export function preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; +} diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index 52974937249eab..b88755499bd45f 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -1,90 +1,60 @@ +/// + /// +/// +/// declare var onmessage: never; -declare var Bun: typeof import("bun"); - declare module "bun" { - interface Env { - [key: string]: string | undefined; - } + interface Env { + [key: string]: string | undefined; + } - export var env: Env; + export var env: Env; - export var fetch: { - (request: Request, init?: RequestInit): Promise; - (url: string | URL | Request, init?: RequestInit): Promise; - ( - input: string | URL | globalThis.Request, - init?: RequestInit, - ): Promise; - preconnect( - url: string | URL, - options?: { - dns?: boolean; - tcp?: boolean; - http?: boolean; - https?: boolean; - }, - ): void; - }; -} - -interface RequestInit { - verbose?: boolean; - proxy?: string; - s3?: import("bun").S3Options; -} - -declare namespace fetch { - export function preconnect( - url: string | URL, - options?: { - dns?: boolean; - tcp?: boolean; - http?: boolean; - https?: boolean; - }, - ): void; + export var fetch: typeof globalThis.fetch; } interface ImportMeta { - url: string; - readonly path: string; - readonly dir: string; - readonly file: string; - readonly env: NodeJS.ProcessEnv; - resolveSync(moduleId: string, parent?: string): string; - require: NodeJS.Require; - readonly main: boolean; - dirname: string; - filename: string; - - hot?: { - data: any; - }; + url: string; + readonly path: string; + readonly dir: string; + readonly file: string; + readonly env: NodeJS.ProcessEnv; + resolveSync(moduleId: string, parent?: string): string; + require: NodeJS.Require; + readonly main: boolean; + dirname: string; + filename: string; + + hot?: { + data: any; + }; } interface Headers { - toJSON(): Record; + toJSON(): Record; } declare namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - isBun: true; - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - - interface ProcessVersions extends Dict { - bun: string; - } + interface Process { + readonly version: string; + browser: boolean; + isBun: true; + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + + interface ProcessVersions extends Dict { + bun: string; + } } declare module "*.svg" { - const content: `${string}.svg`; - export = content; + const content: `${string}.svg`; + export = content; } + +declare var FormData: FormData; diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 9ad92a479353ab..b2d65d24d44678 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -1,8 +1,14 @@ import svgpath from "cool.svg"; svgpath satisfies `${string}.svg`; +type c = BunFetchRequestInit; + fetch; +const g: BunFetchRequestInit = {}; + +Bun.fetch; + // just some APIs new Request("url"); new Response(); @@ -100,18 +106,18 @@ fetch; fetch.preconnect(new URL("")); -Bun.serve({ - port: 3000, - fetch: () => new Response("ok"), +// Bun.serve({ +// port: 3000, +// fetch: () => new Response("ok"), - key: Bun.file(""), - cert: Bun.file(""), +// key: Bun.file(""), +// cert: Bun.file(""), - tls: { - key: Bun.file(""), - cert: Bun.file(""), - }, -}); +// tls: { +// key: Bun.file(""), +// cert: Bun.file(""), +// }, +// }); URL.canParse; URL.createObjectURL; From b59cbbbf1841853e7ba2fd214a80a8c99c1b91ac Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 03:52:07 +0000 Subject: [PATCH 06/72] fixes --- packages/bun-types/bun.d.ts | 121 - packages/bun-types/new/bun.d.ts | 6920 ++++++++++++++++- packages/bun-types/new/extensions.d.ts | 4 + packages/bun-types/new/fetch.d.ts | 16 +- packages/bun-types/new/globals.d.ts | 5 + packages/bun-types/new/index.d.ts | 60 +- packages/bun-types/new/s3.d.ts | 549 ++ packages/bun-types/new/sink.d.ts | 86 + test/integration/bun-types/fixture/bun.lock | 4 +- test/integration/bun-types/fixture/index.ts | 17 +- .../bun-types/fixture/package.json | 2 +- 11 files changed, 7594 insertions(+), 190 deletions(-) create mode 100644 packages/bun-types/new/extensions.d.ts create mode 100644 packages/bun-types/new/globals.d.ts create mode 100644 packages/bun-types/new/sink.d.ts diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index fd9d4cc27d5e92..80447cb4033ed4 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -1045,67 +1045,6 @@ declare module "bun" { 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; - /** - * Close the file descriptor. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; - - 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. @@ -1234,32 +1173,6 @@ declare module "bun" { */ stat(): Promise; } - interface NetworkSink extends FileSink { - /** - * Write a chunk of data to the network. - * - * If the network is not writable yet, the data is buffered. - */ - write( - chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - ): number; - /** - * Flush the internal buffer, committing the data to the network. - */ - flush(): number | Promise; - /** - * Finish the upload. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; - - /** - * Get the stat of the file. - */ - stat(): Promise; - } - - var S3Client: S3Client; - var s3: S3Client; /** * Configuration options for S3 operations @@ -1827,40 +1740,6 @@ declare module "bun" { * await bucket.unlink("old.txt"); */ type S3Client = { - /** - * Create a new instance of an S3 bucket so that credentials can be managed - * from a single instance instead of being passed to every method. - * - * @param options The default options to use for the S3 client. Can be - * overriden by passing options to the methods. - * - * ## Keep S3 credentials in a single instance - * - * @example - * const bucket = new Bun.S3Client({ - * accessKeyId: "your-access-key", - * secretAccessKey: "your-secret-key", - * bucket: "my-bucket", - * endpoint: "https://s3.us-east-1.amazonaws.com", - * sessionToken: "your-session-token", - * }); - * - * // S3Client is callable, so you can do this: - * const file = bucket.file("my-file.txt"); - * - * // or this: - * await file.write("Hello Bun!"); - * await file.text(); - * - * // To delete the file: - * await bucket.delete("my-file.txt"); - * - * // To write a file without returning the instance: - * await bucket.write("my-file.txt", "Hello Bun!"); - * - */ - new (options?: S3Options): S3Client; - /** * Creates an S3File instance for the given path. * diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 2159a7c0e36afe..4c2024fafed8f2 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -1,7 +1,6919 @@ -export {}; +/** + * 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 extends T ? Omit : never; + type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; -import * as BunModule from "bun"; + export interface BlobPropertyBag { + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; + } -declare global { - export import Bun = BunModule; + 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; + + type ShellFunction = (input: Uint8Array) => Uint8Array; + + type ShellExpression = + | { toString(): string } + | Array + | string + | { raw: string } + | Subprocess + | SpawnOptions.Readable + | SpawnOptions.Writable + | ReadableStream; + + class ShellPromise extends Promise { + 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 | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + } + + namespace Shell { + export class ShellError extends Error { + 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; + + bytes(): Uint8Array; + } + } + + 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): 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; + + /** + * 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; + + /** + * 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 | 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; + + /** + * 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; + + /** + * 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: 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; + + /** + * 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; + + /** + * 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: 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; + + 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, + maxLength?: number, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + maxLength: number, + asUint8Array: false, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + 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, + ): Promise | 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, + ): Promise | 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; + + /** + * 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, + multipartBoundaryExcludingDashes?: + | string + | NodeJS.TypedArray + | ArrayBufferView, + ): Promise; + + /** + * 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; + + /** + * 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; + + /** + * 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( + stream: ReadableStream, + ): Promise | T[]; + + /** + * Escape the following characters in a string: + * + * - `"` 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. + * + * @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 { + (promise: T | Promise): Promise | T; + status( + promise: T | Promise, + ): "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; + + /** + * + * **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; + }; + + ADDRCONFIG: number; + ALL: number; + 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 + * + * @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 { + /**.p + * 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; + + /** + * 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; + + /** + * Deletes the file. + */ + unlink(): Promise; + + /** + * Deletes the file. ( same as unlink ) + */ + delete(): Promise; + + /** + * Provides useful information about the file. + */ + stat(): Promise; + } + + /** + * Configuration options for SQL client connection and behavior + * @example + * const config: SQLOptions = { + * host: 'localhost', + * port: 5432, + * user: 'dbuser', + * password: 'secretpass', + * database: 'myapp', + * idleTimeout: 30000, + * max: 20, + * onconnect: (client) => { + * console.log('Connected to database'); + * } + * }; + */ + type 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); + /** Database password for authentication (alias for password) */ + pass?: string | (() => Promise); + /** 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 extends Promise { + /** Indicates if the query is currently executing */ + active: boolean; + /** Indicates if the query has been cancelled */ + cancelled: boolean; + /** Cancels the executing query */ + cancel(): SQLQuery; + /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ + simple(): SQLQuery; + /** Executes the query */ + execute(): SQLQuery; + /** Returns the raw query result */ + raw(): SQLQuery; + /** Returns only the values from the query result */ + values(): SQLQuery; + } + + /** + * Callback function type for transaction contexts + * @param sql Function to execute SQL queries within the transaction + */ + type SQLTransactionContextCallback = ( + sql: TransactionSQL, + ) => Promise | Array; + /** + * Callback function type for savepoint contexts + * @param sql Function to execute SQL queries within the savepoint + */ + type SQLSavepointContextCallback = ( + sql: SavepointSQL, + ) => Promise | Array; + + /** + * Main SQL client interface providing connection and transaction management + */ + interface SQL { + /** Creates a new SQL client instance + * @example + * const sql = new SQL("postgres://localhost:5432/mydb"); + * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); + */ + new (connectionString: string | URL): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); + */ + new (connectionString: string | URL, options: SQLOptions): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); + */ + new (options?: SQLOptions): SQL; + /** Executes a SQL query using template literals + * @example + * const [user] = await sql`select * from users where id = ${1}`; + */ + (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; + /** + * Helper function to allow easy use to insert values into a query + * @example + * const result = await sql`insert into users ${sql(users)} RETURNING *`; + */ + (obj: any): SQLQuery; + /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.commitDistributed("my_distributed_transaction"); + */ + commitDistributed(name: string): Promise; + /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.rollbackDistributed("my_distributed_transaction"); + */ + rollbackDistributed(name: string): Promise; + /** Waits for the database connection to be established + * @example + * await sql.connect(); + */ + connect(): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @example + * await sql.close({ timeout: 1 }); + */ + close(options?: { timeout?: number }): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @alias close + * @example + * await sql.end({ timeout: 1 }); + */ + end(options?: { timeout?: number }): Promise; + /** Flushes any pending operations */ + flush(): void; + /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. + * This can be used for running queries on an isolated connection. + * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). + * @example + * const reserved = await sql.reserve(); + * await reserved`select * from users`; + * await reserved.release(); + * // with in a production scenario would be something more like + * const reserved = await sql.reserve(); + * try { + * // ... queries + * } finally { + * await reserved.release(); + * } + * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose + * { + * // always release after context (safer) + * using reserved = await sql.reserve() + * await reserved`select * from users` + * } + */ + reserve(): Promise; + /** Begins a new transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(fn: SQLTransactionContextCallback): Promise; + /** Begins a new transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(options: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction( + options: string, + fn: SQLTransactionContextCallback, + ): Promise; + /** Begins a distributed transaction + * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. + * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. + * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. + * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. + * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. + * @example + * await sql.beginDistributed("numbers", async sql => { + * await sql`create table if not exists numbers (a int)`; + * await sql`insert into numbers values(1)`; + * }); + * // later you can call + * await sql.commitDistributed("numbers"); + * // or await sql.rollbackDistributed("numbers"); + */ + beginDistributed( + name: string, + fn: SQLTransactionContextCallback, + ): Promise; + /** Alternative method to begin a distributed transaction + * @alias beginDistributed + */ + distributed(name: string, fn: SQLTransactionContextCallback): Promise; + /**If you know what you're doing, you can use unsafe to pass any string you'd like. + * Please note that this can lead to SQL injection if you're not careful. + * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. + * @example + * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) + */ + unsafe(string: string, values?: any[]): SQLQuery; + /** + * Reads a file and uses the contents as a query. + * Optional parameters can be used if the file includes $1, $2, etc + * @example + * const result = await sql.file("query.sql", [1, 2, 3]); + */ + file(filename: string, values?: any[]): SQLQuery; + + /** Current client options */ + options: SQLOptions; + + [Symbol.asyncDispose](): Promise; + } + + /** + * Represents a reserved connection from the connection pool + * Extends SQL with additional release functionality + */ + interface ReservedSQL extends SQL { + /** Releases the client back to the connection pool */ + release(): void; + [Symbol.dispose](): void; + } + + /** + * Represents a client within a transaction context + * Extends SQL with savepoint functionality + */ + interface TransactionSQL extends SQL { + /** Creates a savepoint within the current transaction */ + savepoint(name: string, fn: SQLSavepointContextCallback): Promise; + savepoint(fn: SQLSavepointContextCallback): Promise; + } + /** + * Represents a savepoint within a transaction + */ + interface SavepointSQL extends SQL {} + + var sql: SQL; + var postgres: SQL; + var SQL: SQL; + + /** + * This lets you use macros as regular imports + * @example + * ``` + * { + * "react-relay": { + * "graphql": "bun-macro-relay/bun-macro-relay.tsx" + * } + * } + * ``` + */ + type MacroMap = Record>; + + /** + * 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; + } + + 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; + 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; + + /** 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; + }; + 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 = () =>
Hello World
; + * 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; + /** + * 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-run" + | "entry-point-build"; + + interface Import { + path: string; + kind: ImportKind; + } + + /** + * @see [Bun.build API docs](https://bun.sh/docs/bundler#api) + */ + interface BuildConfig { + entrypoints: string[]; // list of file path + outdir?: string; // output directory + /** + * @default "browser" + */ + 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; + // origin?: string; // e.g. http://mydomain.com + loader?: { [k in string]: Loader }; + /** + * Specifies if and how to generate source maps. + * + * - `"none"` - No source maps are generated + * - `"linked"` - A separate `*.ext.map` file is generated alongside each + * `*.ext` file. A `//# sourceMappingURL` comment is added to the output + * file to link the two. Requires `outdir` to be set. + * - `"inline"` - an inline source map is appended to the output file. + * - `"external"` - Generate a separate source map file for each input file. + * No `//# sourceMappingURL` comment is added to the output file. + * + * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. + * + * @default "none" + * + * @see {@link outdir} required for `"linked"` maps + * @see {@link publicPath} to customize the base url of linked source maps + */ + sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; + /** + * 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; + + /** + * Controls how environment variables are handled during bundling. + * + * Can be one of: + * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` + * references to string literals containing the actual environment variable values + * - `"disable"`: Disables environment variable injection entirely + * - A string ending in `*`: Inlines environment variables that match the given prefix. + * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" + * + * @example + * ```ts + * Bun.build({ + * env: "MY_PUBLIC_*", + * entrypoints: ["src/index.ts"], + * }) + * ``` + */ + env?: "inline" | "disable" | `${string}*`; + /** + * Whether to enable minification. + * + * Use `true`/`false` to enable/disable all minification options. Alternatively, + * you can pass an object for granular control over certain minifications. + * + * @default false + */ + 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; + + /** + * Drop function calls to matching property accesses. + */ + drop?: string[]; + + /** + * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. + * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. + * This defaults to `true`. + */ + throw?: boolean; + } + + 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 password. + * If empty, always returns false + */ + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + * + * If specified and the algorithm does not match the hash, this function + * throws an error. + */ + algorithm?: Password.AlgorithmLabel, + ): Promise; + /** + * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. + * + * @returns A promise that resolves to the hashed password + * + * ## Example with argon2 + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world"); + * console.log(hash); // $argon2id$v=1... + * const verify = await password.verify("hello world", hash); + * ``` + * ## Example with bcrypt + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world", "bcrypt"); + * console.log(hash); // $2b$10$... + * const verify = await password.verify("hello world", hash); + * ``` + */ + hash( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before + */ + algorithm?: + | Password.AlgorithmLabel + | Password.Argon2Algorithm + | Password.BCryptAlgorithm, + ): Promise; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.verify} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + verifySync( + password: Bun.StringOrBuffer, + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + */ + algorithm?: Password.AlgorithmLabel, + ): boolean; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.hash} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + hashSync( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before + */ + algorithm?: + | Password.AlgorithmLabel + | Password.Argon2Algorithm + | Password.BCryptAlgorithm, + ): string; + }; + + interface BuildArtifact extends Blob { + path: string; + loader: Loader; + hash: string | null; + kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; + sourcemap: BuildArtifact | null; + } + + interface BuildOutput { + outputs: BuildArtifact[]; + success: boolean; + logs: Array; + } + + /** + * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. + * + * @param {Object} config - Build configuration options + * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status + * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) + * + * @example Basic usage - Bundle a single entrypoint and check results + ```ts + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist' + }); + + if (!result.success) { + console.error('Build failed:', result.logs); + process.exit(1); + } + ``` + * + * @example Set up multiple entrypoints with code splitting enabled + ```ts + await Bun.build({ + entrypoints: ['./src/app.tsx', './src/admin.tsx'], + outdir: './dist', + splitting: true, + sourcemap: "external" + }); + ``` + * + * @example Configure minification and optimization settings + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + minify: { + whitespace: true, + identifiers: true, + syntax: true + }, + drop: ['console', 'debugger'] + }); + ``` + * + * @example Set up custom loaders and mark packages as external + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + loader: { + '.png': 'dataurl', + '.svg': 'file', + '.txt': 'text', + '.json': 'json' + }, + external: ['react', 'react-dom'] + }); + ``` + * + * @example Configure environment variable handling with different modes + ```ts + // Inline all environment variables + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + env: 'inline' + }); + + // Only include specific env vars + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + env: 'PUBLIC_*' + }); + ``` + * + * @example Set up custom naming patterns for all output types + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + naming: { + entry: '[dir]/[name]-[hash].[ext]', + chunk: 'chunks/[name]-[hash].[ext]', + asset: 'assets/[name]-[hash].[ext]' + } + }); + ``` + @example Work with build artifacts in different formats + ```ts + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'] + }); + + for (const artifact of result.outputs) { + const text = await artifact.text(); + const buffer = await artifact.arrayBuffer(); + const bytes = await artifact.bytes(); + + new Response(artifact); + await Bun.write(artifact.path, artifact); + } + ``` + @example Implement comprehensive error handling with position info + ```ts + try { + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'], + }); + } catch (e) { + const error = e as AggregateError; + console.error('Build failed:'); + for (const msg of error.errors) { + if ('position' in msg) { + console.error( + `${msg.message} at ${msg.position?.file}:${msg.position?.line}:${msg.position?.column}` + ); + } else { + console.error(msg.message); + } + } + } + ``` + @example Set up Node.js target with specific configurations + ```ts + await Bun.build({ + entrypoints: ['./src/server.ts'], + outdir: './dist', + target: 'node', + format: 'cjs', + sourcemap: 'external', + minify: false, + packages: 'external' + }); + ``` + * + * @example Configure experimental CSS bundling with multiple themes + ```ts + await Bun.build({ + entrypoints: [ + './src/styles.css', + './src/themes/dark.css', + './src/themes/light.css' + ], + outdir: './dist/css', + }); + ``` + @example Define compile-time constants and version information + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + define: { + 'process.env.NODE_ENV': JSON.stringify('production'), + 'CONSTANTS.VERSION': JSON.stringify('1.0.0'), + 'CONSTANTS.BUILD_TIME': JSON.stringify(new Date().toISOString()) + } + }); + ``` + @example Create a custom plugin for handling special file types + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + plugins: [ + { + name: 'my-plugin', + setup(build) { + build.onLoad({ filter: /\.custom$/ }, async (args) => { + const content = await Bun.file(args.path).text(); + return { + contents: `export default ${JSON.stringify(content)}`, + loader: 'js' + }; + }); + } + } + ] + }); + ``` + @example Enable bytecode generation for faster startup + ```ts + await Bun.build({ + entrypoints: ['./src/server.ts'], + outdir: './dist', + target: 'bun', + format: 'cjs', + bytecode: true + }); + ``` + @example Add custom banner and footer to output files + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + banner: '"use client";\n// Built with Bun', + footer: '// Generated on ' + new Date().toISOString() + }); + ``` + @example Configure CDN public path for asset loading + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + publicPath: 'https://cdn.example.com/assets/', + loader: { + '.png': 'file', + '.svg': 'file' + } + }); + ``` + @example Set up package export conditions for different environments + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + conditions: ['production', 'browser', 'module'], + packages: 'external' + }); + ``` + */ + function build(config: BuildConfig): Promise; + /** + * A status that represents the outcome of a sent message. + * + * - if **0**, the message was **dropped**. + * - if **-1**, there is **backpressure** of messages. + * - if **>0**, it represents the **number of bytes sent**. + * + * @example + * ```js + * const status = ws.send("Hello!"); + * if (status === 0) { + * console.log("Message was dropped"); + * } else if (status === -1) { + * console.log("Backpressure was applied"); + * } else { + * console.log(`Success! Sent ${status} bytes`); + * } + * ``` + */ + type ServerWebSocketSendStatus = number; + + /** + * A state that represents if a WebSocket is connected. + * + * - `WebSocket.CONNECTING` is `0`, the connection is pending. + * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. + * - `WebSocket.CLOSING` is `2`, the connection is closing. + * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState + */ + type WebSocketReadyState = 0 | 1 | 2 | 3; + + /** + * A fast WebSocket designed for servers. + * + * Features: + * - **Message compression** - Messages can be compressed + * - **Backpressure** - If the client is not ready to receive data, the server will tell you. + * - **Dropped messages** - If the client cannot receive data, the server will tell you. + * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics + * + * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. + * + * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). + * + * @example + * import { serve } from "bun"; + * + * serve({ + * websocket: { + * open(ws) { + * console.log("Connected", ws.remoteAddress); + * }, + * message(ws, data) { + * console.log("Received", data); + * ws.send(data); + * }, + * close(ws, code, reason) { + * console.log("Disconnected", code, reason); + * }, + * } + * }); + */ + interface ServerWebSocket { + /** + * Sends a message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + * ws.send(new Uint8Array([1, 2, 3, 4])); + */ + send( + data: string | BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a text message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + */ + sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send(new TextEncoder().encode("Hello!")); + * ws.send(new Uint8Array([1, 2, 3, 4]), true); + */ + sendBinary( + data: BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Closes the connection. + * + * Here is a list of close codes: + * - `1000` means "normal closure" **(default)** + * - `1009` means a message was too big and was rejected + * - `1011` means the server encountered an error + * - `1012` means the server is restarting + * - `1013` means the server is too busy or the client is rate-limited + * - `4000` through `4999` are reserved for applications (you can use it!) + * + * To close the connection abruptly, use `terminate()`. + * + * @param code The close code to send + * @param reason The close reason to send + */ + close(code?: number, reason?: string): void; + + /** + * Abruptly close the connection. + * + * To gracefully close the connection, use `close()`. + */ + terminate(): void; + + /** + * Sends a ping. + * + * @param data The data to send + */ + ping(data?: string | BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a pong. + * + * @param data The data to send + */ + pong(data?: string | BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); + */ + publish( + topic: string, + data: string | BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a text message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + */ + publishText( + topic: string, + data: string, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Sends a binary message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", new TextEncoder().encode("Hello!")); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); + */ + publishBinary( + topic: string, + data: BufferSource, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Subscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + */ + subscribe(topic: string): void; + + /** + * Unsubscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.unsubscribe("chat"); + */ + unsubscribe(topic: string): void; + + /** + * Is the client subscribed to a topic? + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + * console.log(ws.isSubscribed("chat")); // true + */ + isSubscribed(topic: string): boolean; + + /** + * Batches `send()` and `publish()` operations, which makes it faster to send data. + * + * The `message`, `open`, and `drain` callbacks are automatically corked, so + * you only need to call this if you are sending messages outside of those + * callbacks or in async functions. + * + * @param callback The callback to run. + * @example + * ws.cork((ctx) => { + * ctx.send("These messages"); + * ctx.sendText("are sent"); + * ctx.sendBinary(new TextEncoder().encode("together!")); + * }); + */ + cork(callback: (ws: ServerWebSocket) => T): T; + + /** + * The IP address of the client. + * + * @example + * console.log(socket.remoteAddress); // "127.0.0.1" + */ + readonly remoteAddress: string; + + /** + * The ready state of the client. + * + * - if `0`, the client is connecting. + * - if `1`, the client is connected. + * - if `2`, the client is closing. + * - if `3`, the client is closed. + * + * @example + * console.log(socket.readyState); // 1 + */ + readonly readyState: WebSocketReadyState; + + /** + * Sets how binary data is returned in events. + * + * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** + * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. + * - if `uint8array`, binary data is returned as `Uint8Array` objects. + * + * @example + * let ws: WebSocket; + * ws.binaryType = "uint8array"; + * ws.addEventListener("message", ({ data }) => { + * console.log(data instanceof Uint8Array); // true + * }); + */ + binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; + + /** + * Custom data that you can assign to a client, can be read and written at any time. + * + * @example + * import { serve } from "bun"; + * + * serve({ + * fetch(request, server) { + * const data = { + * accessToken: request.headers.get("Authorization"), + * }; + * if (server.upgrade(request, { data })) { + * return; + * } + * return new Response(); + * }, + * websocket: { + * open(ws) { + * console.log(ws.data.accessToken); + * } + * } + * }); + */ + data: T; + + getBufferedAmount(): number; + } + + /** + * Compression options for WebSocket messages. + */ + type WebSocketCompressor = + | "disable" + | "shared" + | "dedicated" + | "3KB" + | "4KB" + | "8KB" + | "16KB" + | "32KB" + | "64KB" + | "128KB" + | "256KB"; + + /** + * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} + * + * @example + * ```ts + * import { websocket, serve } from "bun"; + * + * serve<{name: string}>({ + * port: 3000, + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log(`${ws.data.name}: ${message}`); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req, { + * data: { + * name: new URL(req.url).searchParams.get("name"), + * }, + * }); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * return; + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + */ + interface WebSocketHandler { + /** + * Called when the server receives an incoming message. + * + * If the message is not a `string`, its type is based on the value of `binaryType`. + * - if `nodebuffer`, then the message is a `Buffer`. + * - if `arraybuffer`, then the message is an `ArrayBuffer`. + * - if `uint8array`, then the message is a `Uint8Array`. + * + * @param ws The websocket that sent the message + * @param message The message received + */ + message( + ws: ServerWebSocket, + message: string | Buffer, + ): void | Promise; + + /** + * Called when a connection is opened. + * + * @param ws The websocket that was opened + */ + open?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection was previously under backpressure, + * meaning it had too many queued messages, but is now ready to receive more data. + * + * @param ws The websocket that is ready for more data + */ + drain?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection is closed. + * + * @param ws The websocket that was closed + * @param code The close code + * @param message The close message + */ + close?( + ws: ServerWebSocket, + code: number, + reason: string, + ): void | Promise; + + /** + * Called when a ping is sent. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + ping?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Called when a pong is received. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + pong?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Sets the maximum size of messages in bytes. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + maxPayloadLength?: number; + + /** + * Sets the maximum number of bytes that can be buffered on a single connection. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + backpressureLimit?: number; + + /** + * Sets if the connection should be closed if `backpressureLimit` is reached. + * + * Default is `false`. + */ + closeOnBackpressureLimit?: boolean; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to no messages or pings. + * + * Default is 2 minutes, or `120` in seconds. + */ + idleTimeout?: number; + + /** + * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? + * + * Default is `false`. + */ + publishToSelf?: boolean; + + /** + * Should the server automatically send and respond to pings to clients? + * + * Default is `true`. + */ + sendPings?: boolean; + + /** + * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. + * + * Default is `false`. + */ + perMessageDeflate?: + | boolean + | { + /** + * Sets the compression level. + */ + compress?: WebSocketCompressor | boolean; + /** + * Sets the decompression level. + */ + decompress?: WebSocketCompressor | boolean; + }; + } + + namespace RouterTypes { + type ExtractRouteParams = + T extends `${string}:${infer Param}/${infer Rest}` + ? { [K in Param]: string } & ExtractRouteParams + : T extends `${string}:${infer Param}` + ? { [K in Param]: string } + : T extends `${string}*` + ? {} + : {}; + + type RouteHandler = ( + req: BunRequest, + server: Server, + ) => Response | Promise; + + type HTTPMethod = + | "GET" + | "POST" + | "PUT" + | "DELETE" + | "PATCH" + | "HEAD" + | "OPTIONS"; + + type RouteHandlerObject = { + [K in HTTPMethod]?: RouteHandler; + }; + + type RouteValue = + | Response + | false + | RouteHandler + | RouteHandlerObject; + } + + interface BunRequest extends Request { + params: RouterTypes.ExtractRouteParams; + } + + interface GenericServeOptions { + /** + * What URI should be used to make {@link Request.url} absolute? + * + * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one + * + * @example + * ```js + * "http://my-app.com" + * ``` + * + * @example + * ```js + * "https://wongmjane.com/" + * ``` + * + * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. + * + * @example + * "http://localhost:3000" + */ + // baseURI?: string; + + /** + * What is the maximum size of a request body? (in bytes) + * @default 1024 * 1024 * 128 // 128MB + */ + maxRequestBodySize?: number; + + /** + * Render contextual errors? This enables bun's error page + * @default process.env.NODE_ENV !== 'production' + */ + development?: + | boolean + | { + /** + * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) + * + * @default true if process.env.NODE_ENV !== 'production' + * + */ + hmr?: boolean; + }; + + error?: ( + this: Server, + error: ErrorLike, + ) => Response | Promise | undefined | Promise; + + /** + * Uniquely identify a server instance with an ID + * + * ### When bun is started with the `--hot` flag + * + * This string will be used to hot reload the server without interrupting + * pending requests or websockets. If not provided, a value will be + * generated. To disable hot reloading, set this value to `null`. + * + * ### When bun is not started with the `--hot` flag + * + * This string will currently do nothing. But in the future it could be useful for logs or metrics. + */ + id?: string | null; + } + + interface ServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * Whether the `SO_REUSEPORT` flag should be set. + * + * This allows multiple processes to bind to the same port, which is useful for load balancing. + * + * @default false + */ + reusePort?: boolean; + + /** + * Whether the `IPV6_V6ONLY` flag should be set. + * @default false + */ + ipv6Only?: boolean; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix?: never; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to inactivity. + * + * Default is `10` seconds. + */ + idleTimeout?: number; + + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | Promise; + } + + interface UnixServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | Promise; + } + + interface WebSocketServeOptions + extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | void | Promise; + } + + interface UnixWebSocketServeOptions + extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | Promise; + } + + interface TLSWebSocketServeOptions + extends WebSocketServeOptions, + TLSOptionsAsDeprecated { + unix?: never; + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSWebSocketServeOptions + extends UnixWebSocketServeOptions, + TLSOptionsAsDeprecated { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + tls?: TLSOptions | TLSOptions[]; + } + + interface ErrorLike extends Error { + code?: string; + errno?: number; + syscall?: string; + } + + interface TLSOptions { + /** + * Passphrase for the TLS key + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + // Note for contributors: TLSOptionsAsDeprecated should be considered immutable + // and new TLS option keys should only be supported on the `.tls` property (which comes + // from the TLSOptions interface above). + /** + * This exists because Bun.serve() extends the TLSOptions object, but + * they're now considered deprecated. You should be passing the + * options on `.tls` instead. + * + * @example + * ```ts + * //// OLD //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * passphrase: "secret", + * }); + * + * //// NEW //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * tls: { + * passphrase: "secret", + * }, + * }); + * ``` + */ + interface TLSOptionsAsDeprecated { + /** + * Passphrase for the TLS key + * + * @deprecated Use `.tls.passphrase` instead + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + * + * @deprecated Use `.tls.dhParamsFile` instead + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + * + * @deprecated Use `.tls.serverName` instead + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + * + * @deprecated Use `.tls.lowMemoryMode` instead + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + * + * @deprecated Use `.tls.rejectUnauthorized` instead + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + * + * @deprecated Use `.tls.requestCert` instead + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + * + * @deprecated Use `.tls.ca` instead + */ + ca?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + * + * @deprecated Use `.tls.cert` instead + */ + cert?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + * + * @deprecated Use `.tls.key` instead + */ + key?: + | string + | Buffer + | BunFile + | Array + | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + * + * @deprecated `Use .tls.secureOptions` instead + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSServeOptions + extends UnixServeOptions, + TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface SocketAddress { + /** + * The IP address of the client. + */ + address: string; + /** + * The port of the client. + */ + port: number; + /** + * The IP family ("IPv4" or "IPv6"). + */ + family: "IPv4" | "IPv6"; + } + + /** + * HTTP & HTTPS Server + * + * To start the server, see {@link serve} + * + * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. + * That means starting a new server allocates about 500 KB of memory. Try to + * avoid starting and stopping the server often (unless it's a new instance of bun). + * + * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. + */ + interface Server extends Disposable { + /** + * Stop listening to prevent new connections from being accepted. + * + * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. + * + * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. + * @default false + */ + stop(closeActiveConnections?: boolean): Promise; + + /** + * Update the `fetch` and `error` handlers without restarting the server. + * + * This is useful if you want to change the behavior of your server without + * restarting it or for hot reloading. + * + * @example + * + * ```js + * // create the server + * const server = Bun.serve({ + * fetch(request) { + * return new Response("Hello World v1") + * } + * }); + * + * // Update the server to return a different response + * server.reload({ + * fetch(request) { + * return new Response("Hello World v2") + * } + * }); + * ``` + * + * Passing other options such as `port` or `hostname` won't do anything. + */ + reload }>( + options: ( + | (Omit & { + routes: R; + fetch?: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | (Omit & { + routes?: never; + fetch: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. + */ + static?: R; + }, + ): Server; + + /** + * Mock the fetch handler for a running server. + * + * This feature is not fully implemented yet. It doesn't normalize URLs + * consistently in all cases and it doesn't yet call the `error` handler + * consistently. This needs to be fixed + */ + fetch(request: Request | string): Response | Promise; + + /** + * Upgrade a {@link Request} to a {@link ServerWebSocket} + * + * @param request The {@link Request} to upgrade + * @param options Pass headers or attach data to the {@link ServerWebSocket} + * + * @returns `true` if the upgrade was successful and `false` if it failed + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * What you pass to `data` is available on the {@link ServerWebSocket.data} property + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + upgrade( + request: Request, + options?: { + /** + * Send any additional headers while upgrading, like cookies + */ + headers?: Bun.HeadersInit; + /** + * This value is passed to the {@link ServerWebSocket.data} property + */ + data?: T; + }, + ): boolean; + + /** + * Send a message to all connected {@link ServerWebSocket} subscribed to a topic + * + * @param topic The topic to publish to + * @param data The data to send + * @param compress Should the data be compressed? Ignored if the client does not support compression. + * + * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. + * + * @example + * + * ```js + * server.publish("chat", "Hello World"); + * ``` + * + * @example + * ```js + * server.publish("chat", new Uint8Array([1, 2, 3, 4])); + * ``` + * + * @example + * ```js + * server.publish("chat", new ArrayBuffer(4), true); + * ``` + * + * @example + * ```js + * server.publish("chat", new DataView(new ArrayBuffer(4))); + * ``` + */ + publish( + topic: string, + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * A count of connections subscribed to a given topic + * + * This operation will loop through each topic internally to get the count. + * + * @param topic the websocket topic to check how many subscribers are connected to + * @returns the number of subscribers + */ + subscriberCount(topic: string): number; + + /** + * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * return new Response(server.requestIP(request)); + * } + * } + * ``` + */ + requestIP(request: Request): SocketAddress | null; + + /** + * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * server.timeout(request, 60); + * await Bun.sleep(30000); + * return new Response("30 seconds have passed"); + * } + * } + * ``` + */ + timeout(request: Request, seconds: number): void; + /** + * Undo a call to {@link Server.unref} + * + * If the Server has already been stopped, this does nothing. + * + * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. + */ + ref(): void; + + /** + * Don't keep the process alive if this server is the only thing left. + * Active connections may continue to keep the process alive. + * + * By default, the server is ref'd. + * + * To prevent new connections from being accepted, use {@link Server.stop} + */ + unref(): void; + + /** + * How many requests are in-flight right now? + */ + readonly pendingRequests: number; + + /** + * How many {@link ServerWebSocket}s are in-flight right now? + */ + readonly pendingWebSockets: number; + + readonly url: URL; + + readonly port: number; + /** + * The hostname the server is listening on. Does not include the port + * @example + * ```js + * "localhost" + * ``` + */ + readonly hostname: string; + /** + * Is the server running in development mode? + * + * In development mode, `Bun.serve()` returns rendered error messages with + * stack traces instead of a generic 500 error. This makes debugging easier, + * but development mode shouldn't be used in production or you will risk + * leaking sensitive information. + */ + readonly development: boolean; + + /** + * An identifier of the server instance + * + * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. + * + * When bun is not started with the `--hot` flag, this ID is currently unused. + */ + readonly id: string; + } + + type Serve = + | ServeOptions + | TLSServeOptions + | UnixServeOptions + | UnixTLSServeOptions + | WebSocketServeOptions + | TLSWebSocketServeOptions + | UnixWebSocketServeOptions + | UnixTLSWebSocketServeOptions; + + /** + Bun.serve provides a high-performance HTTP server with built-in routing support. + It enables both function-based and object-based route handlers with type-safe + parameters and method-specific handling. + + @example Basic Usage + ```ts + Bun.serve({ + port: 3000, + fetch(req) { + return new Response("Hello World"); + } + }); + ``` + + @example Route-based Handlers + ```ts + Bun.serve({ + routes: { + // Static responses + "/": new Response("Home page"), + + // Function handlers with type-safe parameters + "/users/:id": (req) => { + // req.params.id is typed as string + return new Response(`User ${req.params.id}`); + }, + + // Method-specific handlers + "/api/posts": { + GET: () => new Response("Get posts"), + POST: async (req) => { + const body = await req.json(); + return new Response("Created post"); + }, + DELETE: (req) => new Response("Deleted post") + }, + + // Wildcard routes + "/static/*": (req) => { + // Handle any path under /static/ + return new Response("Static file"); + }, + + // Disable route (fall through to fetch handler) + "/api/legacy": false + }, + + // Fallback handler for unmatched routes + fetch(req) { + return new Response("Not Found", { status: 404 }); + } + }); + ``` + + @example Path Parameters + ```ts + Bun.serve({ + routes: { + // Single parameter + "/users/:id": (req: BunRequest<"/users/:id">) => { + return new Response(`User ID: ${req.params.id}`); + }, + + // Multiple parameters + "/posts/:postId/comments/:commentId": ( + req: BunRequest<"/posts/:postId/comments/:commentId"> + ) => { + return new Response(JSON.stringify(req.params)); + // Output: {"postId": "123", "commentId": "456"} + } + } + }); + ``` + + @example Route Precedence + ```ts + // Routes are matched in the following order: + // 1. Exact static routes ("/about") + // 2. Parameter routes ("/users/:id") + // 3. Wildcard routes ("/api/*") + + Bun.serve({ + routes: { + "/api/users": () => new Response("Users list"), + "/api/users/:id": (req) => new Response(`User ${req.params.id}`), + "/api/*": () => new Response("API catchall"), + "/*": () => new Response("Root catchall") + } + }); + ``` + + @example Error Handling + ```ts + Bun.serve({ + routes: { + "/error": () => { + throw new Error("Something went wrong"); + } + }, + error(error) { + // Custom error handler + console.error(error); + return new Response(`Error: ${error.message}`, { + status: 500 + }); + } + }); + ``` + + @example Server Lifecycle + ```ts + const server = Bun.serve({ + // Server config... + }); + + // Update routes at runtime + server.reload({ + routes: { + "/": () => new Response("Updated route") + } + }); + + // Stop the server + server.stop(); + ``` + + @example Development Mode + ```ts + Bun.serve({ + development: true, // Enable hot reloading + routes: { + // Routes will auto-reload on changes + } + }); + ``` + + @example Type-Safe Request Handling + ```ts + type Post = { + id: string; + title: string; + }; + + Bun.serve({ + routes: { + "/api/posts/:id": async ( + req: BunRequest<"/api/posts/:id"> + ) => { + if (req.method === "POST") { + const body: Post = await req.json(); + return Response.json(body); + } + return new Response("Method not allowed", { + status: 405 + }); + } + } + }); + ``` + @param options - Server configuration options + @param options.routes - Route definitions mapping paths to handlers + */ + function serve< + T, + R extends { [K in keyof R]: RouterTypes.RouteValue }, + >( + options: ( + | (DistributedOmit & { + routes: R; + fetch?: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | (DistributedOmit & { + routes?: never; + fetch: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for a while though. + */ + static?: R; + }, + ): Server; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * - `type` is auto-set based on the file extension when possible + * + * @example + * ```js + * const file = Bun.file("./hello.json"); + * console.log(file.type); // "application/json" + * console.log(await file.json()); // { hello: "world" } + * ``` + * + * @example + * ```js + * await Bun.write( + * Bun.file("./hello.txt"), + * "Hello, world!" + * ); + * ``` + * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: string | URL, options?: BlobPropertyBag): BunFile; + + /** + * A list of files embedded into the standalone executable. Lexigraphically sorted by name. + * + * If the process is not a standalone executable, this returns an empty array. + */ + const embeddedFiles: ReadonlyArray; + + /** + * `Blob` that leverages the fastest system calls available to operate on files. + * + * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. + * + * `Blob.size` will not be valid until the contents of the file are read at least once. + * `Blob.type` will have a default set based on the file extension + * + * @example + * ```js + * const file = Bun.file(new TextEncoder.encode("./hello.json")); + * console.log(file.type); // "application/json" + * ``` + * + * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file( + path: ArrayBufferLike | Uint8Array, + options?: BlobPropertyBag, + ): BunFile; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * + * @example + * ```js + * const file = Bun.file(fd); + * ``` + * + * @param fileDescriptor The file descriptor of the file + */ + // tslint:disable-next-line:unified-signatures + function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; + + /** + * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. + * + * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. + */ + function allocUnsafe(size: number): Uint8Array; + + interface BunInspectOptions { + colors?: boolean; + depth?: number; + sorted?: boolean; + compact?: boolean; + } + + /** + * Pretty-print an object the same as {@link console.log} to a `string` + * + * Supports JSX + * + * @param args + */ + function inspect(arg: any, options?: BunInspectOptions): string; + namespace inspect { + /** + * That can be used to declare custom inspect functions. + */ + const custom: typeof import("util").inspect.custom; + + /** + * Pretty-print an object or array as a table + * + * Like {@link console.table}, except it returns a string + */ + function table( + tabularData: object | unknown[], + properties?: string[], + options?: { colors?: boolean }, + ): string; + function table( + tabularData: object | unknown[], + options?: { colors?: boolean }, + ): string; + } + + interface MMapOptions { + /** + * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. + */ + sync?: boolean; + /** + * Allow other processes to see results instantly? + * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. + * @default true + */ + shared?: boolean; + } + /** + * Open a file as a live-updating `Uint8Array` without copying memory + * - Writing to the array writes to the file. + * - Reading from the array reads from the file. + * + * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. + * + * --- + * + * This API inherently has some rough edges: + * - It does not support empty files. It will throw a `SystemError` with `EINVAL` + * - Usage on shared/networked filesystems is discouraged. It will be very slow. + * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. + * + * --- + * + * To close the file, set the array to `null` and it will be garbage collected eventually. + */ + function mmap(path: PathLike, opts?: MMapOptions): Uint8Array; + + /** Write to stdout */ + const stdout: BunFile; + /** Write to stderr */ + const stderr: BunFile; + /** + * Read from stdin + * + * This is read-only + */ + const stdin: BunFile; + + type StringLike = string | { toString(): string }; + + type ColorInput = + | { r: number; g: number; b: number; a?: number } + | [number, number, number] + | [number, number, number, number] + | Uint8Array + | Uint8ClampedArray + | Float32Array + | Float64Array + | string + | number + | { toString(): string }; + + function color( + input: ColorInput, + outputFormat?: /** + * True color ANSI color string, for use in terminals + * @example \x1b[38;2;100;200;200m + */ + | "ansi" + | "ansi-16" + | "ansi-16m" + /** + * 256 color ANSI color string, for use in terminals which don't support true color + * + * Tries to match closest 24-bit color to 256 color palette + */ + | "ansi-256" + /** + * Picks the format that produces the shortest output + */ + | "css" + /** + * Lowercase hex color string without alpha + * @example #ff9800 + */ + | "hex" + /** + * Uppercase hex color string without alpha + * @example #FF9800 + */ + | "HEX" + /** + * @example hsl(35.764706, 1, 0.5) + */ + | "hsl" + /** + * @example lab(0.72732764, 33.938198, -25.311619) + */ + | "lab" + /** + * @example 16750592 + */ + | "number" + /** + * RGB color string without alpha + * @example rgb(255, 152, 0) + */ + | "rgb" + /** + * RGB color string with alpha + * @example rgba(255, 152, 0, 1) + */ + | "rgba", + ): string | null; + + function color( + input: ColorInput, + /** + * An array of numbers representing the RGB color + * @example [100, 200, 200] + */ + outputFormat: "[rgb]", + ): [number, number, number] | null; + function color( + input: ColorInput, + /** + * An array of numbers representing the RGBA color + * @example [100, 200, 200, 255] + */ + outputFormat: "[rgba]", + ): [number, number, number, number] | null; + function color( + input: ColorInput, + /** + * An object representing the RGB color + * @example { r: 100, g: 200, b: 200 } + */ + outputFormat: "{rgb}", + ): { r: number; g: number; b: number } | null; + function color( + input: ColorInput, + /** + * An object representing the RGBA color + * @example { r: 100, g: 200, b: 200, a: 0.5 } + */ + outputFormat: "{rgba}", + ): { r: number; g: number; b: number; a: number } | null; + function color(input: ColorInput, outputFormat: "number"): number | null; + + interface Semver { + /** + * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. + */ + satisfies(version: StringLike, range: StringLike): boolean; + + /** + * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. + * Throws an error if either version is invalid. + */ + order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; + } + var semver: Semver; + + interface Unsafe { + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. + * + * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; + + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` + * + * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + // tslint:disable-next-line:unified-signatures + arrayBufferToString(buffer: Uint16Array): string; + + /** Mock bun's segfault handler. You probably don't want to use this */ + segfault(): void; + + /** + * Force the garbage collector to run extremely often, + * especially inside `bun:test`. + * + * - `0`: default, disable + * - `1`: asynchronously call the garbage collector more often + * - `2`: synchronously call the garbage collector more often. + * + * This is a global setting. It's useful for debugging seemingly random crashes. + * + * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. + * + * @param level + * @returns The previous level + */ + gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; + } + const unsafe: Unsafe; + + type DigestEncoding = + | "utf8" + | "ucs2" + | "utf16le" + | "latin1" + | "ascii" + | "base64" + | "base64url" + | "hex"; + + /** + * Are ANSI colors enabled for stdin and stdout? + * + * Used for {@link console.log} + */ + const enableANSIColors: boolean; + + /** + * What script launched bun? + * + * Absolute file path + * + * @example "/never-gonna-give-you-up.js" + */ + const main: string; + + /** + * Manually trigger the garbage collector + * + * This does two things: + * 1. It tells JavaScriptCore to run the garbage collector + * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. + * + * @param force Synchronously run the garbage collector + */ + function gc(force: boolean): void; + + /** + * JavaScriptCore engine's internal heap snapshot + * + * I don't know how to make this something Chrome or Safari can read. + * + * If you have any ideas, please file an issue https://github.com/oven-sh/bun + */ + interface HeapSnapshot { + /** 2 */ + version: number; + + /** "Inspector" */ + type: string; + + nodes: number[]; + + nodeClassNames: string[]; + edges: number[]; + edgeTypes: string[]; + edgeNames: string[]; + } + + /** + * Returns the number of nanoseconds since the process was started. + * + * This function uses a high-resolution monotonic system timer to provide precise time measurements. + * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), + * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). + * + * Due to this limitation, while the internal counter may continue beyond this point, + * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond + * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but + * with reduced precision, which might affect time calculations and comparisons in long-running applications. + * + * @returns {number} The number of nanoseconds since the process was started, with precise values up to + * Number.MAX_SAFE_INTEGER. + */ + function nanoseconds(): number; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector + */ + function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code + * + * This is a JSON string that can be saved to a file. + * ```ts + * const snapshot = Bun.generateHeapSnapshot("v8"); + * await Bun.write("heap.heapsnapshot", snapshot); + * ``` + */ + function generateHeapSnapshot(format: "v8"): string; + + /** + * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. + */ + function shrink(): void; + + /** + * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` + * + * @param path path to open + */ + function openInEditor(path: string, options?: EditorOptions): void; + + var fetch: typeof globalThis.fetch & { + preconnect(url: string): void; + }; + + interface EditorOptions { + editor?: "vscode" | "subl"; + line?: number; + column?: number; + } + + /** + * This class only exists in types + */ + abstract class CryptoHashInterface { + /** + * Update the hash with data + * + * @param data + */ + update(data: Bun.BlobOrStringOrBuffer): T; + + /** + * Finalize the hash + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash( + input: Bun.BlobOrStringOrBuffer, + hashInto?: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + } + + type SupportedCryptoAlgorithms = + | "blake2b256" + | "blake2b512" + | "md4" + | "md5" + | "ripemd160" + | "sha1" + | "sha224" + | "sha256" + | "sha384" + | "sha512" + | "sha512-224" + | "sha512-256" + | "sha3-224" + | "sha3-256" + | "sha3-384" + | "sha3-512" + | "shake128" + | "shake256"; + + /** + * Hardware-accelerated cryptographic hash functions + * + * Used for `crypto.createHash()` + */ + class CryptoHasher { + /** + * The algorithm chosen to hash the data + */ + readonly algorithm: SupportedCryptoAlgorithms; + + /** + * The length of the output hash in bytes + */ + readonly byteLength: number; + + /** + * Create a new hasher + * + * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms + * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. + */ + constructor( + algorithm: SupportedCryptoAlgorithms, + hmacKey?: string | NodeJS.TypedArray, + ); + + /** + * Update the hash with data + * + * @param input + */ + update( + input: Bun.BlobOrStringOrBuffer, + inputEncoding?: import("crypto").CryptoEncoding, + ): CryptoHasher; + + /** + * Perform a deep copy of the hasher + */ + copy(): CryptoHasher; + + /** + * Finalize the hash. Resets the CryptoHasher so it can be reused. + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(): Buffer; + digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + ): Buffer; + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + hashInto: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + + /** + * List of supported hash algorithms + * + * These are hardware accelerated with BoringSSL + */ + static readonly algorithms: SupportedCryptoAlgorithms[]; + } + + /** + * Resolve a `Promise` after milliseconds. This is like + * {@link setTimeout} except it returns a `Promise`. + * + * @param ms milliseconds to delay resolving the promise. This is a minimum + * number. It may take longer. If a {@link Date} is passed, it will sleep until the + * {@link Date} is reached. + * + * @example + * ## Sleep for 1 second + * ```ts + * import { sleep } from "bun"; + * + * await sleep(1000); + * ``` + * ## Sleep for 10 milliseconds + * ```ts + * await Bun.sleep(10); + * ``` + * ## Sleep until `Date` + * + * ```ts + * const target = new Date(); + * target.setSeconds(target.getSeconds() + 1); + * await Bun.sleep(target); + * ``` + * Internally, `Bun.sleep` is the equivalent of + * ```ts + * await new Promise((resolve) => setTimeout(resolve, ms)); + * ``` + * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. + */ + function sleep(ms: number | Date): Promise; + + /** + * Sleep the thread for a given number of milliseconds + * + * This is a blocking function. + * + * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) + */ + function sleepSync(ms: number): void; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha( + input: Bun.StringOrBuffer, + hashInto?: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param encoding `DigestEncoding` to return the hash in + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; + + /** + * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} + * + * Consider using the ugly-named {@link SHA512_256} instead + */ + class SHA1 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 20; + } + class MD5 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class MD4 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class SHA224 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 28; + } + class SHA512 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 64; + } + class SHA384 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 48; + } + class SHA256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + /** + * See also {@link sha} + */ + class SHA512_256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + + /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ + interface ZlibCompressionOptions { + /** + * The compression level to use. Must be between `-1` and `9`. + * - A value of `-1` uses the default compression level (Currently `6`) + * - A value of `0` gives no compression + * - A value of `1` gives least compression, fastest speed + * - A value of `9` gives best compression, slowest speed + */ + level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * How much memory should be allocated for the internal compression state. + * + * A value of `1` uses minimum memory but is slow and reduces compression ratio. + * + * A value of `9` uses maximum memory for optimal speed. The default is `8`. + */ + memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * The base 2 logarithm of the window size (the size of the history buffer). + * + * Larger values of this parameter result in better compression at the expense of memory usage. + * + * The following value ranges are supported: + * - `9..15`: The output will have a zlib header and footer (Deflate) + * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) + * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) + * + * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. + */ + windowBits?: + | -9 + | -10 + | -11 + | -12 + | -13 + | -14 + | -15 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 25 + | 26 + | 27 + | 28 + | 29 + | 30 + | 31; + /** + * Tunes the compression algorithm. + * + * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** + * - `Z_FILTERED`: For data produced by a filter or predictor + * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) + * - `Z_RLE`: Limit match distances to one (run-length encoding) + * - `Z_FIXED` prevents the use of dynamic Huffman codes + * + * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. + * + * `Z_FILTERED` forces more Huffman coding and less string matching, it is + * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. + * Filtered data consists mostly of small values with a somewhat random distribution. + */ + strategy?: number; + + library?: "zlib"; + } + + interface LibdeflateCompressionOptions { + level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; + library?: "libdeflate"; + } + + /** + * Compresses a chunk of data with `zlib` DEFLATE algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function deflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Compresses a chunk of data with `zlib` GZIP algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function gzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` INFLATE algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function inflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` GUNZIP algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function gunzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + + type Target = + /** + * For generating bundles that are intended to be run by the Bun runtime. In many cases, + * it isn't necessary to bundle server-side code; you can directly execute the source code + * without modification. However, bundling your server code can reduce startup times and + * improve running performance. + * + * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which + * indicates to the Bun runtime that there's no need to re-transpile the file before execution. + */ + | "bun" + /** + * The plugin will be applied to Node.js builds + */ + | "node" + /** + * The plugin will be applied to browser builds + */ + | "browser"; + + /** https://bun.sh/docs/bundler/loaders */ + type Loader = + | "js" + | "jsx" + | "ts" + | "tsx" + | "json" + | "toml" + | "file" + | "napi" + | "wasm" + | "text" + | "css" + | "html"; + + interface PluginConstraints { + /** + * Only apply the plugin when the import specifier matches this regular expression + * + * @example + * ```ts + * // Only apply the plugin when the import specifier matches the regex + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { + * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; + * }); + * } + * }) + * ``` + */ + filter: RegExp; + + /** + * Only apply the plugin when the import specifier has a namespace matching + * this string + * + * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` + * has the namespace `"bun"`. + * + * The default namespace is `"file"` and it can be omitted from import + * specifiers. + */ + namespace?: string; + } + + interface OnLoadResultSourceCode { + /** + * The source code of the module + */ + contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; + /** + * The loader to use for this file + * + * "css" will be added in a future version of Bun. + */ + loader?: Loader; + } + + interface OnLoadResultObject { + /** + * The object to use as the module + * @example + * ```ts + * // In your loader + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * + * // In your script + * import {foo} from "hello:world"; + * console.log(foo); // "bar" + * ``` + */ + exports: Record; + /** + * The loader to use for this file + */ + loader: "object"; + } + + interface OnLoadArgs { + /** + * The resolved import specifier of the module being loaded + * @example + * ```ts + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * console.log(args.path); // "hello:world" + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * ``` + */ + path: string; + /** + * The namespace of the module being loaded + */ + namespace: string; + /** + * The default loader for this file extension + */ + loader: Loader; + /** + * Defer the execution of this callback until all other modules have been parsed. + * + * @returns Promise which will be resolved when all modules have been parsed + */ + defer: () => Promise; + } + + type OnLoadResult = + | OnLoadResultSourceCode + | OnLoadResultObject + | undefined + | void; + type OnLoadCallback = ( + args: OnLoadArgs, + ) => OnLoadResult | Promise; + type OnStartCallback = () => void | Promise; + + interface OnResolveArgs { + /** + * The import specifier of the module being loaded + */ + path: string; + /** + * The module that imported the module being resolved + */ + importer: string; + /** + * The namespace of the importer. + */ + namespace: string; + /** + * The directory to perform file-based resolutions in. + */ + resolveDir: string; + /** + * The kind of import this resolve is for. + */ + kind: ImportKind; + // resolveDir: string; + // pluginData: any; + } + + interface OnResolveResult { + /** + * The destination of the import + */ + path: string; + /** + * The namespace of the destination + * It will be concatenated with `path` to form the final import specifier + * @example + * ```ts + * "foo" // "foo:bar" + * ``` + */ + namespace?: string; + external?: boolean; + } + + type OnResolveCallback = ( + args: OnResolveArgs, + ) => + | OnResolveResult + | Promise + | undefined + | null; + + type FFIFunctionCallable = Function & { + // Making a nominally typed function so that the user must get it from dlopen + readonly __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol; + }; + + interface PluginBuilder { + /** + * Register a callback which will be invoked when bundling starts. When + * using hot module reloading, this is called at the start of each + * incremental rebuild. + * + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onStart(() => { + * console.log("bundle just started!!") + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onStart(callback: OnStartCallback): this; + onBeforeParse( + constraints: PluginConstraints, + callback: { + napiModule: unknown; + symbol: string; + external?: unknown | undefined; + }, + ): this; + /** + * Register a callback to load imports with a specific import specifier + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; + /** + * Register a callback to resolve imports matching a filter and/or namespace + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onResolve({ filter: /^wat$/ }, (args) => { + * return { path: "/tmp/woah.js" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onResolve( + constraints: PluginConstraints, + callback: OnResolveCallback, + ): this; + /** + * The config object passed to `Bun.build` as is. Can be mutated. + */ + config: BuildConfig & { plugins: BunPlugin[] }; + + /** + * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules + * + * @param specifier The module specifier to register the callback for + * @param callback The function to run when the module is imported or required + * + * ### Example + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.module("hello:world", () => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * + * // sometime later + * const { foo } = await import("hello:world"); + * console.log(foo); // "bar" + * + * // or + * const { foo } = require("hello:world"); + * console.log(foo); // "bar" + * ``` + * + * @returns `this` for method chaining + */ + module( + specifier: string, + callback: () => OnLoadResult | Promise, + ): this; + } + + interface BunPlugin { + /** + * Human-readable name of the plugin + * + * In a future version of Bun, this will be used in error messages. + */ + name: string; + + /** + * The target JavaScript environment the plugin should be applied to. + * - `bun`: The default environment when using `bun run` or `bun` to load a script + * - `browser`: The plugin will be applied to browser builds + * - `node`: The plugin will be applied to Node.js builds + * + * If unspecified, it is assumed that the plugin is compatible with all targets. + * + * This field is not read by {@link Bun.plugin} + */ + target?: Target; + /** + * A function that will be called when the plugin is loaded. + * + * This function may be called in the same tick that it is registered, or it + * may be called later. It could potentially be called multiple times for + * different targets. + */ + setup( + /** + * A builder object that can be used to register plugin hooks + * @example + * ```ts + * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), + * })); + * ``` + */ + build: PluginBuilder, + ): void | Promise; + } + + /** + * Extend Bun's module resolution and loading behavior + * + * Plugins are applied in the order they are defined. + * + * Today, there are two kinds of hooks: + * - `onLoad` lets you return source code or an object that will become the module's exports + * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. + * + * Plugin hooks must define a `filter` RegExp and will only be matched if the + * import specifier contains a "." or a ":". + * + * ES Module resolution semantics mean that plugins may be initialized _after_ + * a module is resolved. You might need to load plugins at the very beginning + * of the application and then use a dynamic import to load the rest of the + * application. A future version of Bun may also support specifying plugins + * via `bunfig.toml`. + * + * @example + * A YAML loader plugin + * + * ```js + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) + * })); + * }); + * + * // You can use require() + * const {foo} = require("./file.yaml"); + * + * // Or import + * await import("./file.yaml"); + * + * ``` + */ + interface BunRegisterPlugin { + (options: T): ReturnType; + + /** + * Deactivate all plugins + * + * This prevents registered plugins from being applied to future builds. + */ + clearAll(): void; + } + + const plugin: BunRegisterPlugin; + + /** + * Is the current global scope the main thread? + */ + const isMainThread: boolean; + + /** + * Used when importing an HTML file at runtime. + * + * @example + * + * ```ts + * import app from "./index.html"; + * ``` + * + * Bun.build support for this isn't imlpemented yet. + */ + interface HTMLBundle { + index: string; + } + + interface Socket extends Disposable { + /** + * Write `data` to the socket + * + * @param data The data to write to the socket + * @param byteOffset The offset in the buffer to start writing from (defaults to 0) + * @param byteLength The number of bytes to write (defaults to the length of the buffer) + * + * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. + * + * This is unbuffered as of Bun v0.2.2. That means individual write() calls + * will be slow. In the future, Bun will buffer writes and flush them at the + * end of the tick, when the event loop is idle, or sooner if the buffer is full. + */ + write( + data: string | BufferSource, + byteOffset?: number, + byteLength?: number, + ): number; + + /** + * The data context for the socket. + */ + data: Data; + + /** + * Like {@link Socket.write} except it includes a TCP FIN packet + * + * Use it to send your last message and close the connection. + */ + end( + data?: string | BufferSource, + byteOffset?: number, + byteLength?: number, + ): number; + + /** + * Close the socket immediately + */ + end(): void; + + /** + * Keep Bun's process alive at least until this socket is closed + * + * After the socket has closed, the socket is unref'd, the process may exit, + * and this becomes a no-op + */ + ref(): void; + + /** + * Set a timeout until the socket automatically closes. + * + * To reset the timeout, call this function again. + * + * When a timeout happens, the `timeout` callback is called and the socket is closed. + */ + timeout(seconds: number): void; + + /** + * Forcefully close the socket. The other end may not receive all data, and + * the socket will be closed immediately. + * + * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to + * `0` and then calls `close(2)`. + */ + terminate(): void; + + /** + * Shutdown writes to a socket + * + * This makes the socket a half-closed socket. It can still receive data. + * + * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally + */ + shutdown(halfClose?: boolean): void; + + readonly readyState: "open" | "closing" | "closed"; + + /** + * Allow Bun's process to exit even if this socket is still open + * + * After the socket has closed, this function does nothing. + */ + unref(): void; + + /** + * Flush any buffered data to the socket + */ + flush(): void; + + /** + * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. + * + * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. + */ + reload(handler: SocketHandler): void; + + /** + * Get the server that created this socket + * + * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. + */ + readonly listener?: SocketListener; + + /** + * Remote IP address connected to the socket + */ + readonly remoteAddress: string; + + /** + * local port connected to the socket + */ + readonly localPort: number; + + /** + * This property is `true` if the peer certificate was signed by one of the CAs + * specified when creating the `Socket` instance, otherwise `false`. + */ + readonly authorized: boolean; + + /** + * String containing the selected ALPN protocol. + * Before a handshake has completed, this value is always null. + * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. + */ + readonly alpnProtocol: string | false | null; + + /** + * Disables TLS renegotiation for this `Socket` instance. Once called, attempts + * to renegotiate will trigger an `error` handler on the `Socket`. + * + * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) + */ + disableRenegotiation(): void; + + /** + * Keying material is used for validations to prevent different kind of attacks in + * network protocols, for example in the specifications of IEEE 802.1X. + * + * Example + * + * ```js + * const keyingMaterial = socket.exportKeyingMaterial( + * 128, + * 'client finished'); + * + * /* + * Example return value of keyingMaterial: + * + * + * ``` + * + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the [IANA Exporter Label + * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context Optionally provide a context. + * @return requested bytes of the keying material + */ + exportKeyingMaterial( + length: number, + label: string, + context: Buffer, + ): Buffer; + + /** + * Returns the reason why the peer's certificate was not been verified. This + * property is set only when `socket.authorized === false`. + */ + getAuthorizationError(): Error | null; + + /** + * Returns an object representing the local certificate. The returned object has + * some properties corresponding to the fields of the certificate. + * + * If there is no local certificate, an empty object will be returned. If the + * socket has been destroyed, `null` will be returned. + */ + getCertificate(): import("tls").PeerCertificate | object | null; + getX509Certificate(): import("node:crypto").X509Certificate | undefined; + + /** + * Returns an object containing information on the negotiated cipher suite. + * + * For example, a TLSv1.2 protocol with AES256-SHA cipher: + * + * ```json + * { + * "name": "AES256-SHA", + * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", + * "version": "SSLv3" + * } + * ``` + * + */ + getCipher(): import("tls").CipherNameAndProtocol; + + /** + * Returns an object representing the type, name, and size of parameter of + * an ephemeral key exchange in `perfect forward secrecy` on a client + * connection. It returns an empty object when the key exchange is not + * ephemeral. As this is only supported on a client socket; `null` is returned + * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. + * + * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. + */ + getEphemeralKeyInfo(): import("tls").EphemeralKeyInfo | object | null; + + /** + * Returns an object representing the peer's certificate. If the peer does not + * provide a certificate, an empty object will be returned. If the socket has been + * destroyed, `null` will be returned. + * + * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's + * certificate. + * @return A certificate object. + */ + getPeerCertificate(): import("tls").PeerCertificate; + getPeerX509Certificate(): import("node:crypto").X509Certificate; + + /** + * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. + * @since v12.11.0 + * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. + */ + getSharedSigalgs(): string[]; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. + */ + getTLSFinishedMessage(): Buffer | undefined; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so + * far. + */ + getTLSPeerFinishedMessage(): Buffer | undefined; + + /** + * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. + * + * It may be useful for debugging. + * + * See `Session Resumption` for more information. + */ + getTLSTicket(): Buffer | undefined; + + /** + * Returns a string containing the negotiated SSL/TLS protocol version of the + * current connection. The value `'unknown'` will be returned for connected + * sockets that have not completed the handshaking process. The value `null` will + * be returned for server sockets or disconnected client sockets. + * + * Protocol versions are: + * + * * `'SSLv3'` + * * `'TLSv1'` + * * `'TLSv1.1'` + * * `'TLSv1.2'` + * * `'TLSv1.3'` + * + */ + getTLSVersion(): string; + + /** + * See `Session Resumption` for more information. + * @return `true` if the session was reused, `false` otherwise. + */ + isSessionReused(): boolean; + + /** + * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. + * Returns `true` if setting the limit succeeded; `false` otherwise. + * + * Smaller fragment sizes decrease the buffering latency on the client: larger + * fragments are buffered by the TLS layer until the entire fragment is received + * and its integrity is verified; large fragments can span multiple roundtrips + * and their processing can be delayed due to packet loss or reordering. However, + * smaller fragments add extra TLS framing bytes and CPU overhead, which may + * decrease overall server throughput. + * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. + */ + setMaxSendFragment(size: number): boolean; + + /** + * Enable/disable the use of Nagle's algorithm. + * Only available for already connected sockets, will return false otherwise + * @param noDelay Default: `true` + * @returns true if is able to setNoDelay and false if it fails. + */ + setNoDelay(noDelay?: boolean): boolean; + + /** + * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. + * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. + * Only available for already connected sockets, will return false otherwise. + * + * Enabling the keep-alive functionality will set the following socket options: + * SO_KEEPALIVE=1 + * TCP_KEEPIDLE=initialDelay + * TCP_KEEPCNT=10 + * TCP_KEEPINTVL=1 + * @param enable Default: `false` + * @param initialDelay Default: `0` + * @returns true if is able to setNoDelay and false if it fails. + */ + setKeepAlive(enable?: boolean, initialDelay?: number): boolean; + + /** + * The number of bytes written to the socket. + */ + readonly bytesWritten: number; + } + + interface SocketListener extends Disposable { + stop(closeActiveConnections?: boolean): void; + ref(): void; + unref(): void; + reload(options: Pick, "socket">): void; + data: Data; + } + interface TCPSocketListener extends SocketListener { + readonly port: number; + readonly hostname: string; + } + interface UnixSocketListener extends SocketListener { + readonly unix: string; + } + + interface TCPSocket extends Socket {} + interface TLSSocket extends Socket {} + + interface BinaryTypeList { + arraybuffer: ArrayBuffer; + buffer: Buffer; + uint8array: Uint8Array; + // TODO: DataView + // dataview: DataView; + } + type BinaryType = keyof BinaryTypeList; + + interface SocketHandler< + Data = unknown, + DataBinaryType extends BinaryType = "buffer", + > { + /** + * Is called when the socket connects, or in case of TLS if no handshake is provided + * this will be called only after handshake + * @param socket + */ + open?(socket: Socket): void | Promise; + close?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + ): void | Promise; + drain?(socket: Socket): void | Promise; + + /** + * When handshake is completed, this functions is called. + * @param socket + * @param success Indicates if the server authorized despite the authorizationError. + * @param authorizationError Certificate Authorization Error or null. + */ + handshake?( + socket: Socket, + success: boolean, + authorizationError: Error | null, + ): void; + + /** + * When the socket has been shutdown from the other end, this function is + * called. This is a TCP FIN packet. + */ + end?(socket: Socket): void | Promise; + + /** + * When the socket fails to be created, this function is called. + * + * The promise returned by `Bun.connect` rejects **after** this function is + * called. + * + * When `connectError` is specified, the rejected promise will not be + * added to the promise rejection queue (so it won't be reported as an + * unhandled promise rejection, since connectError handles it). + * + * When `connectError` is not specified, the rejected promise will be added + * to the promise rejection queue. + */ + connectError?(socket: Socket, error: Error): void | Promise; + + /** + * Called when a message times out. + */ + timeout?(socket: Socket): void | Promise; + /** + * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. + * + * @default "buffer" + * + * @remarks + * This lets you select the desired binary type for the `data` callback. + * It's a small performance optimization to let you avoid creating extra + * ArrayBufferView objects when possible. + * + * Bun originally defaulted to `Uint8Array` but when dealing with network + * data, it's more useful to be able to directly read from the bytes which + * `Buffer` allows. + */ + binaryType?: BinaryType; + } + + interface SocketOptions { + socket: SocketHandler; + data?: Data; + } + // interface TCPSocketOptions extends SocketOptions { + // hostname: string; + // port: number; + // } + + interface TCPSocketListenOptions + extends SocketOptions { + hostname: string; + port: number; + tls?: TLSOptions; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface TCPSocketConnectOptions + extends SocketOptions { + hostname: string; + port: number; + tls?: boolean; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface UnixSocketOptions extends SocketOptions { + tls?: TLSOptions; + unix: string; + } + + interface FdSocketOptions extends SocketOptions { + tls?: TLSOptions; + fd: number; + } + + /** + * Create a TCP client that connects to a server + * + * @param options The options to use when creating the client + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function connect( + options: TCPSocketConnectOptions, + ): Promise>; + function connect( + options: UnixSocketOptions, + ): Promise>; + + /** + * Create a TCP server that listens on a port + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function listen( + options: TCPSocketListenOptions, + ): TCPSocketListener; + function listen( + options: UnixSocketOptions, + ): UnixSocketListener; + + namespace udp { + type Data = string | ArrayBufferView | ArrayBufferLike; + + export interface SocketHandler { + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: Socket): void | Promise; + error?( + socket: Socket, + error: Error, + ): void | Promise; + } + + export interface ConnectedSocketHandler { + data?( + socket: ConnectedSocket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: ConnectedSocket): void | Promise; + error?( + socket: ConnectedSocket, + error: Error, + ): void | Promise; + } + + export interface SocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: SocketHandler; + } + + export interface ConnectSocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: ConnectedSocketHandler; + connect: { + hostname: string; + port: number; + }; + } + + export interface BaseUDPSocket { + readonly hostname: string; + readonly port: number; + readonly address: SocketAddress; + readonly binaryType: BinaryType; + readonly closed: boolean; + ref(): void; + unref(): void; + close(): void; + } + + export interface ConnectedSocket + extends BaseUDPSocket { + readonly remoteAddress: SocketAddress; + sendMany(packets: readonly Data[]): number; + send(data: Data): boolean; + reload(handler: ConnectedSocketHandler): void; + } + + export interface Socket + extends BaseUDPSocket { + sendMany(packets: readonly (Data | string | number)[]): number; + send(data: Data, port: number, address: string): boolean; + reload(handler: SocketHandler): void; + } + } + + /** + * Create a UDP socket + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.hostname The hostname to listen on + * @param options.port The port to listen on + * @param options.binaryType The binary type to use for the socket + * @param options.connect The hostname and port to connect to + */ + export function udpSocket( + options: udp.SocketOptions, + ): Promise>; + export function udpSocket( + options: udp.ConnectSocketOptions, + ): Promise>; + + namespace SpawnOptions { + /** + * Option for stdout/stderr + */ + type Readable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number; + + /** + * Option for stdin + */ + type Writable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number + | ReadableStream + | Blob + | Response + | Request; + + interface OptionsObject< + In extends Writable = Writable, + Out extends Readable = Readable, + Err extends Readable = Readable, + > { + /** + * The current working directory of the process + * + * Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * The environment variables of the process + * + * Defaults to `process.env` as it was when the current Bun process launched. + * + * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. + */ + env?: Record; + + /** + * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. + * This overrides the `stdin`, `stdout`, and `stderr` properties. + * + * For stdin you may pass: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. + * - `number`: The process will read from the file descriptor + * + * For stdout and stdin you may pass: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default ["ignore", "pipe", "inherit"] for `spawn` + * ["ignore", "pipe", "pipe"] for `spawnSync` + */ + stdio?: [In, Out, Err]; + /** + * The file descriptor for the standard input. It may be: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`: The process will read from the buffer + * - `number`: The process will read from the file descriptor + * + * @default "ignore" + */ + stdin?: In; + /** + * The file descriptor for the standard output. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "pipe" + */ + stdout?: Out; + /** + * The file descriptor for the standard error. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "inherit" for `spawn` + * "pipe" for `spawnSync` + */ + stderr?: Err; + + /** + * Callback that runs when the {@link Subprocess} exits + * + * This is called even if the process exits with a non-zero exit code. + * + * Warning: this may run before the `Bun.spawn` function returns. + * + * A simple alternative is `await subprocess.exited`. + * + * @example + * + * ```ts + * const subprocess = spawn({ + * cmd: ["echo", "hello"], + * onExit: (subprocess, code) => { + * console.log(`Process exited with code ${code}`); + * }, + * }); + * ``` + */ + onExit?( + subprocess: Subprocess, + exitCode: number | null, + signalCode: number | null, + /** + * If an error occurred in the call to waitpid2, this will be the error. + */ + error?: ErrorLike, + ): void | Promise; + + /** + * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for + * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized + * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + * + * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, + * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. + * + * Currently, this is only compatible with processes that are other `bun` instances. + */ + ipc?( + message: any, + /** + * The {@link Subprocess} that sent the message + */ + subprocess: Subprocess, + ): void; + + /** + * The serialization format to use for IPC messages. Defaults to `"advanced"`. + * + * To communicate with Node.js processes, use `"json"`. + * + * When `ipc` is not specified, this is ignored. + */ + serialization?: "json" | "advanced"; + + /** + * If true, the subprocess will have a hidden window. + */ + windowsHide?: boolean; + + /** + * If true, no quoting or escaping of arguments is done on Windows. + */ + windowsVerbatimArguments?: boolean; + + /** + * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. + * + * One use-case for this is for applications which wrap other applications or to simulate a symlink. + * + * @default cmds[0] + */ + argv0?: string; + + /** + * An {@link AbortSignal} that can be used to abort the subprocess. + * + * This is useful for aborting a subprocess when some other part of the + * program is aborted, such as a `fetch` response. + * + * Internally, this works by calling `subprocess.kill(1)`. + * + * @example + * ```ts + * const controller = new AbortController(); + * const { signal } = controller; + * const start = performance.now(); + * const subprocess = Bun.spawn({ + * cmd: ["sleep", "100"], + * signal, + * }); + * await Bun.sleep(1); + * controller.abort(); + * await subprocess.exited; + * const end = performance.now(); + * console.log(end - start); // 1ms instead of 101ms + * ``` + */ + signal?: AbortSignal; + } + + type OptionsToSubprocess = + Opts extends OptionsObject + ? Subprocess< + // "Writable extends In" means "if In === Writable", + // aka if true that means the user didn't specify anything + Writable extends In ? "ignore" : In, + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "inherit" : Err + > + : Subprocess; + + type OptionsToSyncSubprocess = + Opts extends OptionsObject + ? SyncSubprocess< + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "pipe" : Err + > + : SyncSubprocess; + + type ReadableIO = ReadableStream | number | undefined; + + type ReadableToIO = X extends "pipe" | undefined + ? ReadableStream + : X extends BunFile | ArrayBufferView | number + ? number + : undefined; + + type ReadableToSyncIO = X extends "pipe" | undefined + ? Buffer + : undefined; + + type WritableIO = FileSink | number | undefined; + + type WritableToIO = X extends "pipe" + ? FileSink + : X extends BunFile | ArrayBufferView | Blob | Request | Response | number + ? number + : undefined; + } + + interface ResourceUsage { + /** + * The number of voluntary and involuntary context switches that the process made. + */ + contextSwitches: { + /** + * Voluntary context switches (context switches that the process initiated). + */ + voluntary: number; + /** + * Involuntary context switches (context switches initiated by the system scheduler). + */ + involuntary: number; + }; + + /** + * The amount of CPU time used by the process, in microseconds. + */ + cpuTime: { + /** + * User CPU time used by the process, in microseconds. + */ + user: number; + /** + * System CPU time used by the process, in microseconds. + */ + system: number; + /** + * Total CPU time used by the process, in microseconds. + */ + total: number; + }; + /** + * The maximum amount of resident set size (in bytes) used by the process during its lifetime. + */ + maxRSS: number; + + /** + * IPC messages sent and received by the process. + */ + messages: { + /** + * The number of IPC messages sent. + */ + sent: number; + /** + * The number of IPC messages received. + */ + received: number; + }; + /** + * The number of IO operations done by the process. + */ + ops: { + /** + * The number of input operations via the file system. + */ + in: number; + /** + * The number of output operations via the file system. + */ + out: number; + }; + /** + * The amount of shared memory that the process used. + */ + shmSize: number; + /** + * The number of signals delivered to the process. + */ + signalCount: number; + /** + * The number of times the process was swapped out of main memory. + */ + swapCount: number; + } + + /** + * A process created by {@link Bun.spawn}. + * + * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSubprocess} (any, pipe, pipe) + * - {@link WritableSubprocess} (pipe, any, any) + * - {@link PipedSubprocess} (pipe, pipe, pipe) + * - {@link NullSubprocess} (ignore, ignore, ignore) + */ + interface Subprocess< + In extends SpawnOptions.Writable = SpawnOptions.Writable, + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > extends AsyncDisposable { + readonly stdin: SpawnOptions.WritableToIO; + readonly stdout: SpawnOptions.ReadableToIO; + readonly stderr: SpawnOptions.ReadableToIO; + + /** + * This returns the same value as {@link Subprocess.stdout} + * + * It exists for compatibility with {@link ReadableStream.pipeThrough} + */ + readonly readable: SpawnOptions.ReadableToIO; + + /** + * The process ID of the child process + * @example + * ```ts + * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); + * console.log(pid); // 1234 + * ``` + */ + readonly pid: number; + /** + * The exit code of the process + * + * The promise will resolve when the process exits + */ + readonly exited: Promise; + + /** + * Synchronously get the exit code of the process + * + * If the process hasn't exited yet, this will return `null` + */ + readonly exitCode: number | null; + + /** + * Synchronously get the signal code of the process + * + * If the process never sent a signal code, this will return `null` + * + * To receive signal code changes, use the `onExit` callback. + * + * If the signal code is unknown, it will return the original signal code + * number, but that case should essentially never happen. + */ + readonly signalCode: NodeJS.Signals | null; + + /** + * Has the process exited? + */ + readonly killed: boolean; + + /** + * Kill the process + * @param exitCode The exitCode to send to the process + */ + kill(exitCode?: number | NodeJS.Signals): void; + + /** + * This method will tell Bun to wait for this process to exit after you already + * called `unref()`. + * + * Before shutting down, Bun will wait for all subprocesses to exit by default + */ + ref(): void; + + /** + * Before shutting down, Bun will wait for all subprocesses to exit by default + * + * This method will tell Bun to not wait for this process to exit before shutting down. + */ + unref(): void; + + /** + * Send a message to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option, and is another instance of `bun`. + * + * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + */ + send(message: any): void; + + /** + * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option. + */ + disconnect(): void; + + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + * + * Only available after the process has exited + * + * If the process hasn't exited yet, this will return `undefined` + */ + resourceUsage(): ResourceUsage | undefined; + } + + /** + * A process created by {@link Bun.spawnSync}. + * + * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSyncSubprocess} (pipe, pipe) + * - {@link NullSyncSubprocess} (ignore, ignore) + */ + interface SyncSubprocess< + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > { + stdout: SpawnOptions.ReadableToSyncIO; + stderr: SpawnOptions.ReadableToSyncIO; + exitCode: number; + success: boolean; + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + */ + resourceUsage: ResourceUsage; + + signalCode?: string; + } + + /** + * Spawn a new process + * + * ```js + * const subprocess = Bun.spawn({ + * cmd: ["echo", "hello"], + * stdout: "pipe", + * }); + * const text = await readableStreamToText(subprocess.stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmd: string[]; // to support dynamically constructed commands + }, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawn(["echo", "hello"]); + * const text = await readableStreamToText(stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync({ + * cmd: ["echo", "hello"], + * }); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); + * ``` + */ + cmd: string[]; + + onExit?: never; + }, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** + * Synchronously spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync(["echo", "hello"]); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ + type ReadableSubprocess = Subprocess; + /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ + type WritableSubprocess = Subprocess<"pipe", any, any>; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ + type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ + type NullSubprocess = Subprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ + type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ + type NullSyncSubprocess = SyncSubprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + + // Blocked on https://github.com/oven-sh/bun/issues/8329 + // /** + // * + // * Count the visible width of a string, as it would be displayed in a terminal. + // * + // * By default, strips ANSI escape codes before measuring the string. This is + // * because ANSI escape codes are not visible characters. If passed a non-string, + // * it will return 0. + // * + // * @param str The string to measure + // * @param options + // */ + // function stringWidth( + // str: string, + // options?: { + // /** + // * Whether to include ANSI escape codes in the width calculation + // * + // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. + // * @default false + // */ + // countAnsiEscapeCodes?: boolean; + // }, + // ): number; + + class FileSystemRouter { + /** + * Create a new {@link FileSystemRouter}. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: process.cwd() + "/pages", + * style: "nextjs", + * }); + * + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} + * ``` + * @param options The options to use when creating the router + * @param options.dir The root directory containing the files to route + * @param options.style The style of router to use (only "nextjs" supported + * for now) + */ + constructor(options: { + /** + * The root directory containing the files to route + * + * There is no default value for this option. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: + */ + dir: string; + style: "nextjs"; + + /** The base path to use when routing */ + assetPrefix?: string; + origin?: string; + /** Limit the pages to those with particular file extensions. */ + fileExtensions?: string[]; + }); + + // todo: URL + match(input: string | Request | Response): MatchedRoute | null; + + readonly assetPrefix: string; + readonly origin: string; + readonly style: string; + readonly routes: Record; + + reload(): void; + } + + interface MatchedRoute { + /** + * A map of the parameters from the route + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: "/path/to/files", + * style: "nextjs", + * }); + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params.year); // "2020" + * console.log(params.month); // "01" + * console.log(params.day); // "01" + * console.log(params.slug); // "hello-world" + * ``` + */ + readonly params: Record; + readonly filePath: string; + readonly pathname: string; + readonly query: Record; + readonly name: string; + readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; + readonly src: string; + } + + /** + * The current version of Bun + * @example + * "0.2.0" + */ + const version: string; + + /** + * The current version of Bun with the shortened commit sha of the build + * @example "v1.1.30 (d09df1af)" + */ + const version_with_sha: string; + + /** + * The git sha at the time the currently-running version of Bun was compiled + * @example + * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" + */ + const revision: string; + + /** + * Find the index of a newline character in potentially ill-formed UTF-8 text. + * + * This is sort of like readline() except without the IO. + */ + function indexOfLine( + buffer: ArrayBufferView | ArrayBufferLike, + offset?: number, + ): number; + + interface GlobScanOptions { + /** + * The root directory to start matching from. Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * Allow patterns to match entries that begin with a period (`.`). + * + * @default false + */ + dot?: boolean; + + /** + * Return the absolute path for entries. + * + * @default false + */ + absolute?: boolean; + + /** + * Indicates whether to traverse descendants of symbolic link directories. + * + * @default false + */ + followSymlinks?: boolean; + + /** + * Throw an error when symbolic link is broken + * + * @default false + */ + throwErrorOnBrokenSymlink?: boolean; + + /** + * Return only files. + * + * @default true + */ + onlyFiles?: boolean; + } + + /** + * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). + * + * The supported pattern syntax for is: + * + * - `?` + * Matches any single character. + * - `*` + * Matches zero or more characters, except for path separators ('/' or '\'). + * - `**` + * Matches zero or more characters, including path separators. + * Must match a complete path segment, i.e. followed by a path separator or + * at the end of the pattern. + * - `[ab]` + * Matches one of the characters contained in the brackets. + * Character ranges (e.g. "[a-z]") are also supported. + * Use "[!ab]" or "[^ab]" to match any character *except* those contained + * in the brackets. + * - `{a,b}` + * Match one of the patterns contained in the braces. + * Any of the wildcards listed above can be used in the sub patterns. + * Braces may be nested up to 10 levels deep. + * - `!` + * Negates the result when at the start of the pattern. + * Multiple "!" characters negate the pattern multiple times. + * - `\` + * Used to escape any of the special characters above. + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + */ + export class Glob { + constructor(pattern: string); + + /** + * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for await (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scan( + optionsOrCwd?: string | GlobScanOptions, + ): AsyncIterableIterator; + + /** + * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; + + /** + * Match the glob against a string + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * expect(glob.match('foo.ts')).toBeTrue(); + * ``` + */ + match(str: string): boolean; + } + + /** + * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. + * + * When the same timestamp is used multiple times, a monotonically increasing + * counter is appended to allow sorting. The final 8 bytes are + * cryptographically random. When the timestamp changes, the counter resets to + * a psuedo-random integer. + * + * @param encoding "hex" | "base64" | "base64url" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + * + * @example + * ```js + * import { randomUUIDv7 } from "bun"; + * const array = [ + * randomUUIDv7(), + * randomUUIDv7(), + * randomUUIDv7(), + * ] + * [ + * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", + * "0192ce07-8c4f-7d67-805f-0f71581b5622", + * "0192ce07-8c4f-7d68-8170-6816e4451a58" + * ] + * ``` + */ + function randomUUIDv7( + /** + * @default "hex" + */ + encoding?: "hex" | "base64" | "base64url", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): string; + + /** + * Generate a UUIDv7 as a Buffer + * + * @param encoding "buffer" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + */ + function randomUUIDv7( + encoding: "buffer", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): Buffer; + + /** + * Types for `bun.lock` + */ + type BunLockFile = { + lockfileVersion: 0 | 1; + workspaces: { + [workspace: string]: BunLockFileWorkspacePackage; + }; + overrides?: Record; + patchedDependencies?: Record; + trustedDependencies?: string[]; + + /** + * ``` + * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } + * + * // first index is resolution for each type of package + * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] + * symlink -> [ "name@link:path", INFO ] + * folder -> [ "name@file:path", INFO ] + * workspace -> [ "name@workspace:path" ] // workspace is only path + * tarball -> [ "name@tarball", INFO ] + * root -> [ "name@root:", { bin, binDir } ] + * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] + * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] + * ``` + * */ + packages: { + [pkg: string]: BunLockFilePackageArray; + }; + }; + + type BunLockFileBasePackageInfo = { + dependencies?: Record; + devDependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; + optionalPeers?: string[]; + bin?: string | Record; + binDir?: string; + }; + + type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { + name?: string; + version?: string; + }; + + type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { + os?: string | string[]; + cpu?: string | string[]; + bundled?: true; + }; + + /** @see {@link BunLockFile.packages} for more info */ + type BunLockFilePackageArray = + /** npm */ + | [ + pkg: string, + registry: string, + info: BunLockFilePackageInfo, + integrity: string, + ] + /** symlink, folder, tarball */ + | [pkg: string, info: BunLockFilePackageInfo] + /** workspace */ + | [pkg: string] + /** git, github */ + | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] + /** root */ + | [pkg: string, info: Pick]; } diff --git a/packages/bun-types/new/extensions.d.ts b/packages/bun-types/new/extensions.d.ts new file mode 100644 index 00000000000000..f8c76296b6ecac --- /dev/null +++ b/packages/bun-types/new/extensions.d.ts @@ -0,0 +1,4 @@ +declare module "*.svg" { + const content: `${string}.svg`; + export = content; +} diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts index b2bf3489c49167..6b9da807c76fd3 100644 --- a/packages/bun-types/new/fetch.d.ts +++ b/packages/bun-types/new/fetch.d.ts @@ -1,3 +1,8 @@ +type RequestInit = import("undici-types").RequestInit; +type HeadersInit = import("undici-types").HeadersInit; +type ResponseInit = import("undici-types").ResponseInit; +type BodyInit = import("undici-types").BodyInit; + interface Headers { /** * Convert {@link Headers} to a plain JavaScript object. @@ -35,7 +40,7 @@ interface Headers { declare var Headers: { prototype: Headers; - new (init?: Bun.HeadersInit): Headers; + new (init?: HeadersInit): Headers; }; interface Request { @@ -51,8 +56,8 @@ declare var Request: { declare var Response: { new ( - body?: Bun.BodyInit | null | undefined, - init?: Bun.ResponseInit | undefined, + body?: BodyInit | null | undefined, + init?: ResponseInit | undefined, ): Response; /** * Create a new {@link Response} with a JSON body @@ -77,7 +82,7 @@ declare var Response: { * ``` * @link https://github.com/whatwg/fetch/issues/1389 */ - json(body?: any, options?: Bun.ResponseInit | number): Response; + json(body?: any, options?: ResponseInit | number): Response; /** * Create a new {@link Response} that redirects to url @@ -103,8 +108,7 @@ declare var Response: { error(): Response; }; -type _BunTLSOptions = import("bun").TLSOptions; -interface BunFetchRequestInitTLS extends _BunTLSOptions { +interface BunFetchRequestInitTLS extends Bun.TLSOptions { /** * Custom function to check the server identity * @param hostname - The hostname of the server diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts new file mode 100644 index 00000000000000..ed80aca6b6bb5e --- /dev/null +++ b/packages/bun-types/new/globals.d.ts @@ -0,0 +1,5 @@ +import * as BunModule from "bun"; + +declare global { + export import Bun = BunModule; +} diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index b88755499bd45f..b514b45cff81b6 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -1,60 +1,14 @@ +// Project: https://github.com/oven-sh/bun +// Definitions by: Bun Contributors +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + /// +/// /// /// +/// /// +/// declare var onmessage: never; - -declare module "bun" { - interface Env { - [key: string]: string | undefined; - } - - export var env: Env; - - export var fetch: typeof globalThis.fetch; -} - -interface ImportMeta { - url: string; - readonly path: string; - readonly dir: string; - readonly file: string; - readonly env: NodeJS.ProcessEnv; - resolveSync(moduleId: string, parent?: string): string; - require: NodeJS.Require; - readonly main: boolean; - dirname: string; - filename: string; - - hot?: { - data: any; - }; -} - -interface Headers { - toJSON(): Record; -} - -declare namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - isBun: true; - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - - interface ProcessVersions extends Dict { - bun: string; - } -} - -declare module "*.svg" { - const content: `${string}.svg`; - export = content; -} - -declare var FormData: FormData; diff --git a/packages/bun-types/new/s3.d.ts b/packages/bun-types/new/s3.d.ts index 31591aca89dca7..92274b3f5f608f 100644 --- a/packages/bun-types/new/s3.d.ts +++ b/packages/bun-types/new/s3.d.ts @@ -1,4 +1,7 @@ declare module "bun" { + /** + * Configuration options for S3 operations + */ interface S3Options extends BlobPropertyBag { /** * The Access Control List (ACL) policy for the file. @@ -201,4 +204,550 @@ declare module "bun" { */ highWaterMark?: number; } + + /** + * Options for generating presigned URLs + */ + interface S3FilePresignOptions extends S3Options { + /** + * Number of seconds until the presigned URL expires. + * - Default: 86400 (1 day) + * + * @example + * // Short-lived URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Long-lived public URL + * const url = file.presign({ + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + expiresIn?: number; + + /** + * The HTTP method allowed for the presigned URL. + * + * @example + * // GET URL for downloads + * const downloadUrl = file.presign({ + * method: "GET", + * expiresIn: 3600 + * }); + * + * @example + * // PUT URL for uploads + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "application/json" + * }); + */ + method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; + } + + interface S3Stats { + size: number; + lastModified: Date; + etag: string; + type: string; + } + + /** + * Represents a file in an S3-compatible storage service. + * Extends the Blob interface for compatibility with web APIs. + */ + interface S3File extends Blob { + /** + * The size of the file in bytes. + * This is a Promise because it requires a network request to determine the size. + * + * @example + * // Getting file size + * const size = await file.size; + * console.log(`File size: ${size} bytes`); + * + * @example + * // Check if file is larger than 1MB + * if (await file.size > 1024 * 1024) { + * console.log("Large file detected"); + * } + */ + /** + * TODO: figure out how to get the typescript types to not error for this property. + */ + // size: Promise; + + /** + * Creates a new S3File representing a slice of the original file. + * Uses HTTP Range headers for efficient partial downloads. + * + * @param begin - Starting byte offset + * @param end - Ending byte offset (exclusive) + * @param contentType - Optional MIME type for the slice + * @returns A new S3File representing the specified range + * + * @example + * // Reading file header + * const header = file.slice(0, 1024); + * const headerText = await header.text(); + * + * @example + * // Reading with content type + * const jsonSlice = file.slice(1024, 2048, "application/json"); + * const data = await jsonSlice.json(); + * + * @example + * // Reading from offset to end + * const remainder = file.slice(1024); + * const content = await remainder.text(); + */ + slice(begin?: number, end?: number, contentType?: string): S3File; + slice(begin?: number, contentType?: string): S3File; + slice(contentType?: string): S3File; + + /** + * Creates a writable stream for uploading data. + * Suitable for large files as it uses multipart upload. + * + * @param options - Configuration for the upload + * @returns A NetworkSink for writing data + * + * @example + * // Basic streaming write + * const writer = file.writer({ + * type: "application/json" + * }); + * writer.write('{"hello": '); + * writer.write('"world"}'); + * await writer.end(); + * + * @example + * // Optimized large file upload + * const writer = file.writer({ + * partSize: 10 * 1024 * 1024, // 10MB parts + * queueSize: 4, // Upload 4 parts in parallel + * retry: 3 // Retry failed parts + * }); + * + * // Write large chunks of data efficiently + * for (const chunk of largeDataChunks) { + * writer.write(chunk); + * } + * await writer.end(); + * + * @example + * // Error handling + * const writer = file.writer(); + * try { + * writer.write(data); + * await writer.end(); + * } catch (err) { + * console.error('Upload failed:', err); + * // Writer will automatically abort multipart upload on error + * } + */ + writer(options?: S3Options): NetworkSink; + + /** + * Gets a readable stream of the file's content. + * Useful for processing large files without loading them entirely into memory. + * + * @returns A ReadableStream for the file content + * + * @example + * // Basic streaming read + * const stream = file.stream(); + * for await (const chunk of stream) { + * console.log('Received chunk:', chunk); + * } + * + * @example + * // Piping to response + * const stream = file.stream(); + * return new Response(stream, { + * headers: { 'Content-Type': file.type } + * }); + * + * @example + * // Processing large files + * const stream = file.stream(); + * const textDecoder = new TextDecoder(); + * for await (const chunk of stream) { + * const text = textDecoder.decode(chunk); + * // Process text chunk by chunk + * } + */ + readonly readable: ReadableStream; + stream(): ReadableStream; + + /** + * The name or path of the file in the bucket. + * + * @example + * const file = s3("folder/image.jpg"); + * console.log(file.name); // "folder/image.jpg" + */ + readonly name?: string; + + /** + * The bucket name containing the file. + * + * @example + * const file = s3("s3://my-bucket/file.txt"); + * console.log(file.bucket); // "my-bucket" + */ + readonly bucket?: string; + + /** + * Checks if the file exists in S3. + * Uses HTTP HEAD request to efficiently check existence without downloading. + * + * @returns Promise resolving to true if file exists, false otherwise + * + * @example + * // Basic existence check + * if (await file.exists()) { + * console.log("File exists in S3"); + * } + * + * @example + * // With error handling + * try { + * const exists = await file.exists(); + * if (!exists) { + * console.log("File not found"); + * } + * } catch (err) { + * console.error("Error checking file:", err); + * } + */ + exists(): Promise; + + /** + * Uploads data to S3. + * Supports various input types and automatically handles large files. + * + * @param data - The data to upload + * @param options - Upload configuration options + * @returns Promise resolving to number of bytes written + * + * @example + * // Writing string data + * await file.write("Hello World", { + * type: "text/plain" + * }); + * + * @example + * // Writing JSON + * const data = { hello: "world" }; + * await file.write(JSON.stringify(data), { + * type: "application/json" + * }); + * + * @example + * // Writing from Response + * const response = await fetch("https://example.com/data"); + * await file.write(response); + * + * @example + * // Writing with ACL + * await file.write(data, { + * acl: "public-read", + * type: "application/octet-stream" + * }); + */ + write( + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob, + options?: S3Options, + ): Promise; + + /** + * Generates a presigned URL for the file. + * Allows temporary access to the file without exposing credentials. + * + * @param options - Configuration for the presigned URL + * @returns Presigned URL string + * + * @example + * // Basic download URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Upload URL with specific content type + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * @example + * // URL with custom permissions + * const url = file.presign({ + * method: "GET", + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(options?: S3FilePresignOptions): string; + + /** + * Deletes the file from S3. + * + * @returns Promise that resolves when deletion is complete + * + * @example + * // Basic deletion + * await file.delete(); + * + * @example + * // With error handling + * try { + * await file.delete(); + * console.log("File deleted successfully"); + * } catch (err) { + * console.error("Failed to delete file:", err); + * } + */ + delete(): Promise; + + /** + * Alias for delete() method. + * Provided for compatibility with Node.js fs API naming. + * + * @example + * await file.unlink(); + */ + unlink: S3File["delete"]; + + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @returns Promise resolving to S3Stat + */ + stat(): Promise; + } + + /** + * A configured S3 bucket instance for managing files. + * The instance is callable to create S3File instances and provides methods + * for common operations. + * + * @example + * // Basic bucket setup + * const bucket = new S3Client({ + * bucket: "my-bucket", + * accessKeyId: "key", + * secretAccessKey: "secret" + * }); + * + * // Get file instance + * const file = bucket("image.jpg"); + * + * // Common operations + * await bucket.write("data.json", JSON.stringify({hello: "world"})); + * const url = bucket.presign("file.pdf"); + * await bucket.unlink("old.txt"); + */ + class S3Client { + prototype: S3Client; + /** + * Create a new instance of an S3 bucket so that credentials can be managed + * from a single instance instead of being passed to every method. + * + * @param options The default options to use for the S3 client. Can be + * overriden by passing options to the methods. + * + * ## Keep S3 credentials in a single instance + * + * @example + * const bucket = new Bun.S3Client({ + * accessKeyId: "your-access-key", + * secretAccessKey: "your-secret-key", + * bucket: "my-bucket", + * endpoint: "https://s3.us-east-1.amazonaws.com", + * sessionToken: "your-session-token", + * }); + * + * // S3Client is callable, so you can do this: + * const file = bucket.file("my-file.txt"); + * + * // or this: + * await file.write("Hello Bun!"); + * await file.text(); + * + * // To delete the file: + * await bucket.delete("my-file.txt"); + * + * // To write a file without returning the instance: + * await bucket.write("my-file.txt", "Hello Bun!"); + * + */ + constructor(options?: S3Options); + + /** + * Creates an S3File instance for the given path. + * + * @example + * const file = bucket.file("image.jpg"); + * await file.write(imageData); + * const configFile = bucket("config.json", { + * type: "application/json", + * acl: "private" + * }); + */ + file(path: string, options?: S3Options): S3File; + + /** + * Writes data directly to a path in the bucket. + * Supports strings, buffers, streams, and web API types. + * + * @example + * // Write string + * await bucket.write("hello.txt", "Hello World"); + * + * // Write JSON with type + * await bucket.write( + * "data.json", + * JSON.stringify({hello: "world"}), + * {type: "application/json"} + * ); + * + * // Write from fetch + * const res = await fetch("https://example.com/data"); + * await bucket.write("data.bin", res); + * + * // Write with ACL + * await bucket.write("public.html", html, { + * acl: "public-read", + * type: "text/html" + * }); + */ + write( + path: string, + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob + | File, + options?: S3Options, + ): Promise; + + /** + * Generate a presigned URL for temporary access to a file. + * Useful for generating upload/download URLs without exposing credentials. + * + * @example + * // Download URL + * const downloadUrl = bucket.presign("file.pdf", { + * expiresIn: 3600 // 1 hour + * }); + * + * // Upload URL + * const uploadUrl = bucket.presign("uploads/image.jpg", { + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * // Long-lived public URL + * const publicUrl = bucket.presign("public/doc.pdf", { + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(path: string, options?: S3FilePresignOptions): string; + + /** + * Delete a file from the bucket. + * + * @example + * // Simple delete + * await bucket.unlink("old-file.txt"); + * + * // With error handling + * try { + * await bucket.unlink("file.dat"); + * console.log("File deleted"); + * } catch (err) { + * console.error("Delete failed:", err); + * } + */ + unlink(path: string, options?: S3Options): Promise; + delete: S3Client["unlink"]; + + /** + * Get the size of a file in bytes. + * Uses HEAD request to efficiently get size. + * + * @example + * // Get size + * const bytes = await bucket.size("video.mp4"); + * console.log(`Size: ${bytes} bytes`); + * + * // Check if file is large + * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { + * console.log("File is larger than 100MB"); + * } + */ + size(path: string, options?: S3Options): Promise; + + /** + * Check if a file exists in the bucket. + * Uses HEAD request to check existence. + * + * @example + * // Check existence + * if (await bucket.exists("config.json")) { + * const file = bucket("config.json"); + * const config = await file.json(); + * } + * + * // With error handling + * try { + * if (!await bucket.exists("required.txt")) { + * throw new Error("Required file missing"); + * } + * } catch (err) { + * console.error("Check failed:", err); + * } + */ + exists(path: string, options?: S3Options): Promise; + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @param path The path to the file. + * @param options The options to use for the S3 client. + */ + stat(path: string, options?: S3Options): Promise; + } + + /** + * A default instance of S3Client + * + * Pulls credentials from environment variables. Use `new Bun.S3Client()` if you need to explicitly set credentials. + */ + var s3: S3Client; } diff --git a/packages/bun-types/new/sink.d.ts b/packages/bun-types/new/sink.d.ts new file mode 100644 index 00000000000000..2e0cc4ceb84ea5 --- /dev/null +++ b/packages/bun-types/new/sink.d.ts @@ -0,0 +1,86 @@ +declare module "bun" { + /** + * 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; + /** + * Close the file descriptor. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; + + 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 NetworkSink extends FileSink { + /** + * Write a chunk of data to the network. + * + * If the network is not writable yet, the data is buffered. + */ + write( + chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + ): number; + /** + * Flush the internal buffer, committing the data to the network. + */ + flush(): number | Promise; + /** + * Finish the upload. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; + + /** + * Get the stat of the file. + */ + stat(): Promise; + } +} diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index 64b81e21ad8248..52a2a9b41f16cd 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -4,7 +4,7 @@ "": { "name": "fixture", "dependencies": { - "@types/bun": "types-bun-1.2.3.tgz", + "@types/bun": "types-bun-1.2.4.tgz", }, "peerDependencies": { "typescript": "^5.0.0", @@ -12,7 +12,7 @@ }, }, "packages": { - "@types/bun": ["@types/bun@types-bun-1.2.3.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }], + "@types/bun": ["@types/bun@types-bun-1.2.4.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }], "@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index b2d65d24d44678..f6fb2c061f353d 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -1,11 +1,20 @@ import svgpath from "cool.svg"; svgpath satisfies `${string}.svg`; -type c = BunFetchRequestInit; +Bun satisfies typeof import("bun"); -fetch; +type S3OptionsFromNamespace = Bun.S3Options; +type S3OptionsFromImport = import("bun").S3Options; + +type c = import("bun").S3Client; + +Bun.s3.file("").name; -const g: BunFetchRequestInit = {}; +const client = new Bun.S3Client({ + secretAccessKey: "", +}); + +client.file(""); Bun.fetch; @@ -31,6 +40,8 @@ Bun.fetch("", { proxy: "", }); +Bun.S3Client; + new Bun.$.ShellError(); new Promise(resolve => { diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index c25f8849a1873a..33e0b6344f11fb 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -9,6 +9,6 @@ }, "type": "module", "dependencies": { - "@types/bun": "types-bun-1.2.3.tgz" + "@types/bun": "types-bun-1.2.4.tgz" } } From 596ebe27ac1380393290fd909c6eb690d7316887 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 04:01:45 +0000 Subject: [PATCH 07/72] changes --- packages/bun-types/globals.d.ts | 565 ------------------------------- packages/bun-types/new/bun.d.ts | 556 ++++++++++++++++++++++++++++++ packages/bun-types/new/sink.d.ts | 154 ++++----- 3 files changed, 631 insertions(+), 644 deletions(-) diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index f8c1bab554eea7..7263946b604113 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -79,571 +79,6 @@ declare global { } } - namespace Bun { - type ArrayBufferView = NodeJS.TypedArray | DataView; - type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type PathLike = import("bun").PathLike; - type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; - type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; - type ReadableStreamController = ReadableStreamDefaultController; - type ReadableStreamDefaultReadResult = - | ReadableStreamDefaultReadValueResult - | ReadableStreamDefaultReadDoneResult; - type ReadableStreamReader = ReadableStreamDefaultReader; - type Transferable = ArrayBuffer | import("worker_threads").MessagePort; - type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; - type DOMHighResTimeStamp = number; - type EventListenerOrEventListenerObject = - | EventListener - | EventListenerObject; - - type BlobOrStringOrBuffer = - | string - | NodeJS.TypedArray - | ArrayBufferLike - | Blob; - - type Platform = - | "aix" - | "android" - | "darwin" - | "freebsd" - | "haiku" - | "linux" - | "openbsd" - | "sunos" - | "win32" - | "cygwin" - | "netbsd"; - type Architecture = - | "arm" - | "arm64" - | "ia32" - | "mips" - | "mipsel" - | "ppc" - | "ppc64" - | "s390" - | "s390x" - | "x64"; - - 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. - */ - type UnhandledRejectionListener = ( - reason: unknown, - promise: Promise, - ) => void; - - type MultipleResolveListener = ( - type: MultipleResolveType, - promise: Promise, - value: unknown, - ) => void; - - type HeadersInit = - | Headers - | Record - | Array<[string, string]> - | IterableIterator<[string, string]>; - - type ResponseType = - | "basic" - | "cors" - | "default" - | "error" - | "opaque" - | "opaqueredirect"; - - type _TextEncoder = import("util").TextEncoder; - interface TextEncoder extends _TextEncoder { - new ( - encoding?: Bun.Encoding, - options?: { fatal?: boolean; ignoreBOM?: boolean }, - ): TextEncoder; - /** - * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object - * containing the read Unicode code units and written UTF-8 bytes. - * - * ```js - * const encoder = new TextEncoder(); - * const src = 'this is some data'; - * const dest = new Uint8Array(10); - * const { read, written } = encoder.encodeInto(src, dest); - * ``` - * @param src The text to encode. - * @param dest The array to hold the encode result. - */ - encodeInto( - src?: string, - dest?: Bun.BufferSource, - ): import("util").EncodeIntoResult; - } - - type _TextDecoder = import("util").TextDecoder; - interface TextDecoder extends _TextDecoder { - new ( - encoding?: Bun.Encoding, - options?: { fatal?: boolean; ignoreBOM?: boolean }, - ): TextDecoder; - } - - 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 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 extends Bun.EventInit { - detail?: T; - } - - /** A message received by a target object. */ - interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; - readonly source: Bun.MessageEventSource | null; - } - - interface ReadableStreamDefaultReadManyResult { - done: boolean; - /** Number of bytes */ - size: number; - value: T[]; - } - - interface ResponseInit { - headers?: HeadersInit; - /** @default 200 */ - status?: number; - - /** @default "OK" */ - statusText?: string; - } - - interface EventSourceEventMap { - error: Event; - message: MessageEvent; - open: Event; - } - - interface EventInit { - bubbles?: boolean; - cancelable?: boolean; - composed?: boolean; - } - - interface EventListenerOptions { - /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ - capture?: boolean; - } - - 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): void; - respondWith(response: Response | Promise): 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( - 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( - 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 { - ( - controller: TransformStreamDefaultController, - ): void | PromiseLike; - } - - interface TransformerStartCallback { - (controller: TransformStreamDefaultController): any; - } - - interface TransformerTransformCallback { - ( - chunk: I, - controller: TransformStreamDefaultController, - ): void | PromiseLike; - } - - interface UnderlyingSinkAbortCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSinkCloseCallback { - (): void | PromiseLike; - } - - interface UnderlyingSinkStartCallback { - (controller: WritableStreamDefaultController): any; - } - - interface UnderlyingSinkWriteCallback { - ( - chunk: W, - controller: WritableStreamDefaultController, - ): void | PromiseLike; - } - - interface UnderlyingSourceCancelCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSink { - abort?: UnderlyingSinkAbortCallback; - close?: UnderlyingSinkCloseCallback; - start?: UnderlyingSinkStartCallback; - type?: undefined | "default" | "bytes"; - write?: UnderlyingSinkWriteCallback; - } - - interface UnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull?: UnderlyingSourcePullCallback; - start?: UnderlyingSourceStartCallback; - /** - * Mode "bytes" is not currently supported. - */ - type?: undefined; - } - - interface DirectUnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull: ( - controller: ReadableStreamDirectController, - ) => void | PromiseLike; - type: "direct"; - } - - interface UnderlyingSourcePullCallback { - (controller: ReadableStreamController): void | PromiseLike; - } - - interface UnderlyingSourceStartCallback { - (controller: ReadableStreamController): 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( - type: K, - listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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 - | 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( - type: K, - listener: (this: Worker, ev: WorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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; - } - } - type _ReadableStream = import("stream/web").ReadableStream; interface ReadableStream extends _ReadableStream {} var ReadableStream: { diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 4c2024fafed8f2..83ed71e19e6f58 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -17,6 +17,562 @@ declare module "bun" { type DistributedOmit = T extends T ? Omit : never; type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; + type ArrayBufferView = NodeJS.TypedArray | DataView; + type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; + type PathLike = import("bun").PathLike; + type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; + type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; + type ReadableStreamController = ReadableStreamDefaultController; + type ReadableStreamDefaultReadResult = + | ReadableStreamDefaultReadValueResult + | ReadableStreamDefaultReadDoneResult; + type ReadableStreamReader = ReadableStreamDefaultReader; + type Transferable = ArrayBuffer | import("worker_threads").MessagePort; + type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; + type DOMHighResTimeStamp = number; + type EventListenerOrEventListenerObject = EventListener | EventListenerObject; + + type BlobOrStringOrBuffer = + | string + | NodeJS.TypedArray + | ArrayBufferLike + | Blob; + + type Platform = + | "aix" + | "android" + | "darwin" + | "freebsd" + | "haiku" + | "linux" + | "openbsd" + | "sunos" + | "win32" + | "cygwin" + | "netbsd"; + type Architecture = + | "arm" + | "arm64" + | "ia32" + | "mips" + | "mipsel" + | "ppc" + | "ppc64" + | "s390" + | "s390x" + | "x64"; + + 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. + */ + type UnhandledRejectionListener = ( + reason: unknown, + promise: Promise, + ) => void; + + type MultipleResolveListener = ( + type: MultipleResolveType, + promise: Promise, + value: unknown, + ) => void; + + type HeadersInit = + | Headers + | Record + | Array<[string, string]> + | IterableIterator<[string, string]>; + + type ResponseType = + | "basic" + | "cors" + | "default" + | "error" + | "opaque" + | "opaqueredirect"; + + type _TextEncoder = import("util").TextEncoder; + interface TextEncoder extends _TextEncoder { + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): TextEncoder; + /** + * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object + * containing the read Unicode code units and written UTF-8 bytes. + * + * ```js + * const encoder = new TextEncoder(); + * const src = 'this is some data'; + * const dest = new Uint8Array(10); + * const { read, written } = encoder.encodeInto(src, dest); + * ``` + * @param src The text to encode. + * @param dest The array to hold the encode result. + */ + encodeInto( + src?: string, + dest?: Bun.BufferSource, + ): import("util").EncodeIntoResult; + } + + type _TextDecoder = import("util").TextDecoder; + interface TextDecoder extends _TextDecoder { + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): TextDecoder; + } + + 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 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 extends Bun.EventInit { + detail?: T; + } + + /** A message received by a target object. */ + interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; + readonly source: Bun.MessageEventSource | null; + } + + interface ReadableStreamDefaultReadManyResult { + done: boolean; + /** Number of bytes */ + size: number; + value: T[]; + } + + interface ResponseInit { + headers?: HeadersInit; + /** @default 200 */ + status?: number; + + /** @default "OK" */ + statusText?: string; + } + + interface EventSourceEventMap { + error: Event; + message: MessageEvent; + open: Event; + } + + interface EventInit { + bubbles?: boolean; + cancelable?: boolean; + composed?: boolean; + } + + interface EventListenerOptions { + /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ + capture?: boolean; + } + + 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): void; + respondWith(response: Response | Promise): 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( + 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( + 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 { + (controller: TransformStreamDefaultController): void | PromiseLike; + } + + interface TransformerStartCallback { + (controller: TransformStreamDefaultController): any; + } + + interface TransformerTransformCallback { + ( + chunk: I, + controller: TransformStreamDefaultController, + ): void | PromiseLike; + } + + interface UnderlyingSinkAbortCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSinkCloseCallback { + (): void | PromiseLike; + } + + interface UnderlyingSinkStartCallback { + (controller: WritableStreamDefaultController): any; + } + + interface UnderlyingSinkWriteCallback { + ( + chunk: W, + controller: WritableStreamDefaultController, + ): void | PromiseLike; + } + + interface UnderlyingSourceCancelCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSink { + abort?: UnderlyingSinkAbortCallback; + close?: UnderlyingSinkCloseCallback; + start?: UnderlyingSinkStartCallback; + type?: undefined | "default" | "bytes"; + write?: UnderlyingSinkWriteCallback; + } + + interface UnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull?: UnderlyingSourcePullCallback; + start?: UnderlyingSourceStartCallback; + /** + * Mode "bytes" is not currently supported. + */ + type?: undefined; + } + + interface DirectUnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull: ( + controller: ReadableStreamDirectController, + ) => void | PromiseLike; + type: "direct"; + } + + interface UnderlyingSourcePullCallback { + (controller: ReadableStreamController): void | PromiseLike; + } + + interface UnderlyingSourceStartCallback { + (controller: ReadableStreamController): 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( + type: K, + listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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 + | 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( + type: K, + listener: (this: Worker, ev: WorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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; + } + export interface BlobPropertyBag { /** Set a default "type". Not yet implemented. */ type?: string; diff --git a/packages/bun-types/new/sink.d.ts b/packages/bun-types/new/sink.d.ts index 2e0cc4ceb84ea5..e0ace23621c53e 100644 --- a/packages/bun-types/new/sink.d.ts +++ b/packages/bun-types/new/sink.d.ts @@ -1,86 +1,82 @@ declare module "bun" { - /** - * 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; - /** - * Close the file descriptor. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; + /** + * 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; + /** + * Close the file descriptor. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; - start(options?: { - /** - * Preallocate an internal buffer of this size - * This can significantly improve performance when the chunk size is small - */ - highWaterMark?: number; - }): void; + 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. + * + * 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; - } + /** + * 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 NetworkSink extends FileSink { - /** - * Write a chunk of data to the network. - * - * If the network is not writable yet, the data is buffered. - */ - write( - chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - ): number; - /** - * Flush the internal buffer, committing the data to the network. - */ - flush(): number | Promise; - /** - * Finish the upload. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; + interface NetworkSink extends FileSink { + /** + * Write a chunk of data to the network. + * + * If the network is not writable yet, the data is buffered. + */ + write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number; + /** + * Flush the internal buffer, committing the data to the network. + */ + flush(): number | Promise; + /** + * Finish the upload. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; - /** - * Get the stat of the file. - */ - stat(): Promise; - } + /** + * Get the stat of the file. + */ + stat(): Promise; + } } From 43c9547c6b496c1f75daee56d27206295f947007 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 12:53:01 +0000 Subject: [PATCH 08/72] some more changes --- packages/bun-types/bun.d.ts | 2 +- packages/bun-types/new/bun.d.ts | 175 +++++++++--------- packages/bun-types/new/sink.d.ts | 154 +++++++-------- src/js/builtins/shell.ts | 1 + test/integration/bun-types/fixture/bun.lock | 4 +- test/integration/bun-types/fixture/index.ts | 2 + .../bun-types/fixture/package.json | 2 +- 7 files changed, 177 insertions(+), 163 deletions(-) diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 80447cb4033ed4..9d96f5d21b33a0 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -459,7 +459,7 @@ declare module "bun" { blob(): Blob; } - export const $: Shell; + const $: Shell; interface TOML { /** diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 83ed71e19e6f58..0f545aa5f888d2 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -573,7 +573,7 @@ declare module "bun" { threadId: number; } - export interface BlobPropertyBag { + interface BlobPropertyBag { /** Set a default "type". Not yet implemented. */ type?: string; /** Not implemented in Bun yet. */ @@ -793,79 +793,6 @@ declare module "bun" { new (): Shell; } - namespace Shell { - export class ShellError extends Error { - 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; - - bytes(): Uint8Array; - } - } - interface Shell { ( strings: TemplateStringsArray, @@ -924,11 +851,91 @@ declare module "bun" { */ throws(shouldThrow: boolean): this; - readonly ShellPromise: typeof ShellPromise; readonly Shell: ShellConstructor; + + readonly ShellPromise: { + prototype: ShellPromise; + new (args: unknown, throws: boolean): ShellPromise; + }; + + readonly ShellError: { + prototype: ShellError; + new (): ShellError; + }; } - export interface ShellOutput { + interface ShellError extends Error { + 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; + + bytes(): Uint8Array; + } + + interface ShellOutput { readonly stdout: Buffer; readonly stderr: Buffer; readonly exitCode: number; @@ -1010,7 +1017,7 @@ declare module "bun" { blob(): Blob; } - export const $: Shell; + const $: Shell; interface TOML { /** @@ -4890,9 +4897,6 @@ declare module "bun" { // tslint:disable-next-line:unified-signatures arrayBufferToString(buffer: Uint16Array): string; - /** Mock bun's segfault handler. You probably don't want to use this */ - segfault(): void; - /** * Force the garbage collector to run extremely often, * especially inside `bun:test`. @@ -4909,6 +4913,11 @@ declare module "bun" { * @returns The previous level */ gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; + + /** + * Dump the mimalloc heap to the console + */ + mimallocDump(): void; } const unsafe: Unsafe; @@ -4930,7 +4939,7 @@ declare module "bun" { const enableANSIColors: boolean; /** - * What script launched bun? + * What script launched Bun? * * Absolute file path * @@ -5020,9 +5029,7 @@ declare module "bun" { */ function openInEditor(path: string, options?: EditorOptions): void; - var fetch: typeof globalThis.fetch & { - preconnect(url: string): void; - }; + var fetch: typeof globalThis.fetch; interface EditorOptions { editor?: "vscode" | "subl"; diff --git a/packages/bun-types/new/sink.d.ts b/packages/bun-types/new/sink.d.ts index e0ace23621c53e..d4557529193c5c 100644 --- a/packages/bun-types/new/sink.d.ts +++ b/packages/bun-types/new/sink.d.ts @@ -1,82 +1,86 @@ declare module "bun" { - /** - * 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; - /** - * Close the file descriptor. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; + /** + * 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; + /** + * Close the file descriptor. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; - start(options?: { - /** - * Preallocate an internal buffer of this size - * This can significantly improve performance when the chunk size is small - */ - highWaterMark?: number; - }): void; + 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. + * + * 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; - } + /** + * 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 NetworkSink extends FileSink { - /** - * Write a chunk of data to the network. - * - * If the network is not writable yet, the data is buffered. - */ - write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number; - /** - * Flush the internal buffer, committing the data to the network. - */ - flush(): number | Promise; - /** - * Finish the upload. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; + interface NetworkSink extends FileSink { + /** + * Write a chunk of data to the network. + * + * If the network is not writable yet, the data is buffered. + */ + write( + chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + ): number; + /** + * Flush the internal buffer, committing the data to the network. + */ + flush(): number | Promise; + /** + * Finish the upload. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; - /** - * Get the stat of the file. - */ - stat(): Promise; - } + /** + * Get the stat of the file. + */ + stat(): Promise; + } } diff --git a/src/js/builtins/shell.ts b/src/js/builtins/shell.ts index 8567a2cced810a..a88f4a6fec0d45 100644 --- a/src/js/builtins/shell.ts +++ b/src/js/builtins/shell.ts @@ -71,6 +71,7 @@ export function createBunShellTemplateFunction(createShellInterpreter, createPar stdout: Buffer; stderr: Buffer; exitCode: number; + constructor(stdout: Buffer, stderr: Buffer, exitCode: number) { this.stdout = stdout; this.stderr = stderr; diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index 52a2a9b41f16cd..195c545b32a4fb 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -4,7 +4,7 @@ "": { "name": "fixture", "dependencies": { - "@types/bun": "types-bun-1.2.4.tgz", + "@types/bun": "types-bun-1.2.5.tgz", }, "peerDependencies": { "typescript": "^5.0.0", @@ -12,7 +12,7 @@ }, }, "packages": { - "@types/bun": ["@types/bun@types-bun-1.2.4.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }], + "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }], "@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index f6fb2c061f353d..332059a376a4ba 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -42,6 +42,8 @@ Bun.fetch("", { Bun.S3Client; +Bun.$.ShellPromise; + new Bun.$.ShellError(); new Promise(resolve => { diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index 33e0b6344f11fb..61fc6d115f617c 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -9,6 +9,6 @@ }, "type": "module", "dependencies": { - "@types/bun": "types-bun-1.2.4.tgz" + "@types/bun": "types-bun-1.2.5.tgz" } } From 7d5de9989f5da5ee9454af178008e5f210cbb694 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 18:05:33 +0000 Subject: [PATCH 09/72] more stuff --- packages/bun-types/ffi.d.ts | 8 - packages/bun-types/new/bun.d.ts | 9 - packages/bun-types/new/devserver.d.ts | 136 ++ packages/bun-types/new/fetch.d.ts | 48 +- packages/bun-types/new/ffi.d.ts | 1168 +++++++++++++++++ packages/bun-types/new/globals.d.ts | 1239 ++++++++++++++++++- packages/bun-types/new/index.d.ts | 3 + packages/bun-types/new/ns.d.ts | 7 + packages/bun-types/new/overrides.d.ts | 17 + test/integration/bun-types/fixture/index.ts | 4 + 10 files changed, 2610 insertions(+), 29 deletions(-) create mode 100644 packages/bun-types/new/devserver.d.ts create mode 100644 packages/bun-types/new/ffi.d.ts create mode 100644 packages/bun-types/new/ns.d.ts create mode 100644 packages/bun-types/new/overrides.d.ts diff --git a/packages/bun-types/ffi.d.ts b/packages/bun-types/ffi.d.ts index c705348c8298bf..db21b4d03aa3d7 100644 --- a/packages/bun-types/ffi.d.ts +++ b/packages/bun-types/ffi.d.ts @@ -543,14 +543,6 @@ declare module "bun:ffi" { type Symbols = Readonly>; - // /** - // * Compile a callback function - // * - // * Returns a function pointer - // * - // */ - // export function callback(ffi: FFIFunction, cb: Function): number; - interface Library { symbols: ConvertFns; diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 0f545aa5f888d2..7231f3b9c12d57 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -16,11 +16,8 @@ declare module "bun" { type DistributedOmit = T extends T ? Omit : never; type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; - type ArrayBufferView = NodeJS.TypedArray | DataView; type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type PathLike = import("bun").PathLike; - type BodyInit = ReadableStream | XMLHttpRequestBodyInit | URLSearchParams; type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; type ReadableStreamController = ReadableStreamDefaultController; type ReadableStreamDefaultReadResult = @@ -95,12 +92,6 @@ declare module "bun" { value: unknown, ) => void; - type HeadersInit = - | Headers - | Record - | Array<[string, string]> - | IterableIterator<[string, string]>; - type ResponseType = | "basic" | "cors" diff --git a/packages/bun-types/new/devserver.d.ts b/packages/bun-types/new/devserver.d.ts new file mode 100644 index 00000000000000..81699996a7b9c9 --- /dev/null +++ b/packages/bun-types/new/devserver.d.ts @@ -0,0 +1,136 @@ +export {}; + +declare global { + interface ImportMeta { + /** + * Hot module replacement APIs. This value is `undefined` in production and + * can be used in an `if` statement to check if HMR APIs are available + * + * ```ts + * if (import.meta.hot) { + * // HMR APIs are available + * } + * ``` + * + * However, this check is usually not needed as Bun will dead-code-eliminate + * calls to all of the HMR APIs in production builds. + * + * https://bun.sh/docs/bundler/hmr + */ + hot: { + /** + * `import.meta.hot.data` maintains state between module instances during + * hot replacement, enabling data transfer from previous to new versions. + * When `import.meta.hot.data` is written to, Bun will mark this module as + * capable of self-accepting (equivalent of calling `accept()`). + * + * @example + * ```ts + * const root = import.meta.hot.data.root ??= createRoot(elem); + * root.render(); // re-use an existing root + * ``` + * + * In production, `data` is inlined to be `{}`. This is handy because Bun + * knows it can minify `{}.prop ??= value` into `value` in production. + * + * + */ + data: any; + + /** + * Indicate that this module can be replaced simply by re-evaluating the + * file. After a hot update, importers of this module will be + * automatically patched. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + * + * @example + * ```ts + * import { getCount } from "./foo"; + * + * console.log("count is ", getCount()); + * + * import.meta.hot.accept(); + * ``` + */ + accept(): void; + + /** + * Indicate that this module can be replaced by evaluating the new module, + * and then calling the callback with the new module. In this mode, the + * importers do not get patched. This is to match Vite, which is unable + * to patch their import statements. Prefer using `import.meta.hot.accept()` + * without an argument as it usually makes your code easier to understand. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + * + * @example + * ```ts + * export const count = 0; + * + * import.meta.hot.accept((newModule) => { + * if (newModule) { + * // newModule is undefined when SyntaxError happened + * console.log('updated: count is now ', newModule.count) + * } + * }); + * ``` + * + * In production, calls to this are dead-code-eliminated. + */ + accept(cb: (newModule: any | undefined) => void): void; + + /** + * Indicate that a dependency's module can be accepted. When the dependency + * is updated, the callback will be called with the new module. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + * + * @example + * ```ts + * import.meta.hot.accept('./foo', (newModule) => { + * if (newModule) { + * // newModule is undefined when SyntaxError happened + * console.log('updated: count is now ', newModule.count) + * } + * }); + * ``` + */ + accept(specifier: string, callback: (newModule: any) => void): void; + + /** + * Indicate that a dependency's module can be accepted. This variant + * accepts an array of dependencies, where the callback will receive + * the one updated module, and `undefined` for the rest. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + */ + accept( + specifiers: string[], + callback: (newModules: (any | undefined)[]) => void, + ): void; + + /** + * Attach an on-dispose callback. This is called: + * - Just before the module is replaced with another copy (before the next is loaded) + * - After the module is detached (removing all imports to this module) + * + * This callback is not called on route navigation or when the browser tab closes. + * + * Returning a promise will delay module replacement until the module is + * disposed. All dispose callbacks are called in parallel. + */ + dispose(cb: (data: any) => void | Promise): void; + + /** + * No-op + * @deprecated + */ + decline(): void; + }; + } +} diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts index 6b9da807c76fd3..73985e98ec728e 100644 --- a/packages/bun-types/new/fetch.d.ts +++ b/packages/bun-types/new/fetch.d.ts @@ -1,9 +1,35 @@ -type RequestInit = import("undici-types").RequestInit; -type HeadersInit = import("undici-types").HeadersInit; -type ResponseInit = import("undici-types").ResponseInit; -type BodyInit = import("undici-types").BodyInit; +type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; -interface Headers { +type HeadersInit = + | Headers + | Record + | Array<[string, string]> + | IterableIterator<[string, string]>; + +// Comes from @types/node as they're declared globally +interface RequestInit {} + +// Comes from @types/node as they're declared globally +interface ResponseInit {} + +declare module "bun" { + /** + * @internal + */ + type UndiciRequest = import("undici-types").Request; + + /** + * @internal + */ + type UndiciResponse = import("undici-types").Response; + + /** + * @internal + */ + type UndiciHeaders = import("undici-types").Headers; +} + +interface Headers extends Bun.UndiciHeaders { /** * Convert {@link Headers} to a plain JavaScript object. * @@ -43,17 +69,21 @@ declare var Headers: { new (init?: HeadersInit): Headers; }; -interface Request { +interface Request extends Bun.UndiciRequest { headers: Headers; } declare var Request: { prototype: Request; - new (requestInfo: string, requestInit?: RequestInit): Request; + new (requestInfo: string, init?: RequestInit): Request; new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, requestInit?: RequestInit): Request; + new (requestInfo: Request, init?: RequestInit): Request; }; +interface Response extends Bun.UndiciResponse { + headers: Headers; +} + declare var Response: { new ( body?: BodyInit | null | undefined, @@ -168,7 +198,7 @@ declare function fetch( * @returns A promise that resolves to {@link Response} object. */ declare function fetch( - input: string | URL | globalThis.Request, + input: string | URL | Request, init?: BunFetchRequestInit, ): Promise; diff --git a/packages/bun-types/new/ffi.d.ts b/packages/bun-types/new/ffi.d.ts new file mode 100644 index 00000000000000..db21b4d03aa3d7 --- /dev/null +++ b/packages/bun-types/new/ffi.d.ts @@ -0,0 +1,1168 @@ +/** + * `bun:ffi` lets you efficiently call C functions & FFI functions from JavaScript + * without writing bindings yourself. + * + * ```js + * import {dlopen, CString, ptr} from 'bun:ffi'; + * + * const lib = dlopen('libsqlite3', { + * }); + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ +declare module "bun:ffi" { + enum FFIType { + char = 0, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int8_t = 1, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i8 = 1, + + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint8_t = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u8 = 2, + + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int16_t = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i16 = 3, + + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint16_t = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u16 = 4, + + /** + * 32-bit signed integer + */ + int32_t = 5, + + /** + * 32-bit signed integer + * + * Alias of {@link FFIType.int32_t} + */ + i32 = 5, + /** + * 32-bit signed integer + * + * The same as `int` in C + * + * ```c + * int + * ``` + */ + int = 5, + + /** + * 32-bit unsigned integer + * + * The same as `unsigned int` in C (on x64 & arm64) + * + * C: + * ```c + * unsigned int + * ``` + * JavaScript: + * ```js + * ptr(new Uint32Array(1)) + * ``` + */ + uint32_t = 6, + /** + * 32-bit unsigned integer + * + * Alias of {@link FFIType.uint32_t} + */ + u32 = 6, + + /** + * int64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + int64_t = 7, + /** + * i64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + i64 = 7, + + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + uint64_t = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + u64 = 8, + + /** + * Doubles are not supported yet! + */ + double = 9, + /** + * Doubles are not supported yet! + */ + f64 = 9, + /** + * Floats are not supported yet! + */ + float = 10, + /** + * Floats are not supported yet! + */ + f32 = 10, + + /** + * Boolean value + * + * Must be `true` or `false`. `0` and `1` type coercion is not supported. + * + * In C, this corresponds to: + * ```c + * bool + * _Bool + * ``` + */ + bool = 11, + + /** + * Pointer value + * + * See {@link Bun.FFI.ptr} for more information + * + * In C: + * ```c + * void* + * ``` + * + * In JavaScript: + * ```js + * ptr(new Uint8Array(1)) + * ``` + */ + ptr = 12, + /** + * Pointer value + * + * alias of {@link FFIType.ptr} + */ + pointer = 12, + + /** + * void value + * + * void arguments are not supported + * + * void return type is the default return type + * + * In C: + * ```c + * void + * ``` + */ + void = 13, + + /** + * When used as a `returns`, this will automatically become a {@link CString}. + * + * When used in `args` it is equivalent to {@link FFIType.pointer} + */ + cstring = 14, + + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `int64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + i64_fast = 15, + + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `uint64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + u64_fast = 16, + function = 17, + + napi_env = 18, + napi_value = 19, + buffer = 20, + } + + type Pointer = number & { __pointer__: null }; + + interface FFITypeToArgsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: number | bigint; + [FFIType.i64]: number | bigint; + [FFIType.uint64_t]: number | bigint; + [FFIType.u64]: number | bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.void]: undefined; + [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | JSCallback; // cannot be null + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeToReturnsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: bigint; + [FFIType.i64]: bigint; + [FFIType.uint64_t]: bigint; + [FFIType.u64]: bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: Pointer | null; + [FFIType.pointer]: Pointer | null; + [FFIType.void]: undefined; + [FFIType.cstring]: CString; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | null; + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeStringToType { + ["char"]: FFIType.char; + ["int8_t"]: FFIType.int8_t; + ["i8"]: FFIType.i8; + ["uint8_t"]: FFIType.uint8_t; + ["u8"]: FFIType.u8; + ["int16_t"]: FFIType.int16_t; + ["i16"]: FFIType.i16; + ["uint16_t"]: FFIType.uint16_t; + ["u16"]: FFIType.u16; + ["int32_t"]: FFIType.int32_t; + ["i32"]: FFIType.i32; + ["int"]: FFIType.int; + ["uint32_t"]: FFIType.uint32_t; + ["u32"]: FFIType.u32; + ["int64_t"]: FFIType.int64_t; + ["i64"]: FFIType.i64; + ["uint64_t"]: FFIType.uint64_t; + ["u64"]: FFIType.u64; + ["double"]: FFIType.double; + ["f64"]: FFIType.f64; + ["float"]: FFIType.float; + ["f32"]: FFIType.f32; + ["bool"]: FFIType.bool; + ["ptr"]: FFIType.ptr; + ["pointer"]: FFIType.pointer; + ["void"]: FFIType.void; + ["cstring"]: FFIType.cstring; + ["function"]: FFIType.pointer; // for now + ["usize"]: FFIType.uint64_t; // for now + ["callback"]: FFIType.pointer; // for now + ["napi_env"]: FFIType.napi_env; + ["napi_value"]: FFIType.napi_value; + ["buffer"]: FFIType.buffer; + } + + type FFITypeOrString = FFIType | keyof FFITypeStringToType; + + interface FFIFunction { + /** + * Arguments to a FFI function (C ABI) + * + * Defaults to an empty array, which means no arguments. + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, FFIType, suffix } from "bun:ffi" + * + * const lib = dlopen(`adder.${suffix}`, { + * add: { + * // FFIType can be used or you can pass string labels. + * args: [FFIType.i32, "i32"], + * returns: "i32", + * }, + * }) + * lib.symbols.add(1, 2) + * ``` + * In C: + * ```c + * int add(int a, int b) { + * return a + b; + * } + * ``` + */ + readonly args?: readonly FFITypeOrString[]; + /** + * Return type to a FFI function (C ABI) + * + * Defaults to {@link FFIType.void} + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, CString } from "bun:ffi" + * + * const lib = dlopen('z', { + * version: { + * returns: "ptr", + * } + * }); + * console.log(new CString(lib.symbols.version())); + * ``` + * In C: + * ```c + * char* version() + * { + * return "1.0.0"; + * } + * ``` + */ + readonly returns?: FFITypeOrString; + + /** + * Function pointer to the native function + * + * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. + * This pointer should not be null (0). + * + * This is useful if the library has already been loaded + * or if the module is also using Node-API. + */ + readonly ptr?: Pointer | bigint; + + /** + * Can C/FFI code call this function from a separate thread? + * + * Only supported with {@link JSCallback}. + * + * This does not make the function run in a separate thread. It is still up to the application/library + * to run their code in a separate thread. + * + * By default, {@link JSCallback} calls are not thread-safe. Turning this on + * incurs a small performance penalty for every function call. That small + * performance penalty needs to be less than the performance gain from + * running the function in a separate thread. + * + * @default false + */ + readonly threadsafe?: boolean; + } + + type Symbols = Readonly>; + + interface Library { + symbols: ConvertFns; + + /** + * `dlclose` the library, unloading the symbols and freeing allocated memory. + * + * Once called, the library is no longer usable. + * + * Calling a function from a library that has been closed is undefined behavior. + */ + close(): void; + } + + type ToFFIType = T extends FFIType + ? T + : T extends string + ? FFITypeStringToType[T] + : never; + + const FFIFunctionCallableSymbol: unique symbol; + type ConvertFns = { + [K in keyof Fns]: { + ( + ...args: Fns[K]["args"] extends infer A extends + readonly FFITypeOrString[] + ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } + : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [unknown] extends [Fns[K]["args"]] + ? [] + : never + ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + ? undefined + : FFITypeToReturnsType[ToFFIType>]; + __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + }; + + /** + * Open a library using `"bun:ffi"` + * + * @param name The name of the library or file path. This will be passed to `dlopen()` + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import {dlopen} from 'bun:ffi'; + * + * const lib = dlopen("duckdb.dylib", { + * get_version: { + * returns: "cstring", + * args: [], + * }, + * }); + * lib.symbols.get_version(); + * // "1.0.0" + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function dlopen>( + name: string | import("bun").BunFile | URL, + symbols: Fns, + ): Library; + + /** + * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. + * + * @param options + * @returns Library + * + * @example + * ## Hello, World! + * + * JavaScript: + * ```js + * import { cc } from "bun:ffi"; + * import hello from "./hello.c" with {type: "file"}; + * const {symbols: {hello}} = cc({ + * source: hello, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * // "Hello, World!" + * console.log(hello()); + * ``` + * + * `./hello.c`: + * ```c + * #include + * const char* hello() { + * return "Hello, World!"; + * } + * ``` + */ + function cc>(options: { + /** + * File path to an ISO C11 source file to compile and link + */ + source: string | import("bun").BunFile | URL; + + /** + * Library names to link against + * + * Equivalent to `-l` option in gcc/clang. + */ + library?: string[] | string; + + /** + * Include directories to pass to the compiler + * + * Equivalent to `-I` option in gcc/clang. + */ + include?: string[] | string; + + /** + * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + */ + symbols: Fns; + + /** + * Map of symbols to define where the key is the symbol name and the value is the symbol value + * + * Equivalent to `-D` option in gcc/clang. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * define: { + * "NDEBUG": "1", + * }, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + define?: Record; + + /** + * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. + * + * @default "-std=c11 -Wl,--export-all-symbols -g -O2" + * + * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * flags: ["-framework CoreFoundation", "-framework Security"], + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + flags?: string | string[]; + }): Library; + + /** + * Turn a native library's function pointer into a JavaScript function + * + * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. + * + * @param fn {@link FFIFunction} declaration. `ptr` is required + * + * @example + * + * ```js + * import {CFunction} from 'bun:ffi'; + * + * const getVersion = new CFunction({ + * returns: "cstring", + * args: [], + * ptr: myNativeLibraryGetVersion, + * }); + * getVersion(); + * getVersion.close(); + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { + /** + * Free the memory allocated by the wrapping function + */ + close(): void; + }; + + /** + * Link a map of symbols to JavaScript functions + * + * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. + * + * You could use this with Node-API to skip loading a second time. + * + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import { linkSymbols } from "bun:ffi"; + * + * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); + * + * const lib = linkSymbols({ + * // Unlike with dlopen(), the names here can be whatever you want + * getMajor: { + * returns: "cstring", + * args: [], + * + * // Since this doesn't use dlsym(), you have to provide a valid ptr + * // That ptr could be a number or a bigint + * // An invalid pointer will crash your program. + * ptr: majorPtr, + * }, + * getMinor: { + * returns: "cstring", + * args: [], + * ptr: minorPtr, + * }, + * getPatch: { + * returns: "cstring", + * args: [], + * ptr: patchPtr, + * }, + * }); + * + * const [major, minor, patch] = [ + * lib.symbols.getMajor(), + * lib.symbols.getMinor(), + * lib.symbols.getPatch(), + * ]; + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function linkSymbols>( + symbols: Fns, + ): Library; + + /** + * Read a pointer as a {@link Buffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toBuffer( + ptr: Pointer, + byteOffset?: number, + byteLength?: number, + ): Buffer; + + /** + * Read a pointer as an {@link ArrayBuffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toArrayBuffer( + ptr: Pointer, + byteOffset?: number, + byteLength?: number, + ): ArrayBuffer; + + namespace read { + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f64(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function ptr(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function intptr(ptr: Pointer, byteOffset?: number): number; + } + + /** + * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} + * + * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. + * + * This is for use with FFI functions. For performance reasons, FFI will + * not automatically convert typed arrays to C pointers. + * + * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for + * @param {number} byteOffset optional offset into the view in bytes + * + * @example + * + * From JavaScript: + * ```js + * const array = new Uint8Array(10); + * const rawPtr = ptr(array); + * myFFIFunction(rawPtr); + * ``` + * To C: + * ```c + * void myFFIFunction(char* rawPtr) { + * // Do something with rawPtr + * } + * ``` + */ + function ptr( + view: NodeJS.TypedArray | ArrayBufferLike | DataView, + byteOffset?: number, + ): Pointer; + + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + + class CString extends String { + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @param ptr The pointer to the C string + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); + + /** + * The ptr to the C string + * + * This `CString` instance is a clone of the string, so it + * is safe to continue using this instance after the `ptr` has been + * freed. + */ + ptr: Pointer; + byteOffset?: number; + byteLength?: number; + + /** + * Get the {@link ptr} as an `ArrayBuffer` + * + * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 + */ + get arrayBuffer(): ArrayBuffer; + } + + /** + * Pass a JavaScript function to FFI (Foreign Function Interface) + */ + class JSCallback { + /** + * Enable a JavaScript callback function to be passed to C with bun:ffi + * + * @param callback The JavaScript function to be called + * @param definition The C function definition + */ + constructor(callback: (...args: any[]) => any, definition: FFIFunction); + + /** + * The pointer to the C function + * + * Becomes `null` once {@link JSCallback.prototype.close} is called + */ + readonly ptr: Pointer | null; + + /** + * Can the callback be called from a different thread? + */ + readonly threadsafe: boolean; + + /** + * Free the memory allocated for the callback + * + * If called multiple times, does nothing after the first call. + */ + close(): void; + } + + /** + * View the generated C code for FFI bindings + * + * You probably won't need this unless there's a bug in the FFI bindings + * generator or you're just curious. + */ + function viewSource(symbols: Symbols, is_callback?: false): string[]; + function viewSource(callback: FFIFunction, is_callback: true): string; + + /** + * Platform-specific file extension name for dynamic libraries + * + * "." is not included + * + * @example + * ```js + * "dylib" // macOS + * ``` + * + * @example + * ```js + * "so" // linux + * ``` + */ + const suffix: string; +} diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index ed80aca6b6bb5e..204e8e61be89c1 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -1,5 +1,1238 @@ -import * as BunModule from "bun"; +interface ReadableStream {} +var ReadableStream: { + prototype: ReadableStream; + new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; +}; -declare global { - export import Bun = BunModule; +interface WritableStream {} +var WritableStream: { + prototype: WritableStream; + new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; +}; + +interface Worker {} +var Worker: { + prototype: Worker; + new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; +}; + +var WebSocket: typeof import("ws").WebSocket; + +interface Crypto {} +var Crypto: { + prototype: Crypto; + new (): Crypto; +}; + +var crypto: Crypto; + +/** + * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All + * instances of `TextEncoder` only support UTF-8 encoding. + * + * ```js + * const encoder = new TextEncoder(); + * const uint8array = encoder.encode('this is some data'); + * ``` + */ +interface TextEncoder extends Bun.TextEncoder {} +var TextEncoder: typeof TextEncoder; + +interface TextDecoder extends Bun.TextDecoder {} +var TextDecoder: typeof TextDecoder; + +type _Performance = import("perf_hooks").Performance; +interface Performance extends _Performance {} +var performance: Performance; + +interface Event { + /** This is not used in Node.js and is provided purely for completeness. */ + readonly bubbles: boolean; + /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ + cancelBubble: () => void; + /** True if the event was created with the cancelable option */ + readonly cancelable: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly composed: boolean; + /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ + composedPath(): [EventTarget?]; + /** Alias for event.target. */ + readonly currentTarget: EventTarget | null; + /** Is true if cancelable is true and event.preventDefault() has been called. */ + readonly defaultPrevented: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly eventPhase: 0 | 2; + /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ + readonly isTrusted: boolean; + /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ + preventDefault(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + returnValue: boolean; + /** Alias for event.target. */ + readonly srcElement: EventTarget | null; + /** Stops the invocation of event listeners after the current one completes. */ + stopImmediatePropagation(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + stopPropagation(): void; + /** The `EventTarget` dispatching the event */ + readonly target: EventTarget | null; + /** The millisecond timestamp when the Event object was created. */ + readonly timeStamp: number; + /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ + readonly type: string; +} +var Event: { + prototype: Event; + new (type: string, eventInitDict?: Bun.EventInit): Event; +}; + +interface EventTarget { + /** + * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. + * + * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. + * + * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. + * Specifically, the `capture` option is used as part of the key when registering a `listener`. + * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. + */ + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ + dispatchEvent(event: Event): boolean; + /** Removes the event listener in target's event listener list with the same type, callback, and options. */ + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; +} +var EventTarget: { + prototype: EventTarget; + new (): EventTarget; +}; + +interface File extends Blob { + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; + readonly lastModified: number; + readonly name: string; +} + +var File: typeof File; + +type _RequestInit = import("undici-types").RequestInit; +interface RequestInit extends _RequestInit { + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: import("bun").S3Options; +} + +/** + * ShadowRealms are a distinct global environment, with its own global object + * containing its own intrinsics and built-ins (standard objects that are not + * bound to global variables, like the initial value of Object.prototype). + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ +interface ShadowRealm { + /** + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; +} + +var ShadowRealm: { + prototype: ShadowRealm; + new (): ShadowRealm; +}; + +function queueMicrotask(callback: (...args: any[]) => void): void; +/** + * Log an error using the default exception handler + * @param error Error or string + */ +function reportError(error: any): void; + +interface Timer { + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; + + [Symbol.toPrimitive](): number; +} + +/** + * Cancel a repeating timer by its timer ID. + * @param id timer id + */ +function clearInterval(id?: number | Timer): void; +/** + * Cancel a delayed function call by its timer ID. + * @param id timer id + */ +function clearTimeout(id?: number | Timer): void; +/** + * Cancel an immediate function call by its immediate ID. + * @param id immediate id + */ +function clearImmediate(id?: number | Timer): void; +/** + * Run a function immediately after main event loop is vacant + * @param handler function to call + */ +function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; +/** + * Run a function every `interval` milliseconds + * @param handler function to call + * @param interval milliseconds to wait between calls + */ +function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; +/** + * Run a function after `timeout` (milliseconds) + * @param handler function to call + * @param timeout milliseconds to wait between calls + */ +function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; + +function addEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | AddEventListenerOptions, +): void; +function addEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, +): void; +function removeEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | Bun.EventListenerOptions, +): void; +function removeEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | Bun.EventListenerOptions, +): void; + +/** + * Events providing information related to errors in scripts or in files. + */ +interface ErrorEvent extends Event { + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; +} + +var ErrorEvent: { + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; +}; + +/** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ +interface CloseEvent extends Event { + /** Returns the WebSocket connection close code provided by the server. */ + readonly code: number; + /** Returns the WebSocket connection close reason provided by the server. */ + readonly reason: string; + /** Returns true if the connection closed cleanly; false otherwise. */ + readonly wasClean: boolean; +} + +var CloseEvent: { + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; +}; + +interface MessageEvent extends Bun.MessageEvent {} +var MessageEvent: { + prototype: MessageEvent; + new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; +}; + +interface CustomEvent extends Event { + /** Returns any custom data event was created with. Typically used for synthetic events. */ + readonly detail: T; +} + +var CustomEvent: { + prototype: CustomEvent; + new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; +}; + +// /** +// * The URL interface represents an object providing static methods used for +// * creating object URLs. +// */ +// interface URL extends _URL { +// new (url: string | URL, base?: string | URL): URL; +// /** Not implemented yet */ +// createObjectURL(obj: Blob): string; +// /** Not implemented yet */ +// revokeObjectURL(url: string): void; + +// /** +// * Check if `url` is a valid URL string +// * +// * @param url URL string to parse +// * @param base URL to resolve against +// */ +// canParse(url: string, base?: string): boolean; +// } + +interface EventListener { + (evt: Event): void; +} + +interface EventListenerObject { + handleEvent(object: Event): void; +} + +interface FetchEvent extends Event { + readonly request: Request; + readonly url: string; + + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; +} + +interface EventMap { + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; + // exit: Event; +} + +interface AddEventListenerOptions extends Bun.EventListenerOptions { + once?: boolean; + passive?: boolean; + signal?: AbortSignal; +} + +/** + * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) + * + * Before using this, be aware of a few things: + * + * **Using this incorrectly will crash your application**. + * + * This API may change any time JavaScriptCore is updated. + * + * Bun may rewrite ESM import specifiers to point to bundled code. This will + * be confusing when using this API, as it will return a string like + * "/node_modules.server.bun". + * + * Bun may inject additional imports into your code. This usually has a `bun:` prefix. + */ +var Loader: { + /** + * ESM module registry + * + * This lets you implement live reload in Bun. If you + * delete a module specifier from this map, the next time it's imported, it + * will be re-transpiled and loaded again. + * + * The keys are the module specifiers and the + * values are metadata about the module. + * + * The keys are an implementation detail for Bun that will change between + * versions. + * + * - Userland modules are an absolute file path + * - Virtual modules have a `bun:` prefix or `node:` prefix + * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill + * - If you have a `node_modules.bun` file, many modules will point to that file + * + * Virtual modules and JS polyfills are embedded in bun's binary. They don't + * point to anywhere in your local filesystem. + */ + registry: Map< + string, + { + key: string; + /** + * This refers to the state the ESM module is in + * + * TODO: make an enum for this number + */ + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; + /** + * Your application will probably crash if you mess with this. + */ + module: { + dependenciesMap: (typeof Loader)["registry"]; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; + /** + * For an already-evaluated module, return the dependencies as module specifiers + * + * This list is already sorted and uniqued. + * + * @example + * + * For this code: + * ```js + * // /foo.js + * import classNames from 'classnames'; + * import React from 'react'; + * import {createElement} from 'react'; + * ``` + * + * This would return: + * ```js + * Loader.dependencyKeysIfEvaluated("/foo.js") + * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] + * ``` + * + * @param specifier - module specifier as it appears in transpiled source code + */ + dependencyKeysIfEvaluated: (specifier: string) => string[]; + /** + * The function JavaScriptCore internally calls when you use an import statement. + * + * This may return a path to `node_modules.server.bun`, which will be confusing. + * + * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} + * instead. + * + * @param specifier - module specifier as it appears in transpiled source code + * @param referrer - module specifier that is resolving this specifier + */ + resolve: (specifier: string, referrer: string) => string; +}; + +interface QueuingStrategy { + highWaterMark?: number; + size?: QueuingStrategySize; +} + +interface QueuingStrategyInit { + /** + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. + */ + highWaterMark: number; +} + +/** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ +interface ByteLengthQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + // changed from QueuingStrategySize + // to avoid conflict with lib.dom.d.ts + readonly size: QueuingStrategySize; +} + +var ByteLengthQueuingStrategy: { + prototype: ByteLengthQueuingStrategy; + new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; +}; + +interface ReadableStreamDefaultController { + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; +} + +interface ReadableStreamDirectController { + close(error?: Error): void; + write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; + end(): number | Promise; + flush(): number | Promise; + start(): void; +} + +var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; +}; + +interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { + read(): Promise>; + /** + * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. + * Will only return a promise if the data is not immediately available. + */ + readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; + releaseLock(): void; +} + +var ReadableStreamDefaultReader: { + prototype: ReadableStreamDefaultReader; + new (stream: ReadableStream): ReadableStreamDefaultReader; +}; + +interface ReadableStreamGenericReader { + readonly closed: Promise; + cancel(reason?: any): Promise; +} + +interface ReadableStreamDefaultReadDoneResult { + done: true; + value?: undefined; +} + +interface ReadableStreamDefaultReadValueResult { + done: false; + value: T; +} + +interface ReadableWritablePair { + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; +} + +interface WritableStreamDefaultController { + error(e?: any): void; +} + +var WritableStreamDefaultController: { + prototype: WritableStreamDefaultController; + new (): WritableStreamDefaultController; +}; + +/** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ +interface WritableStreamDefaultWriter { + readonly closed: Promise; + readonly desiredSize: number | null; + readonly ready: Promise; + abort(reason?: any): Promise; + close(): Promise; + releaseLock(): void; + write(chunk?: W): Promise; +} + +var WritableStreamDefaultWriter: { + prototype: WritableStreamDefaultWriter; + new (stream: WritableStream): WritableStreamDefaultWriter; +}; + +interface TransformStream { + readonly readable: ReadableStream; + readonly writable: WritableStream; +} + +var TransformStream: { + prototype: TransformStream; + new ( + transformer?: Transformer, + writableStrategy?: QueuingStrategy, + readableStrategy?: QueuingStrategy, + ): TransformStream; +}; + +interface TransformStreamDefaultController { + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; } + +var TransformStreamDefaultController: { + prototype: TransformStreamDefaultController; + new (): TransformStreamDefaultController; +}; + +interface StreamPipeOptions { + preventAbort?: boolean; + preventCancel?: boolean; + /** + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + * + * Errors and closures of the source and destination streams propagate as follows: + * + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. + * + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. + * + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. + * + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. + */ + preventClose?: boolean; + signal?: AbortSignal; +} + +/** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ +interface CountQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + readonly size: QueuingStrategySize; +} + +var CountQueuingStrategy: { + prototype: CountQueuingStrategy; + new (init: QueuingStrategyInit): CountQueuingStrategy; +}; + +interface QueuingStrategySize { + (chunk?: T): number; +} + +interface Transformer { + flush?: Bun.TransformerFlushCallback; + readableType?: undefined; + start?: Bun.TransformerStartCallback; + transform?: Bun.TransformerTransformCallback; + writableType?: undefined; +} + +interface Dict { + [key: string]: T | undefined; +} + +interface ReadOnlyDict { + readonly [key: string]: T | undefined; +} + +interface ErrnoException extends Error { + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; +} + +/** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ +interface DOMException extends Error { + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; +} + +var DOMException: { + prototype: DOMException; + new (message?: string, name?: string): DOMException; +}; + +function alert(message?: string): void; +function confirm(message?: string): boolean; +function prompt(message?: string, _default?: string): string | null; + +type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; +var SubtleCrypto: { + prototype: _SubtleCrypto; + new (): _SubtleCrypto; +}; + +type _CryptoKey = import("crypto").webcrypto.CryptoKey; +interface CryptoKey extends _CryptoKey {} +var CryptoKey: { + prototype: CryptoKey; + new (): CryptoKey; +}; + +interface Position { + lineText: string; + file: string; + namespace: string; + line: number; + column: number; + length: number; + offset: number; +} + +class ResolveMessage { + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; +} + +class BuildMessage { + readonly name: "BuildMessage"; + readonly position: Position | null; + readonly message: string; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; +} + +// Declare "static" methods in Error +interface ErrorConstructor { + /** Create .stack property on a target object */ + // eslint-disable-next-line @typescript-eslint/ban-types + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; + + stackTraceLimit: number; +} + +interface ArrayBufferConstructor { + new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; +} + +interface ArrayBuffer { + /** + * Read-only. The length of the ArrayBuffer (in bytes). + */ + readonly byteLength: number; + /** + * Resize an ArrayBuffer in-place. + */ + resize(byteLength: number): ArrayBuffer; + + /** + * Returns a section of an ArrayBuffer. + */ + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; +} + +interface SharedArrayBuffer { + /** + * Grow the SharedArrayBuffer in-place. + */ + grow(size: number): SharedArrayBuffer; +} + +interface ArrayConstructor { + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; + + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. Results of the map function are also awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * await Array.fromAsync([1], (n) => n + 1); // [2] + * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. + * @param thisArg - The `this` to which `mapFn` is bound. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; +} + +interface ConsoleOptions { + stdout: import("stream").Writable; + stderr?: import("stream").Writable; + ignoreErrors?: boolean; + colorMode?: boolean | "auto"; + inspectOptions?: import("util").InspectOptions; + groupIndentation?: number; +} + +interface Console { + /** + * Asynchronously read lines from standard input (fd 0) + * + * ```ts + * for await (const line of console) { + * console.log(line); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterableIterator; + + /** + * Write text or bytes to stdout + * + * Unlike {@link console.log}, this does no formatting and doesn't add a + * newline or spaces between arguments. You can pass it strings or bytes or + * any combination of the two. + * + * ```ts + * console.write("hello world!", "\n"); // "hello world\n" + * ``` + * + * @param data - The data to write + * @returns The number of bytes written + * + * This function is not available in the browser. + */ + write(...data: Array): number; + + /** + * Clear the console + */ + clear(): void; + + assert(condition?: boolean, ...data: any[]): void; + + /** + * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) + * @param label label counter + */ + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: any): void; + dirxml(...data: any[]): void; + /** + * Log to stderr in your terminal + * + * Appears in red + * + * @param data something to display + */ + error(...data: any[]): void; + /** Does nothing currently */ + group(...data: any[]): void; + /** Does nothing currently */ + groupCollapsed(...data: any[]): void; + /** Does nothing currently */ + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + /** + * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just + * logging the argument if it can't be parsed as tabular. + * + * ```js + * // These can't be parsed as tabular data + * console.table(Symbol()); + * // Symbol() + * + * console.table(undefined); + * // undefined + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ b โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * ``` + * @param properties Alternate properties for constructing the table. + */ + table(tabularData?: any, properties?: string[]): void; + /** + * Begin a timer to log with {@link console.timeEnd} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + time(label?: string): void; + /** + * End a timer to log with {@link console.time} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + timeStamp(label?: string): void; + trace(...data: any[]): void; + warn(...data: any[]): void; + + /** + * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. + */ + // Console: { + // new (options: ConsoleOptions): Console; + // new ( + // stdout: import("stream").Writable, + // stderr?: import("stream").Writable, + // ignoreErrors?: boolean, + // ): Console; + // }; +} + +var console: Console; + +interface ImportMeta { + /** + * `file://` url string for the current module. + * + * @example + * ```ts + * console.log(import.meta.url); + * "file:///Users/me/projects/my-app/src/my-app.ts" + * ``` + */ + url: string; + /** + * Absolute path to the source file + */ + readonly path: string; + /** + * Absolute path to the directory containing the source file. + * + * Does not have a trailing slash + */ + readonly dir: string; + /** + * Filename of the source file + */ + readonly file: string; + /** + * The environment variables of the process + * + * ```ts + * import.meta.env === process.env + * ``` + */ + readonly env: NodeJS.ProcessEnv; + + /** + * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead + * + * Resolve a module ID the same as if you imported it + * + * The `parent` argument is optional, and defaults to the current module's path. + */ + resolveSync(moduleId: string, parent?: string): string; + + /** + * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all + * calls to `require` with `import.meta.require` when transpiling ES Modules + * for the runtime. + * + * Warning: **This API is not stable** and may change or be removed in the + * future. Use at your own risk. + */ + require: NodeJS.Require; + + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; + + /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ + dirname: string; + + /** Alias of `import.meta.path`. Exists for Node.js compatibility */ + filename: string; +} + +/** + * NodeJS-style `require` function + * + * @param moduleId - The module ID to resolve + */ +var require: NodeJS.Require; + +/** Same as module.exports */ +var exports: any; + +interface NodeModule { + exports: any; +} + +var module: NodeModule; + +/** + * Creates a deep clone of an object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) + */ +function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; + +/** + * Post a message to the parent thread. + * + * Only useful in a worker thread; calling this from the main thread does nothing. + */ +function postMessage(message: any, transfer?: Bun.Transferable[]): void; + +interface EventSourceInit { + withCredentials?: boolean; +} + +interface PromiseConstructor { + /** + * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called + * separately. + * + * This is useful when you want to return a Promise and have code outside the Promise + * resolve or reject it. + * + * ## Example + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); + * + * setTimeout(() => { + * resolve("Hello world!"); + * }, 1000); + * + * await promise; // "Hello world!" + * ``` + * + * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). + */ + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; +} + +interface Navigator { + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; +} + +var navigator: Navigator; + +interface BlobPropertyBag { + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; +} + +interface Blob { + /** + * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + */ + new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; + /** + * Read the data from the blob as a JSON object. + * + * This first decodes the data from UTF-8, then parses it as JSON. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + json(): Promise; + + /** + * Read the data from the blob as a {@link FormData} object. + * + * This first decodes the data from UTF-8, then parses it as a + * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. + * + * The `type` property of the blob is used to determine the format of the + * body. + * + * This is a non-standard addition to the `Blob` API, to make it conform more + * closely to the `BodyMixin` API. + */ + formData(): Promise; + + arrayBuffer(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + */ + bytes(): Promise; +} + +declare var Blob: typeof Blob; diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index b514b45cff81b6..6d95c866552734 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -10,5 +10,8 @@ /// /// /// +/// +/// +/// declare var onmessage: never; diff --git a/packages/bun-types/new/ns.d.ts b/packages/bun-types/new/ns.d.ts new file mode 100644 index 00000000000000..d55c3f5352c60a --- /dev/null +++ b/packages/bun-types/new/ns.d.ts @@ -0,0 +1,7 @@ +import * as BunModule from "bun"; + +declare global { + export import Bun = BunModule; +} + +export {}; diff --git a/packages/bun-types/new/overrides.d.ts b/packages/bun-types/new/overrides.d.ts new file mode 100644 index 00000000000000..b150e1c1a32824 --- /dev/null +++ b/packages/bun-types/new/overrides.d.ts @@ -0,0 +1,17 @@ +export {}; // `declare global` requires the ambient file to be a module + +declare global { + namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; + + /** Whether you are using Bun */ + isBun: true; + /** The current git sha of Bun **/ + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + } +} diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 332059a376a4ba..af380b5674527c 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -75,6 +75,8 @@ r.method; r.body; r.headers.get("content-type"); +new Request("", {}); + await r.json(); await r.text(); @@ -153,6 +155,8 @@ Response.redirect("bun.sh", { Bun.fetch.preconnect; +type g = BodyInit; + Bun.fetch("", { proxy: "", s3: { From d9353e15e5bf5ca80cccc90865c399681793ccb5 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 18:23:39 +0000 Subject: [PATCH 10/72] Use Bun.__internal to hide extended imports that dont create ugly `_Type`s --- .../bun-types/new/{ns.d.ts => bun.ns.d.ts} | 2 +- packages/bun-types/new/fetch.d.ts | 36 +- packages/bun-types/new/globals.d.ts | 1820 +++++++++-------- packages/bun-types/new/index.d.ts | 3 +- packages/bun-types/new/overrides.d.ts | 24 +- test/integration/bun-types/fixture/index.ts | 11 + 6 files changed, 979 insertions(+), 917 deletions(-) rename packages/bun-types/new/{ns.d.ts => bun.ns.d.ts} (66%) diff --git a/packages/bun-types/new/ns.d.ts b/packages/bun-types/new/bun.ns.d.ts similarity index 66% rename from packages/bun-types/new/ns.d.ts rename to packages/bun-types/new/bun.ns.d.ts index d55c3f5352c60a..629bcf1e4642f6 100644 --- a/packages/bun-types/new/ns.d.ts +++ b/packages/bun-types/new/bun.ns.d.ts @@ -1,7 +1,7 @@ import * as BunModule from "bun"; declare global { - export import Bun = BunModule; + export import Bun = BunModule; } export {}; diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts index 73985e98ec728e..f938c9f2fc972f 100644 --- a/packages/bun-types/new/fetch.d.ts +++ b/packages/bun-types/new/fetch.d.ts @@ -13,23 +13,25 @@ interface RequestInit {} interface ResponseInit {} declare module "bun" { - /** - * @internal - */ - type UndiciRequest = import("undici-types").Request; - - /** - * @internal - */ - type UndiciResponse = import("undici-types").Response; - - /** - * @internal - */ - type UndiciHeaders = import("undici-types").Headers; + namespace __internal { + /** + * @internal + */ + type UndiciRequest = import("undici-types").Request; + + /** + * @internal + */ + type UndiciResponse = import("undici-types").Response; + + /** + * @internal + */ + type UndiciHeaders = import("undici-types").Headers; + } } -interface Headers extends Bun.UndiciHeaders { +interface Headers extends Bun.__internal.UndiciHeaders { /** * Convert {@link Headers} to a plain JavaScript object. * @@ -69,7 +71,7 @@ declare var Headers: { new (init?: HeadersInit): Headers; }; -interface Request extends Bun.UndiciRequest { +interface Request extends Bun.__internal.UndiciRequest { headers: Headers; } @@ -80,7 +82,7 @@ declare var Request: { new (requestInfo: Request, init?: RequestInit): Request; }; -interface Response extends Bun.UndiciResponse { +interface Response extends Bun.__internal.UndiciResponse { headers: Headers; } diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 204e8e61be89c1..56d285d9589528 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -1,37 +1,55 @@ interface ReadableStream {} -var ReadableStream: { - prototype: ReadableStream; - new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; +declare var ReadableStream: { + prototype: ReadableStream; + new ( + underlyingSource?: Bun.UnderlyingSource, + strategy?: QueuingStrategy, + ): ReadableStream; + new ( + underlyingSource?: Bun.DirectUnderlyingSource, + strategy?: QueuingStrategy, + ): ReadableStream; }; interface WritableStream {} -var WritableStream: { - prototype: WritableStream; - new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; +declare var WritableStream: { + prototype: WritableStream; + new ( + underlyingSink?: Bun.UnderlyingSink, + strategy?: QueuingStrategy, + ): WritableStream; }; -interface Worker {} -var Worker: { - prototype: Worker; - new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; +declare module "bun" { + namespace __internal { + type NodeWorkerThreadsWorker = import("worker_threads").Worker; + } +} + +interface Worker extends Bun.__internal.NodeWorkerThreadsWorker {} +declare var Worker: { + prototype: Worker; + new ( + scriptURL: string | URL, + options?: Bun.WorkerOptions | undefined, + ): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; }; -var WebSocket: typeof import("ws").WebSocket; +declare var WebSocket: typeof import("ws").WebSocket; interface Crypto {} -var Crypto: { - prototype: Crypto; - new (): Crypto; +declare var Crypto: { + prototype: Crypto; + new (): Crypto; }; -var crypto: Crypto; +declare var crypto: Crypto; /** * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All @@ -43,119 +61,139 @@ var crypto: Crypto; * ``` */ interface TextEncoder extends Bun.TextEncoder {} -var TextEncoder: typeof TextEncoder; +declare var TextEncoder: { + prototype: TextEncoder; + new (): TextEncoder; +}; +/** + * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextDecoder` API. All + * instances of `TextDecoder` only support UTF-8 decoding. + * + * ```js + * const decoder = new TextDecoder(); + * const uint8array = decoder.decode('this is some data'); + */ interface TextDecoder extends Bun.TextDecoder {} -var TextDecoder: typeof TextDecoder; +declare var TextDecoder: { + prototype: TextDecoder; + new (): TextDecoder; +}; type _Performance = import("perf_hooks").Performance; interface Performance extends _Performance {} -var performance: Performance; +declare var performance: Performance; interface Event { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly bubbles: boolean; + /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ + cancelBubble: () => void; + /** True if the event was created with the cancelable option */ + readonly cancelable: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly composed: boolean; + /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ + composedPath(): [EventTarget?]; + /** Alias for event.target. */ + readonly currentTarget: EventTarget | null; + /** Is true if cancelable is true and event.preventDefault() has been called. */ + readonly defaultPrevented: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly eventPhase: 0 | 2; + /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ + readonly isTrusted: boolean; + /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ + preventDefault(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + returnValue: boolean; + /** Alias for event.target. */ + readonly srcElement: EventTarget | null; + /** Stops the invocation of event listeners after the current one completes. */ + stopImmediatePropagation(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + stopPropagation(): void; + /** The `EventTarget` dispatching the event */ + readonly target: EventTarget | null; + /** The millisecond timestamp when the Event object was created. */ + readonly timeStamp: number; + /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ + readonly type: string; } -var Event: { - prototype: Event; - new (type: string, eventInitDict?: Bun.EventInit): Event; +declare var Event: { + prototype: Event; + new (type: string, eventInitDict?: Bun.EventInit): Event; }; interface EventTarget { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; + /** + * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. + * + * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. + * + * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. + * Specifically, the `capture` option is used as part of the key when registering a `listener`. + * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. + */ + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ + dispatchEvent(event: Event): boolean; + /** Removes the event listener in target's event listener list with the same type, callback, and options. */ + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; } -var EventTarget: { - prototype: EventTarget; - new (): EventTarget; +declare var EventTarget: { + prototype: EventTarget; + new (): EventTarget; }; interface File extends Blob { - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; - readonly lastModified: number; - readonly name: string; + readonly lastModified: number; + readonly name: string; } -var File: typeof File; +declare var File: { + prototype: File; + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new ( + parts: Bun.BlobPart[], + name: string, + options?: BlobPropertyBag & { lastModified?: Date | number }, + ): File; +}; type _RequestInit = import("undici-types").RequestInit; interface RequestInit extends _RequestInit { - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: import("bun").S3Options; + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: import("bun").S3Options; } /** @@ -198,216 +236,210 @@ interface RequestInit extends _RequestInit { * ``` */ interface ShadowRealm { - /** - * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; + /** + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; } -var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; +declare var ShadowRealm: { + prototype: ShadowRealm; + new (): ShadowRealm; }; -function queueMicrotask(callback: (...args: any[]) => void): void; +declare function queueMicrotask(callback: (...args: any[]) => void): void; /** * Log an error using the default exception handler * @param error Error or string */ -function reportError(error: any): void; +declare function reportError(error: any): void; interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; - [Symbol.toPrimitive](): number; + [Symbol.toPrimitive](): number; } /** * Cancel a repeating timer by its timer ID. * @param id timer id */ -function clearInterval(id?: number | Timer): void; +declare function clearInterval(id?: number | Timer): void; /** * Cancel a delayed function call by its timer ID. * @param id timer id */ -function clearTimeout(id?: number | Timer): void; +declare function clearTimeout(id?: number | Timer): void; /** * Cancel an immediate function call by its immediate ID. * @param id immediate id */ -function clearImmediate(id?: number | Timer): void; +declare function clearImmediate(id?: number | Timer): void; /** * Run a function immediately after main event loop is vacant * @param handler function to call */ -function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; +declare function setImmediate( + handler: Bun.TimerHandler, + ...arguments: any[] +): Timer; /** * Run a function every `interval` milliseconds * @param handler function to call * @param interval milliseconds to wait between calls */ -function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; +declare function setInterval( + handler: Bun.TimerHandler, + interval?: number, + ...arguments: any[] +): Timer; /** * Run a function after `timeout` (milliseconds) * @param handler function to call * @param timeout milliseconds to wait between calls */ -function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; - -function addEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | AddEventListenerOptions, +declare function setTimeout( + handler: Bun.TimerHandler, + timeout?: number, + ...arguments: any[] +): Timer; + +declare function addEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | AddEventListenerOptions, ): void; -function addEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, +declare function addEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, ): void; -function removeEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | Bun.EventListenerOptions, +declare function removeEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | Bun.EventListenerOptions, ): void; -function removeEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | Bun.EventListenerOptions, +declare function removeEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | Bun.EventListenerOptions, ): void; /** * Events providing information related to errors in scripts or in files. */ interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; } -var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; +declare var ErrorEvent: { + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; }; /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ interface CloseEvent extends Event { - /** Returns the WebSocket connection close code provided by the server. */ - readonly code: number; - /** Returns the WebSocket connection close reason provided by the server. */ - readonly reason: string; - /** Returns true if the connection closed cleanly; false otherwise. */ - readonly wasClean: boolean; + /** Returns the WebSocket connection close code provided by the server. */ + readonly code: number; + /** Returns the WebSocket connection close reason provided by the server. */ + readonly reason: string; + /** Returns true if the connection closed cleanly; false otherwise. */ + readonly wasClean: boolean; } -var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; +declare var CloseEvent: { + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; }; interface MessageEvent extends Bun.MessageEvent {} -var MessageEvent: { - prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; +declare var MessageEvent: { + prototype: MessageEvent; + new ( + type: string, + eventInitDict?: Bun.MessageEventInit, + ): MessageEvent; }; interface CustomEvent extends Event { - /** Returns any custom data event was created with. Typically used for synthetic events. */ - readonly detail: T; + /** Returns any custom data event was created with. Typically used for synthetic events. */ + readonly detail: T; } -var CustomEvent: { - prototype: CustomEvent; - new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; +declare var CustomEvent: { + prototype: CustomEvent; + new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; }; -// /** -// * The URL interface represents an object providing static methods used for -// * creating object URLs. -// */ -// interface URL extends _URL { -// new (url: string | URL, base?: string | URL): URL; -// /** Not implemented yet */ -// createObjectURL(obj: Blob): string; -// /** Not implemented yet */ -// revokeObjectURL(url: string): void; - -// /** -// * Check if `url` is a valid URL string -// * -// * @param url URL string to parse -// * @param base URL to resolve against -// */ -// canParse(url: string, base?: string): boolean; -// } - interface EventListener { - (evt: Event): void; + (evt: Event): void; } interface EventListenerObject { - handleEvent(object: Event): void; + handleEvent(object: Event): void; } interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; + readonly request: Request; + readonly url: string; - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; } interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; - // exit: Event; + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; + // exit: Event; } interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; + once?: boolean; + passive?: boolean; + signal?: AbortSignal; } /** @@ -425,699 +457,710 @@ interface AddEventListenerOptions extends Bun.EventListenerOptions { * * Bun may inject additional imports into your code. This usually has a `bun:` prefix. */ -var Loader: { - /** - * ESM module registry - * - * This lets you implement live reload in Bun. If you - * delete a module specifier from this map, the next time it's imported, it - * will be re-transpiled and loaded again. - * - * The keys are the module specifiers and the - * values are metadata about the module. - * - * The keys are an implementation detail for Bun that will change between - * versions. - * - * - Userland modules are an absolute file path - * - Virtual modules have a `bun:` prefix or `node:` prefix - * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill - * - If you have a `node_modules.bun` file, many modules will point to that file - * - * Virtual modules and JS polyfills are embedded in bun's binary. They don't - * point to anywhere in your local filesystem. - */ - registry: Map< - string, - { - key: string; - /** - * This refers to the state the ESM module is in - * - * TODO: make an enum for this number - */ - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; - /** - * Your application will probably crash if you mess with this. - */ - module: { - dependenciesMap: (typeof Loader)["registry"]; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - /** - * For an already-evaluated module, return the dependencies as module specifiers - * - * This list is already sorted and uniqued. - * - * @example - * - * For this code: - * ```js - * // /foo.js - * import classNames from 'classnames'; - * import React from 'react'; - * import {createElement} from 'react'; - * ``` - * - * This would return: - * ```js - * Loader.dependencyKeysIfEvaluated("/foo.js") - * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] - * ``` - * - * @param specifier - module specifier as it appears in transpiled source code - */ - dependencyKeysIfEvaluated: (specifier: string) => string[]; - /** - * The function JavaScriptCore internally calls when you use an import statement. - * - * This may return a path to `node_modules.server.bun`, which will be confusing. - * - * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} - * instead. - * - * @param specifier - module specifier as it appears in transpiled source code - * @param referrer - module specifier that is resolving this specifier - */ - resolve: (specifier: string, referrer: string) => string; +declare var Loader: { + /** + * ESM module registry + * + * This lets you implement live reload in Bun. If you + * delete a module specifier from this map, the next time it's imported, it + * will be re-transpiled and loaded again. + * + * The keys are the module specifiers and the + * values are metadata about the module. + * + * The keys are an implementation detail for Bun that will change between + * versions. + * + * - Userland modules are an absolute file path + * - Virtual modules have a `bun:` prefix or `node:` prefix + * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill + * - If you have a `node_modules.bun` file, many modules will point to that file + * + * Virtual modules and JS polyfills are embedded in bun's binary. They don't + * point to anywhere in your local filesystem. + */ + registry: Map< + string, + { + key: string; + /** + * This refers to the state the ESM module is in + * + * TODO: make an enum for this number + */ + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array< + (typeof Loader)["registry"] extends Map ? V : any + >; + /** + * Your application will probably crash if you mess with this. + */ + module: { + dependenciesMap: (typeof Loader)["registry"]; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; + /** + * For an already-evaluated module, return the dependencies as module specifiers + * + * This list is already sorted and uniqued. + * + * @example + * + * For this code: + * ```js + * // /foo.js + * import classNames from 'classnames'; + * import React from 'react'; + * import {createElement} from 'react'; + * ``` + * + * This would return: + * ```js + * Loader.dependencyKeysIfEvaluated("/foo.js") + * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] + * ``` + * + * @param specifier - module specifier as it appears in transpiled source code + */ + dependencyKeysIfEvaluated: (specifier: string) => string[]; + /** + * The function JavaScriptCore internally calls when you use an import statement. + * + * This may return a path to `node_modules.server.bun`, which will be confusing. + * + * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} + * instead. + * + * @param specifier - module specifier as it appears in transpiled source code + * @param referrer - module specifier that is resolving this specifier + */ + resolve: (specifier: string, referrer: string) => string; }; interface QueuingStrategy { - highWaterMark?: number; - size?: QueuingStrategySize; + highWaterMark?: number; + size?: QueuingStrategySize; } interface QueuingStrategyInit { - /** - * Creates a new ByteLengthQueuingStrategy with the provided high water mark. - * - * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. - */ - highWaterMark: number; + /** + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. + */ + highWaterMark: number; } /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ interface ByteLengthQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - // changed from QueuingStrategySize - // to avoid conflict with lib.dom.d.ts - readonly size: QueuingStrategySize; + readonly highWaterMark: number; + // changed from QueuingStrategySize + // to avoid conflict with lib.dom.d.ts + readonly size: QueuingStrategySize; } -var ByteLengthQueuingStrategy: { - prototype: ByteLengthQueuingStrategy; - new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; +declare var ByteLengthQueuingStrategy: { + prototype: ByteLengthQueuingStrategy; + new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; }; interface ReadableStreamDefaultController { - readonly desiredSize: number | null; - close(): void; - enqueue(chunk?: R): void; - error(e?: any): void; + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; } interface ReadableStreamDirectController { - close(error?: Error): void; - write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; - end(): number | Promise; - flush(): number | Promise; - start(): void; + close(error?: Error): void; + write( + data: Bun.BufferSource | ArrayBuffer | string, + ): number | Promise; + end(): number | Promise; + flush(): number | Promise; + start(): void; } -var ReadableStreamDefaultController: { - prototype: ReadableStreamDefaultController; - new (): ReadableStreamDefaultController; +declare var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; }; -interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { - read(): Promise>; - /** - * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. - * Will only return a promise if the data is not immediately available. - */ - readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; - releaseLock(): void; +interface ReadableStreamDefaultReader + extends ReadableStreamGenericReader { + read(): Promise>; + /** + * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. + * Will only return a promise if the data is not immediately available. + */ + readMany(): + | Promise> + | Bun.ReadableStreamDefaultReadManyResult; + releaseLock(): void; } -var ReadableStreamDefaultReader: { - prototype: ReadableStreamDefaultReader; - new (stream: ReadableStream): ReadableStreamDefaultReader; +declare var ReadableStreamDefaultReader: { + prototype: ReadableStreamDefaultReader; + new (stream: ReadableStream): ReadableStreamDefaultReader; }; interface ReadableStreamGenericReader { - readonly closed: Promise; - cancel(reason?: any): Promise; + readonly closed: Promise; + cancel(reason?: any): Promise; } interface ReadableStreamDefaultReadDoneResult { - done: true; - value?: undefined; + done: true; + value?: undefined; } interface ReadableStreamDefaultReadValueResult { - done: false; - value: T; + done: false; + value: T; } interface ReadableWritablePair { - readable: ReadableStream; - /** - * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - */ - writable: WritableStream; + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; } interface WritableStreamDefaultController { - error(e?: any): void; + error(e?: any): void; } -var WritableStreamDefaultController: { - prototype: WritableStreamDefaultController; - new (): WritableStreamDefaultController; +declare var WritableStreamDefaultController: { + prototype: WritableStreamDefaultController; + new (): WritableStreamDefaultController; }; /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ interface WritableStreamDefaultWriter { - readonly closed: Promise; - readonly desiredSize: number | null; - readonly ready: Promise; - abort(reason?: any): Promise; - close(): Promise; - releaseLock(): void; - write(chunk?: W): Promise; + readonly closed: Promise; + readonly desiredSize: number | null; + readonly ready: Promise; + abort(reason?: any): Promise; + close(): Promise; + releaseLock(): void; + write(chunk?: W): Promise; } -var WritableStreamDefaultWriter: { - prototype: WritableStreamDefaultWriter; - new (stream: WritableStream): WritableStreamDefaultWriter; +declare var WritableStreamDefaultWriter: { + prototype: WritableStreamDefaultWriter; + new (stream: WritableStream): WritableStreamDefaultWriter; }; interface TransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; + readonly readable: ReadableStream; + readonly writable: WritableStream; } -var TransformStream: { - prototype: TransformStream; - new ( - transformer?: Transformer, - writableStrategy?: QueuingStrategy, - readableStrategy?: QueuingStrategy, - ): TransformStream; +declare var TransformStream: { + prototype: TransformStream; + new ( + transformer?: Transformer, + writableStrategy?: QueuingStrategy, + readableStrategy?: QueuingStrategy, + ): TransformStream; }; interface TransformStreamDefaultController { - readonly desiredSize: number | null; - enqueue(chunk?: O): void; - error(reason?: any): void; - terminate(): void; + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; } -var TransformStreamDefaultController: { - prototype: TransformStreamDefaultController; - new (): TransformStreamDefaultController; +declare var TransformStreamDefaultController: { + prototype: TransformStreamDefaultController; + new (): TransformStreamDefaultController; }; interface StreamPipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - /** - * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - * - * Errors and closures of the source and destination streams propagate as follows: - * - * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. - * - * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. - * - * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. - * - * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. - * - * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. - */ - preventClose?: boolean; - signal?: AbortSignal; + preventAbort?: boolean; + preventCancel?: boolean; + /** + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + * + * Errors and closures of the source and destination streams propagate as follows: + * + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. + * + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. + * + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. + * + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. + */ + preventClose?: boolean; + signal?: AbortSignal; } /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ interface CountQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - readonly size: QueuingStrategySize; + readonly highWaterMark: number; + readonly size: QueuingStrategySize; } -var CountQueuingStrategy: { - prototype: CountQueuingStrategy; - new (init: QueuingStrategyInit): CountQueuingStrategy; +declare var CountQueuingStrategy: { + prototype: CountQueuingStrategy; + new (init: QueuingStrategyInit): CountQueuingStrategy; }; interface QueuingStrategySize { - (chunk?: T): number; + (chunk?: T): number; } interface Transformer { - flush?: Bun.TransformerFlushCallback; - readableType?: undefined; - start?: Bun.TransformerStartCallback; - transform?: Bun.TransformerTransformCallback; - writableType?: undefined; + flush?: Bun.TransformerFlushCallback; + readableType?: undefined; + start?: Bun.TransformerStartCallback; + transform?: Bun.TransformerTransformCallback; + writableType?: undefined; } interface Dict { - [key: string]: T | undefined; + [key: string]: T | undefined; } interface ReadOnlyDict { - readonly [key: string]: T | undefined; + readonly [key: string]: T | undefined; } interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; } /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; } -var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; +declare var DOMException: { + prototype: DOMException; + new (message?: string, name?: string): DOMException; }; -function alert(message?: string): void; -function confirm(message?: string): boolean; -function prompt(message?: string, _default?: string): string | null; +declare function alert(message?: string): void; +declare function confirm(message?: string): boolean; +declare function prompt(message?: string, _default?: string): string | null; type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; -var SubtleCrypto: { - prototype: _SubtleCrypto; - new (): _SubtleCrypto; +declare var SubtleCrypto: { + prototype: _SubtleCrypto; + new (): _SubtleCrypto; }; type _CryptoKey = import("crypto").webcrypto.CryptoKey; interface CryptoKey extends _CryptoKey {} -var CryptoKey: { - prototype: CryptoKey; - new (): CryptoKey; +declare var CryptoKey: { + prototype: CryptoKey; + new (): CryptoKey; }; interface Position { - lineText: string; - file: string; - namespace: string; - line: number; - column: number; - length: number; - offset: number; + lineText: string; + file: string; + namespace: string; + line: number; + column: number; + length: number; + offset: number; } -class ResolveMessage { - readonly name: "ResolveMessage"; - readonly position: Position | null; - readonly code: string; - readonly message: string; - readonly referrer: string; - readonly specifier: string; - readonly importKind: - | "entry_point" - | "stmt" - | "require" - | "import" - | "dynamic" - | "require_resolve" - | "at" - | "at_conditional" - | "url" - | "internal"; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - - toString(): string; +declare class ResolveMessage { + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; } -class BuildMessage { - readonly name: "BuildMessage"; - readonly position: Position | null; - readonly message: string; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; +declare class BuildMessage { + readonly name: "BuildMessage"; + readonly position: Position | null; + readonly message: string; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; } // Declare "static" methods in Error interface ErrorConstructor { - /** Create .stack property on a target object */ - // eslint-disable-next-line @typescript-eslint/ban-types - captureStackTrace(targetObject: object, constructorOpt?: Function): void; - - /** - * Optional override for formatting stack traces - * - * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces - */ - prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; - - stackTraceLimit: number; + /** Create .stack property on a target object */ + // eslint-disable-next-line @typescript-eslint/ban-types + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: + | ((err: Error, stackTraces: NodeJS.CallSite[]) => any) + | undefined; + + stackTraceLimit: number; } interface ArrayBufferConstructor { - new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; + new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; } interface ArrayBuffer { - /** - * Read-only. The length of the ArrayBuffer (in bytes). - */ - readonly byteLength: number; - /** - * Resize an ArrayBuffer in-place. - */ - resize(byteLength: number): ArrayBuffer; - - /** - * Returns a section of an ArrayBuffer. - */ - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; + /** + * Read-only. The length of the ArrayBuffer (in bytes). + */ + readonly byteLength: number; + /** + * Resize an ArrayBuffer in-place. + */ + resize(byteLength: number): ArrayBuffer; + + /** + * Returns a section of an ArrayBuffer. + */ + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; } interface SharedArrayBuffer { - /** - * Grow the SharedArrayBuffer in-place. - */ - grow(size: number): SharedArrayBuffer; + /** + * Grow the SharedArrayBuffer in-place. + */ + grow(size: number): SharedArrayBuffer; } interface ArrayConstructor { - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; - - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. Results of the map function are also awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * await Array.fromAsync([1], (n) => n + 1); // [2] - * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. - * @param thisArg - The `this` to which `mapFn` is bound. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + ): Promise[]>; + + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. Results of the map function are also awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * await Array.fromAsync([1], (n) => n + 1); // [2] + * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. + * @param thisArg - The `this` to which `mapFn` is bound. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; } interface ConsoleOptions { - stdout: import("stream").Writable; - stderr?: import("stream").Writable; - ignoreErrors?: boolean; - colorMode?: boolean | "auto"; - inspectOptions?: import("util").InspectOptions; - groupIndentation?: number; + stdout: import("stream").Writable; + stderr?: import("stream").Writable; + ignoreErrors?: boolean; + colorMode?: boolean | "auto"; + inspectOptions?: import("util").InspectOptions; + groupIndentation?: number; } interface Console { - /** - * Asynchronously read lines from standard input (fd 0) - * - * ```ts - * for await (const line of console) { - * console.log(line); - * } - * ``` - */ - [Symbol.asyncIterator](): AsyncIterableIterator; - - /** - * Write text or bytes to stdout - * - * Unlike {@link console.log}, this does no formatting and doesn't add a - * newline or spaces between arguments. You can pass it strings or bytes or - * any combination of the two. - * - * ```ts - * console.write("hello world!", "\n"); // "hello world\n" - * ``` - * - * @param data - The data to write - * @returns The number of bytes written - * - * This function is not available in the browser. - */ - write(...data: Array): number; - - /** - * Clear the console - */ - clear(): void; - - assert(condition?: boolean, ...data: any[]): void; - - /** - * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) - * @param label label counter - */ - count(label?: string): void; - countReset(label?: string): void; - debug(...data: any[]): void; - dir(item?: any, options?: any): void; - dirxml(...data: any[]): void; - /** - * Log to stderr in your terminal - * - * Appears in red - * - * @param data something to display - */ - error(...data: any[]): void; - /** Does nothing currently */ - group(...data: any[]): void; - /** Does nothing currently */ - groupCollapsed(...data: any[]): void; - /** Does nothing currently */ - groupEnd(): void; - info(...data: any[]): void; - log(...data: any[]): void; - /** - * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just - * logging the argument if it can't be parsed as tabular. - * - * ```js - * // These can't be parsed as tabular data - * console.table(Symbol()); - * // Symbol() - * - * console.table(undefined); - * // undefined - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ b โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * ``` - * @param properties Alternate properties for constructing the table. - */ - table(tabularData?: any, properties?: string[]): void; - /** - * Begin a timer to log with {@link console.timeEnd} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - time(label?: string): void; - /** - * End a timer to log with {@link console.time} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - timeEnd(label?: string): void; - timeLog(label?: string, ...data: any[]): void; - timeStamp(label?: string): void; - trace(...data: any[]): void; - warn(...data: any[]): void; - - /** - * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. - */ - // Console: { - // new (options: ConsoleOptions): Console; - // new ( - // stdout: import("stream").Writable, - // stderr?: import("stream").Writable, - // ignoreErrors?: boolean, - // ): Console; - // }; + /** + * Asynchronously read lines from standard input (fd 0) + * + * ```ts + * for await (const line of console) { + * console.log(line); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterableIterator; + + /** + * Write text or bytes to stdout + * + * Unlike {@link console.log}, this does no formatting and doesn't add a + * newline or spaces between arguments. You can pass it strings or bytes or + * any combination of the two. + * + * ```ts + * console.write("hello world!", "\n"); // "hello world\n" + * ``` + * + * @param data - The data to write + * @returns The number of bytes written + * + * This function is not available in the browser. + */ + write(...data: Array): number; + + /** + * Clear the console + */ + clear(): void; + + assert(condition?: boolean, ...data: any[]): void; + + /** + * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) + * @param label label counter + */ + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: any): void; + dirxml(...data: any[]): void; + /** + * Log to stderr in your terminal + * + * Appears in red + * + * @param data something to display + */ + error(...data: any[]): void; + /** Does nothing currently */ + group(...data: any[]): void; + /** Does nothing currently */ + groupCollapsed(...data: any[]): void; + /** Does nothing currently */ + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + /** + * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just + * logging the argument if it can't be parsed as tabular. + * + * ```js + * // These can't be parsed as tabular data + * console.table(Symbol()); + * // Symbol() + * + * console.table(undefined); + * // undefined + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ b โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * ``` + * @param properties Alternate properties for constructing the table. + */ + table(tabularData?: any, properties?: string[]): void; + /** + * Begin a timer to log with {@link console.timeEnd} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + time(label?: string): void; + /** + * End a timer to log with {@link console.time} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + timeStamp(label?: string): void; + trace(...data: any[]): void; + warn(...data: any[]): void; + + /** + * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. + */ + // Console: { + // new (options: ConsoleOptions): Console; + // new ( + // stdout: import("stream").Writable, + // stderr?: import("stream").Writable, + // ignoreErrors?: boolean, + // ): Console; + // }; } -var console: Console; +declare var console: Console; interface ImportMeta { - /** - * `file://` url string for the current module. - * - * @example - * ```ts - * console.log(import.meta.url); - * "file:///Users/me/projects/my-app/src/my-app.ts" - * ``` - */ - url: string; - /** - * Absolute path to the source file - */ - readonly path: string; - /** - * Absolute path to the directory containing the source file. - * - * Does not have a trailing slash - */ - readonly dir: string; - /** - * Filename of the source file - */ - readonly file: string; - /** - * The environment variables of the process - * - * ```ts - * import.meta.env === process.env - * ``` - */ - readonly env: NodeJS.ProcessEnv; - - /** - * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead - * - * Resolve a module ID the same as if you imported it - * - * The `parent` argument is optional, and defaults to the current module's path. - */ - resolveSync(moduleId: string, parent?: string): string; - - /** - * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all - * calls to `require` with `import.meta.require` when transpiling ES Modules - * for the runtime. - * - * Warning: **This API is not stable** and may change or be removed in the - * future. Use at your own risk. - */ - require: NodeJS.Require; - - /** - * Did the current file start the process? - * - * @example - * ```ts - * if (import.meta.main) { - * console.log("I started the process!"); - * } - * ``` - * - * @example - * ```ts - * console.log( - * import.meta.main === (import.meta.path === Bun.main) - * ) - * ``` - */ - readonly main: boolean; - - /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ - dirname: string; - - /** Alias of `import.meta.path`. Exists for Node.js compatibility */ - filename: string; + /** + * `file://` url string for the current module. + * + * @example + * ```ts + * console.log(import.meta.url); + * "file:///Users/me/projects/my-app/src/my-app.ts" + * ``` + */ + url: string; + /** + * Absolute path to the source file + */ + readonly path: string; + /** + * Absolute path to the directory containing the source file. + * + * Does not have a trailing slash + */ + readonly dir: string; + /** + * Filename of the source file + */ + readonly file: string; + /** + * The environment variables of the process + * + * ```ts + * import.meta.env === process.env + * ``` + */ + readonly env: NodeJS.ProcessEnv; + + /** + * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead + * + * Resolve a module ID the same as if you imported it + * + * The `parent` argument is optional, and defaults to the current module's path. + */ + resolveSync(moduleId: string, parent?: string): string; + + /** + * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all + * calls to `require` with `import.meta.require` when transpiling ES Modules + * for the runtime. + * + * Warning: **This API is not stable** and may change or be removed in the + * future. Use at your own risk. + */ + require: NodeJS.Require; + + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; + + /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ + dirname: string; + + /** Alias of `import.meta.path`. Exists for Node.js compatibility */ + filename: string; } /** @@ -1125,114 +1168,119 @@ interface ImportMeta { * * @param moduleId - The module ID to resolve */ -var require: NodeJS.Require; +declare var require: NodeJS.Require; /** Same as module.exports */ -var exports: any; +declare var exports: any; interface NodeModule { - exports: any; + exports: any; } -var module: NodeModule; +declare var module: NodeModule; /** * Creates a deep clone of an object. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) */ -function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; +declare function structuredClone( + value: T, + options?: Bun.StructuredSerializeOptions, +): T; /** * Post a message to the parent thread. * * Only useful in a worker thread; calling this from the main thread does nothing. */ -function postMessage(message: any, transfer?: Bun.Transferable[]): void; +declare function postMessage(message: any, transfer?: Bun.Transferable[]): void; interface EventSourceInit { - withCredentials?: boolean; + withCredentials?: boolean; } interface PromiseConstructor { - /** - * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called - * separately. - * - * This is useful when you want to return a Promise and have code outside the Promise - * resolve or reject it. - * - * ## Example - * ```ts - * const { promise, resolve, reject } = Promise.withResolvers(); - * - * setTimeout(() => { - * resolve("Hello world!"); - * }, 1000); - * - * await promise; // "Hello world!" - * ``` - * - * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). - */ - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; + /** + * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called + * separately. + * + * This is useful when you want to return a Promise and have code outside the Promise + * resolve or reject it. + * + * ## Example + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); + * + * setTimeout(() => { + * resolve("Hello world!"); + * }, 1000); + * + * await promise; // "Hello world!" + * ``` + * + * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). + */ + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; } interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; } -var navigator: Navigator; +declare var navigator: Navigator; interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; } interface Blob { - /** - * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - */ - new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; - /** - * Read the data from the blob as a JSON object. - * - * This first decodes the data from UTF-8, then parses it as JSON. - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - json(): Promise; - - /** - * Read the data from the blob as a {@link FormData} object. - * - * This first decodes the data from UTF-8, then parses it as a - * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. - * - * The `type` property of the blob is used to determine the format of the - * body. - * - * This is a non-standard addition to the `Blob` API, to make it conform more - * closely to the `BodyMixin` API. - */ - formData(): Promise; - - arrayBuffer(): Promise; - - /** - * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` - */ - bytes(): Promise; + /** + * Read the data from the blob as a JSON object. + * + * This first decodes the data from UTF-8, then parses it as JSON. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + json(): Promise; + + /** + * Read the data from the blob as a {@link FormData} object. + * + * This first decodes the data from UTF-8, then parses it as a + * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. + * + * The `type` property of the blob is used to determine the format of the + * body. + * + * This is a non-standard addition to the `Blob` API, to make it conform more + * closely to the `BodyMixin` API. + */ + formData(): Promise; + + arrayBuffer(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + */ + bytes(): Promise; } -declare var Blob: typeof Blob; +/** + * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + */ +declare var Blob: { + prototype: Blob; + new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; +}; diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index 6d95c866552734..6874fdc5e4f7f8 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -12,6 +12,7 @@ /// /// /// -/// + +/// declare var onmessage: never; diff --git a/packages/bun-types/new/overrides.d.ts b/packages/bun-types/new/overrides.d.ts index b150e1c1a32824..152db35bd28d20 100644 --- a/packages/bun-types/new/overrides.d.ts +++ b/packages/bun-types/new/overrides.d.ts @@ -1,17 +1,17 @@ export {}; // `declare global` requires the ambient file to be a module declare global { - namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; + namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; - /** Whether you are using Bun */ - isBun: true; - /** The current git sha of Bun **/ - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - } + /** Whether you are using Bun */ + isBun: true; + /** The current git sha of Bun **/ + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + } } diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index af380b5674527c..300ef728235b83 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -14,6 +14,8 @@ const client = new Bun.S3Client({ secretAccessKey: "", }); +new TextEncoder(); + client.file(""); Bun.fetch; @@ -32,6 +34,9 @@ new TransformStream(); new AbortSignal(); new AbortController(); +new TextDecoder(); +new TextEncoder(); + fetch("url", { proxy: "", }); @@ -178,6 +183,12 @@ Bun.serve({ }, }); +fetch("", { + tls: { + rejectUnauthorized: false, + }, +}); + import.meta.hot?.data; import { serve } from "bun"; From 34045dc5f85f2067cd58f2bfaf9eeba89a79516e Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 18:25:44 +0000 Subject: [PATCH 11/72] Only failing types are now in node!!! --- packages/bun-types/new/bun.d.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 7231f3b9c12d57..2eab4c3e4cd897 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -14,7 +14,9 @@ * This module aliases `globalThis.Bun`. */ declare module "bun" { - type DistributedOmit = T extends T ? Omit : never; + type DistributedOmit = T extends T + ? Omit + : never; type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; type ArrayBufferView = NodeJS.TypedArray | DataView; type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; @@ -4247,7 +4249,7 @@ declare module "bun" { /** * Send any additional headers while upgrading, like cookies */ - headers?: Bun.HeadersInit; + headers?: HeadersInit; /** * This value is passed to the {@link ServerWebSocket.data} property */ @@ -5132,7 +5134,7 @@ declare module "bun" { */ update( input: Bun.BlobOrStringOrBuffer, - inputEncoding?: import("crypto").CryptoEncoding, + inputEncoding?: import("crypto").Encoding, ): CryptoHasher; /** From 2c25cd1b29d3476a68007394793ab56fc29afbbc Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 18:39:01 +0000 Subject: [PATCH 12/72] fix RequestInit types --- packages/bun-types/new/fetch.d.ts | 19 ++++++++++++++++ packages/bun-types/new/globals.d.ts | 21 ------------------ test/integration/bun-types/fixture/index.ts | 24 ++++++++++----------- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts index f938c9f2fc972f..0cbdb8895b314c 100644 --- a/packages/bun-types/new/fetch.d.ts +++ b/packages/bun-types/new/fetch.d.ts @@ -164,6 +164,25 @@ interface BunFetchRequestInit extends RequestInit { * Override the default TLS options */ tls?: BunFetchRequestInitTLS; + + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: Bun.S3Options; } /** diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 56d285d9589528..5c00445d0f734a 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -175,27 +175,6 @@ declare var File: { ): File; }; -type _RequestInit = import("undici-types").RequestInit; -interface RequestInit extends _RequestInit { - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: import("bun").S3Options; -} - /** * ShadowRealms are a distinct global environment, with its own global object * containing its own intrinsics and built-ins (standard objects that are not diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 300ef728235b83..ae35aaecfc20d8 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -126,18 +126,18 @@ fetch; fetch.preconnect(new URL("")); -// Bun.serve({ -// port: 3000, -// fetch: () => new Response("ok"), - -// key: Bun.file(""), -// cert: Bun.file(""), - -// tls: { -// key: Bun.file(""), -// cert: Bun.file(""), -// }, -// }); +Bun.serve({ + port: 3000, + fetch: () => new Response("ok"), + + key: Bun.file(""), + cert: Bun.file(""), + + tls: { + key: Bun.file(""), + cert: Bun.file(""), + }, +}); URL.canParse; URL.createObjectURL; From fdf93dd4ccccf09dcdd8a4068f89c3df78d9b464 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 18:43:58 +0000 Subject: [PATCH 13/72] URL stuff --- packages/bun-types/new/globals.d.ts | 10 ++++++++++ test/integration/bun-types/fixture/index.ts | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 5c00445d0f734a..6b91aec9d7ab06 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -1263,3 +1263,13 @@ declare var Blob: { prototype: Blob; new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; }; + +interface URL {} +declare var URL: { + prototype: URL; + new (url: string | URL, base?: string | URL): URL; + canParse(url: string): boolean; + createObjectURL(object: any): string; + revokeObjectURL(url: string): void; + parse(url: string): URL; +}; diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index ae35aaecfc20d8..1d3842c66a5e07 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -41,7 +41,11 @@ fetch("url", { proxy: "", }); -Bun.fetch("", { +fetch(new URL("url"), { + proxy: "", +}); + +Bun.fetch(new URL("url"), { proxy: "", }); From eeeec68dd38268329bdfa14f81d00b2bf40dc42d Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 7 Mar 2025 18:50:43 +0000 Subject: [PATCH 14/72] jsx, sqlite, html-rewriter, test --- packages/bun-types/new/html-rewriter.d.ts | 189 ++ packages/bun-types/new/index.d.ts | 4 + packages/bun-types/new/jsc.d.ts | 243 ++ packages/bun-types/new/sqlite.d.ts | 1166 ++++++++++ packages/bun-types/new/test.d.ts | 2282 +++++++++++++++++++ test/integration/bun-types/fixture/index.ts | 7 + 6 files changed, 3891 insertions(+) create mode 100644 packages/bun-types/new/html-rewriter.d.ts create mode 100644 packages/bun-types/new/jsc.d.ts create mode 100644 packages/bun-types/new/sqlite.d.ts create mode 100644 packages/bun-types/new/test.d.ts diff --git a/packages/bun-types/new/html-rewriter.d.ts b/packages/bun-types/new/html-rewriter.d.ts new file mode 100644 index 00000000000000..6bec7fea979ab2 --- /dev/null +++ b/packages/bun-types/new/html-rewriter.d.ts @@ -0,0 +1,189 @@ +declare namespace HTMLRewriterTypes { + interface HTMLRewriterElementContentHandlers { + element?(element: Element): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + } + + interface HTMLRewriterDocumentContentHandlers { + doctype?(doctype: Doctype): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + end?(end: DocumentEnd): void | Promise; + } + + interface Text { + /** The text content */ + readonly text: string; + /** Whether this chunk is the last piece of text in a text node */ + readonly lastInTextNode: boolean; + /** Whether this chunk was removed */ + readonly removed: boolean; + /** Insert content before this chunk */ + before(content: Content, options?: ContentOptions): Text; + /** Insert content after this chunk */ + after(content: Content, options?: ContentOptions): Text; + /** Replace this chunk with new content */ + replace(content: Content, options?: ContentOptions): Text; + /** Remove this chunk */ + remove(): Text; + } + + interface Doctype { + /** The doctype name (e.g. "html" for ) */ + readonly name: string | null; + /** The doctype public identifier */ + readonly publicId: string | null; + /** The doctype system identifier */ + readonly systemId: string | null; + /** Whether this doctype was removed */ + readonly removed: boolean; + /** Remove this doctype */ + remove(): Doctype; + } + + interface DocumentEnd { + /** Append content at the end of the document */ + append(content: Content, options?: ContentOptions): DocumentEnd; + } + + interface ContentOptions { + /** Whether to parse the content as HTML */ + html?: boolean; + } + + type Content = string; + + interface Comment { + /** The comment text */ + text: string; + /** Whether this comment was removed */ + readonly removed: boolean; + /** Insert content before this comment */ + before(content: Content, options?: ContentOptions): Comment; + /** Insert content after this comment */ + after(content: Content, options?: ContentOptions): Comment; + /** Replace this comment with new content */ + replace(content: Content, options?: ContentOptions): Comment; + /** Remove this comment */ + remove(): Comment; + } + + interface Element { + /** The tag name in lowercase (e.g. "div", "span") */ + tagName: string; + /** Iterator for the element's attributes */ + readonly attributes: IterableIterator<[string, string]>; + /** Whether this element was removed */ + readonly removed: boolean; + /** Whether the element is explicitly self-closing, e.g. */ + readonly selfClosing: boolean; + /** + * Whether the element can have inner content. Returns `true` unless + * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) + * - or it's self-closing in a foreign context (eg. in SVG, MathML). + */ + readonly canHaveContent: boolean; + /** The element's namespace URI */ + readonly namespaceURI: string; + /** Get an attribute value by name */ + getAttribute(name: string): string | null; + /** Check if an attribute exists */ + hasAttribute(name: string): boolean; + /** Set an attribute value */ + setAttribute(name: string, value: string): Element; + /** Remove an attribute */ + removeAttribute(name: string): Element; + /** Insert content before this element */ + before(content: Content, options?: ContentOptions): Element; + /** Insert content after this element */ + after(content: Content, options?: ContentOptions): Element; + /** Insert content at the start of this element */ + prepend(content: Content, options?: ContentOptions): Element; + /** Insert content at the end of this element */ + append(content: Content, options?: ContentOptions): Element; + /** Replace this element with new content */ + replace(content: Content, options?: ContentOptions): Element; + /** Remove this element and its contents */ + remove(): Element; + /** Remove this element but keep its contents */ + removeAndKeepContent(): Element; + /** Set the inner content of this element */ + setInnerContent(content: Content, options?: ContentOptions): Element; + /** Add a handler for the end tag of this element */ + onEndTag(handler: (tag: EndTag) => void | Promise): void; + } + + interface EndTag { + /** The tag name in lowercase */ + name: string; + /** Insert content before this end tag */ + before(content: Content, options?: ContentOptions): EndTag; + /** Insert content after this end tag */ + after(content: Content, options?: ContentOptions): EndTag; + /** Remove this end tag */ + remove(): EndTag; + } +} + +/** + * [HTMLRewriter](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter?bun) is a fast API for transforming HTML. + * + * Bun leverages a native implementation powered by [lol-html](https://github.com/cloudflare/lol-html). + * + * HTMLRewriter can be used to transform HTML in a variety of ways, including: + * * Rewriting URLs + * * Adding meta tags + * * Removing elements + * * Adding elements to the head + * + * @example + * ```ts + * const rewriter = new HTMLRewriter().on('a[href]', { + * element(element: Element) { + * // Rewrite all the URLs to this youtube video + * element.setAttribute('href', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + * } + * }); + * rewriter.transform(await fetch("https://remix.run")); + * ``` + */ +declare class HTMLRewriter { + constructor(); + /** + * Add handlers for elements matching a CSS selector + * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") + * @param handlers - Object containing handler functions for elements, comments, and text nodes + */ + on( + selector: string, + handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers, + ): HTMLRewriter; + + /** + * Add handlers for document-level events + * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end + */ + onDocument( + handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers, + ): HTMLRewriter; + + /** + * Transform HTML content + * @param input - The HTML to transform + * @returns A new {@link Response} with the transformed HTML + */ + transform(input: Response | Blob | Bun.BufferSource): Response; + /** + * Transform HTML content + * @param input - The HTML string to transform + * @returns A new {@link String} containing the transformed HTML + */ + transform(input: string): string; + /** + * Transform HTML content + * @param input - The HTML to transform as a {@link ArrayBuffer} + * @returns A new {@link ArrayBuffer} with the transformed HTML + */ + transform(input: ArrayBuffer): ArrayBuffer; +} diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index 6874fdc5e4f7f8..249ee82803cdd9 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -12,6 +12,10 @@ /// /// /// +/// +/// +/// +/// /// diff --git a/packages/bun-types/new/jsc.d.ts b/packages/bun-types/new/jsc.d.ts new file mode 100644 index 00000000000000..c5942da2813fb5 --- /dev/null +++ b/packages/bun-types/new/jsc.d.ts @@ -0,0 +1,243 @@ +declare module "bun:jsc" { + /** + * This used to be called "describe" but it could be confused with the test runner. + */ + function jscDescribe(value: any): string; + function jscDescribeArray(args: any[]): string; + function gcAndSweep(): number; + function fullGC(): number; + function edenGC(): number; + function heapSize(): number; + function heapStats(): { + heapSize: number; + heapCapacity: number; + extraMemorySize: number; + objectCount: number; + protectedObjectCount: number; + globalObjectCount: number; + protectedGlobalObjectCount: number; + objectTypeCounts: Record; + protectedObjectTypeCounts: Record; + }; + function memoryUsage(): { + current: number; + peak: number; + currentCommit: number; + peakCommit: number; + pageFaults: number; + }; + function getRandomSeed(): number; + function setRandomSeed(value: number): void; + function isRope(input: string): boolean; + function callerSourceOrigin(): string; + function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; + function noOSRExitFuzzing( + func: (...args: any[]) => any, + ): (...args: any[]) => any; + function optimizeNextInvocation(func: (...args: any[]) => any): void; + function numberOfDFGCompiles(func: (...args: any[]) => any): number; + function releaseWeakRefs(): void; + function totalCompileTime(func: (...args: any[]) => any): number; + function reoptimizationRetryCount(func: (...args: any[]) => any): number; + function drainMicrotasks(): void; + + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A SharedArrayBuffer that can be sent to another Bun instance. + */ + function serialize( + value: any, + options?: { binaryType?: "arraybuffer" }, + ): SharedArrayBuffer; + + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A Buffer that can be sent to another Bun instance. + */ + function serialize( + value: any, + options?: { binaryType: "nodebuffer" }, + ): Buffer; + + /** + * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. + * + * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. + */ + function deserialize( + value: ArrayBufferLike | NodeJS.TypedArray | Buffer, + ): any; + + /** + * Set the timezone used by Intl, Date, etc. + * + * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" + * + * @returns The normalized time zone string + * + * You can also set process.env.TZ to the time zone you want to use. + * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` + */ + function setTimeZone(timeZone: string): string; + + interface SamplingProfile { + /** + * A formatted summary of the top functions + * + * Example output: + * ```js + * + * Sampling rate: 100.000000 microseconds. Total samples: 6858 + * Top functions as + * 2948 '#:8' + * 393 'visit#:8' + * 263 'push#:8' + * 164 'scan_ref_scoped#:8' + * 164 'walk#:8' + * 144 'pop#:8' + * 107 'extract_candidates#:8' + * 94 'get#:8' + * 82 'Function#:4294967295' + * 79 'set#:8' + * 67 'forEach#:5' + * 58 'collapse#:8' + * ``` + */ + functions: string; + /** + * A formatted summary of the top bytecodes + * + * Example output: + * ```js + * Tier breakdown: + * ----------------------------------- + * LLInt: 106 (1.545640%) + * Baseline: 2355 (34.339458%) + * DFG: 3290 (47.973170%) + * FTL: 833 (12.146398%) + * js builtin: 132 (1.924759%) + * Wasm: 0 (0.000000%) + * Host: 111 (1.618548%) + * RegExp: 15 (0.218723%) + * C/C++: 0 (0.000000%) + * Unknown Executable: 148 (2.158064%) + * + * Hottest bytecodes as + * 273 'visit#:DFG:bc#63' + * 121 'walk#:DFG:bc#7' + * 119 '#:Baseline:bc#1' + * 82 'Function#:None:' + * 66 '#:DFG:bc#11' + * 65 '#:DFG:bc#33' + * 58 '#:Baseline:bc#7' + * 53 '#:Baseline:bc#23' + * 50 'forEach#:DFG:bc#83' + * 49 'pop#:FTL:bc#65' + * 47 '#:DFG:bc#99' + * 45 '#:DFG:bc#16' + * 44 '#:DFG:bc#7' + * 44 '#:Baseline:bc#30' + * 44 'push#:FTL:bc#214' + * 41 '#:DFG:bc#50' + * 39 'get#:DFG:bc#27' + * 39 '#:Baseline:bc#0' + * 36 '#:DFG:bc#27' + * 36 'Dictionary#:DFG:bc#41' + * 36 'visit#:DFG:bc#81' + * 36 'get#:FTL:bc#11' + * 32 'push#:FTL:bc#49' + * 31 '#:DFG:bc#76' + * 31 '#:DFG:bc#10' + * 31 '#:DFG:bc#73' + * 29 'set#:DFG:bc#28' + * 28 'in_boolean_context#:DFG:bc#104' + * 28 '#:Baseline:' + * 28 'regExpSplitFast#:None:' + * 26 'visit#:DFG:bc#95' + * 26 'pop#:FTL:bc#120' + * 25 '#:DFG:bc#23' + * 25 'push#:FTL:bc#152' + * 24 'push#:FTL:bc#262' + * 24 '#:FTL:bc#10' + * 23 'is_identifier_char#:DFG:bc#22' + * 23 'visit#:DFG:bc#22' + * 22 '#:FTL:bc#27' + * 22 'indexOf#:None:' + * ``` + */ + bytecodes: string; + + /** + * Stack traces of the top functions + */ + stackTraces: string[]; + } + + /** + * Run JavaScriptCore's sampling profiler for a particular function + * + * This is pretty low-level. + * + * Things to know: + * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation + * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile + * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile + * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile + */ + function profile any>( + callback: T, + sampleInterval?: number, + ...args: Parameters + ): ReturnType extends Promise + ? Promise + : SamplingProfile; + + /** + * This returns objects which native code has explicitly protected from being + * garbage collected + * + * By calling this function you create another reference to the object, which + * will further prevent it from being garbage collected + * + * This function is mostly a debugging tool for bun itself. + * + * Warning: not all objects returned are supposed to be observable from JavaScript + */ + function getProtectedObjects(): any[]; + + /** + * Start a remote debugging socket server on the given port. + * + * This exposes JavaScriptCore's built-in debugging server. + * + * This is untested. May not be supported yet on macOS + */ + function startRemoteDebugger(host?: string, port?: number): void; + + /** + * Run JavaScriptCore's sampling profiler + */ + function startSamplingProfiler(optionalDirectory?: string): void; + + /** + * Non-recursively estimate the memory usage of an object, excluding the memory usage of + * properties or other objects it references. For more accurate per-object + * memory usage, use {@link Bun.generateHeapSnapshot}. + * + * This is a best-effort estimate. It may not be 100% accurate. When it's + * wrong, it may mean the memory is non-contiguous (such as a large array). + * + * Passing a primitive type that isn't heap allocated returns 0. + */ + function estimateShallowMemoryUsageOf( + value: object | CallableFunction | bigint | symbol | string, + ): number; +} diff --git a/packages/bun-types/new/sqlite.d.ts b/packages/bun-types/new/sqlite.d.ts new file mode 100644 index 00000000000000..303469772cb98c --- /dev/null +++ b/packages/bun-types/new/sqlite.d.ts @@ -0,0 +1,1166 @@ +/** + * Fast SQLite3 driver for Bun.js + * @since v0.0.83 + * + * @example + * ```ts + * import { Database } from 'bun:sqlite'; + * + * var db = new Database('app.db'); + * db.query('SELECT * FROM users WHERE name = ?').all('John'); + * // => [{ id: 1, name: 'John' }] + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ +declare module "bun:sqlite" { + export class Database implements Disposable { + /** + * Open or create a SQLite3 database + * + * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. + * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. + * + * @example + * + * ```ts + * const db = new Database("mydb.sqlite"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open an in-memory database + * + * ```ts + * const db = new Database(":memory:"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open read-only + * + * ```ts + * const db = new Database("mydb.sqlite", {readonly: true}); + * ``` + */ + constructor( + filename?: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; + + /** + * When set to `true`, integers are returned as `bigint` types. + * + * When set to `false`, integers are returned as `number` types and truncated to 52 bits. + * + * @default false + * @since v1.1.14 + */ + safeIntegers?: boolean; + + /** + * When set to `false` or `undefined`: + * - Queries missing bound parameters will NOT throw an error + * - Bound named parameters in JavaScript need to exactly match the SQL query. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: false }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); + * ``` + * + * When set to `true`: + * - Queries missing bound parameters will throw an error + * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: true }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); + * ``` + * @since v1.1.14 + */ + strict?: boolean; + }, + ); + + /** + * This is an alias of `new Database()` + * + * See {@link Database} + */ + static open( + filename: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; + }, + ): Database; + + /** + * Execute a SQL query **without returning any results**. + * + * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * ``` + * + * Useful for queries like: + * - `CREATE TABLE` + * - `INSERT INTO` + * - `UPDATE` + * - `DELETE FROM` + * - `DROP TABLE` + * - `PRAGMA` + * - `ATTACH DATABASE` + * - `DETACH DATABASE` + * - `REINDEX` + * - `VACUUM` + * - `EXPLAIN ANALYZE` + * - `CREATE INDEX` + * - `CREATE TRIGGER` + * - `CREATE VIEW` + * - `CREATE VIRTUAL TABLE` + * - `CREATE TEMPORARY TABLE` + * + * @param sql The SQL query to run + * + * @param bindings Optional bindings for the query + * + * @returns `Database` instance + * + * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. + * + * * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run( + sqlQuery: string, + ...bindings: ParamsType[] + ): Changes; + /** + This is an alias of {@link Database.prototype.run} + */ + exec( + sqlQuery: string, + ...bindings: ParamsType[] + ): Changes; + + /** + * Compile a SQL query and return a {@link Statement} object. This is the + * same as {@link prepare} except that it caches the compiled query. + * + * This **does not execute** the query, but instead prepares it for later + * execution and caches the compiled query if possible. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * + * // run the query again + * stmt.all(); + * ``` + * + * @param sql The SQL query to compile + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + query( + sqlQuery: string, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; + + /** + * Compile a SQL query and return a {@link Statement} object. + * + * This does not cache the compiled query and does not execute the query. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * ``` + * + * @param sql The SQL query to compile + * @param params Optional bindings for the query + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + prepare< + ReturnType, + ParamsType extends SQLQueryBindings | SQLQueryBindings[], + >( + sqlQuery: string, + params?: ParamsType, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; + + /** + * Is the database in a transaction? + * + * @returns `true` if the database is in a transaction, `false` otherwise + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * db.run("BEGIN"); + * db.run("INSERT INTO foo VALUES (?)", ["qux"]); + * console.log(db.inTransaction()); + * ``` + */ + get inTransaction(): boolean; + + /** + * Close the database connection. + * + * It is safe to call this method multiple times. If the database is already + * closed, this is a no-op. Running queries after the database has been + * closed will throw an error. + * + * @example + * ```ts + * db.close(); + * ``` + * This is called automatically when the database instance is garbage collected. + * + * Internally, this calls `sqlite3_close_v2`. + */ + close( + /** + * If `true`, then the database will throw an error if it is in use + * @default false + * + * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. + * + * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). + * + * Bun will automatically call close by default when the database instance is garbage collected. + * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. + */ + throwOnError?: boolean, + ): void; + + /** + * The filename passed when `new Database()` was called + * @example + * ```ts + * const db = new Database("mydb.sqlite"); + * console.log(db.filename); + * // => "mydb.sqlite" + * ``` + */ + readonly filename: string; + + /** + * The underlying `sqlite3` database handle + * + * In native code, this is not a file descriptor, but an index into an array of database handles + */ + readonly handle: number; + + /** + * Load a SQLite3 extension + * + * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} + * + * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. + * + * @param extension name/path of the extension to load + * @param entryPoint optional entry point of the extension + */ + loadExtension(extension: string, entryPoint?: string): void; + + /** + * Change the dynamic library path to SQLite + * + * @note macOS-only + * + * This only works before SQLite is loaded, so + * that's before you call `new Database()`. + * + * It can only be run once because this will load + * the SQLite library into the process. + * + * @param path The path to the SQLite library + */ + static setCustomSQLite(path: string): boolean; + + [Symbol.dispose](): void; + + /** + * Creates a function that always runs inside a transaction. When the + * function is invoked, it will begin a new transaction. When the function + * returns, the transaction will be committed. If an exception is thrown, + * the transaction will be rolled back (and the exception will propagate as + * usual). + * + * @param insideTransaction The callback which runs inside a transaction + * + * @example + * ```ts + * // setup + * import { Database } from "bun:sqlite"; + * const db = Database.open(":memory:"); + * db.exec( + * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" + * ); + * + * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); + * const insertMany = db.transaction((cats) => { + * for (const cat of cats) insert.run(cat); + * }); + * + * insertMany([ + * { $name: "Joey", $age: 2 }, + * { $name: "Sally", $age: 4 }, + * { $name: "Junior", $age: 1 }, + * ]); + * ``` + */ + transaction(insideTransaction: (...args: any) => void): CallableFunction & { + /** + * uses "BEGIN DEFERRED" + */ + deferred: (...args: any) => void; + /** + * uses "BEGIN IMMEDIATE" + */ + immediate: (...args: any) => void; + /** + * uses "BEGIN EXCLUSIVE" + */ + exclusive: (...args: any) => void; + }; + + /** + * Save the database to an in-memory {@link Buffer} object. + * + * Internally, this calls `sqlite3_serialize`. + * + * @param name Name to save the database as @default "main" + * @returns Buffer containing the serialized database + */ + serialize(name?: string): Buffer; + + /** + * Load a serialized SQLite3 database + * + * Internally, this calls `sqlite3_deserialize`. + * + * @param serialized Data to load + * @returns `Database` instance + * + * @example + * ```ts + * test("supports serialize/deserialize", () => { + * const db = Database.open(":memory:"); + * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); + * db.exec('INSERT INTO test (name) VALUES ("Hello")'); + * db.exec('INSERT INTO test (name) VALUES ("World")'); + * + * const input = db.serialize(); + * const db2 = new Database(input); + * + * const stmt = db2.prepare("SELECT * FROM test"); + * expect(JSON.stringify(stmt.get())).toBe( + * JSON.stringify({ + * id: 1, + * name: "Hello", + * }), + * ); + * + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * ]), + * ); + * db2.exec("insert into test (name) values ('foo')"); + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * { + * id: 3, + * name: "foo", + * }, + * ]), + * ); + * + * const db3 = Database.deserialize(input, true); + * try { + * db3.exec("insert into test (name) values ('foo')"); + * throw new Error("Expected error"); + * } catch (e) { + * expect(e.message).toBe("attempt to write a readonly database"); + * } + * }); + * ``` + */ + static deserialize( + serialized: NodeJS.TypedArray | ArrayBufferLike, + isReadOnly?: boolean, + ): Database; + + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(op: number, arg?: ArrayBufferView | number): number; + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl( + zDbName: string, + op: number, + arg?: ArrayBufferView | number, + ): number; + } + + /** + * A prepared statement. + * + * This is returned by {@link Database.prepare} and {@link Database.query}. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.all("baz"); + * // => [{bar: "baz"}] + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.get("baz"); + * // => {bar: "baz"} + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.run("baz"); + * // => undefined + * ``` + */ + export class Statement< + ReturnType = unknown, + ParamsType extends SQLQueryBindings[] = any[], + > implements Disposable + { + /** + * Creates a new prepared statement from native code. + * + * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. + */ + constructor(nativeHandle: any); + + /** + * Execute the prepared statement and return all results as objects. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.all("baz"); + * // => [{bar: "baz"}] + * + * stmt.all(); + * // => [] + * + * stmt.all("foo"); + * // => [{bar: "foo"}] + * ``` + */ + all(...params: ParamsType): ReturnType[]; + + /** + * Execute the prepared statement and return **the first** result. + * + * If no result is returned, this returns `null`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.get("baz"); + * // => {bar: "baz"} + * + * stmt.get(); + * // => null + * + * stmt.get("foo"); + * // => {bar: "foo"} + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + get(...params: ParamsType): ReturnType | null; + + /** + * Execute the prepared statement and return an + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + */ + iterate(...params: ParamsType): IterableIterator; + [Symbol.iterator](): IterableIterator; + + /** + * Execute the prepared statement. This returns `undefined`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("UPDATE foo SET bar = ?"); + * stmt.run("baz"); + * // => undefined + * + * stmt.run(); + * // => undefined + * + * stmt.run("foo"); + * // => undefined + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(...params: ParamsType): Changes; + + /** + * Execute the prepared statement and return the results as an array of arrays. + * + * In Bun v0.6.7 and earlier, this method returned `null` if there were no + * results instead of `[]`. This was changed in v0.6.8 to align + * more with what people expect. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.values("baz"); + * // => [['baz']] + * + * stmt.values(); + * // => [['baz']] + * + * stmt.values("foo"); + * // => [['foo']] + * + * stmt.values("not-found"); + * // => [] + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | ---------------|-------------| + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + values( + ...params: ParamsType + ): Array>; + + /** + * The names of the columns returned by the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); + * + * console.log(stmt.columnNames); + * // => ["bar"] + * ``` + */ + readonly columnNames: string[]; + + /** + * The number of parameters expected in the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * console.log(stmt.paramsCount); + * // => 1 + * ``` + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); + * console.log(stmt.paramsCount); + * // => 2 + * ``` + */ + readonly paramsCount: number; + + /** + * Finalize the prepared statement, freeing the resources used by the + * statement and preventing it from being executed again. + * + * This is called automatically when the prepared statement is garbage collected. + * + * It is safe to call this multiple times. Calling this on a finalized + * statement has no effect. + * + * Internally, this calls `sqlite3_finalize`. + */ + finalize(): void; + + /** + * Calls {@link finalize} if it wasn't already called. + */ + [Symbol.dispose](): void; + + /** + * Return the expanded SQL string for the prepared statement. + * + * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); + * console.log(stmt.toString()); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * console.log(stmt); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * ``` + */ + toString(): string; + + /** + * + * Make {@link get} and {@link all} return an instance of the provided + * `Class` instead of the default `Object`. + * + * @param Class A class to use + * @returns The same statement instance, modified to return an instance of `Class` + * + * This lets you attach methods, getters, and setters to the returned + * objects. + * + * For performance reasons, constructors for classes are not called, which means + * initializers will not be called and private fields will not be + * accessible. + * + * @example + * + * ## Custom class + * ```ts + * class User { + * rawBirthdate: string; + * get birthdate() { + * return new Date(this.rawBirthdate); + * } + * } + * + * const db = new Database(":memory:"); + * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); + * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); + * const query = db.query("SELECT * FROM users"); + * query.as(User); + * const user = query.get(); + * console.log(user.birthdate); + * // => Date(1995, 12, 19) + * ``` + */ + as(Class: new (...args: any[]) => T): Statement; + + /** + * Native object representing the underlying `sqlite3_stmt` + * + * This is left untyped because the ABI of the native bindings may change at any time. + */ + readonly native: any; + } + + /** + * Constants from `sqlite3.h` + * + * This list isn't exhaustive, but some of the ones which are relevant + */ + export const constants: { + /** + * Open the database as read-only (no write operations, no create). + * @constant 0x00000001 + */ + SQLITE_OPEN_READONLY: number; + /** + * Open the database for reading and writing + * @constant 0x00000002 + */ + SQLITE_OPEN_READWRITE: number; + /** + * Allow creating a new database + * @constant 0x00000004 + */ + SQLITE_OPEN_CREATE: number; + /** + * @constant 0x00000008 + */ + SQLITE_OPEN_DELETEONCLOSE: number; + /** + * @constant 0x00000010 + */ + SQLITE_OPEN_EXCLUSIVE: number; + /** + * @constant 0x00000020 + */ + SQLITE_OPEN_AUTOPROXY: number; + /** + * @constant 0x00000040 + */ + SQLITE_OPEN_URI: number; + /** + * @constant 0x00000080 + */ + SQLITE_OPEN_MEMORY: number; + /** + * @constant 0x00000100 + */ + SQLITE_OPEN_MAIN_DB: number; + /** + * @constant 0x00000200 + */ + SQLITE_OPEN_TEMP_DB: number; + /** + * @constant 0x00000400 + */ + SQLITE_OPEN_TRANSIENT_DB: number; + /** + * @constant 0x00000800 + */ + SQLITE_OPEN_MAIN_JOURNAL: number; + /** + * @constant 0x00001000 + */ + SQLITE_OPEN_TEMP_JOURNAL: number; + /** + * @constant 0x00002000 + */ + SQLITE_OPEN_SUBJOURNAL: number; + /** + * @constant 0x00004000 + */ + SQLITE_OPEN_SUPER_JOURNAL: number; + /** + * @constant 0x00008000 + */ + SQLITE_OPEN_NOMUTEX: number; + /** + * @constant 0x00010000 + */ + SQLITE_OPEN_FULLMUTEX: number; + /** + * @constant 0x00020000 + */ + SQLITE_OPEN_SHAREDCACHE: number; + /** + * @constant 0x00040000 + */ + SQLITE_OPEN_PRIVATECACHE: number; + /** + * @constant 0x00080000 + */ + SQLITE_OPEN_WAL: number; + /** + * @constant 0x01000000 + */ + SQLITE_OPEN_NOFOLLOW: number; + /** + * @constant 0x02000000 + */ + SQLITE_OPEN_EXRESCODE: number; + /** + * @constant 0x01 + */ + SQLITE_PREPARE_PERSISTENT: number; + /** + * @constant 0x02 + */ + SQLITE_PREPARE_NORMALIZE: number; + /** + * @constant 0x04 + */ + SQLITE_PREPARE_NO_VTAB: number; + + /** + * @constant 1 + */ + SQLITE_FCNTL_LOCKSTATE: number; + /** + * @constant 2 + */ + SQLITE_FCNTL_GET_LOCKPROXYFILE: number; + /** + * @constant 3 + */ + SQLITE_FCNTL_SET_LOCKPROXYFILE: number; + /** + * @constant 4 + */ + SQLITE_FCNTL_LAST_ERRNO: number; + /** + * @constant 5 + */ + SQLITE_FCNTL_SIZE_HINT: number; + /** + * @constant 6 + */ + SQLITE_FCNTL_CHUNK_SIZE: number; + /** + * @constant 7 + */ + SQLITE_FCNTL_FILE_POINTER: number; + /** + * @constant 8 + */ + SQLITE_FCNTL_SYNC_OMITTED: number; + /** + * @constant 9 + */ + SQLITE_FCNTL_WIN32_AV_RETRY: number; + /** + * @constant 10 + * + * Control whether or not the WAL is persisted + * Some versions of macOS configure WAL to be persistent by default. + * + * You can change this with code like the below: + * ```ts + * import { Database } from "bun:sqlite"; + * + * const db = Database.open("mydb.sqlite"); + * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); + * // enable WAL + * db.exec("PRAGMA journal_mode = WAL"); + * // .. do some work + * db.close(); + * ``` + * + */ + SQLITE_FCNTL_PERSIST_WAL: number; + /** + * @constant 11 + */ + SQLITE_FCNTL_OVERWRITE: number; + /** + * @constant 12 + */ + SQLITE_FCNTL_VFSNAME: number; + /** + * @constant 13 + */ + SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; + /** + * @constant 14 + */ + SQLITE_FCNTL_PRAGMA: number; + /** + * @constant 15 + */ + SQLITE_FCNTL_BUSYHANDLER: number; + /** + * @constant 16 + */ + SQLITE_FCNTL_TEMPFILENAME: number; + /** + * @constant 18 + */ + SQLITE_FCNTL_MMAP_SIZE: number; + /** + * @constant 19 + */ + SQLITE_FCNTL_TRACE: number; + /** + * @constant 20 + */ + SQLITE_FCNTL_HAS_MOVED: number; + /** + * @constant 21 + */ + SQLITE_FCNTL_SYNC: number; + /** + * @constant 22 + */ + SQLITE_FCNTL_COMMIT_PHASETWO: number; + /** + * @constant 23 + */ + SQLITE_FCNTL_WIN32_SET_HANDLE: number; + /** + * @constant 24 + */ + SQLITE_FCNTL_WAL_BLOCK: number; + /** + * @constant 25 + */ + SQLITE_FCNTL_ZIPVFS: number; + /** + * @constant 26 + */ + SQLITE_FCNTL_RBU: number; + /** + * @constant 27 + */ + SQLITE_FCNTL_VFS_POINTER: number; + /** + * @constant 28 + */ + SQLITE_FCNTL_JOURNAL_POINTER: number; + /** + * @constant 29 + */ + SQLITE_FCNTL_WIN32_GET_HANDLE: number; + /** + * @constant 30 + */ + SQLITE_FCNTL_PDB: number; + /** + * @constant 31 + */ + SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; + /** + * @constant 32 + */ + SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; + /** + * @constant 33 + */ + SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; + /** + * @constant 34 + */ + SQLITE_FCNTL_LOCK_TIMEOUT: number; + /** + * @constant 35 + */ + SQLITE_FCNTL_DATA_VERSION: number; + /** + * @constant 36 + */ + SQLITE_FCNTL_SIZE_LIMIT: number; + /** + * @constant 37 + */ + SQLITE_FCNTL_CKPT_DONE: number; + /** + * @constant 38 + */ + SQLITE_FCNTL_RESERVE_BYTES: number; + /** + * @constant 39 + */ + SQLITE_FCNTL_CKPT_START: number; + /** + * @constant 40 + */ + SQLITE_FCNTL_EXTERNAL_READER: number; + /** + * @constant 41 + */ + SQLITE_FCNTL_CKSM_FILE: number; + /** + * @constant 42 + */ + SQLITE_FCNTL_RESET_CACHE: number; + }; + + /** + * The native module implementing the sqlite3 C bindings + * + * It is lazily-initialized, so this will return `undefined` until the first + * call to new Database(). + * + * The native module makes no gurantees about ABI stability, so it is left + * untyped + * + * If you need to use it directly for some reason, please let us know because + * that probably points to a deficiency in this API. + */ + export var native: any; + + export type SQLQueryBindings = + | string + | bigint + | NodeJS.TypedArray + | number + | boolean + | null + | Record< + string, + string | bigint | NodeJS.TypedArray | number | boolean | null + >; + + export default Database; + + /** + * Errors from SQLite have a name `SQLiteError`. + * + */ + export class SQLiteError extends Error { + readonly name: "SQLiteError"; + + /** + * The SQLite3 extended error code + * + * This corresponds to `sqlite3_extended_errcode`. + * + * @since v1.0.21 + */ + errno: number; + + /** + * The name of the SQLite3 error code + * + * @example + * "SQLITE_CONSTRAINT_UNIQUE" + * + * @since v1.0.21 + */ + code?: string; + + /** + * The UTF-8 byte offset of the sqlite3 query that failed, if known + * + * This corresponds to `sqlite3_error_offset`. + * + * @since v1.0.21 + */ + readonly byteOffset: number; + } + + /** + * An object representing the changes made to the database since the last `run` or `exec` call. + * + * @since Bun v1.1.14 + */ + export interface Changes { + /** + * The number of rows changed by the last `run` or `exec` call. + */ + changes: number; + + /** + * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. + */ + lastInsertRowid: number | bigint; + } +} diff --git a/packages/bun-types/new/test.d.ts b/packages/bun-types/new/test.d.ts new file mode 100644 index 00000000000000..e2d4a01871c381 --- /dev/null +++ b/packages/bun-types/new/test.d.ts @@ -0,0 +1,2282 @@ +/** + * + * To run tests, run `bun test` + * + * @example + * + * ```bash + * $ bun test + * ``` + * + * @example + * ```bash + * $ bun test + * ``` + */ +declare module "bun:test" { + /** + * -- Mocks -- + */ + export type Mock any> = JestMock.Mock; + + export const mock: { + any>(Function?: T): Mock; + + /** + * Replace the module `id` with the return value of `factory`. + * + * This is useful for mocking modules. + * + * @param id module ID to mock + * @param factory a function returning an object that will be used as the exports of the mocked module + * + * @example + * ## Example + * ```ts + * import { mock } from "bun:test"; + * + * mock.module("fs/promises", () => { + * return { + * readFile: () => Promise.resolve("hello world"), + * }; + * }); + * + * import { readFile } from "fs/promises"; + * + * console.log(await readFile("hello.txt", "utf8")); // hello world + * ``` + * + * ## More notes + * + * If the module is already loaded, exports are overwritten with the return + * value of `factory`. If the export didn't exist before, it will not be + * added to existing import statements. This is due to how ESM works. + */ + module(id: string, factory: () => any): void | Promise; + /** + * Restore the previous value of mocks. + */ + restore(): void; + }; + + /** + * Control the system time used by: + * - `Date.now()` + * - `new Date()` + * - `Intl.DateTimeFormat().format()` + * + * In the future, we may add support for more functions, but we haven't done that yet. + * + * @param now The time to set the system time to. If not provided, the system time will be reset. + * @returns `this` + * @since v0.6.13 + * + * ## Set Date to a specific time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); + * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z + * ``` + * ## Reset Date to the current time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(); + * ``` + */ + export function setSystemTime(now?: Date | number): ThisType; + + interface Jest { + restoreAllMocks(): void; + clearAllMocks(): void; + fn any>(func?: T): Mock; + setSystemTime(now?: number | Date): void; + setTimeout(milliseconds: number): void; + } + export const jest: Jest; + export namespace jest { + /** + * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. + */ + type Mock any = (...args: any[]) => any> = + JestMock.Mock; + /** + * Wraps a class, function or object type with Jest mock type definitions. + */ + // type Mocked = JestMock.Mocked; + /** + * Wraps a class type with Jest mock type definitions. + */ + // type MockedClass = JestMock.MockedClass; + /** + * Wraps a function type with Jest mock type definitions. + */ + // type MockedFunction any> = JestMock.MockedFunction; + /** + * Wraps an object type with Jest mock type definitions. + */ + // type MockedObject = JestMock.MockedObject; + /** + * Constructs the type of a replaced property. + */ + type Replaced = JestMock.Replaced; + /** + * Constructs the type of a spied class or function. + */ + type Spied any)> = + JestMock.Spied; + /** + * Constructs the type of a spied class. + */ + type SpiedClass = JestMock.SpiedClass; + /** + * Constructs the type of a spied function. + */ + type SpiedFunction any> = + JestMock.SpiedFunction; + /** + * Constructs the type of a spied getter. + */ + type SpiedGetter = JestMock.SpiedGetter; + /** + * Constructs the type of a spied setter. + */ + type SpiedSetter = JestMock.SpiedSetter; + } + + export function spyOn( + obj: T, + methodOrPropertyValue: K, + ): Mock any ? T[K] : never>; + + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export interface Describe { + (label: string, fn: () => void): void; + /** + * Skips all other tests, except this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + only(label: string, fn: () => void): void; + /** + * Skips this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + skip(label: string, fn: () => void): void; + /** + * Marks this group of tests as to be written or to be fixed. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + todo(label: string, fn?: () => void): void; + /** + * Runs this group of tests, only if `condition` is true. + * + * This is the opposite of `describe.skipIf()`. + * + * @param condition if these tests should run + */ + if(condition: boolean): (label: string, fn: () => void) => void; + /** + * Skips this group of tests, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + skipIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Marks this group of tests as to be written or to be fixed, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + todoIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): ( + label: string, + fn: (...args: [...T]) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: readonly T[], + ): ( + label: string, + fn: (...args: Readonly) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: T[], + ): ( + label: string, + fn: (...args: T[]) => void | Promise, + options?: number | TestOptions, + ) => void; + } + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export const describe: Describe; + /** + * Runs a function, once, before all the tests. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, tests will not run in this file. + * + * @example + * let database; + * beforeAll(async () => { + * database = await connect("localhost"); + * }); + * + * @param fn the function to run + */ + export function beforeAll( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function before each test. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, the test will not run. + * + * @param fn the function to run + */ + export function beforeEach( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function, once, after all the tests. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @example + * let database; + * afterAll(async () => { + * if (database) { + * await database.close(); + * } + * }); + * + * @param fn the function to run + */ + export function afterAll( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs a function after each test. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @param fn the function to run + */ + export function afterEach( + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will + * override this value. The default timeout is 5000ms (5 seconds). + * + * @param milliseconds the number of milliseconds for the default timeout + */ + export function setDefaultTimeout(milliseconds: number): void; + export interface TestOptions { + /** + * Sets the timeout for the test in milliseconds. + * + * If the test does not complete within this time, the test will fail with: + * ```ts + * 'Timeout: test {name} timed out after 5000ms' + * ``` + * + * @default 5000 // 5 seconds + */ + timeout?: number; + /** + * Sets the number of times to retry the test if it fails. + * + * @default 0 + */ + retry?: number; + /** + * Sets the number of times to repeat the test, regardless of whether it passed or failed. + * + * @default 0 + */ + repeats?: number; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * test("can set a timeout", async () => { + * await Bun.sleep(100); + * }, 50); // or { timeout: 50 } + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + export interface Test { + ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + /** + * - If a `number`, sets the timeout for the test in milliseconds. + * - If an `object`, sets the options for the test. + * - `timeout` sets the timeout for the test in milliseconds. + * - `retry` sets the number of times to retry the test if it fails. + * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. + */ + options?: number | TestOptions, + ): void; + /** + * Skips all other tests, except this test when run with the `--only` option. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + only( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Skips this test. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + skip( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as to be written or to be fixed. + * + * These tests will not be executed unless the `--todo` flag is passed. With the flag, + * if the test passes, the test will be marked as `fail` in the results; you will have to + * remove the `.todo` or check that your test + * is implemented correctly. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + todo( + label: string, + fn?: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as failing. + * + * Use `test.failing` when you are writing a test and expecting it to fail. + * These tests will behave the other way normal tests do. If failing test + * will throw any errors then it will pass. If it does not throw it will + * fail. + * + * `test.failing` is very similar to {@link test.todo} except that it always + * runs, regardless of the `--todo` flag. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + failing( + label: string, + fn?: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + ): void; + /** + * Runs this test, if `condition` is true. + * + * This is the opposite of `test.skipIf()`. + * + * @param condition if the test should run + */ + if( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Skips this test, if `condition` is true. + * + * @param condition if the test should be skipped + */ + skipIf( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Marks this test as to be written or to be fixed, if `condition` is true. + * + * @param condition if the test should be marked TODO + */ + todoIf( + condition: boolean, + ): ( + label: string, + fn: + | (() => void | Promise) + | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): ( + label: string, + fn: (...args: [...T]) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: readonly T[], + ): ( + label: string, + fn: (...args: Readonly) => void | Promise, + options?: number | TestOptions, + ) => void; + each( + table: T[], + ): ( + label: string, + fn: (...args: T[]) => void | Promise, + options?: number | TestOptions, + ) => void; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * @param label the label for the test + * @param fn the test function + */ + export const test: Test; + export { test as it }; + + /** + * Asserts that a value matches some criteria. + * + * @link https://jestjs.io/docs/expect#reference + * @example + * expect(1 + 1).toBe(2); + * expect([1,2,3]).toContain(2); + * expect(null).toBeNull(); + * + * @param actual The actual (received) value + */ + export const expect: Expect; + + type ExpectNot = Omit & + AsymmetricMatchersBuiltinNegated; + + export interface Expect extends AsymmetricMatchers { + // the `expect()` callable signature + /** + * @param actual the actual value + * @param customFailMessage an optional custom message to display if the test fails. + * */ + + (actual?: T, customFailMessage?: string): Matchers; + + /** + * Access to negated asymmetric matchers. + * + * @example + * expect("abc").toEqual(expect.stringContaining("abc")); // will pass + * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail + */ + not: ExpectNot; + + /** + * Create an asymmetric matcher for a promise resolved value. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass + * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail + * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail + */ + resolvesTo: AsymmetricMatchers; + + /** + * Create an asymmetric matcher for a promise rejected value. + * + * @example + * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass + * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail + * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail + */ + rejectsTo: AsymmetricMatchers; + + /** + * Register new custom matchers. + * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. + * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` + * + * @example + * expect.extend({ + * toBeWithinRange(actual, min, max) { + * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') + * throw new Error('Invalid usage'); + * const pass = actual >= min && actual <= max; + * return { + * pass: pass, + * message: () => `expected ${this.utils.printReceived(actual)} ` + + * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, + * }; + * }, + * }); + * + * test('some test', () => { + * expect(50).toBeWithinRange(0, 100); // will pass + * expect(50).toBeWithinRange(100, 200); // will fail + * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass + * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass + * }); + */ + extend(matchers: ExpectExtendMatchers): void; + + /** + * Throw an error if this function is called. + * + * @param msg Optional message to display if the test fails + * @returns never + * + * @example + * ## Example + * + * ```ts + * import { expect, test } from "bun:test"; + * + * test("!!abc!! is not a module", () => { + * try { + * require("!!abc!!"); + * expect.unreachable(); + * } catch(e) { + * expect(e.name).not.toBe("UnreachableError"); + * } + * }); + * ``` + */ + unreachable(msg?: string | Error): never; + + /** + * Ensures that an assertion is made + */ + hasAssertions(): void; + + /** + * Ensures that a specific number of assertions are made + */ + assertions(neededAssertions: number): void; + } + + /** + * You can extend this interface with declaration merging, in order to add type support for custom matchers. + * @template T Type of the actual value + * + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface Matchers extends MatchersBuiltin {} + + /** + * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} + + export interface AsymmetricMatchersBuiltin { + /** + * Matches anything that was created with the given constructor. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * @example + * + * function randocall(fn) { + * return fn(Math.floor(Math.random() * 6 + 1)); + * } + * + * test('randocall calls its callback with a number', () => { + * const mock = jest.fn(); + * randocall(mock); + * expect(mock).toBeCalledWith(expect.any(Number)); + * }); + */ + any( + constructor: ((...args: any[]) => any) | { new (...args: any[]): any }, + ): AsymmetricMatcher; + /** + * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead + * of a literal value. For example, if you want to check that a mock function is called with a + * non-null argument: + * + * @example + * + * test('map calls its argument with a non-null argument', () => { + * const mock = jest.fn(); + * [1].map(x => mock(x)); + * expect(mock).toBeCalledWith(expect.anything()); + * }); + */ + anything(): AsymmetricMatcher; + /** + * Matches any array made up entirely of elements in the provided array. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + /** + * Matches any object that recursively matches the provided keys. + * This is often handy in conjunction with other asymmetric matchers. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + /** + * Matches any received string that contains the exact expected string + */ + stringContaining(str: string | String): AsymmetricMatcher; + /** + * Matches any string that contains the exact provided string + */ + stringMatching(regex: string | String | RegExp): AsymmetricMatcher; + /** + * Useful when comparing floating point numbers in object properties or array item. + * If you need to compare a number, use `.toBeCloseTo` instead. + * + * The optional `numDigits` argument limits the number of digits to check after the decimal point. + * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + interface AsymmetricMatchersBuiltinNegated { + /** + * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail + * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + */ + resolvesTo: ExpectNot; + + /** + * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. + * + * @example + * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail + * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + */ + rejectsTo: ExpectNot; + + /** + * `expect.not.arrayContaining(array)` matches a received array which + * does not contain all of the elements in the expected array. That is, + * the expected array is not a subset of the received array. It is the + * inverse of `expect.arrayContaining`. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + + /** + * `expect.not.objectContaining(object)` matches any received object + * that does not recursively match the expected properties. That is, the + * expected object is not a subset of the received object. Therefore, + * it matches a received object which contains properties that are not + * in the expected object. It is the inverse of `expect.objectContaining`. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + + /** + * `expect.not.stringContaining(string)` matches the received string + * that does not contain the exact expected string. It is the inverse of + * `expect.stringContaining`. + */ + stringContaining(str: string | String): AsymmetricMatcher; + + /** + * `expect.not.stringMatching(string | regexp)` matches the received + * string that does not match the expected regexp. It is the inverse of + * `expect.stringMatching`. + */ + stringMatching(str: string | String | RegExp): AsymmetricMatcher; + + /** + * `expect.not.closeTo` matches a number not close to the provided value. + * Useful when comparing floating point numbers in object properties or array item. + * It is the inverse of `expect.closeTo`. + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + export interface MatchersBuiltin { + /** + * Negates the result of a subsequent assertion. + * If you know how to test something, `.not` lets you test its opposite. + * + * @example + * expect(1).not.toBe(0); + * expect(null).not.toBeNull(); + * + * @example + * expect(42).toEqual(42); // will pass + * expect(42).not.toEqual(42); // will fail + */ + not: Matchers; + + /** + * Expects the value to be a promise that resolves. + * + * @example + * expect(Promise.resolve(1)).resolves.toBe(1); + */ + resolves: Matchers>; + + /** + * Expects the value to be a promise that rejects. + * + * @example + * expect(Promise.reject("error")).rejects.toBe("error"); + */ + rejects: Matchers; + + /** + * Assertion which passes. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass + * @example + * expect().pass(); + * expect().pass("message is optional"); + * expect().not.pass(); + * expect().not.pass("hi"); + * + * @param message the message to display if the test fails (optional) + */ + pass: (message?: string) => void; + /** + * Assertion which fails. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail + * @example + * expect().fail(); + * expect().fail("message is optional"); + * expect().not.fail(); + * expect().not.fail("hi"); + */ + fail: (message?: string) => void; + /** + * Asserts that a value equals what is expected. + * + * - For non-primitive values, like objects and arrays, + * use `toEqual()` instead. + * - For floating-point numbers, use `toBeCloseTo()` instead. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([123]).toBe([123]); // fail, use toEqual() + * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() + * + * @param expected the expected value + */ + toBe(expected: T): void; + /** + * Asserts that a number is odd. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd + * @example + * expect(1).toBeOdd(); + * expect(2).not.toBeOdd(); + */ + toBeOdd(): void; + /** + * Asserts that a number is even. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven + * @example + * expect(2).toBeEven(); + * expect(1).not.toBeEven(); + */ + toBeEven(): void; + /** + * Asserts that value is close to the expected by floating point precision. + * + * For example, the following fails because arithmetic on decimal (base 10) + * values often have rounding errors in limited precision binary (base 2) representation. + * + * @example + * expect(0.2 + 0.1).toBe(0.3); // fails + * + * Use `toBeCloseTo` to compare floating point numbers for approximate equality. + * + * @example + * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes + * + * @param expected the expected value + * @param numDigits the number of digits to check after the decimal point. Default is `2` + */ + toBeCloseTo(expected: number, numDigits?: number): void; + /** + * Asserts that a value is deeply equal to what is expected. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([456]).toEqual([456]); + * expect({ value: 1 }).toEqual({ value: 1 }); + * + * @param expected the expected value + */ + toEqual(expected: T): void; + /** + * Asserts that a value is deeply and strictly equal to + * what is expected. + * + * There are two key differences from `toEqual()`: + * 1. It checks that the class is the same. + * 2. It checks that `undefined` values match as well. + * + * @example + * class Dog { + * type = "dog"; + * } + * const actual = new Dog(); + * expect(actual).toStrictEqual(new Dog()); + * expect(actual).toStrictEqual({ type: "dog" }); // fail + * + * @example + * const actual = { value: 1, name: undefined }; + * expect(actual).toEqual({ value: 1 }); + * expect(actual).toStrictEqual({ value: 1 }); // fail + * + * @param expected the expected value + */ + toStrictEqual(expected: T): void; + /** + * Asserts that the value is deep equal to an element in the expected array. + * + * The value must be an array or iterable, which includes strings. + * + * @example + * expect(1).toBeOneOf([1,2,3]); + * expect("foo").toBeOneOf(["foo", "bar"]); + * expect(true).toBeOneOf(new Set([true])); + * + * @param expected the expected value + */ + toBeOneOf(expected: Array | Iterable): void; + /** + * Asserts that a value contains what is expected. + * + * The value must be an array or iterable, which + * includes strings. + * + * @example + * expect([1, 2, 3]).toContain(1); + * expect(new Set([true])).toContain(true); + * expect("hello").toContain("o"); + * + * @param expected the expected value + */ + toContain(expected: unknown): void; + /** + * Asserts that an `object` contains a key. + * + * The value must be an object + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); + * + * @param expected the expected value + */ + toContainKey(expected: unknown): void; + /** + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); + * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); + * + * @param expected the expected value + */ + toContainAllKeys(expected: unknown): void; + /** + * Asserts that an `object` contains at least one of the provided keys. + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); + * + * @param expected the expected value + */ + toContainAnyKeys(expected: unknown): void; + + /** + * Asserts that an `object` contain the provided value. + * + * The value must be an object + * + * @example + * const shallow = { hello: "world" }; + * const deep = { message: shallow }; + * const deepArray = { message: [shallow] }; + * const o = { a: "foo", b: [1, "hello", true], c: "baz" }; + + * expect(shallow).toContainValue("world"); + * expect({ foo: false }).toContainValue(false); + * expect(deep).toContainValue({ hello: "world" }); + * expect(deepArray).toContainValue([{ hello: "world" }]); + + * expect(o).toContainValue("foo", "barr"); + * expect(o).toContainValue([1, "hello", true]); + * expect(o).not.toContainValue("qux"); + + // NOT + * expect(shallow).not.toContainValue("foo"); + * expect(deep).not.toContainValue({ foo: "bar" }); + * expect(deepArray).not.toContainValue([{ foo: "bar" }]); + * + * @param expected the expected value + */ + toContainValue(expected: unknown): void; + + /** + * Asserts that an `object` contain the provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainValues(['foo']); + * expect(o).toContainValues(['baz', 'bar']); + * expect(o).not.toContainValues(['qux', 'foo']); + * @param expected the expected value + */ + toContainValues(expected: unknown): void; + + /** + * Asserts that an `object` contain all the provided values. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAllValues(['foo', 'bar', 'baz']); + * expect(o).toContainAllValues(['baz', 'bar', 'foo']); + * expect(o).not.toContainAllValues(['bar', 'foo']); + * @param expected the expected value + */ + toContainAllValues(expected: unknown): void; + + /** + * Asserts that an `object` contain any provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAnyValues(['qux', 'foo']); + * expect(o).toContainAnyValues(['qux', 'bar']); + * expect(o).toContainAnyValues(['qux', 'baz']); + * expect(o).not.toContainAnyValues(['qux']); + * @param expected the expected value + */ + toContainAnyValues(expected: unknown): void; + + /** + * Asserts that an `object` contains all the provided keys. + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); + * + * @param expected the expected value + */ + toContainKeys(expected: unknown): void; + /** + * Asserts that a value contains and equals what is expected. + * + * This matcher will perform a deep equality check for members + * of arrays, rather than checking for object identity. + * + * @example + * expect([{ a: 1 }]).toContainEqual({ a: 1 }); + * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); + * + * @param expected the expected value + */ + toContainEqual(expected: unknown): void; + /** + * Asserts that a value has a `.length` property + * that is equal to the expected length. + * + * @example + * expect([]).toHaveLength(0); + * expect("hello").toHaveLength(4); + * + * @param length the expected length + */ + toHaveLength(length: number): void; + /** + * Asserts that a value has a property with the + * expected name, and value if provided. + * + * @example + * expect(new Set()).toHaveProperty("size"); + * expect(new Uint8Array()).toHaveProperty("byteLength", 0); + * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); + * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); + * + * @param keyPath the expected property name or path, or an index + * @param value the expected property value, if provided + */ + toHaveProperty( + keyPath: string | number | Array, + value?: unknown, + ): void; + /** + * Asserts that a value is "truthy". + * + * To assert that a value equals `true`, use `toBe(true)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeTruthy(): void; + /** + * Asserts that a value is "falsy". + * + * To assert that a value equals `false`, use `toBe(false)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeFalsy(): void; + /** + * Asserts that a value is defined. (e.g. is not `undefined`) + * + * @example + * expect(true).toBeDefined(); + * expect(undefined).toBeDefined(); // fail + */ + toBeDefined(): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that a value is `undefined`. + * + * @example + * expect(undefined).toBeUndefined(); + * expect(null).toBeUndefined(); // fail + */ + toBeUndefined(): void; + /** + * Asserts that a value is `null`. + * + * @example + * expect(null).toBeNull(); + * expect(undefined).toBeNull(); // fail + */ + toBeNull(): void; + /** + * Asserts that a value is `NaN`. + * + * Same as using `Number.isNaN()`. + * + * @example + * expect(NaN).toBeNaN(); + * expect(Infinity).toBeNaN(); // fail + * expect("notanumber").toBeNaN(); // fail + */ + toBeNaN(): void; + /** + * Asserts that a value is a `number` and is greater than the expected value. + * + * @example + * expect(1).toBeGreaterThan(0); + * expect(3.14).toBeGreaterThan(3); + * expect(9).toBeGreaterThan(9); // fail + * + * @param expected the expected number + */ + toBeGreaterThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is greater than or equal to the expected value. + * + * @example + * expect(1).toBeGreaterThanOrEqual(0); + * expect(3.14).toBeGreaterThanOrEqual(3); + * expect(9).toBeGreaterThanOrEqual(9); + * + * @param expected the expected number + */ + toBeGreaterThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than the expected value. + * + * @example + * expect(-1).toBeLessThan(0); + * expect(3).toBeLessThan(3.14); + * expect(9).toBeLessThan(9); // fail + * + * @param expected the expected number + */ + toBeLessThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than or equal to the expected value. + * + * @example + * expect(-1).toBeLessThanOrEqual(0); + * expect(3).toBeLessThanOrEqual(3.14); + * expect(9).toBeLessThanOrEqual(9); + * + * @param expected the expected number + */ + toBeLessThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrow("Oops!"); + * expect(fail).toThrow(/oops/i); + * expect(fail).toThrow(Error); + * expect(fail).toThrow(); + * + * @param expected the expected error, error message, or error pattern + */ + toThrow(expected?: unknown): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowError("Oops!"); + * expect(fail).toThrowError(/oops/i); + * expect(fail).toThrowError(Error); + * expect(fail).toThrowError(); + * + * @param expected the expected error, error message, or error pattern + * @alias toThrow + */ + toThrowError(expected?: unknown): void; + /** + * Asserts that a value matches a regular expression or includes a substring. + * + * @example + * expect("dog").toMatch(/dog/); + * expect("dog").toMatch("og"); + * + * @param expected the expected substring or pattern. + */ + toMatch(expected: string | RegExp): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot('hint message'); + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(hint?: string): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot(); + * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); + * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(propertyMatchers?: object, hint?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect("Hello").toMatchInlineSnapshot(); + * expect("Hello").toMatchInlineSnapshot(`"Hello"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(value?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` + * { + * "v": Any, + * } + * `); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingSnapshot(); + * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingSnapshot(hint?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingInlineSnapshot(); + * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingInlineSnapshot(value?: string): void; + /** + * Asserts that an object matches a subset of properties. + * + * @example + * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); + * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); + * + * @param subset Subset of properties to match with. + */ + toMatchObject(subset: object): void; + /** + * Asserts that a value is empty. + * + * @example + * expect("").toBeEmpty(); + * expect([]).toBeEmpty(); + * expect({}).toBeEmpty(); + * expect(new Set()).toBeEmpty(); + */ + toBeEmpty(): void; + /** + * Asserts that a value is an empty `object`. + * + * @example + * expect({}).toBeEmptyObject(); + * expect({ a: 'hello' }).not.toBeEmptyObject(); + */ + toBeEmptyObject(): void; + /** + * Asserts that a value is `null` or `undefined`. + * + * @example + * expect(null).toBeNil(); + * expect(undefined).toBeNil(); + */ + toBeNil(): void; + /** + * Asserts that a value is a `array`. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray + * @example + * expect([1]).toBeArray(); + * expect(new Array(1)).toBeArray(); + * expect({}).not.toBeArray(); + */ + toBeArray(): void; + /** + * Asserts that a value is a `array` of a certain length. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize + * @example + * expect([]).toBeArrayOfSize(0); + * expect([1]).toBeArrayOfSize(1); + * expect(new Array(1)).toBeArrayOfSize(1); + * expect({}).not.toBeArrayOfSize(0); + */ + toBeArrayOfSize(size: number): void; + /** + * Asserts that a value is a `boolean`. + * + * @example + * expect(true).toBeBoolean(); + * expect(false).toBeBoolean(); + * expect(null).not.toBeBoolean(); + * expect(0).not.toBeBoolean(); + */ + toBeBoolean(): void; + /** + * Asserts that a value is `true`. + * + * @example + * expect(true).toBeTrue(); + * expect(false).not.toBeTrue(); + * expect(1).not.toBeTrue(); + */ + toBeTrue(): void; + /** + * Asserts that a value matches a specific type. + * + * @link https://vitest.dev/api/expect.html#tobetypeof + * @example + * expect(1).toBeTypeOf("number"); + * expect("hello").toBeTypeOf("string"); + * expect([]).not.toBeTypeOf("boolean"); + */ + toBeTypeOf( + type: + | "bigint" + | "boolean" + | "function" + | "number" + | "object" + | "string" + | "symbol" + | "undefined", + ): void; + /** + * Asserts that a value is `false`. + * + * @example + * expect(false).toBeFalse(); + * expect(true).not.toBeFalse(); + * expect(0).not.toBeFalse(); + */ + toBeFalse(): void; + /** + * Asserts that a value is a `number`. + * + * @example + * expect(1).toBeNumber(); + * expect(3.14).toBeNumber(); + * expect(NaN).toBeNumber(); + * expect(BigInt(1)).not.toBeNumber(); + */ + toBeNumber(): void; + /** + * Asserts that a value is a `number`, and is an integer. + * + * @example + * expect(1).toBeInteger(); + * expect(3.14).not.toBeInteger(); + * expect(NaN).not.toBeInteger(); + */ + toBeInteger(): void; + /** + * Asserts that a value is an `object`. + * + * @example + * expect({}).toBeObject(); + * expect("notAnObject").not.toBeObject(); + * expect(NaN).not.toBeObject(); + */ + toBeObject(): void; + /** + * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. + * + * @example + * expect(1).toBeFinite(); + * expect(3.14).toBeFinite(); + * expect(NaN).not.toBeFinite(); + * expect(Infinity).not.toBeFinite(); + */ + toBeFinite(): void; + /** + * Asserts that a value is a positive `number`. + * + * @example + * expect(1).toBePositive(); + * expect(-3.14).not.toBePositive(); + * expect(NaN).not.toBePositive(); + */ + toBePositive(): void; + /** + * Asserts that a value is a negative `number`. + * + * @example + * expect(-3.14).toBeNegative(); + * expect(1).not.toBeNegative(); + * expect(NaN).not.toBeNegative(); + */ + toBeNegative(): void; + /** + * Asserts that a value is a number between a start and end value. + * + * @param start the start number (inclusive) + * @param end the end number (exclusive) + */ + toBeWithin(start: number, end: number): void; + /** + * Asserts that a value is equal to the expected string, ignoring any whitespace. + * + * @example + * expect(" foo ").toEqualIgnoringWhitespace("foo"); + * expect("bar").toEqualIgnoringWhitespace(" bar "); + * + * @param expected the expected string + */ + toEqualIgnoringWhitespace(expected: string): void; + /** + * Asserts that a value is a `symbol`. + * + * @example + * expect(Symbol("foo")).toBeSymbol(); + * expect("foo").not.toBeSymbol(); + */ + toBeSymbol(): void; + /** + * Asserts that a value is a `function`. + * + * @example + * expect(() => {}).toBeFunction(); + */ + toBeFunction(): void; + /** + * Asserts that a value is a `Date` object. + * + * To check if a date is valid, use `toBeValidDate()` instead. + * + * @example + * expect(new Date()).toBeDate(); + * expect(new Date(null)).toBeDate(); + * expect("2020-03-01").not.toBeDate(); + */ + toBeDate(): void; + /** + * Asserts that a value is a valid `Date` object. + * + * @example + * expect(new Date()).toBeValidDate(); + * expect(new Date(null)).not.toBeValidDate(); + * expect("2020-03-01").not.toBeValidDate(); + */ + toBeValidDate(): void; + /** + * Asserts that a value is a `string`. + * + * @example + * expect("foo").toBeString(); + * expect(new String("bar")).toBeString(); + * expect(123).not.toBeString(); + */ + toBeString(): void; + /** + * Asserts that a value includes a `string`. + * + * For non-string values, use `toContain()` instead. + * + * @param expected the expected substring + */ + toInclude(expected: string): void; + /** + * Asserts that a value includes a `string` {times} times. + * @param expected the expected substring + * @param times the number of times the substring should occur + */ + toIncludeRepeated(expected: string, times: number): void; + /** + * Checks whether a value satisfies a custom condition. + * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. + * @example + * expect(1).toSatisfy((val) => val > 0); + * expect("foo").toSatisfy((val) => val === "foo"); + * expect("bar").not.toSatisfy((val) => val === "bun"); + * @link https://vitest.dev/api/expect.html#tosatisfy + * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy + */ + toSatisfy(predicate: (value: T) => boolean): void; + /** + * Asserts that a value starts with a `string`. + * + * @param expected the string to start with + */ + toStartWith(expected: string): void; + /** + * Asserts that a value ends with a `string`. + * + * @param expected the string to end with + */ + toEndWith(expected: string): void; + /** + * Ensures that a mock function has returned successfully at least once. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturned(): void; + + /** + * Ensures that a mock function has returned successfully at `times` times. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturnedTimes(times: number): void; + + /** + * Ensures that a mock function is called. + */ + toHaveBeenCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + * @alias toHaveBeenCalled + */ + toBeCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + */ + toHaveBeenCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledTimes + */ + toBeCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + */ + toHaveBeenCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledWith + */ + toBeCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the last call. + */ + toHaveBeenLastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + lastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + */ + toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + nthCalledWith(n: number, ...expected: unknown[]): void; + } + + /** + * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. + */ + // Defined as an alias of `any` so that it does not trigger any type mismatch + export type AsymmetricMatcher = any; + + export interface MatcherResult { + pass: boolean; + message?: string | (() => string); + } + + export type CustomMatcher = ( + this: MatcherContext, + expected: E, + ...matcherArguments: P + ) => MatcherResult | Promise; + + /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ + export type CustomMatchersDetected = Omit< + Matchers, + keyof MatchersBuiltin + > & + Omit; + + /** + * If the types has been defined through declaration merging, enforce it. + * Otherwise enforce the generic custom matcher signature. + */ + export type ExpectExtendMatchers = { + [k in keyof M]: k extends keyof CustomMatchersDetected + ? CustomMatcher> + : CustomMatcher; + }; + + /** Custom equality tester */ + export type Tester = ( + this: TesterContext, + a: any, + b: any, + customTesters: Tester[], + ) => boolean | undefined; + + export type EqualsFunction = ( + a: unknown, + b: unknown, + //customTesters?: Array, + //strictCheck?: boolean, + ) => boolean; + + export interface TesterContext { + equals: EqualsFunction; + } + + interface MatcherState { + //assertionCalls: number; + //currentConcurrentTestName?: () => string | undefined; + //currentTestName?: string; + //error?: Error; + //expand: boolean; + //expectedAssertionsNumber: number | null; + //expectedAssertionsNumberError?: Error; + //isExpectingAssertions: boolean; + //isExpectingAssertionsError?: Error; + isNot: boolean; + //numPassingAsserts: number; + promise: string; + //suppressedErrors: Array; + //testPath?: string; + } + + type MatcherHintColor = (arg: string) => string; // subset of Chalk type + + interface MatcherUtils { + //customTesters: Array; + //dontThrow(): void; // (internally used by jest snapshot) + equals: EqualsFunction; + utils: Readonly<{ + stringify(value: unknown): string; + printReceived(value: unknown): string; + printExpected(value: unknown): string; + matcherHint( + matcherName: string, + received?: unknown, + expected?: unknown, + options?: { + isNot?: boolean; + promise?: string; + isDirectExpectCall?: boolean; // (internal) + comment?: string; + expectedColor?: MatcherHintColor; + receivedColor?: MatcherHintColor; + secondArgument?: string; + secondArgumentColor?: MatcherHintColor; + }, + ): string; + //iterableEquality: Tester; + //subsetEquality: Tester; + // ... + }>; + } + + type MatcherContext = MatcherUtils & MatcherState; +} + +declare module "test" { + export type * from "bun:test"; +} + +declare namespace JestMock { + /** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + export interface ClassLike { + new (...args: any): any; + } + + export type ConstructorLikeKeys = keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + }; + + // export const fn: ( + // implementation?: T | undefined, + // ) => Mock; + + export type FunctionLike = (...args: any) => any; + + export type MethodLikeKeys = keyof { + [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; + }; + + export interface Mock any> + extends MockInstance { + (...args: Parameters): ReturnType; + } + + /** + * All what the internal typings need is to be sure that we have any-function. + * `FunctionLike` type ensures that and helps to constrain the type as well. + * The default of `UnknownFunction` makes sure that `any`s do not leak to the + * user side. For instance, calling `fn()` without implementation will return + * a mock of `(...args: Array) => unknown` type. If implementation + * is provided, its typings are inferred correctly. + */ + // export interface Mock + // extends Function, + // MockInstance { + // new (...args: Parameters): ReturnType; + // (...args: Parameters): ReturnType; + // } + + // export type Mocked = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunction + // : T extends object + // ? MockedObject + // : T; + + // export const mocked: { + // ( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // ( + // source: T_1, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // }; + + // export type MockedClass = MockInstance< + // (...args: ConstructorParameters) => Mocked> + // > & + // MockedObject; + + // export type MockedFunction = MockInstance & + // MockedObject; + + // type MockedFunctionShallow = MockInstance & T; + + // export type MockedObject = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunction + // : T[K] extends object + // ? MockedObject + // : T[K]; + // } & T; + + // type MockedObjectShallow = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunctionShallow + // : T[K]; + // } & T; + + // export type MockedShallow = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunctionShallow + // : T extends object + // ? MockedObjectShallow + // : T; + + // export type MockFunctionMetadata< + // T = unknown, + // MetadataType = MockMetadataType, + // > = MockMetadata; + + // export type MockFunctionMetadataType = MockMetadataType; + + type MockFunctionResult = + | MockFunctionResultIncomplete + | MockFunctionResultReturn + | MockFunctionResultThrow; + + interface MockFunctionResultIncomplete { + type: "incomplete"; + /** + * Result of a single call to a mock function that has not yet completed. + * This occurs if you test the result from within the mock function itself, + * or from within a function that was called by the mock. + */ + value: undefined; + } + + interface MockFunctionResultReturn { + type: "return"; + /** + * Result of a single call to a mock function that returned. + */ + value: ReturnType; + } + + interface MockFunctionResultThrow { + type: "throw"; + /** + * Result of a single call to a mock function that threw. + */ + value: unknown; + } + + interface MockFunctionState { + /** + * List of the call arguments of all calls that have been made to the mock. + */ + calls: Array>; + /** + * List of all the object instances that have been instantiated from the mock. + */ + instances: Array>; + /** + * List of all the function contexts that have been applied to calls to the mock. + */ + contexts: Array>; + /** + * List of the call order indexes of the mock. Jest is indexing the order of + * invocations of all mocks in a test file. The index is starting with `1`. + */ + invocationCallOrder: number[]; + /** + * List of the call arguments of the last call that was made to the mock. + * If the function was not called, it will return `undefined`. + */ + lastCall?: Parameters; + /** + * List of the results of all calls that have been made to the mock. + */ + results: Array>; + } + + export interface MockInstance { + _isMockFunction: true; + _protoImpl: Function; + getMockImplementation(): T | undefined; + getMockName(): string; + mock: MockFunctionState; + mockClear(): this; + mockReset(): this; + mockRestore(): void; + mockImplementation(fn: T): this; + mockImplementationOnce(fn: T): this; + withImplementation(fn: T, callback: () => Promise): Promise; + withImplementation(fn: T, callback: () => void): void; + mockName(name: string): this; + mockReturnThis(): this; + mockReturnValue(value: ReturnType): this; + mockReturnValueOnce(value: ReturnType): this; + mockResolvedValue(value: ResolveType): this; + mockResolvedValueOnce(value: ResolveType): this; + mockRejectedValue(value: RejectType): this; + mockRejectedValueOnce(value: RejectType): this; + } + + // export type MockMetadata = { + // ref?: number; + // members?: Record>; + // mockImpl?: T; + // name?: string; + // refID?: number; + // type?: MetadataType; + // value?: T; + // length?: number; + // }; + + // export type MockMetadataType = + // | "object" + // | "array" + // | "regexp" + // | "function" + // | "constant" + // | "collection" + // | "null" + // | "undefined"; + + // export class ModuleMocker { + // private readonly _environmentGlobal; + // private _mockState; + // private _mockConfigRegistry; + // private _spyState; + // private _invocationCallCounter; + // /** + // * @see README.md + // * @param global Global object of the test environment, used to create + // * mocks + // */ + // constructor(global: typeof globalThis); + // private _getSlots; + // private _ensureMockConfig; + // private _ensureMockState; + // private _defaultMockConfig; + // private _defaultMockState; + // private _makeComponent; + // private _createMockFunction; + // private _generateMock; + // /** + // * Check whether the given property of an object has been already replaced. + // */ + // private _findReplacedProperty; + // /** + // * @see README.md + // * @param metadata Metadata for the mock in the schema returned by the + // * getMetadata method of this module. + // */ + // generateFromMetadata(metadata: MockMetadata): Mocked; + // /** + // * @see README.md + // * @param component The component for which to retrieve metadata. + // */ + // getMetadata( + // component: T, + // _refs?: Map, + // ): MockMetadata | null; + // isMockFunction( + // fn: MockInstance, + // ): fn is MockInstance; + // isMockFunction

, R>( + // fn: (...args: P) => R, + // ): fn is Mock<(...args: P) => R>; + // isMockFunction(fn: unknown): fn is Mock; + // fn(implementation?: T): Mock; + // private _attachMockImplementation; + // spyOn< + // T extends object, + // K extends PropertyLikeKeys, + // A extends "get" | "set", + // >( + // object: T, + // methodKey: K, + // accessType: A, + // ): A extends "get" + // ? SpiedGetter + // : A extends "set" + // ? SpiedSetter + // : never; + // spyOn< + // T extends object, + // K extends ConstructorLikeKeys | MethodLikeKeys, + // V extends Required[K], + // >( + // object: T, + // methodKey: K, + // ): V extends ClassLike | FunctionLike ? Spied : never; + // private _spyOnProperty; + // replaceProperty< + // T extends object, + // K extends PropertyLikeKeys, + // V extends T[K], + // >(object: T, propertyKey: K, value: V): Replaced; + // clearAllMocks(): void; + // resetAllMocks(): void; + // restoreAllMocks(): void; + // private _typeOf; + // mocked( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // mocked( + // source: T, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // } + + export type PropertyLikeKeys = Exclude< + keyof T, + ConstructorLikeKeys | MethodLikeKeys + >; + + export type RejectType = + ReturnType extends PromiseLike ? unknown : never; + + export interface Replaced { + /** + * Restore property to its original value known at the time of mocking. + */ + restore(): void; + /** + * Change the value of the property. + */ + replaceValue(value: T): this; + } + + export function replaceProperty< + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike + ? K_1 + : never]: T[K_1]; + } + >, + V extends T[K_2], + >(object: T, propertyKey: K_2, value: V): Replaced; + + export type ResolveType = + ReturnType extends PromiseLike ? U : never; + + export type Spied = T extends ClassLike + ? SpiedClass + : T extends FunctionLike + ? SpiedFunction + : never; + + export type SpiedClass = MockInstance< + (...args: ConstructorParameters) => InstanceType + >; + + export type SpiedFunction = + MockInstance<(...args: Parameters) => ReturnType>; + + export type SpiedGetter = MockInstance<() => T>; + + export type SpiedSetter = MockInstance<(arg: T) => void>; + + export interface SpyInstance + extends MockInstance {} + + export const spyOn: { + < + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike + ? K + : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike + ? K_1 + : never]: T[K_1]; + } + >, + V extends Required[K_2], + A extends "set" | "get", + >( + object: T, + methodKey: K_2, + accessType: A, + ): A extends "get" + ? SpiedGetter + : A extends "set" + ? SpiedSetter + : never; + < + T_1 extends object, + K_5 extends + | keyof { + [K_3 in keyof T_1 as Required[K_3] extends ClassLike + ? K_3 + : never]: T_1[K_3]; + } + | keyof { + [K_4 in keyof T_1 as Required[K_4] extends FunctionLike + ? K_4 + : never]: T_1[K_4]; + }, + V_1 extends Required[K_5], + >( + object: T_1, + methodKey: K_5, + ): V_1 extends ClassLike | FunctionLike ? Spied : never; + }; + + export interface UnknownClass { + new (...args: unknown[]): unknown; + } + + export type UnknownFunction = (...args: unknown[]) => unknown; +} diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 1d3842c66a5e07..c0bdeb2b59f07e 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -1,6 +1,13 @@ import svgpath from "cool.svg"; svgpath satisfies `${string}.svg`; +import * as test from "bun:test"; +test.describe; +test.it; + +import * as sqlite from "bun:sqlite"; +sqlite.Database; + Bun satisfies typeof import("bun"); type S3OptionsFromNamespace = Bun.S3Options; From 1e21cd6de85af884c01f132923cedacaf0fca808 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 19:08:32 +0000 Subject: [PATCH 15/72] changes --- packages/bun-types/ambient.d.ts | 28 +- packages/bun-types/bun.d.ts | 14768 ++++++++--------- packages/bun-types/deprecated.d.ts | 105 +- packages/bun-types/fetch.d.ts | 256 +- packages/bun-types/ffi.d.ts | 2182 ++- packages/bun-types/globals.d.ts | 2556 ++- packages/bun-types/html-rewriter.d.ts | 297 +- packages/bun-types/jsc.d.ts | 446 +- packages/bun-types/new/bun.d.ts | 13807 ++++++++------- packages/bun-types/new/bun.ns.d.ts | 2 +- packages/bun-types/new/devserver.d.ts | 249 +- packages/bun-types/new/extensions.d.ts | 30 +- packages/bun-types/new/fetch.d.ts | 312 +- packages/bun-types/new/ffi.d.ts | 2182 ++- packages/bun-types/new/globals.d.ts | 1656 +- packages/bun-types/new/html-rewriter.d.ts | 297 +- packages/bun-types/new/index.d.ts | 2 + packages/bun-types/new/jsc.d.ts | 446 +- packages/bun-types/new/overrides.d.ts | 90 +- packages/bun-types/new/s3.d.ts | 1493 +- packages/bun-types/new/sink.d.ts | 154 +- packages/bun-types/new/sqlite.d.ts | 2167 ++- packages/bun-types/new/test.d.ts | 4366 +++-- packages/bun-types/new/wasm.d.ts | 188 + packages/bun-types/overrides.d.ts | 112 +- packages/bun-types/package.json | 67 +- packages/bun-types/sqlite.d.ts | 2167 ++- packages/bun-types/test/array-buffer.test.ts | 2 +- packages/bun-types/test/array.test.ts | 30 +- packages/bun-types/test/broadcast.test.ts | 6 +- packages/bun-types/test/bun.test.ts | 62 +- packages/bun-types/test/console.test.ts | 26 +- packages/bun-types/test/diag.test.ts | 2 +- packages/bun-types/test/dom.test.ts | 16 +- packages/bun-types/test/env.test.ts | 18 +- packages/bun-types/test/events.test.ts | 6 +- packages/bun-types/test/ffi.test.ts | 223 +- packages/bun-types/test/fs.test.ts | 8 +- packages/bun-types/test/fsrouter.test.ts | 4 +- packages/bun-types/test/globals.test.ts | 170 +- packages/bun-types/test/http.test.ts | 2 +- packages/bun-types/test/jsc.test.ts | 2 +- packages/bun-types/test/mocks.test.ts | 2 +- packages/bun-types/test/net.test.ts | 8 +- packages/bun-types/test/process.test.ts | 12 +- packages/bun-types/test/readline.test.ts | 10 +- packages/bun-types/test/serve.test.ts | 246 +- packages/bun-types/test/spawn.test.ts | 243 +- packages/bun-types/test/sqlite.test.ts | 14 +- packages/bun-types/test/streams.test.ts | 32 +- packages/bun-types/test/tcp.test.ts | 216 +- packages/bun-types/test/test.test.ts | 171 +- packages/bun-types/test/tls.test.ts | 34 +- packages/bun-types/test/tty.test.ts | 8 +- packages/bun-types/test/utilities.test.ts | 4 +- packages/bun-types/test/wasm.test.ts | 80 +- packages/bun-types/test/worker.test.ts | 38 +- packages/bun-types/test/ws.test.ts | 4 +- packages/bun-types/wasm.d.ts | 508 +- test/integration/bun-types/fixture/bun.lock | 2 +- test/integration/bun-types/fixture/index.ts | 26 + 61 files changed, 25914 insertions(+), 26746 deletions(-) create mode 100644 packages/bun-types/new/wasm.d.ts diff --git a/packages/bun-types/ambient.d.ts b/packages/bun-types/ambient.d.ts index db712274c46e99..05d908557716b6 100644 --- a/packages/bun-types/ambient.d.ts +++ b/packages/bun-types/ambient.d.ts @@ -1,31 +1,31 @@ declare module "*.txt" { - var text: string; - export = text; + var text: string; + export = text; } declare module "*.toml" { - var contents: any; - export = contents; + var contents: any; + export = contents; } declare module "*.jsonc" { - var contents: any; - export = contents; + var contents: any; + export = contents; } declare module "*/bun.lock" { - var contents: import("bun").BunLockFile; - export = contents; + var contents: import("bun").BunLockFile; + export = contents; } declare module "*.html" { - // In Bun v1.2, we might change this to Bun.HTMLBundle - var contents: any; - export = contents; + // In Bun v1.2, we might change this to Bun.HTMLBundle + var contents: any; + export = contents; } declare module "*.svg" { - // Bun 1.2.3 added support for frontend dev server - var contents: `${string}.svg`; - export = contents; + // Bun 1.2.3 added support for frontend dev server + var contents: `${string}.svg`; + export = contents; } diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 9d96f5d21b33a0..100a54eea3fd62 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -1,72 +1,72 @@ declare 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; - - bytes(): Uint8Array; + 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; + + bytes(): Uint8Array; } /** @@ -85,7549 +85,7231 @@ declare class _ShellError extends Error implements ShellOutput { * This module aliases `globalThis.Bun`. */ declare module "bun" { - import type { FFIFunctionCallableSymbol } from "bun:ffi"; - import type { Encoding as CryptoEncoding } from "crypto"; - import type { X509Certificate } from "node:crypto"; - import type { Stats } from "node:fs"; - import type { - CipherNameAndProtocol, - EphemeralKeyInfo, - PeerCertificate, - } from "tls"; - - type DistributedOmit = T extends T ? Omit : never; - type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; - - 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 - | string - | { raw: string } - | Subprocess - | SpawnOptions.Readable - | SpawnOptions.Writable - | ReadableStream; - - class ShellPromise extends Promise { - 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 | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - } - - type ShellError = _ShellError; - - export interface Shell { - ( - strings: TemplateStringsArray, - ...expressions: ShellExpression[] - ): ShellPromise; - - readonly ShellError: typeof _ShellError; - - /** - * 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): 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; - } - - 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; - - /** - * 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; - - /** - * 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 | S3File | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - 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, - maxLength?: number, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - maxLength: number, - asUint8Array: false, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - 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, - ): Promise | 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, - ): Promise | 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; - - /** - * 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, - multipartBoundaryExcludingDashes?: - | string - | NodeJS.TypedArray - | ArrayBufferView, - ): Promise; - - /** - * 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; - - /** - * 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; - - /** - * 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( - stream: ReadableStream, - ): Promise | T[]; - - /** - * Escape the following characters in a string: - * - * - `"` 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. - * - * @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 { - (promise: T | Promise): Promise | T; - status( - promise: T | Promise, - ): "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; - - /** - * - * **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; - }; - - ADDRCONFIG: number; - ALL: number; - 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 - * - * @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; - - /** - * 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; - - /** - * Deletes the file. - */ - unlink(): Promise; - - /** - * Deletes the file. ( same as unlink ) - */ - delete(): Promise; - - /** - * Provides useful information about the file. - */ - stat(): Promise; - } - - /** - * Configuration options for S3 operations - */ - interface S3Options extends BlobPropertyBag { - /** - * The Access Control List (ACL) policy for the file. - * Controls who can access the file and what permissions they have. - * - * @example - * // Setting public read access - * const file = s3("public-file.txt", { - * acl: "public-read", - * bucket: "my-bucket" - * }); - * - * @example - * // Using with presigned URLs - * const url = file.presign({ - * acl: "public-read", - * expiresIn: 3600 - * }); - */ - acl?: - | "private" - | "public-read" - | "public-read-write" - | "aws-exec-read" - | "authenticated-read" - | "bucket-owner-read" - | "bucket-owner-full-control" - | "log-delivery-write"; - - /** - * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. - * - * @example - * // Using explicit bucket - * const file = s3("my-file.txt", { bucket: "my-bucket" }); - * - * @example - * // Using environment variables - * // With S3_BUCKET=my-bucket in .env - * const file = s3("my-file.txt"); - */ - bucket?: string; - - /** - * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. - * - * @example - * const file = s3("my-file.txt", { - * bucket: "my-bucket", - * region: "us-west-2" - * }); - */ - region?: string; - - /** - * The access key ID for authentication. - * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. - */ - accessKeyId?: string; - - /** - * The secret access key for authentication. - * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. - */ - secretAccessKey?: string; - - /** - * Optional session token for temporary credentials. - * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. - * - * @example - * // Using temporary credentials - * const file = s3("my-file.txt", { - * accessKeyId: tempAccessKey, - * secretAccessKey: tempSecretKey, - * sessionToken: tempSessionToken - * }); - */ - sessionToken?: string; - - /** - * The S3-compatible service endpoint URL. - * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. - * - * @example - * // AWS S3 - * const file = s3("my-file.txt", { - * endpoint: "https://s3.us-east-1.amazonaws.com" - * }); - * - * @example - * // Cloudflare R2 - * const file = s3("my-file.txt", { - * endpoint: "https://.r2.cloudflarestorage.com" - * }); - * - * @example - * // DigitalOcean Spaces - * const file = s3("my-file.txt", { - * endpoint: "https://.digitaloceanspaces.com" - * }); - * - * @example - * // MinIO (local development) - * const file = s3("my-file.txt", { - * endpoint: "http://localhost:9000" - * }); - */ - endpoint?: string; - - /** - * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` - * - * @example - * // Using virtual hosted style - * const file = s3("my-file.txt", { - * virtualHostedStyle: true, - * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" - * }); - */ - virtualHostedStyle?: boolean; - - /** - * The size of each part in multipart uploads (in bytes). - * - Minimum: 5 MiB - * - Maximum: 5120 MiB - * - Default: 5 MiB - * - * @example - * // Configuring multipart uploads - * const file = s3("large-file.dat", { - * partSize: 10 * 1024 * 1024, // 10 MiB parts - * queueSize: 4 // Upload 4 parts in parallel - * }); - * - * const writer = file.writer(); - * // ... write large file in chunks - */ - partSize?: number; - - /** - * Number of parts to upload in parallel for multipart uploads. - * - Default: 5 - * - Maximum: 255 - * - * Increasing this value can improve upload speeds for large files - * but will use more memory. - */ - queueSize?: number; - - /** - * Number of retry attempts for failed uploads. - * - Default: 3 - * - Maximum: 255 - * - * @example - * // Setting retry attempts - * const file = s3("my-file.txt", { - * retry: 5 // Retry failed uploads up to 5 times - * }); - */ - retry?: number; - - /** - * The Content-Type of the file. - * Automatically set based on file extension when possible. - * - * @example - * // Setting explicit content type - * const file = s3("data.bin", { - * type: "application/octet-stream" - * }); - */ - type?: string; - - /** - * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. - * - * @example - * // Setting explicit Storage class - * const file = s3("my-file.json", { - * storageClass: "STANDARD_IA" - * }); - */ - storageClass?: - | "STANDARD" - | "DEEP_ARCHIVE" - | "EXPRESS_ONEZONE" - | "GLACIER" - | "GLACIER_IR" - | "INTELLIGENT_TIERING" - | "ONEZONE_IA" - | "OUTPOSTS" - | "REDUCED_REDUNDANCY" - | "SNOW" - | "STANDARD_IA"; - - /** - * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. - */ - highWaterMark?: number; - } - - /** - * Options for generating presigned URLs - */ - interface S3FilePresignOptions extends S3Options { - /** - * Number of seconds until the presigned URL expires. - * - Default: 86400 (1 day) - * - * @example - * // Short-lived URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Long-lived public URL - * const url = file.presign({ - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - expiresIn?: number; - - /** - * The HTTP method allowed for the presigned URL. - * - * @example - * // GET URL for downloads - * const downloadUrl = file.presign({ - * method: "GET", - * expiresIn: 3600 - * }); - * - * @example - * // PUT URL for uploads - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "application/json" - * }); - */ - method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; - } - - interface S3Stats { - size: number; - lastModified: Date; - etag: string; - type: string; - } - - /** - * Represents a file in an S3-compatible storage service. - * Extends the Blob interface for compatibility with web APIs. - */ - interface S3File extends Blob { - /** - * The size of the file in bytes. - * This is a Promise because it requires a network request to determine the size. - * - * @example - * // Getting file size - * const size = await file.size; - * console.log(`File size: ${size} bytes`); - * - * @example - * // Check if file is larger than 1MB - * if (await file.size > 1024 * 1024) { - * console.log("Large file detected"); - * } - */ - /** - * TODO: figure out how to get the typescript types to not error for this property. - */ - // size: Promise; - - /** - * Creates a new S3File representing a slice of the original file. - * Uses HTTP Range headers for efficient partial downloads. - * - * @param begin - Starting byte offset - * @param end - Ending byte offset (exclusive) - * @param contentType - Optional MIME type for the slice - * @returns A new S3File representing the specified range - * - * @example - * // Reading file header - * const header = file.slice(0, 1024); - * const headerText = await header.text(); - * - * @example - * // Reading with content type - * const jsonSlice = file.slice(1024, 2048, "application/json"); - * const data = await jsonSlice.json(); - * - * @example - * // Reading from offset to end - * const remainder = file.slice(1024); - * const content = await remainder.text(); - */ - slice(begin?: number, end?: number, contentType?: string): S3File; - slice(begin?: number, contentType?: string): S3File; - slice(contentType?: string): S3File; - - /** - * Creates a writable stream for uploading data. - * Suitable for large files as it uses multipart upload. - * - * @param options - Configuration for the upload - * @returns A NetworkSink for writing data - * - * @example - * // Basic streaming write - * const writer = file.writer({ - * type: "application/json" - * }); - * writer.write('{"hello": '); - * writer.write('"world"}'); - * await writer.end(); - * - * @example - * // Optimized large file upload - * const writer = file.writer({ - * partSize: 10 * 1024 * 1024, // 10MB parts - * queueSize: 4, // Upload 4 parts in parallel - * retry: 3 // Retry failed parts - * }); - * - * // Write large chunks of data efficiently - * for (const chunk of largeDataChunks) { - * writer.write(chunk); - * } - * await writer.end(); - * - * @example - * // Error handling - * const writer = file.writer(); - * try { - * writer.write(data); - * await writer.end(); - * } catch (err) { - * console.error('Upload failed:', err); - * // Writer will automatically abort multipart upload on error - * } - */ - writer(options?: S3Options): NetworkSink; - - /** - * Gets a readable stream of the file's content. - * Useful for processing large files without loading them entirely into memory. - * - * @returns A ReadableStream for the file content - * - * @example - * // Basic streaming read - * const stream = file.stream(); - * for await (const chunk of stream) { - * console.log('Received chunk:', chunk); - * } - * - * @example - * // Piping to response - * const stream = file.stream(); - * return new Response(stream, { - * headers: { 'Content-Type': file.type } - * }); - * - * @example - * // Processing large files - * const stream = file.stream(); - * const textDecoder = new TextDecoder(); - * for await (const chunk of stream) { - * const text = textDecoder.decode(chunk); - * // Process text chunk by chunk - * } - */ - readonly readable: ReadableStream; - stream(): ReadableStream; - - /** - * The name or path of the file in the bucket. - * - * @example - * const file = s3("folder/image.jpg"); - * console.log(file.name); // "folder/image.jpg" - */ - readonly name?: string; - - /** - * The bucket name containing the file. - * - * @example - * const file = s3("s3://my-bucket/file.txt"); - * console.log(file.bucket); // "my-bucket" - */ - readonly bucket?: string; - - /** - * Checks if the file exists in S3. - * Uses HTTP HEAD request to efficiently check existence without downloading. - * - * @returns Promise resolving to true if file exists, false otherwise - * - * @example - * // Basic existence check - * if (await file.exists()) { - * console.log("File exists in S3"); - * } - * - * @example - * // With error handling - * try { - * const exists = await file.exists(); - * if (!exists) { - * console.log("File not found"); - * } - * } catch (err) { - * console.error("Error checking file:", err); - * } - */ - exists(): Promise; - - /** - * Uploads data to S3. - * Supports various input types and automatically handles large files. - * - * @param data - The data to upload - * @param options - Upload configuration options - * @returns Promise resolving to number of bytes written - * - * @example - * // Writing string data - * await file.write("Hello World", { - * type: "text/plain" - * }); - * - * @example - * // Writing JSON - * const data = { hello: "world" }; - * await file.write(JSON.stringify(data), { - * type: "application/json" - * }); - * - * @example - * // Writing from Response - * const response = await fetch("https://example.com/data"); - * await file.write(response); - * - * @example - * // Writing with ACL - * await file.write(data, { - * acl: "public-read", - * type: "application/octet-stream" - * }); - */ - write( - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob, - options?: S3Options, - ): Promise; - - /** - * Generates a presigned URL for the file. - * Allows temporary access to the file without exposing credentials. - * - * @param options - Configuration for the presigned URL - * @returns Presigned URL string - * - * @example - * // Basic download URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Upload URL with specific content type - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * @example - * // URL with custom permissions - * const url = file.presign({ - * method: "GET", - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(options?: S3FilePresignOptions): string; - - /** - * Deletes the file from S3. - * - * @returns Promise that resolves when deletion is complete - * - * @example - * // Basic deletion - * await file.delete(); - * - * @example - * // With error handling - * try { - * await file.delete(); - * console.log("File deleted successfully"); - * } catch (err) { - * console.error("Failed to delete file:", err); - * } - */ - delete(): Promise; - - /** - * Alias for delete() method. - * Provided for compatibility with Node.js fs API naming. - * - * @example - * await file.unlink(); - */ - unlink: S3File["delete"]; - - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @returns Promise resolving to S3Stat - */ - stat(): Promise; - } - - /** - * A configured S3 bucket instance for managing files. - * The instance is callable to create S3File instances and provides methods - * for common operations. - * - * @example - * // Basic bucket setup - * const bucket = new S3Client({ - * bucket: "my-bucket", - * accessKeyId: "key", - * secretAccessKey: "secret" - * }); - * - * // Get file instance - * const file = bucket("image.jpg"); - * - * // Common operations - * await bucket.write("data.json", JSON.stringify({hello: "world"})); - * const url = bucket.presign("file.pdf"); - * await bucket.unlink("old.txt"); - */ - type S3Client = { - /** - * Creates an S3File instance for the given path. - * - * @example - * const file = bucket.file("image.jpg"); - * await file.write(imageData); - * const configFile = bucket("config.json", { - * type: "application/json", - * acl: "private" - * }); - */ - file(path: string, options?: S3Options): S3File; - - /** - * Writes data directly to a path in the bucket. - * Supports strings, buffers, streams, and web API types. - * - * @example - * // Write string - * await bucket.write("hello.txt", "Hello World"); - * - * // Write JSON with type - * await bucket.write( - * "data.json", - * JSON.stringify({hello: "world"}), - * {type: "application/json"} - * ); - * - * // Write from fetch - * const res = await fetch("https://example.com/data"); - * await bucket.write("data.bin", res); - * - * // Write with ACL - * await bucket.write("public.html", html, { - * acl: "public-read", - * type: "text/html" - * }); - */ - write( - path: string, - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob - | File, - options?: S3Options, - ): Promise; - - /** - * Generate a presigned URL for temporary access to a file. - * Useful for generating upload/download URLs without exposing credentials. - * - * @example - * // Download URL - * const downloadUrl = bucket.presign("file.pdf", { - * expiresIn: 3600 // 1 hour - * }); - * - * // Upload URL - * const uploadUrl = bucket.presign("uploads/image.jpg", { - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * // Long-lived public URL - * const publicUrl = bucket.presign("public/doc.pdf", { - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(path: string, options?: S3FilePresignOptions): string; - - /** - * Delete a file from the bucket. - * - * @example - * // Simple delete - * await bucket.unlink("old-file.txt"); - * - * // With error handling - * try { - * await bucket.unlink("file.dat"); - * console.log("File deleted"); - * } catch (err) { - * console.error("Delete failed:", err); - * } - */ - unlink(path: string, options?: S3Options): Promise; - delete: S3Client["unlink"]; - - /** - * Get the size of a file in bytes. - * Uses HEAD request to efficiently get size. - * - * @example - * // Get size - * const bytes = await bucket.size("video.mp4"); - * console.log(`Size: ${bytes} bytes`); - * - * // Check if file is large - * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { - * console.log("File is larger than 100MB"); - * } - */ - size(path: string, options?: S3Options): Promise; - - /** - * Check if a file exists in the bucket. - * Uses HEAD request to check existence. - * - * @example - * // Check existence - * if (await bucket.exists("config.json")) { - * const file = bucket("config.json"); - * const config = await file.json(); - * } - * - * // With error handling - * try { - * if (!await bucket.exists("required.txt")) { - * throw new Error("Required file missing"); - * } - * } catch (err) { - * console.error("Check failed:", err); - * } - */ - exists(path: string, options?: S3Options): Promise; - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @param path The path to the file. - * @param options The options to use for the S3 client. - */ - stat(path: string, options?: S3Options): Promise; - }; - /** - * Configuration options for SQL client connection and behavior - * @example - * const config: SQLOptions = { - * host: 'localhost', - * port: 5432, - * user: 'dbuser', - * password: 'secretpass', - * database: 'myapp', - * idleTimeout: 30000, - * max: 20, - * onconnect: (client) => { - * console.log('Connected to database'); - * } - * }; - */ - type 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); - /** Database password for authentication (alias for password) */ - pass?: string | (() => Promise); - /** 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 extends Promise { - /** Indicates if the query is currently executing */ - active: boolean; - /** Indicates if the query has been cancelled */ - cancelled: boolean; - /** Cancels the executing query */ - cancel(): SQLQuery; - /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ - simple(): SQLQuery; - /** Executes the query */ - execute(): SQLQuery; - /** Returns the raw query result */ - raw(): SQLQuery; - /** Returns only the values from the query result */ - values(): SQLQuery; - } - - /** - * Callback function type for transaction contexts - * @param sql Function to execute SQL queries within the transaction - */ - type SQLTransactionContextCallback = ( - sql: TransactionSQL, - ) => Promise | Array; - /** - * Callback function type for savepoint contexts - * @param sql Function to execute SQL queries within the savepoint - */ - type SQLSavepointContextCallback = ( - sql: SavepointSQL, - ) => Promise | Array; - - /** - * Main SQL client interface providing connection and transaction management - */ - interface SQL { - /** Creates a new SQL client instance - * @example - * const sql = new SQL("postgres://localhost:5432/mydb"); - * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); - */ - new (connectionString: string | URL): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); - */ - new (connectionString: string | URL, options: SQLOptions): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); - */ - new (options?: SQLOptions): SQL; - /** Executes a SQL query using template literals - * @example - * const [user] = await sql`select * from users where id = ${1}`; - */ - (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; - /** - * Helper function to allow easy use to insert values into a query - * @example - * const result = await sql`insert into users ${sql(users)} RETURNING *`; - */ - (obj: any): SQLQuery; - /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.commitDistributed("my_distributed_transaction"); - */ - commitDistributed(name: string): Promise; - /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.rollbackDistributed("my_distributed_transaction"); - */ - rollbackDistributed(name: string): Promise; - /** Waits for the database connection to be established - * @example - * await sql.connect(); - */ - connect(): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @example - * await sql.close({ timeout: 1 }); - */ - close(options?: { timeout?: number }): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @alias close - * @example - * await sql.end({ timeout: 1 }); - */ - end(options?: { timeout?: number }): Promise; - /** Flushes any pending operations */ - flush(): void; - /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. - * This can be used for running queries on an isolated connection. - * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). - * @example - * const reserved = await sql.reserve(); - * await reserved`select * from users`; - * await reserved.release(); - * // with in a production scenario would be something more like - * const reserved = await sql.reserve(); - * try { - * // ... queries - * } finally { - * await reserved.release(); - * } - * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose - * { - * // always release after context (safer) - * using reserved = await sql.reserve() - * await reserved`select * from users` - * } - */ - reserve(): Promise; - /** Begins a new transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(fn: SQLTransactionContextCallback): Promise; - /** Begins a new transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(options: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction( - options: string, - fn: SQLTransactionContextCallback, - ): Promise; - /** Begins a distributed transaction - * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. - * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. - * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. - * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. - * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. - * @example - * await sql.beginDistributed("numbers", async sql => { - * await sql`create table if not exists numbers (a int)`; - * await sql`insert into numbers values(1)`; - * }); - * // later you can call - * await sql.commitDistributed("numbers"); - * // or await sql.rollbackDistributed("numbers"); - */ - beginDistributed( - name: string, - fn: SQLTransactionContextCallback, - ): Promise; - /** Alternative method to begin a distributed transaction - * @alias beginDistributed - */ - distributed(name: string, fn: SQLTransactionContextCallback): Promise; - /**If you know what you're doing, you can use unsafe to pass any string you'd like. - * Please note that this can lead to SQL injection if you're not careful. - * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. - * @example - * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) - */ - unsafe(string: string, values?: any[]): SQLQuery; - /** - * Reads a file and uses the contents as a query. - * Optional parameters can be used if the file includes $1, $2, etc - * @example - * const result = await sql.file("query.sql", [1, 2, 3]); - */ - file(filename: string, values?: any[]): SQLQuery; - - /** Current client options */ - options: SQLOptions; - - [Symbol.asyncDispose](): Promise; - } - - /** - * Represents a reserved connection from the connection pool - * Extends SQL with additional release functionality - */ - interface ReservedSQL extends SQL { - /** Releases the client back to the connection pool */ - release(): void; - [Symbol.dispose](): void; - } - - /** - * Represents a client within a transaction context - * Extends SQL with savepoint functionality - */ - interface TransactionSQL extends SQL { - /** Creates a savepoint within the current transaction */ - savepoint(name: string, fn: SQLSavepointContextCallback): Promise; - savepoint(fn: SQLSavepointContextCallback): Promise; - } - /** - * Represents a savepoint within a transaction - */ - interface SavepointSQL extends SQL {} - - var sql: SQL; - var postgres: SQL; - var SQL: SQL; - - /** - * This lets you use macros as regular imports - * @example - * ``` - * { - * "react-relay": { - * "graphql": "bun-macro-relay/bun-macro-relay.tsx" - * } - * } - * ``` - */ - type MacroMap = Record>; - - /** - * 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; - } - - 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; - 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; - - /** 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; - }; - 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 = () =>

Hello World
; - * 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; - /** - * 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-run" - | "entry-point-build"; - - interface Import { - path: string; - kind: ImportKind; - } - - /** - * @see [Bun.build API docs](https://bun.sh/docs/bundler#api) - */ - interface BuildConfig { - entrypoints: string[]; // list of file path - outdir?: string; // output directory - /** - * @default "browser" - */ - 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?: /** + import type { FFIFunctionCallableSymbol } from "bun:ffi"; + import type { Encoding as CryptoEncoding } from "crypto"; + import type { X509Certificate } from "node:crypto"; + import type { Stats } from "node:fs"; + import type { CipherNameAndProtocol, EphemeralKeyInfo, PeerCertificate } from "tls"; + + type DistributedOmit = T extends T ? Omit : never; + type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; + + interface Env { + NODE_ENV?: string; + /** + * Can be used to change the default timezone at runtime + */ + TZ?: string; + } - * ECMAScript Module format + /** + * 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 */ - | "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; - // origin?: string; // e.g. http://mydomain.com - loader?: { [k in string]: Loader }; - /** - * Specifies if and how to generate source maps. - * - * - `"none"` - No source maps are generated - * - `"linked"` - A separate `*.ext.map` file is generated alongside each - * `*.ext` file. A `//# sourceMappingURL` comment is added to the output - * file to link the two. Requires `outdir` to be set. - * - `"inline"` - an inline source map is appended to the output file. - * - `"external"` - Generate a separate source map file for each input file. - * No `//# sourceMappingURL` comment is added to the output file. - * - * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. - * - * @default "none" - * - * @see {@link outdir} required for `"linked"` maps - * @see {@link publicPath} to customize the base url of linked source maps - */ - sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; - /** - * 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; - - /** - * Controls how environment variables are handled during bundling. - * - * Can be one of: - * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` - * references to string literals containing the actual environment variable values - * - `"disable"`: Disables environment variable injection entirely - * - A string ending in `*`: Inlines environment variables that match the given prefix. - * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" - * - * @example - * ```ts - * Bun.build({ - * env: "MY_PUBLIC_*", - * entrypoints: ["src/index.ts"], - * }) - * ``` - */ - env?: "inline" | "disable" | `${string}*`; - /** - * Whether to enable minification. - * - * Use `true`/`false` to enable/disable all minification options. Alternatively, - * you can pass an object for granular control over certain minifications. - * - * @default false - */ - 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; - - /** - * Drop function calls to matching property accesses. - */ - drop?: string[]; - - /** - * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. - * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. - * This defaults to `true`. - */ - throw?: boolean; - } - - 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 password. - * If empty, always returns false - */ - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - * - * If specified and the algorithm does not match the hash, this function - * throws an error. - */ - algorithm?: Password.AlgorithmLabel, - ): Promise; - /** - * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. - * - * @returns A promise that resolves to the hashed password - * - * ## Example with argon2 - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world"); - * console.log(hash); // $argon2id$v=1... - * const verify = await password.verify("hello world", hash); - * ``` - * ## Example with bcrypt - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world", "bcrypt"); - * console.log(hash); // $2b$10$... - * const verify = await password.verify("hello world", hash); - * ``` - */ - hash( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before - */ - algorithm?: - | Password.AlgorithmLabel - | Password.Argon2Algorithm - | Password.BCryptAlgorithm, - ): Promise; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.verify} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - verifySync( - password: Bun.StringOrBuffer, - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - */ - algorithm?: Password.AlgorithmLabel, - ): boolean; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.hash} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - hashSync( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before - */ - algorithm?: - | Password.AlgorithmLabel - | Password.Argon2Algorithm - | Password.BCryptAlgorithm, - ): string; - }; - - interface BuildArtifact extends Blob { - path: string; - loader: Loader; - hash: string | null; - kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; - sourcemap: BuildArtifact | null; - } - - interface BuildOutput { - outputs: BuildArtifact[]; - success: boolean; - logs: Array; - } - - /** - * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. + 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 + | string + | { raw: string } + | Subprocess + | SpawnOptions.Readable + | SpawnOptions.Writable + | ReadableStream; + + class ShellPromise extends Promise { + 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 | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + } + + type ShellError = _ShellError; + + export interface Shell { + (strings: TemplateStringsArray, ...expressions: ShellExpression[]): ShellPromise; + + readonly ShellError: typeof _ShellError; + + /** + * 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): 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; + } + + 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; + + /** + * Synchronously resolve a `moduleId` as though it were imported from `parent` * - * @param {Object} config - Build configuration options - * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status - * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) + * 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` * - * @example Basic usage - Bundle a single entrypoint and check results - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist' - }); + * 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; - if (!result.success) { - console.error('Build failed:', result.logs); - process.exit(1); - } - ``` - * - * @example Set up multiple entrypoints with code splitting enabled - ```ts - await Bun.build({ - entrypoints: ['./src/app.tsx', './src/admin.tsx'], - outdir: './dist', - splitting: true, - sourcemap: "external" - }); - ``` - * - * @example Configure minification and optimization settings - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - minify: { - whitespace: true, - identifiers: true, - syntax: true - }, - drop: ['console', 'debugger'] - }); - ``` - * - * @example Set up custom loaders and mark packages as external - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - loader: { - '.png': 'dataurl', - '.svg': 'file', - '.txt': 'text', - '.json': 'json' + /** + * 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 | S3File | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + 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, maxLength?: number): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + maxLength: number, + asUint8Array: false, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + 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, + ): Promise | 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, + ): Promise | 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; + + /** + * 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, + multipartBoundaryExcludingDashes?: string | NodeJS.TypedArray | ArrayBufferView, + ): Promise; + + /** + * 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; + + /** + * 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; + + /** + * 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(stream: ReadableStream): Promise | T[]; + + /** + * Escape the following characters in a string: + * + * - `"` 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. + * + * @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 { + (promise: T | Promise): Promise | T; + status(promise: T | Promise): "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"; }, - external: ['react', 'react-dom'] - }); - ``` - * - * @example Configure environment variable handling with different modes - ```ts - // Inline all environment variables - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'inline' - }); + ): Promise; + + /** + * + * **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; - // Only include specific env vars - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'PUBLIC_*' - }); - ``` - * - * @example Set up custom naming patterns for all output types - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - naming: { - entry: '[dir]/[name]-[hash].[ext]', - chunk: 'chunks/[name]-[hash].[ext]', - asset: 'assets/[name]-[hash].[ext]' - } - }); - ``` - @example Work with build artifacts in different formats - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'] - }); + /** + * **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; + }; - for (const artifact of result.outputs) { - const text = await artifact.text(); - const buffer = await artifact.arrayBuffer(); - const bytes = await artifact.bytes(); + ADDRCONFIG: number; + ALL: number; + 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; + } - new Response(artifact); - await Bun.write(artifact.path, artifact); - } - ``` - @example Implement comprehensive error handling with position info - ```ts - try { - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'], - }); - } catch (e) { - const error = e as AggregateError; - console.error('Build failed:'); - for (const msg of error.errors) { - if ('position' in msg) { - console.error( - `${msg.message} at ${msg.position?.file}:${msg.position?.line}:${msg.position?.column}` - ); - } else { - console.error(msg.message); - } - } - } - ``` - @example Set up Node.js target with specific configurations - ```ts - await Bun.build({ - entrypoints: ['./src/server.ts'], - outdir: './dist', - target: 'node', - format: 'cjs', - sourcemap: 'external', - minify: false, - packages: 'external' - }); - ``` - * - * @example Configure experimental CSS bundling with multiple themes - ```ts - await Bun.build({ - entrypoints: [ - './src/styles.css', - './src/themes/dark.css', - './src/themes/light.css' - ], - outdir: './dist/css', - }); - ``` - @example Define compile-time constants and version information + 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; + + /** + * 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; + + /** + * Deletes the file. + */ + unlink(): Promise; + + /** + * Deletes the file. ( same as unlink ) + */ + delete(): Promise; + + /** + * Provides useful information about the file. + */ + stat(): Promise; + } + + /** + * Configuration options for S3 operations + */ + interface S3Options extends BlobPropertyBag { + /** + * The Access Control List (ACL) policy for the file. + * Controls who can access the file and what permissions they have. + * + * @example + * // Setting public read access + * const file = s3("public-file.txt", { + * acl: "public-read", + * bucket: "my-bucket" + * }); + * + * @example + * // Using with presigned URLs + * const url = file.presign({ + * acl: "public-read", + * expiresIn: 3600 + * }); + */ + acl?: + | "private" + | "public-read" + | "public-read-write" + | "aws-exec-read" + | "authenticated-read" + | "bucket-owner-read" + | "bucket-owner-full-control" + | "log-delivery-write"; + + /** + * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. + * + * @example + * // Using explicit bucket + * const file = s3("my-file.txt", { bucket: "my-bucket" }); + * + * @example + * // Using environment variables + * // With S3_BUCKET=my-bucket in .env + * const file = s3("my-file.txt"); + */ + bucket?: string; + + /** + * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. + * + * @example + * const file = s3("my-file.txt", { + * bucket: "my-bucket", + * region: "us-west-2" + * }); + */ + region?: string; + + /** + * The access key ID for authentication. + * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. + */ + accessKeyId?: string; + + /** + * The secret access key for authentication. + * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. + */ + secretAccessKey?: string; + + /** + * Optional session token for temporary credentials. + * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. + * + * @example + * // Using temporary credentials + * const file = s3("my-file.txt", { + * accessKeyId: tempAccessKey, + * secretAccessKey: tempSecretKey, + * sessionToken: tempSessionToken + * }); + */ + sessionToken?: string; + + /** + * The S3-compatible service endpoint URL. + * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. + * + * @example + * // AWS S3 + * const file = s3("my-file.txt", { + * endpoint: "https://s3.us-east-1.amazonaws.com" + * }); + * + * @example + * // Cloudflare R2 + * const file = s3("my-file.txt", { + * endpoint: "https://.r2.cloudflarestorage.com" + * }); + * + * @example + * // DigitalOcean Spaces + * const file = s3("my-file.txt", { + * endpoint: "https://.digitaloceanspaces.com" + * }); + * + * @example + * // MinIO (local development) + * const file = s3("my-file.txt", { + * endpoint: "http://localhost:9000" + * }); + */ + endpoint?: string; + + /** + * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` + * + * @example + * // Using virtual hosted style + * const file = s3("my-file.txt", { + * virtualHostedStyle: true, + * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" + * }); + */ + virtualHostedStyle?: boolean; + + /** + * The size of each part in multipart uploads (in bytes). + * - Minimum: 5 MiB + * - Maximum: 5120 MiB + * - Default: 5 MiB + * + * @example + * // Configuring multipart uploads + * const file = s3("large-file.dat", { + * partSize: 10 * 1024 * 1024, // 10 MiB parts + * queueSize: 4 // Upload 4 parts in parallel + * }); + * + * const writer = file.writer(); + * // ... write large file in chunks + */ + partSize?: number; + + /** + * Number of parts to upload in parallel for multipart uploads. + * - Default: 5 + * - Maximum: 255 + * + * Increasing this value can improve upload speeds for large files + * but will use more memory. + */ + queueSize?: number; + + /** + * Number of retry attempts for failed uploads. + * - Default: 3 + * - Maximum: 255 + * + * @example + * // Setting retry attempts + * const file = s3("my-file.txt", { + * retry: 5 // Retry failed uploads up to 5 times + * }); + */ + retry?: number; + + /** + * The Content-Type of the file. + * Automatically set based on file extension when possible. + * + * @example + * // Setting explicit content type + * const file = s3("data.bin", { + * type: "application/octet-stream" + * }); + */ + type?: string; + + /** + * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. + * + * @example + * // Setting explicit Storage class + * const file = s3("my-file.json", { + * storageClass: "STANDARD_IA" + * }); + */ + storageClass?: + | "STANDARD" + | "DEEP_ARCHIVE" + | "EXPRESS_ONEZONE" + | "GLACIER" + | "GLACIER_IR" + | "INTELLIGENT_TIERING" + | "ONEZONE_IA" + | "OUTPOSTS" + | "REDUCED_REDUNDANCY" + | "SNOW" + | "STANDARD_IA"; + + /** + * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. + */ + highWaterMark?: number; + } + + /** + * Options for generating presigned URLs + */ + interface S3FilePresignOptions extends S3Options { + /** + * Number of seconds until the presigned URL expires. + * - Default: 86400 (1 day) + * + * @example + * // Short-lived URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Long-lived public URL + * const url = file.presign({ + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + expiresIn?: number; + + /** + * The HTTP method allowed for the presigned URL. + * + * @example + * // GET URL for downloads + * const downloadUrl = file.presign({ + * method: "GET", + * expiresIn: 3600 + * }); + * + * @example + * // PUT URL for uploads + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "application/json" + * }); + */ + method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; + } + + interface S3Stats { + size: number; + lastModified: Date; + etag: string; + type: string; + } + + /** + * Represents a file in an S3-compatible storage service. + * Extends the Blob interface for compatibility with web APIs. + */ + interface S3File extends Blob { + /** + * The size of the file in bytes. + * This is a Promise because it requires a network request to determine the size. + * + * @example + * // Getting file size + * const size = await file.size; + * console.log(`File size: ${size} bytes`); + * + * @example + * // Check if file is larger than 1MB + * if (await file.size > 1024 * 1024) { + * console.log("Large file detected"); + * } + */ + /** + * TODO: figure out how to get the typescript types to not error for this property. + */ + // size: Promise; + + /** + * Creates a new S3File representing a slice of the original file. + * Uses HTTP Range headers for efficient partial downloads. + * + * @param begin - Starting byte offset + * @param end - Ending byte offset (exclusive) + * @param contentType - Optional MIME type for the slice + * @returns A new S3File representing the specified range + * + * @example + * // Reading file header + * const header = file.slice(0, 1024); + * const headerText = await header.text(); + * + * @example + * // Reading with content type + * const jsonSlice = file.slice(1024, 2048, "application/json"); + * const data = await jsonSlice.json(); + * + * @example + * // Reading from offset to end + * const remainder = file.slice(1024); + * const content = await remainder.text(); + */ + slice(begin?: number, end?: number, contentType?: string): S3File; + slice(begin?: number, contentType?: string): S3File; + slice(contentType?: string): S3File; + + /** + * Creates a writable stream for uploading data. + * Suitable for large files as it uses multipart upload. + * + * @param options - Configuration for the upload + * @returns A NetworkSink for writing data + * + * @example + * // Basic streaming write + * const writer = file.writer({ + * type: "application/json" + * }); + * writer.write('{"hello": '); + * writer.write('"world"}'); + * await writer.end(); + * + * @example + * // Optimized large file upload + * const writer = file.writer({ + * partSize: 10 * 1024 * 1024, // 10MB parts + * queueSize: 4, // Upload 4 parts in parallel + * retry: 3 // Retry failed parts + * }); + * + * // Write large chunks of data efficiently + * for (const chunk of largeDataChunks) { + * writer.write(chunk); + * } + * await writer.end(); + * + * @example + * // Error handling + * const writer = file.writer(); + * try { + * writer.write(data); + * await writer.end(); + * } catch (err) { + * console.error('Upload failed:', err); + * // Writer will automatically abort multipart upload on error + * } + */ + writer(options?: S3Options): NetworkSink; + + /** + * Gets a readable stream of the file's content. + * Useful for processing large files without loading them entirely into memory. + * + * @returns A ReadableStream for the file content + * + * @example + * // Basic streaming read + * const stream = file.stream(); + * for await (const chunk of stream) { + * console.log('Received chunk:', chunk); + * } + * + * @example + * // Piping to response + * const stream = file.stream(); + * return new Response(stream, { + * headers: { 'Content-Type': file.type } + * }); + * + * @example + * // Processing large files + * const stream = file.stream(); + * const textDecoder = new TextDecoder(); + * for await (const chunk of stream) { + * const text = textDecoder.decode(chunk); + * // Process text chunk by chunk + * } + */ + readonly readable: ReadableStream; + stream(): ReadableStream; + + /** + * The name or path of the file in the bucket. + * + * @example + * const file = s3("folder/image.jpg"); + * console.log(file.name); // "folder/image.jpg" + */ + readonly name?: string; + + /** + * The bucket name containing the file. + * + * @example + * const file = s3("s3://my-bucket/file.txt"); + * console.log(file.bucket); // "my-bucket" + */ + readonly bucket?: string; + + /** + * Checks if the file exists in S3. + * Uses HTTP HEAD request to efficiently check existence without downloading. + * + * @returns Promise resolving to true if file exists, false otherwise + * + * @example + * // Basic existence check + * if (await file.exists()) { + * console.log("File exists in S3"); + * } + * + * @example + * // With error handling + * try { + * const exists = await file.exists(); + * if (!exists) { + * console.log("File not found"); + * } + * } catch (err) { + * console.error("Error checking file:", err); + * } + */ + exists(): Promise; + + /** + * Uploads data to S3. + * Supports various input types and automatically handles large files. + * + * @param data - The data to upload + * @param options - Upload configuration options + * @returns Promise resolving to number of bytes written + * + * @example + * // Writing string data + * await file.write("Hello World", { + * type: "text/plain" + * }); + * + * @example + * // Writing JSON + * const data = { hello: "world" }; + * await file.write(JSON.stringify(data), { + * type: "application/json" + * }); + * + * @example + * // Writing from Response + * const response = await fetch("https://example.com/data"); + * await file.write(response); + * + * @example + * // Writing with ACL + * await file.write(data, { + * acl: "public-read", + * type: "application/octet-stream" + * }); + */ + write( + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | Request | Response | BunFile | S3File | Blob, + options?: S3Options, + ): Promise; + + /** + * Generates a presigned URL for the file. + * Allows temporary access to the file without exposing credentials. + * + * @param options - Configuration for the presigned URL + * @returns Presigned URL string + * + * @example + * // Basic download URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Upload URL with specific content type + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * @example + * // URL with custom permissions + * const url = file.presign({ + * method: "GET", + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(options?: S3FilePresignOptions): string; + + /** + * Deletes the file from S3. + * + * @returns Promise that resolves when deletion is complete + * + * @example + * // Basic deletion + * await file.delete(); + * + * @example + * // With error handling + * try { + * await file.delete(); + * console.log("File deleted successfully"); + * } catch (err) { + * console.error("Failed to delete file:", err); + * } + */ + delete(): Promise; + + /** + * Alias for delete() method. + * Provided for compatibility with Node.js fs API naming. + * + * @example + * await file.unlink(); + */ + unlink: S3File["delete"]; + + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @returns Promise resolving to S3Stat + */ + stat(): Promise; + } + + /** + * A configured S3 bucket instance for managing files. + * The instance is callable to create S3File instances and provides methods + * for common operations. + * + * @example + * // Basic bucket setup + * const bucket = new S3Client({ + * bucket: "my-bucket", + * accessKeyId: "key", + * secretAccessKey: "secret" + * }); + * + * // Get file instance + * const file = bucket("image.jpg"); + * + * // Common operations + * await bucket.write("data.json", JSON.stringify({hello: "world"})); + * const url = bucket.presign("file.pdf"); + * await bucket.unlink("old.txt"); + */ + type S3Client = { + /** + * Creates an S3File instance for the given path. + * + * @example + * const file = bucket.file("image.jpg"); + * await file.write(imageData); + * const configFile = bucket("config.json", { + * type: "application/json", + * acl: "private" + * }); + */ + file(path: string, options?: S3Options): S3File; + + /** + * Writes data directly to a path in the bucket. + * Supports strings, buffers, streams, and web API types. + * + * @example + * // Write string + * await bucket.write("hello.txt", "Hello World"); + * + * // Write JSON with type + * await bucket.write( + * "data.json", + * JSON.stringify({hello: "world"}), + * {type: "application/json"} + * ); + * + * // Write from fetch + * const res = await fetch("https://example.com/data"); + * await bucket.write("data.bin", res); + * + * // Write with ACL + * await bucket.write("public.html", html, { + * acl: "public-read", + * type: "text/html" + * }); + */ + write( + path: string, + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob + | File, + options?: S3Options, + ): Promise; + + /** + * Generate a presigned URL for temporary access to a file. + * Useful for generating upload/download URLs without exposing credentials. + * + * @example + * // Download URL + * const downloadUrl = bucket.presign("file.pdf", { + * expiresIn: 3600 // 1 hour + * }); + * + * // Upload URL + * const uploadUrl = bucket.presign("uploads/image.jpg", { + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * // Long-lived public URL + * const publicUrl = bucket.presign("public/doc.pdf", { + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(path: string, options?: S3FilePresignOptions): string; + + /** + * Delete a file from the bucket. + * + * @example + * // Simple delete + * await bucket.unlink("old-file.txt"); + * + * // With error handling + * try { + * await bucket.unlink("file.dat"); + * console.log("File deleted"); + * } catch (err) { + * console.error("Delete failed:", err); + * } + */ + unlink(path: string, options?: S3Options): Promise; + delete: S3Client["unlink"]; + + /** + * Get the size of a file in bytes. + * Uses HEAD request to efficiently get size. + * + * @example + * // Get size + * const bytes = await bucket.size("video.mp4"); + * console.log(`Size: ${bytes} bytes`); + * + * // Check if file is large + * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { + * console.log("File is larger than 100MB"); + * } + */ + size(path: string, options?: S3Options): Promise; + + /** + * Check if a file exists in the bucket. + * Uses HEAD request to check existence. + * + * @example + * // Check existence + * if (await bucket.exists("config.json")) { + * const file = bucket("config.json"); + * const config = await file.json(); + * } + * + * // With error handling + * try { + * if (!await bucket.exists("required.txt")) { + * throw new Error("Required file missing"); + * } + * } catch (err) { + * console.error("Check failed:", err); + * } + */ + exists(path: string, options?: S3Options): Promise; + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @param path The path to the file. + * @param options The options to use for the S3 client. + */ + stat(path: string, options?: S3Options): Promise; + }; + /** + * Configuration options for SQL client connection and behavior + * @example + * const config: SQLOptions = { + * host: 'localhost', + * port: 5432, + * user: 'dbuser', + * password: 'secretpass', + * database: 'myapp', + * idleTimeout: 30000, + * max: 20, + * onconnect: (client) => { + * console.log('Connected to database'); + * } + * }; + */ + type 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); + /** Database password for authentication (alias for password) */ + pass?: string | (() => Promise); + /** 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 extends Promise { + /** Indicates if the query is currently executing */ + active: boolean; + /** Indicates if the query has been cancelled */ + cancelled: boolean; + /** Cancels the executing query */ + cancel(): SQLQuery; + /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ + simple(): SQLQuery; + /** Executes the query */ + execute(): SQLQuery; + /** Returns the raw query result */ + raw(): SQLQuery; + /** Returns only the values from the query result */ + values(): SQLQuery; + } + + /** + * Callback function type for transaction contexts + * @param sql Function to execute SQL queries within the transaction + */ + type SQLTransactionContextCallback = (sql: TransactionSQL) => Promise | Array; + /** + * Callback function type for savepoint contexts + * @param sql Function to execute SQL queries within the savepoint + */ + type SQLSavepointContextCallback = (sql: SavepointSQL) => Promise | Array; + + /** + * Main SQL client interface providing connection and transaction management + */ + interface SQL { + /** Creates a new SQL client instance + * @example + * const sql = new SQL("postgres://localhost:5432/mydb"); + * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); + */ + new (connectionString: string | URL): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); + */ + new (connectionString: string | URL, options: SQLOptions): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); + */ + new (options?: SQLOptions): SQL; + /** Executes a SQL query using template literals + * @example + * const [user] = await sql`select * from users where id = ${1}`; + */ + (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; + /** + * Helper function to allow easy use to insert values into a query + * @example + * const result = await sql`insert into users ${sql(users)} RETURNING *`; + */ + (obj: any): SQLQuery; + /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.commitDistributed("my_distributed_transaction"); + */ + commitDistributed(name: string): Promise; + /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.rollbackDistributed("my_distributed_transaction"); + */ + rollbackDistributed(name: string): Promise; + /** Waits for the database connection to be established + * @example + * await sql.connect(); + */ + connect(): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @example + * await sql.close({ timeout: 1 }); + */ + close(options?: { timeout?: number }): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @alias close + * @example + * await sql.end({ timeout: 1 }); + */ + end(options?: { timeout?: number }): Promise; + /** Flushes any pending operations */ + flush(): void; + /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. + * This can be used for running queries on an isolated connection. + * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). + * @example + * const reserved = await sql.reserve(); + * await reserved`select * from users`; + * await reserved.release(); + * // with in a production scenario would be something more like + * const reserved = await sql.reserve(); + * try { + * // ... queries + * } finally { + * await reserved.release(); + * } + * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose + * { + * // always release after context (safer) + * using reserved = await sql.reserve() + * await reserved`select * from users` + * } + */ + reserve(): Promise; + /** Begins a new transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(fn: SQLTransactionContextCallback): Promise; + /** Begins a new transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(options: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(options: string, fn: SQLTransactionContextCallback): Promise; + /** Begins a distributed transaction + * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. + * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. + * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. + * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. + * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. + * @example + * await sql.beginDistributed("numbers", async sql => { + * await sql`create table if not exists numbers (a int)`; + * await sql`insert into numbers values(1)`; + * }); + * // later you can call + * await sql.commitDistributed("numbers"); + * // or await sql.rollbackDistributed("numbers"); + */ + beginDistributed(name: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a distributed transaction + * @alias beginDistributed + */ + distributed(name: string, fn: SQLTransactionContextCallback): Promise; + /**If you know what you're doing, you can use unsafe to pass any string you'd like. + * Please note that this can lead to SQL injection if you're not careful. + * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. + * @example + * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) + */ + unsafe(string: string, values?: any[]): SQLQuery; + /** + * Reads a file and uses the contents as a query. + * Optional parameters can be used if the file includes $1, $2, etc + * @example + * const result = await sql.file("query.sql", [1, 2, 3]); + */ + file(filename: string, values?: any[]): SQLQuery; + + /** Current client options */ + options: SQLOptions; + + [Symbol.asyncDispose](): Promise; + } + + /** + * Represents a reserved connection from the connection pool + * Extends SQL with additional release functionality + */ + interface ReservedSQL extends SQL { + /** Releases the client back to the connection pool */ + release(): void; + [Symbol.dispose](): void; + } + + /** + * Represents a client within a transaction context + * Extends SQL with savepoint functionality + */ + interface TransactionSQL extends SQL { + /** Creates a savepoint within the current transaction */ + savepoint(name: string, fn: SQLSavepointContextCallback): Promise; + savepoint(fn: SQLSavepointContextCallback): Promise; + } + /** + * Represents a savepoint within a transaction + */ + interface SavepointSQL extends SQL {} + + var sql: SQL; + var postgres: SQL; + var SQL: SQL; + + /** + * This lets you use macros as regular imports + * @example + * ``` + * { + * "react-relay": { + * "graphql": "bun-macro-relay/bun-macro-relay.tsx" + * } + * } + * ``` + */ + type MacroMap = Record>; + + /** + * 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; + } + + 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; + 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; + + /** 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; + }; + 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 = () =>
Hello World
; + * 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; + /** + * 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-run" + | "entry-point-build"; + + interface Import { + path: string; + kind: ImportKind; + } + + /** + * @see [Bun.build API docs](https://bun.sh/docs/bundler#api) + */ + interface BuildConfig { + entrypoints: string[]; // list of file path + outdir?: string; // output directory + /** + * @default "browser" + */ + 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; + // origin?: string; // e.g. http://mydomain.com + loader?: { [k in string]: Loader }; + /** + * Specifies if and how to generate source maps. + * + * - `"none"` - No source maps are generated + * - `"linked"` - A separate `*.ext.map` file is generated alongside each + * `*.ext` file. A `//# sourceMappingURL` comment is added to the output + * file to link the two. Requires `outdir` to be set. + * - `"inline"` - an inline source map is appended to the output file. + * - `"external"` - Generate a separate source map file for each input file. + * No `//# sourceMappingURL` comment is added to the output file. + * + * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. + * + * @default "none" + * + * @see {@link outdir} required for `"linked"` maps + * @see {@link publicPath} to customize the base url of linked source maps + */ + sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; + /** + * 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; + + /** + * Controls how environment variables are handled during bundling. + * + * Can be one of: + * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` + * references to string literals containing the actual environment variable values + * - `"disable"`: Disables environment variable injection entirely + * - A string ending in `*`: Inlines environment variables that match the given prefix. + * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" + * + * @example + * ```ts + * Bun.build({ + * env: "MY_PUBLIC_*", + * entrypoints: ["src/index.ts"], + * }) + * ``` + */ + env?: "inline" | "disable" | `${string}*`; + /** + * Whether to enable minification. + * + * Use `true`/`false` to enable/disable all minification options. Alternatively, + * you can pass an object for granular control over certain minifications. + * + * @default false + */ + 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; + + /** + * Drop function calls to matching property accesses. + */ + drop?: string[]; + + /** + * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. + * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. + * This defaults to `true`. + */ + throw?: boolean; + } + + 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 password. + * If empty, always returns false + */ + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + * + * If specified and the algorithm does not match the hash, this function + * throws an error. + */ + algorithm?: Password.AlgorithmLabel, + ): Promise; + /** + * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. + * + * @returns A promise that resolves to the hashed password + * + * ## Example with argon2 + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world"); + * console.log(hash); // $argon2id$v=1... + * const verify = await password.verify("hello world", hash); + * ``` + * ## Example with bcrypt + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world", "bcrypt"); + * console.log(hash); // $2b$10$... + * const verify = await password.verify("hello world", hash); + * ``` + */ + hash( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before + */ + algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, + ): Promise; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.verify} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + verifySync( + password: Bun.StringOrBuffer, + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + */ + algorithm?: Password.AlgorithmLabel, + ): boolean; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.hash} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + hashSync( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before + */ + algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, + ): string; + }; + + interface BuildArtifact extends Blob { + path: string; + loader: Loader; + hash: string | null; + kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; + sourcemap: BuildArtifact | null; + } + + interface BuildOutput { + outputs: BuildArtifact[]; + success: boolean; + logs: Array; + } + + /** + * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. + * + * @param {Object} config - Build configuration options + * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status + * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) + * + * @example Basic usage - Bundle a single entrypoint and check results + ```ts + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist' + }); + + if (!result.success) { + console.error('Build failed:', result.logs); + process.exit(1); + } + ``` + * + * @example Set up multiple entrypoints with code splitting enabled ```ts await Bun.build({ - entrypoints: ['./src/index.tsx'], + entrypoints: ['./src/app.tsx', './src/admin.tsx'], outdir: './dist', - define: { - 'process.env.NODE_ENV': JSON.stringify('production'), - 'CONSTANTS.VERSION': JSON.stringify('1.0.0'), - 'CONSTANTS.BUILD_TIME': JSON.stringify(new Date().toISOString()) - } + splitting: true, + sourcemap: "external" }); ``` - @example Create a custom plugin for handling special file types + * + * @example Configure minification and optimization settings ```ts await Bun.build({ entrypoints: ['./src/index.tsx'], outdir: './dist', - plugins: [ - { - name: 'my-plugin', - setup(build) { - build.onLoad({ filter: /\.custom$/ }, async (args) => { - const content = await Bun.file(args.path).text(); - return { - contents: `export default ${JSON.stringify(content)}`, - loader: 'js' - }; - }); - } - } - ] + minify: { + whitespace: true, + identifiers: true, + syntax: true + }, + drop: ['console', 'debugger'] }); ``` - @example Enable bytecode generation for faster startup + * + * @example Set up custom loaders and mark packages as external ```ts await Bun.build({ - entrypoints: ['./src/server.ts'], + entrypoints: ['./src/index.tsx'], outdir: './dist', - target: 'bun', - format: 'cjs', - bytecode: true + loader: { + '.png': 'dataurl', + '.svg': 'file', + '.txt': 'text', + '.json': 'json' + }, + external: ['react', 'react-dom'] }); ``` - @example Add custom banner and footer to output files + * + * @example Configure environment variable handling with different modes ```ts + // Inline all environment variables await Bun.build({ entrypoints: ['./src/index.tsx'], outdir: './dist', - banner: '"use client";\n// Built with Bun', - footer: '// Generated on ' + new Date().toISOString() + env: 'inline' }); - ``` - @example Configure CDN public path for asset loading - ```ts + + // Only include specific env vars await Bun.build({ entrypoints: ['./src/index.tsx'], outdir: './dist', - publicPath: 'https://cdn.example.com/assets/', - loader: { - '.png': 'file', - '.svg': 'file' - } + env: 'PUBLIC_*' }); ``` - @example Set up package export conditions for different environments + * + * @example Set up custom naming patterns for all output types ```ts await Bun.build({ entrypoints: ['./src/index.tsx'], outdir: './dist', - conditions: ['production', 'browser', 'module'], - packages: 'external' + naming: { + entry: '[dir]/[name]-[hash].[ext]', + chunk: 'chunks/[name]-[hash].[ext]', + asset: 'assets/[name]-[hash].[ext]' + } }); ``` - */ - function build(config: BuildConfig): Promise; - /** - * A status that represents the outcome of a sent message. - * - * - if **0**, the message was **dropped**. - * - if **-1**, there is **backpressure** of messages. - * - if **>0**, it represents the **number of bytes sent**. - * - * @example - * ```js - * const status = ws.send("Hello!"); - * if (status === 0) { - * console.log("Message was dropped"); - * } else if (status === -1) { - * console.log("Backpressure was applied"); - * } else { - * console.log(`Success! Sent ${status} bytes`); - * } - * ``` - */ - type ServerWebSocketSendStatus = number; - - /** - * A state that represents if a WebSocket is connected. - * - * - `WebSocket.CONNECTING` is `0`, the connection is pending. - * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. - * - `WebSocket.CLOSING` is `2`, the connection is closing. - * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState - */ - type WebSocketReadyState = 0 | 1 | 2 | 3; - - /** - * A fast WebSocket designed for servers. - * - * Features: - * - **Message compression** - Messages can be compressed - * - **Backpressure** - If the client is not ready to receive data, the server will tell you. - * - **Dropped messages** - If the client cannot receive data, the server will tell you. - * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics - * - * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. - * - * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). - * - * @example - * import { serve } from "bun"; - * - * serve({ - * websocket: { - * open(ws) { - * console.log("Connected", ws.remoteAddress); - * }, - * message(ws, data) { - * console.log("Received", data); - * ws.send(data); - * }, - * close(ws, code, reason) { - * console.log("Disconnected", code, reason); - * }, - * } - * }); - */ - interface ServerWebSocket { - /** - * Sends a message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - * ws.send(new Uint8Array([1, 2, 3, 4])); - */ - send( - data: string | Bun.BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a text message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - */ - sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send(new TextEncoder().encode("Hello!")); - * ws.send(new Uint8Array([1, 2, 3, 4]), true); - */ - sendBinary( - data: Bun.BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Closes the connection. - * - * Here is a list of close codes: - * - `1000` means "normal closure" **(default)** - * - `1009` means a message was too big and was rejected - * - `1011` means the server encountered an error - * - `1012` means the server is restarting - * - `1013` means the server is too busy or the client is rate-limited - * - `4000` through `4999` are reserved for applications (you can use it!) - * - * To close the connection abruptly, use `terminate()`. - * - * @param code The close code to send - * @param reason The close reason to send - */ - close(code?: number, reason?: string): void; - - /** - * Abruptly close the connection. - * - * To gracefully close the connection, use `close()`. - */ - terminate(): void; - - /** - * Sends a ping. - * - * @param data The data to send - */ - ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a pong. - * - * @param data The data to send - */ - pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); - */ - publish( - topic: string, - data: string | Bun.BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a text message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - */ - publishText( - topic: string, - data: string, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a binary message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", new TextEncoder().encode("Hello!")); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); - */ - publishBinary( - topic: string, - data: Bun.BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Subscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - */ - subscribe(topic: string): void; - - /** - * Unsubscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.unsubscribe("chat"); - */ - unsubscribe(topic: string): void; - - /** - * Is the client subscribed to a topic? - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - * console.log(ws.isSubscribed("chat")); // true - */ - isSubscribed(topic: string): boolean; - - /** - * Batches `send()` and `publish()` operations, which makes it faster to send data. - * - * The `message`, `open`, and `drain` callbacks are automatically corked, so - * you only need to call this if you are sending messages outside of those - * callbacks or in async functions. - * - * @param callback The callback to run. - * @example - * ws.cork((ctx) => { - * ctx.send("These messages"); - * ctx.sendText("are sent"); - * ctx.sendBinary(new TextEncoder().encode("together!")); - * }); - */ - cork(callback: (ws: ServerWebSocket) => T): T; - - /** - * The IP address of the client. - * - * @example - * console.log(socket.remoteAddress); // "127.0.0.1" - */ - readonly remoteAddress: string; - - /** - * The ready state of the client. - * - * - if `0`, the client is connecting. - * - if `1`, the client is connected. - * - if `2`, the client is closing. - * - if `3`, the client is closed. - * - * @example - * console.log(socket.readyState); // 1 - */ - readonly readyState: WebSocketReadyState; - - /** - * Sets how binary data is returned in events. - * - * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** - * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. - * - if `uint8array`, binary data is returned as `Uint8Array` objects. - * - * @example - * let ws: WebSocket; - * ws.binaryType = "uint8array"; - * ws.addEventListener("message", ({ data }) => { - * console.log(data instanceof Uint8Array); // true - * }); - */ - binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; - - /** - * Custom data that you can assign to a client, can be read and written at any time. - * - * @example - * import { serve } from "bun"; - * - * serve({ - * fetch(request, server) { - * const data = { - * accessToken: request.headers.get("Authorization"), - * }; - * if (server.upgrade(request, { data })) { - * return; - * } - * return new Response(); - * }, - * websocket: { - * open(ws) { - * console.log(ws.data.accessToken); - * } - * } - * }); - */ - data: T; - - getBufferedAmount(): number; - } - - /** - * Compression options for WebSocket messages. - */ - type WebSocketCompressor = - | "disable" - | "shared" - | "dedicated" - | "3KB" - | "4KB" - | "8KB" - | "16KB" - | "32KB" - | "64KB" - | "128KB" - | "256KB"; - - /** - * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} - * - * @example - * ```ts - * import { websocket, serve } from "bun"; - * - * serve<{name: string}>({ - * port: 3000, - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log(`${ws.data.name}: ${message}`); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req, { - * data: { - * name: new URL(req.url).searchParams.get("name"), - * }, - * }); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * return; - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - */ - interface WebSocketHandler { - /** - * Called when the server receives an incoming message. - * - * If the message is not a `string`, its type is based on the value of `binaryType`. - * - if `nodebuffer`, then the message is a `Buffer`. - * - if `arraybuffer`, then the message is an `ArrayBuffer`. - * - if `uint8array`, then the message is a `Uint8Array`. - * - * @param ws The websocket that sent the message - * @param message The message received - */ - message( - ws: ServerWebSocket, - message: string | Buffer, - ): void | Promise; - - /** - * Called when a connection is opened. - * - * @param ws The websocket that was opened - */ - open?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection was previously under backpressure, - * meaning it had too many queued messages, but is now ready to receive more data. - * - * @param ws The websocket that is ready for more data - */ - drain?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection is closed. - * - * @param ws The websocket that was closed - * @param code The close code - * @param message The close message - */ - close?( - ws: ServerWebSocket, - code: number, - reason: string, - ): void | Promise; - - /** - * Called when a ping is sent. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - ping?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Called when a pong is received. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - pong?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Sets the maximum size of messages in bytes. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - maxPayloadLength?: number; - - /** - * Sets the maximum number of bytes that can be buffered on a single connection. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - backpressureLimit?: number; - - /** - * Sets if the connection should be closed if `backpressureLimit` is reached. - * - * Default is `false`. - */ - closeOnBackpressureLimit?: boolean; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to no messages or pings. - * - * Default is 2 minutes, or `120` in seconds. - */ - idleTimeout?: number; - - /** - * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? - * - * Default is `false`. - */ - publishToSelf?: boolean; - - /** - * Should the server automatically send and respond to pings to clients? - * - * Default is `true`. - */ - sendPings?: boolean; - - /** - * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. - * - * Default is `false`. - */ - perMessageDeflate?: - | boolean - | { - /** - * Sets the compression level. - */ - compress?: WebSocketCompressor | boolean; - /** - * Sets the decompression level. - */ - decompress?: WebSocketCompressor | boolean; - }; - } - - namespace RouterTypes { - type ExtractRouteParams = - T extends `${string}:${infer Param}/${infer Rest}` - ? { [K in Param]: string } & ExtractRouteParams - : T extends `${string}:${infer Param}` - ? { [K in Param]: string } - : T extends `${string}*` - ? {} - : {}; - - type RouteHandler = ( - req: BunRequest, - server: Server, - ) => Response | Promise; - - type HTTPMethod = - | "GET" - | "POST" - | "PUT" - | "DELETE" - | "PATCH" - | "HEAD" - | "OPTIONS"; - - type RouteHandlerObject = { - [K in HTTPMethod]?: RouteHandler; - }; - - type RouteValue = - | Response - | false - | RouteHandler - | RouteHandlerObject; - } - - interface BunRequest extends Request { - params: RouterTypes.ExtractRouteParams; - } - - interface GenericServeOptions { - /** - * What URI should be used to make {@link Request.url} absolute? - * - * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one - * - * @example - * ```js - * "http://my-app.com" - * ``` - * - * @example - * ```js - * "https://wongmjane.com/" - * ``` - * - * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. - * - * @example - * "http://localhost:3000" - */ - // baseURI?: string; - - /** - * What is the maximum size of a request body? (in bytes) - * @default 1024 * 1024 * 128 // 128MB - */ - maxRequestBodySize?: number; - - /** - * Render contextual errors? This enables bun's error page - * @default process.env.NODE_ENV !== 'production' - */ - development?: - | boolean - | { - /** - * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) - * - * @default true if process.env.NODE_ENV !== 'production' - * - */ - hmr?: boolean; - }; - - error?: ( - this: Server, - error: ErrorLike, - ) => Response | Promise | undefined | Promise; - - /** - * Uniquely identify a server instance with an ID - * - * ### When bun is started with the `--hot` flag - * - * This string will be used to hot reload the server without interrupting - * pending requests or websockets. If not provided, a value will be - * generated. To disable hot reloading, set this value to `null`. - * - * ### When bun is not started with the `--hot` flag - * - * This string will currently do nothing. But in the future it could be useful for logs or metrics. - */ - id?: string | null; - } - - interface ServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * Whether the `SO_REUSEPORT` flag should be set. - * - * This allows multiple processes to bind to the same port, which is useful for load balancing. - * - * @default false - */ - reusePort?: boolean; - - /** - * Whether the `IPV6_V6ONLY` flag should be set. - * @default false - */ - ipv6Only?: boolean; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix?: never; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to inactivity. - * - * Default is `10` seconds. - */ - idleTimeout?: number; - - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | Promise; - } - - interface UnixServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | Promise; - } - - interface WebSocketServeOptions - extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | void | Promise; - } - - interface UnixWebSocketServeOptions - extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | Promise; - } - - interface TLSWebSocketServeOptions - extends WebSocketServeOptions, - TLSOptionsAsDeprecated { - unix?: never; - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSWebSocketServeOptions - extends UnixWebSocketServeOptions, - TLSOptionsAsDeprecated { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - tls?: TLSOptions | TLSOptions[]; - } - - interface ErrorLike extends Error { - code?: string; - errno?: number; - syscall?: string; - } - - interface TLSOptions { - /** - * Passphrase for the TLS key - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - // Note for contributors: TLSOptionsAsDeprecated should be considered immutable - // and new TLS option keys should only be supported on the `.tls` property (which comes - // from the TLSOptions interface above). - /** - * This exists because Bun.serve() extends the TLSOptions object, but - * they're now considered deprecated. You should be passing the - * options on `.tls` instead. - * - * @example - * ```ts - * //// OLD //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * passphrase: "secret", - * }); - * - * //// NEW //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * tls: { - * passphrase: "secret", - * }, - * }); - * ``` - */ - interface TLSOptionsAsDeprecated { - /** - * Passphrase for the TLS key - * - * @deprecated Use `.tls.passphrase` instead - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - * - * @deprecated Use `.tls.dhParamsFile` instead - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - * - * @deprecated Use `.tls.serverName` instead - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - * - * @deprecated Use `.tls.lowMemoryMode` instead - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - * - * @deprecated Use `.tls.rejectUnauthorized` instead - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - * - * @deprecated Use `.tls.requestCert` instead - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - * - * @deprecated Use `.tls.ca` instead - */ - ca?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - * - * @deprecated Use `.tls.cert` instead - */ - cert?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - * - * @deprecated Use `.tls.key` instead - */ - key?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - * - * @deprecated `Use .tls.secureOptions` instead - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSServeOptions - extends UnixServeOptions, - TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface SocketAddress { - /** - * The IP address of the client. - */ - address: string; - /** - * The port of the client. - */ - port: number; - /** - * The IP family ("IPv4" or "IPv6"). - */ - family: "IPv4" | "IPv6"; - } - - /** - * HTTP & HTTPS Server - * - * To start the server, see {@link serve} - * - * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. - * That means starting a new server allocates about 500 KB of memory. Try to - * avoid starting and stopping the server often (unless it's a new instance of bun). - * - * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. - */ - interface Server extends Disposable { - /** - * Stop listening to prevent new connections from being accepted. - * - * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. - * - * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. - * @default false - */ - stop(closeActiveConnections?: boolean): Promise; - - /** - * Update the `fetch` and `error` handlers without restarting the server. - * - * This is useful if you want to change the behavior of your server without - * restarting it or for hot reloading. - * - * @example - * - * ```js - * // create the server - * const server = Bun.serve({ - * fetch(request) { - * return new Response("Hello World v1") - * } - * }); - * - * // Update the server to return a different response - * server.reload({ - * fetch(request) { - * return new Response("Hello World v2") - * } - * }); - * ``` - * - * Passing other options such as `port` or `hostname` won't do anything. - */ - reload }>( - options: ( - | (Omit & { - routes: R; - fetch?: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | (Omit & { - routes?: never; - fetch: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. - */ - static?: R; - }, - ): Server; - - /** - * Mock the fetch handler for a running server. - * - * This feature is not fully implemented yet. It doesn't normalize URLs - * consistently in all cases and it doesn't yet call the `error` handler - * consistently. This needs to be fixed - */ - fetch(request: Request | string): Response | Promise; - - /** - * Upgrade a {@link Request} to a {@link ServerWebSocket} - * - * @param request The {@link Request} to upgrade - * @param options Pass headers or attach data to the {@link ServerWebSocket} - * - * @returns `true` if the upgrade was successful and `false` if it failed - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * What you pass to `data` is available on the {@link ServerWebSocket.data} property - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - upgrade( - request: Request, - options?: { - /** - * Send any additional headers while upgrading, like cookies - */ - headers?: Bun.HeadersInit; - /** - * This value is passed to the {@link ServerWebSocket.data} property - */ - data?: T; - }, - ): boolean; - - /** - * Send a message to all connected {@link ServerWebSocket} subscribed to a topic - * - * @param topic The topic to publish to - * @param data The data to send - * @param compress Should the data be compressed? Ignored if the client does not support compression. - * - * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. - * - * @example - * - * ```js - * server.publish("chat", "Hello World"); - * ``` - * - * @example - * ```js - * server.publish("chat", new Uint8Array([1, 2, 3, 4])); - * ``` - * - * @example - * ```js - * server.publish("chat", new ArrayBuffer(4), true); - * ``` - * - * @example - * ```js - * server.publish("chat", new DataView(new ArrayBuffer(4))); - * ``` - */ - publish( - topic: string, - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * A count of connections subscribed to a given topic - * - * This operation will loop through each topic internally to get the count. - * - * @param topic the websocket topic to check how many subscribers are connected to - * @returns the number of subscribers - */ - subscriberCount(topic: string): number; - - /** - * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * return new Response(server.requestIP(request)); - * } - * } - * ``` - */ - requestIP(request: Request): SocketAddress | null; - - /** - * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * server.timeout(request, 60); - * await Bun.sleep(30000); - * return new Response("30 seconds have passed"); - * } - * } - * ``` - */ - timeout(request: Request, seconds: number): void; - /** - * Undo a call to {@link Server.unref} - * - * If the Server has already been stopped, this does nothing. - * - * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. - */ - ref(): void; - - /** - * Don't keep the process alive if this server is the only thing left. - * Active connections may continue to keep the process alive. - * - * By default, the server is ref'd. - * - * To prevent new connections from being accepted, use {@link Server.stop} - */ - unref(): void; - - /** - * How many requests are in-flight right now? - */ - readonly pendingRequests: number; - - /** - * How many {@link ServerWebSocket}s are in-flight right now? - */ - readonly pendingWebSockets: number; - - readonly url: URL; - - readonly port: number; - /** - * The hostname the server is listening on. Does not include the port - * @example - * ```js - * "localhost" - * ``` - */ - readonly hostname: string; - /** - * Is the server running in development mode? - * - * In development mode, `Bun.serve()` returns rendered error messages with - * stack traces instead of a generic 500 error. This makes debugging easier, - * but development mode shouldn't be used in production or you will risk - * leaking sensitive information. - */ - readonly development: boolean; - - /** - * An identifier of the server instance - * - * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. - * - * When bun is not started with the `--hot` flag, this ID is currently unused. - */ - readonly id: string; - } - - type Serve = - | ServeOptions - | TLSServeOptions - | UnixServeOptions - | UnixTLSServeOptions - | WebSocketServeOptions - | TLSWebSocketServeOptions - | UnixWebSocketServeOptions - | UnixTLSWebSocketServeOptions; - - /** - Bun.serve provides a high-performance HTTP server with built-in routing support. - It enables both function-based and object-based route handlers with type-safe - parameters and method-specific handling. - - @example Basic Usage + @example Work with build artifacts in different formats ```ts - Bun.serve({ - port: 3000, - fetch(req) { - return new Response("Hello World"); - } + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'] }); - ``` - @example Route-based Handlers + for (const artifact of result.outputs) { + const text = await artifact.text(); + const buffer = await artifact.arrayBuffer(); + const bytes = await artifact.bytes(); + + new Response(artifact); + await Bun.write(artifact.path, artifact); + } + ``` + @example Implement comprehensive error handling with position info ```ts - Bun.serve({ - routes: { - // Static responses - "/": new Response("Home page"), - - // Function handlers with type-safe parameters - "/users/:id": (req) => { - // req.params.id is typed as string - return new Response(`User ${req.params.id}`); - }, - - // Method-specific handlers - "/api/posts": { - GET: () => new Response("Get posts"), - POST: async (req) => { - const body = await req.json(); - return new Response("Created post"); - }, - DELETE: (req) => new Response("Deleted post") - }, - - // Wildcard routes - "/static/*": (req) => { - // Handle any path under /static/ - return new Response("Static file"); - }, - - // Disable route (fall through to fetch handler) - "/api/legacy": false - }, - - // Fallback handler for unmatched routes - fetch(req) { - return new Response("Not Found", { status: 404 }); + try { + const result = await Bun.build({ + entrypoints: ['./src/index.tsx'], + }); + } catch (e) { + const error = e as AggregateError; + console.error('Build failed:'); + for (const msg of error.errors) { + if ('position' in msg) { + console.error( + `${msg.message} at ${msg.position?.file}:${msg.position?.line}:${msg.position?.column}` + ); + } else { + console.error(msg.message); + } } + } + ``` + @example Set up Node.js target with specific configurations + ```ts + await Bun.build({ + entrypoints: ['./src/server.ts'], + outdir: './dist', + target: 'node', + format: 'cjs', + sourcemap: 'external', + minify: false, + packages: 'external' }); ``` - - @example Path Parameters + * + * @example Configure experimental CSS bundling with multiple themes ```ts - Bun.serve({ - routes: { - // Single parameter - "/users/:id": (req: BunRequest<"/users/:id">) => { - return new Response(`User ID: ${req.params.id}`); - }, - - // Multiple parameters - "/posts/:postId/comments/:commentId": ( - req: BunRequest<"/posts/:postId/comments/:commentId"> - ) => { - return new Response(JSON.stringify(req.params)); - // Output: {"postId": "123", "commentId": "456"} - } - } + await Bun.build({ + entrypoints: [ + './src/styles.css', + './src/themes/dark.css', + './src/themes/light.css' + ], + outdir: './dist/css', }); ``` - - @example Route Precedence + @example Define compile-time constants and version information ```ts - // Routes are matched in the following order: - // 1. Exact static routes ("/about") - // 2. Parameter routes ("/users/:id") - // 3. Wildcard routes ("/api/*") - - Bun.serve({ - routes: { - "/api/users": () => new Response("Users list"), - "/api/users/:id": (req) => new Response(`User ${req.params.id}`), - "/api/*": () => new Response("API catchall"), - "/*": () => new Response("Root catchall") + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + define: { + 'process.env.NODE_ENV': JSON.stringify('production'), + 'CONSTANTS.VERSION': JSON.stringify('1.0.0'), + 'CONSTANTS.BUILD_TIME': JSON.stringify(new Date().toISOString()) } }); ``` - - @example Error Handling + @example Create a custom plugin for handling special file types ```ts - Bun.serve({ - routes: { - "/error": () => { - throw new Error("Something went wrong"); + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + plugins: [ + { + name: 'my-plugin', + setup(build) { + build.onLoad({ filter: /\.custom$/ }, async (args) => { + const content = await Bun.file(args.path).text(); + return { + contents: `export default ${JSON.stringify(content)}`, + loader: 'js' + }; + }); + } } - }, - error(error) { - // Custom error handler - console.error(error); - return new Response(`Error: ${error.message}`, { - status: 500 - }); - } + ] }); ``` - - @example Server Lifecycle + @example Enable bytecode generation for faster startup ```ts - const server = Bun.serve({ - // Server config... + await Bun.build({ + entrypoints: ['./src/server.ts'], + outdir: './dist', + target: 'bun', + format: 'cjs', + bytecode: true }); - - // Update routes at runtime - server.reload({ - routes: { - "/": () => new Response("Updated route") - } + ``` + @example Add custom banner and footer to output files + ```ts + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + banner: '"use client";\n// Built with Bun', + footer: '// Generated on ' + new Date().toISOString() }); - - // Stop the server - server.stop(); ``` - - @example Development Mode + @example Configure CDN public path for asset loading ```ts - Bun.serve({ - development: true, // Enable hot reloading - routes: { - // Routes will auto-reload on changes + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + publicPath: 'https://cdn.example.com/assets/', + loader: { + '.png': 'file', + '.svg': 'file' } }); ``` - - @example Type-Safe Request Handling + @example Set up package export conditions for different environments ```ts - type Post = { - id: string; - title: string; - }; - - Bun.serve({ - routes: { - "/api/posts/:id": async ( - req: BunRequest<"/api/posts/:id"> - ) => { - if (req.method === "POST") { - const body: Post = await req.json(); - return Response.json(body); - } - return new Response("Method not allowed", { - status: 405 - }); - } - } + await Bun.build({ + entrypoints: ['./src/index.tsx'], + outdir: './dist', + conditions: ['production', 'browser', 'module'], + packages: 'external' }); ``` - @param options - Server configuration options - @param options.routes - Route definitions mapping paths to handlers - */ - function serve< - T, - R extends { [K in keyof R]: RouterTypes.RouteValue }, - >( - options: ( - | (DistributedOmit & { - routes: R; - fetch?: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | (DistributedOmit & { - routes?: never; - fetch: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for a while though. - */ - static?: R; - }, - ): Server; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - `type` is auto-set based on the file extension when possible - * - * @example - * ```js - * const file = Bun.file("./hello.json"); - * console.log(file.type); // "application/json" - * console.log(await file.json()); // { hello: "world" } - * ``` - * - * @example - * ```js - * await Bun.write( - * Bun.file("./hello.txt"), - * "Hello, world!" - * ); - * ``` - * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file(path: string | URL, options?: BlobPropertyBag): BunFile; - - /** - * A list of files embedded into the standalone executable. Lexigraphically sorted by name. - * - * If the process is not a standalone executable, this returns an empty array. - */ - const embeddedFiles: ReadonlyArray; - - /** - * `Blob` that leverages the fastest system calls available to operate on files. - * - * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. - * - * `Blob.size` will not be valid until the contents of the file are read at least once. - * `Blob.type` will have a default set based on the file extension - * - * @example - * ```js - * const file = Bun.file(new TextEncoder.encode("./hello.json")); - * console.log(file.type); // "application/json" - * ``` - * - * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file( - path: ArrayBufferLike | Uint8Array, - options?: BlobPropertyBag, - ): BunFile; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - * @example - * ```js - * const file = Bun.file(fd); - * ``` - * - * @param fileDescriptor The file descriptor of the file - */ - // tslint:disable-next-line:unified-signatures - function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; - - /** - * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. - * - * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. - */ - function allocUnsafe(size: number): Uint8Array; - - interface BunInspectOptions { - colors?: boolean; - depth?: number; - sorted?: boolean; - compact?: boolean; - } - - /** - * Pretty-print an object the same as {@link console.log} to a `string` - * - * Supports JSX - * - * @param args - */ - function inspect(arg: any, options?: BunInspectOptions): string; - namespace inspect { - /** - * That can be used to declare custom inspect functions. - */ - const custom: typeof import("util").inspect.custom; - - /** - * Pretty-print an object or array as a table - * - * Like {@link console.table}, except it returns a string - */ - function table( - tabularData: object | unknown[], - properties?: string[], - options?: { colors?: boolean }, - ): string; - function table( - tabularData: object | unknown[], - options?: { colors?: boolean }, - ): string; - } - - interface MMapOptions { - /** - * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. - */ - sync?: boolean; - /** - * Allow other processes to see results instantly? - * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. - * @default true - */ - shared?: boolean; - } - /** - * Open a file as a live-updating `Uint8Array` without copying memory - * - Writing to the array writes to the file. - * - Reading from the array reads from the file. - * - * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. - * - * --- - * - * This API inherently has some rough edges: - * - It does not support empty files. It will throw a `SystemError` with `EINVAL` - * - Usage on shared/networked filesystems is discouraged. It will be very slow. - * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. - * - * --- - * - * To close the file, set the array to `null` and it will be garbage collected eventually. - */ - function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; - - /** Write to stdout */ - const stdout: BunFile; - /** Write to stderr */ - const stderr: BunFile; - /** - * Read from stdin - * - * This is read-only - */ - const stdin: BunFile; - - type StringLike = string | { toString(): string }; - - type ColorInput = - | { r: number; g: number; b: number; a?: number } - | [number, number, number] - | [number, number, number, number] - | Uint8Array - | Uint8ClampedArray - | Float32Array - | Float64Array - | string - | number - | { toString(): string }; - - function color( - input: ColorInput, - outputFormat?: /** - * True color ANSI color string, for use in terminals - * @example \x1b[38;2;100;200;200m - */ - | "ansi" - | "ansi-16" - | "ansi-16m" - /** - * 256 color ANSI color string, for use in terminals which don't support true color - * - * Tries to match closest 24-bit color to 256 color palette - */ - | "ansi-256" - /** - * Picks the format that produces the shortest output - */ - | "css" - /** - * Lowercase hex color string without alpha - * @example #ff9800 - */ - | "hex" - /** - * Uppercase hex color string without alpha - * @example #FF9800 - */ - | "HEX" - /** - * @example hsl(35.764706, 1, 0.5) - */ - | "hsl" - /** - * @example lab(0.72732764, 33.938198, -25.311619) - */ - | "lab" - /** - * @example 16750592 - */ - | "number" - /** - * RGB color string without alpha - * @example rgb(255, 152, 0) - */ - | "rgb" - /** - * RGB color string with alpha - * @example rgba(255, 152, 0, 1) - */ - | "rgba", - ): string | null; - - function color( - input: ColorInput, - /** - * An array of numbers representing the RGB color - * @example [100, 200, 200] - */ - outputFormat: "[rgb]", - ): [number, number, number] | null; - function color( - input: ColorInput, - /** - * An array of numbers representing the RGBA color - * @example [100, 200, 200, 255] - */ - outputFormat: "[rgba]", - ): [number, number, number, number] | null; - function color( - input: ColorInput, - /** - * An object representing the RGB color - * @example { r: 100, g: 200, b: 200 } - */ - outputFormat: "{rgb}", - ): { r: number; g: number; b: number } | null; - function color( - input: ColorInput, - /** - * An object representing the RGBA color - * @example { r: 100, g: 200, b: 200, a: 0.5 } - */ - outputFormat: "{rgba}", - ): { r: number; g: number; b: number; a: number } | null; - function color(input: ColorInput, outputFormat: "number"): number | null; - - interface Semver { - /** - * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. - */ - satisfies(version: StringLike, range: StringLike): boolean; - - /** - * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. - * Throws an error if either version is invalid. - */ - order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; - } - var semver: Semver; - - interface Unsafe { - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. - * - * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; - - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` - * - * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - // tslint:disable-next-line:unified-signatures - arrayBufferToString(buffer: Uint16Array): string; - - /** Mock bun's segfault handler. You probably don't want to use this */ - segfault(): void; - - /** - * Force the garbage collector to run extremely often, - * especially inside `bun:test`. - * - * - `0`: default, disable - * - `1`: asynchronously call the garbage collector more often - * - `2`: synchronously call the garbage collector more often. - * - * This is a global setting. It's useful for debugging seemingly random crashes. - * - * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. - * - * @param level - * @returns The previous level - */ - gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; - } - const unsafe: Unsafe; - - type DigestEncoding = - | "utf8" - | "ucs2" - | "utf16le" - | "latin1" - | "ascii" - | "base64" - | "base64url" - | "hex"; - - /** - * Are ANSI colors enabled for stdin and stdout? - * - * Used for {@link console.log} - */ - const enableANSIColors: boolean; - - /** - * What script launched bun? - * - * Absolute file path - * - * @example "/never-gonna-give-you-up.js" - */ - const main: string; - - /** - * Manually trigger the garbage collector - * - * This does two things: - * 1. It tells JavaScriptCore to run the garbage collector - * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. - * - * @param force Synchronously run the garbage collector - */ - function gc(force: boolean): void; - - /** - * JavaScriptCore engine's internal heap snapshot - * - * I don't know how to make this something Chrome or Safari can read. - * - * If you have any ideas, please file an issue https://github.com/oven-sh/bun - */ - interface HeapSnapshot { - /** 2 */ - version: number; - - /** "Inspector" */ - type: string; - - nodes: number[]; - - nodeClassNames: string[]; - edges: number[]; - edgeTypes: string[]; - edgeNames: string[]; - } - - /** - * Returns the number of nanoseconds since the process was started. - * - * This function uses a high-resolution monotonic system timer to provide precise time measurements. - * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), - * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). - * - * Due to this limitation, while the internal counter may continue beyond this point, - * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond - * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but - * with reduced precision, which might affect time calculations and comparisons in long-running applications. - * - * @returns {number} The number of nanoseconds since the process was started, with precise values up to - * Number.MAX_SAFE_INTEGER. - */ - function nanoseconds(): number; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector - */ - function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code - * - * This is a JSON string that can be saved to a file. - * ```ts - * const snapshot = Bun.generateHeapSnapshot("v8"); - * await Bun.write("heap.heapsnapshot", snapshot); - * ``` - */ - function generateHeapSnapshot(format: "v8"): string; - - /** - * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. - */ - function shrink(): void; - - /** - * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` - * - * @param path path to open - */ - function openInEditor(path: string, options?: EditorOptions): void; - - var fetch: typeof globalThis.fetch & { - preconnect(url: string): void; - }; - - interface EditorOptions { - editor?: "vscode" | "subl"; - line?: number; - column?: number; - } - - /** - * This class only exists in types - */ - abstract class CryptoHashInterface { - /** - * Update the hash with data - * - * @param data - */ - update(data: Bun.BlobOrStringOrBuffer): T; - - /** - * Finalize the hash - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash( - input: Bun.BlobOrStringOrBuffer, - hashInto?: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - } - - type SupportedCryptoAlgorithms = - | "blake2b256" - | "blake2b512" - | "md4" - | "md5" - | "ripemd160" - | "sha1" - | "sha224" - | "sha256" - | "sha384" - | "sha512" - | "sha512-224" - | "sha512-256" - | "sha3-224" - | "sha3-256" - | "sha3-384" - | "sha3-512" - | "shake128" - | "shake256"; - - /** - * Hardware-accelerated cryptographic hash functions - * - * Used for `crypto.createHash()` - */ - class CryptoHasher { - /** - * The algorithm chosen to hash the data - */ - readonly algorithm: SupportedCryptoAlgorithms; - - /** - * The length of the output hash in bytes - */ - readonly byteLength: number; - - /** - * Create a new hasher - * - * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms - * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. - */ - constructor( - algorithm: SupportedCryptoAlgorithms, - hmacKey?: string | NodeJS.TypedArray, - ); - - /** - * Update the hash with data - * - * @param input - */ - update( - input: Bun.BlobOrStringOrBuffer, - inputEncoding?: CryptoEncoding, - ): CryptoHasher; - - /** - * Perform a deep copy of the hasher - */ - copy(): CryptoHasher; - - /** - * Finalize the hash. Resets the CryptoHasher so it can be reused. - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(): Buffer; - digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - ): Buffer; - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - hashInto: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - - /** - * List of supported hash algorithms - * - * These are hardware accelerated with BoringSSL - */ - static readonly algorithms: SupportedCryptoAlgorithms[]; - } - - /** - * Resolve a `Promise` after milliseconds. This is like - * {@link setTimeout} except it returns a `Promise`. - * - * @param ms milliseconds to delay resolving the promise. This is a minimum - * number. It may take longer. If a {@link Date} is passed, it will sleep until the - * {@link Date} is reached. - * - * @example - * ## Sleep for 1 second - * ```ts - * import { sleep } from "bun"; - * - * await sleep(1000); - * ``` - * ## Sleep for 10 milliseconds - * ```ts - * await Bun.sleep(10); - * ``` - * ## Sleep until `Date` - * - * ```ts - * const target = new Date(); - * target.setSeconds(target.getSeconds() + 1); - * await Bun.sleep(target); - * ``` - * Internally, `Bun.sleep` is the equivalent of - * ```ts - * await new Promise((resolve) => setTimeout(resolve, ms)); - * ``` - * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. - */ - function sleep(ms: number | Date): Promise; - - /** - * Sleep the thread for a given number of milliseconds - * - * This is a blocking function. - * - * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) - */ - function sleepSync(ms: number): void; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha( - input: Bun.StringOrBuffer, - hashInto?: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param encoding `DigestEncoding` to return the hash in - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; - - /** - * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} - * - * Consider using the ugly-named {@link SHA512_256} instead - */ - class SHA1 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 20; - } - class MD5 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class MD4 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class SHA224 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 28; - } - class SHA512 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 64; - } - class SHA384 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 48; - } - class SHA256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - /** - * See also {@link sha} - */ - class SHA512_256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - - /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ - interface ZlibCompressionOptions { - /** - * The compression level to use. Must be between `-1` and `9`. - * - A value of `-1` uses the default compression level (Currently `6`) - * - A value of `0` gives no compression - * - A value of `1` gives least compression, fastest speed - * - A value of `9` gives best compression, slowest speed - */ - level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * How much memory should be allocated for the internal compression state. - * - * A value of `1` uses minimum memory but is slow and reduces compression ratio. - * - * A value of `9` uses maximum memory for optimal speed. The default is `8`. - */ - memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * The base 2 logarithm of the window size (the size of the history buffer). - * - * Larger values of this parameter result in better compression at the expense of memory usage. - * - * The following value ranges are supported: - * - `9..15`: The output will have a zlib header and footer (Deflate) - * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) - * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) - * - * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. - */ - windowBits?: - | -9 - | -10 - | -11 - | -12 - | -13 - | -14 - | -15 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 25 - | 26 - | 27 - | 28 - | 29 - | 30 - | 31; - /** - * Tunes the compression algorithm. - * - * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** - * - `Z_FILTERED`: For data produced by a filter or predictor - * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) - * - `Z_RLE`: Limit match distances to one (run-length encoding) - * - `Z_FIXED` prevents the use of dynamic Huffman codes - * - * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. - * - * `Z_FILTERED` forces more Huffman coding and less string matching, it is - * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. - * Filtered data consists mostly of small values with a somewhat random distribution. - */ - strategy?: number; - - library?: "zlib"; - } - - interface LibdeflateCompressionOptions { - level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; - library?: "libdeflate"; - } - - /** - * Compresses a chunk of data with `zlib` DEFLATE algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function deflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Compresses a chunk of data with `zlib` GZIP algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function gzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` INFLATE algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function inflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` GUNZIP algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function gunzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - - type Target = - /** - * For generating bundles that are intended to be run by the Bun runtime. In many cases, - * it isn't necessary to bundle server-side code; you can directly execute the source code - * without modification. However, bundling your server code can reduce startup times and - * improve running performance. - * - * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which - * indicates to the Bun runtime that there's no need to re-transpile the file before execution. - */ - | "bun" - /** - * The plugin will be applied to Node.js builds - */ - | "node" - /** - * The plugin will be applied to browser builds - */ - | "browser"; - - /** https://bun.sh/docs/bundler/loaders */ - type Loader = - | "js" - | "jsx" - | "ts" - | "tsx" - | "json" - | "toml" - | "file" - | "napi" - | "wasm" - | "text" - | "css" - | "html"; - - interface PluginConstraints { - /** - * Only apply the plugin when the import specifier matches this regular expression - * - * @example - * ```ts - * // Only apply the plugin when the import specifier matches the regex - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { - * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; - * }); - * } - * }) - * ``` - */ - filter: RegExp; - - /** - * Only apply the plugin when the import specifier has a namespace matching - * this string - * - * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` - * has the namespace `"bun"`. - * - * The default namespace is `"file"` and it can be omitted from import - * specifiers. - */ - namespace?: string; - } - - interface OnLoadResultSourceCode { - /** - * The source code of the module - */ - contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; - /** - * The loader to use for this file - * - * "css" will be added in a future version of Bun. - */ - loader?: Loader; - } - - interface OnLoadResultObject { - /** - * The object to use as the module - * @example - * ```ts - * // In your loader - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * - * // In your script - * import {foo} from "hello:world"; - * console.log(foo); // "bar" - * ``` - */ - exports: Record; - /** - * The loader to use for this file - */ - loader: "object"; - } - - interface OnLoadArgs { - /** - * The resolved import specifier of the module being loaded - * @example - * ```ts - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * console.log(args.path); // "hello:world" - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * ``` - */ - path: string; - /** - * The namespace of the module being loaded - */ - namespace: string; - /** - * The default loader for this file extension - */ - loader: Loader; - /** - * Defer the execution of this callback until all other modules have been parsed. - * - * @returns Promise which will be resolved when all modules have been parsed - */ - defer: () => Promise; - } - - type OnLoadResult = - | OnLoadResultSourceCode - | OnLoadResultObject - | undefined - | void; - type OnLoadCallback = ( - args: OnLoadArgs, - ) => OnLoadResult | Promise; - type OnStartCallback = () => void | Promise; - - interface OnResolveArgs { - /** - * The import specifier of the module being loaded - */ - path: string; - /** - * The module that imported the module being resolved - */ - importer: string; - /** - * The namespace of the importer. - */ - namespace: string; - /** - * The directory to perform file-based resolutions in. - */ - resolveDir: string; - /** - * The kind of import this resolve is for. - */ - kind: ImportKind; - // resolveDir: string; - // pluginData: any; - } - - interface OnResolveResult { - /** - * The destination of the import - */ - path: string; - /** - * The namespace of the destination - * It will be concatenated with `path` to form the final import specifier - * @example - * ```ts - * "foo" // "foo:bar" - * ``` - */ - namespace?: string; - external?: boolean; - } - - type OnResolveCallback = ( - args: OnResolveArgs, - ) => - | OnResolveResult - | Promise - | undefined - | null; - - type FFIFunctionCallable = Function & { - // Making a nominally typed function so that the user must get it from dlopen - readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - - interface PluginBuilder { - /** - * Register a callback which will be invoked when bundling starts. When - * using hot module reloading, this is called at the start of each - * incremental rebuild. - * - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onStart(() => { - * console.log("bundle just started!!") - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onStart(callback: OnStartCallback): this; - onBeforeParse( - constraints: PluginConstraints, - callback: { - napiModule: unknown; - symbol: string; - external?: unknown | undefined; - }, - ): this; - /** - * Register a callback to load imports with a specific import specifier - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; - /** - * Register a callback to resolve imports matching a filter and/or namespace - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onResolve({ filter: /^wat$/ }, (args) => { - * return { path: "/tmp/woah.js" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onResolve( - constraints: PluginConstraints, - callback: OnResolveCallback, - ): this; - /** - * The config object passed to `Bun.build` as is. Can be mutated. - */ - config: BuildConfig & { plugins: BunPlugin[] }; - - /** - * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules - * - * @param specifier The module specifier to register the callback for - * @param callback The function to run when the module is imported or required - * - * ### Example - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.module("hello:world", () => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * - * // sometime later - * const { foo } = await import("hello:world"); - * console.log(foo); // "bar" - * - * // or - * const { foo } = require("hello:world"); - * console.log(foo); // "bar" - * ``` - * - * @returns `this` for method chaining - */ - module( - specifier: string, - callback: () => OnLoadResult | Promise, - ): this; - } - - interface BunPlugin { - /** - * Human-readable name of the plugin - * - * In a future version of Bun, this will be used in error messages. - */ - name: string; - - /** - * The target JavaScript environment the plugin should be applied to. - * - `bun`: The default environment when using `bun run` or `bun` to load a script - * - `browser`: The plugin will be applied to browser builds - * - `node`: The plugin will be applied to Node.js builds - * - * If unspecified, it is assumed that the plugin is compatible with all targets. - * - * This field is not read by {@link Bun.plugin} - */ - target?: Target; - /** - * A function that will be called when the plugin is loaded. - * - * This function may be called in the same tick that it is registered, or it - * may be called later. It could potentially be called multiple times for - * different targets. - */ - setup( - /** - * A builder object that can be used to register plugin hooks - * @example - * ```ts - * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), - * })); - * ``` - */ - build: PluginBuilder, - ): void | Promise; - } - - /** - * Extend Bun's module resolution and loading behavior - * - * Plugins are applied in the order they are defined. - * - * Today, there are two kinds of hooks: - * - `onLoad` lets you return source code or an object that will become the module's exports - * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. - * - * Plugin hooks must define a `filter` RegExp and will only be matched if the - * import specifier contains a "." or a ":". - * - * ES Module resolution semantics mean that plugins may be initialized _after_ - * a module is resolved. You might need to load plugins at the very beginning - * of the application and then use a dynamic import to load the rest of the - * application. A future version of Bun may also support specifying plugins - * via `bunfig.toml`. - * - * @example - * A YAML loader plugin - * - * ```js - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) - * })); - * }); - * - * // You can use require() - * const {foo} = require("./file.yaml"); - * - * // Or import - * await import("./file.yaml"); - * - * ``` - */ - interface BunRegisterPlugin { - (options: T): ReturnType; - - /** - * Deactivate all plugins - * - * This prevents registered plugins from being applied to future builds. - */ - clearAll(): void; - } - - const plugin: BunRegisterPlugin; - - /** - * Is the current global scope the main thread? - */ - const isMainThread: boolean; - - /** - * Used when importing an HTML file at runtime. - * - * @example - * - * ```ts - * import app from "./index.html"; - * ``` - * - * Bun.build support for this isn't imlpemented yet. - */ - interface HTMLBundle { - index: string; - } - - interface Socket extends Disposable { - /** - * Write `data` to the socket - * - * @param data The data to write to the socket - * @param byteOffset The offset in the buffer to start writing from (defaults to 0) - * @param byteLength The number of bytes to write (defaults to the length of the buffer) - * - * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. - * - * This is unbuffered as of Bun v0.2.2. That means individual write() calls - * will be slow. In the future, Bun will buffer writes and flush them at the - * end of the tick, when the event loop is idle, or sooner if the buffer is full. - */ - write( - data: string | Bun.BufferSource, - byteOffset?: number, - byteLength?: number, - ): number; - - /** - * The data context for the socket. - */ - data: Data; - - /** - * Like {@link Socket.write} except it includes a TCP FIN packet - * - * Use it to send your last message and close the connection. - */ - end( - data?: string | Bun.BufferSource, - byteOffset?: number, - byteLength?: number, - ): number; - - /** - * Close the socket immediately - */ - end(): void; - - /** - * Keep Bun's process alive at least until this socket is closed - * - * After the socket has closed, the socket is unref'd, the process may exit, - * and this becomes a no-op - */ - ref(): void; - - /** - * Set a timeout until the socket automatically closes. - * - * To reset the timeout, call this function again. - * - * When a timeout happens, the `timeout` callback is called and the socket is closed. - */ - timeout(seconds: number): void; - - /** - * Forcefully close the socket. The other end may not receive all data, and - * the socket will be closed immediately. - * - * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to - * `0` and then calls `close(2)`. - */ - terminate(): void; - - /** - * Shutdown writes to a socket - * - * This makes the socket a half-closed socket. It can still receive data. - * - * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally - */ - shutdown(halfClose?: boolean): void; - - readonly readyState: "open" | "closing" | "closed"; - - /** - * Allow Bun's process to exit even if this socket is still open - * - * After the socket has closed, this function does nothing. - */ - unref(): void; - - /** - * Flush any buffered data to the socket - */ - flush(): void; - - /** - * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. - * - * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. - */ - reload(handler: SocketHandler): void; - - /** - * Get the server that created this socket - * - * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. - */ - readonly listener?: SocketListener; - - /** - * Remote IP address connected to the socket - */ - readonly remoteAddress: string; - - /** - * local port connected to the socket - */ - readonly localPort: number; - - /** - * This property is `true` if the peer certificate was signed by one of the CAs - * specified when creating the `Socket` instance, otherwise `false`. - */ - readonly authorized: boolean; - - /** - * String containing the selected ALPN protocol. - * Before a handshake has completed, this value is always null. - * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. - */ - readonly alpnProtocol: string | false | null; - - /** - * Disables TLS renegotiation for this `Socket` instance. Once called, attempts - * to renegotiate will trigger an `error` handler on the `Socket`. - * - * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) - */ - disableRenegotiation(): void; - - /** - * Keying material is used for validations to prevent different kind of attacks in - * network protocols, for example in the specifications of IEEE 802.1X. - * - * Example - * - * ```js - * const keyingMaterial = socket.exportKeyingMaterial( - * 128, - * 'client finished'); - * - * /* - * Example return value of keyingMaterial: - * - * - * ``` - * - * @param length number of bytes to retrieve from keying material - * @param label an application specific label, typically this will be a value from the [IANA Exporter Label - * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). - * @param context Optionally provide a context. - * @return requested bytes of the keying material - */ - exportKeyingMaterial( - length: number, - label: string, - context: Buffer, - ): Buffer; - - /** - * Returns the reason why the peer's certificate was not been verified. This - * property is set only when `socket.authorized === false`. - */ - getAuthorizationError(): Error | null; - - /** - * Returns an object representing the local certificate. The returned object has - * some properties corresponding to the fields of the certificate. - * - * If there is no local certificate, an empty object will be returned. If the - * socket has been destroyed, `null` will be returned. - */ - getCertificate(): PeerCertificate | object | null; - getX509Certificate(): X509Certificate | undefined; - - /** - * Returns an object containing information on the negotiated cipher suite. - * - * For example, a TLSv1.2 protocol with AES256-SHA cipher: - * - * ```json - * { - * "name": "AES256-SHA", - * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", - * "version": "SSLv3" - * } - * ``` - * - */ - getCipher(): CipherNameAndProtocol; - - /** - * Returns an object representing the type, name, and size of parameter of - * an ephemeral key exchange in `perfect forward secrecy` on a client - * connection. It returns an empty object when the key exchange is not - * ephemeral. As this is only supported on a client socket; `null` is returned - * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. - * - * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. - */ - getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; - - /** - * Returns an object representing the peer's certificate. If the peer does not - * provide a certificate, an empty object will be returned. If the socket has been - * destroyed, `null` will be returned. - * - * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's - * certificate. - * @return A certificate object. - */ - getPeerCertificate(): PeerCertificate; - getPeerX509Certificate(): X509Certificate; - - /** - * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. - * @since v12.11.0 - * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. - */ - getSharedSigalgs(): string[]; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. - */ - getTLSFinishedMessage(): Buffer | undefined; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so - * far. - */ - getTLSPeerFinishedMessage(): Buffer | undefined; - - /** - * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. - * - * It may be useful for debugging. - * - * See `Session Resumption` for more information. - */ - getTLSTicket(): Buffer | undefined; - - /** - * Returns a string containing the negotiated SSL/TLS protocol version of the - * current connection. The value `'unknown'` will be returned for connected - * sockets that have not completed the handshaking process. The value `null` will - * be returned for server sockets or disconnected client sockets. - * - * Protocol versions are: - * - * * `'SSLv3'` - * * `'TLSv1'` - * * `'TLSv1.1'` - * * `'TLSv1.2'` - * * `'TLSv1.3'` - * - */ - getTLSVersion(): string; - - /** - * See `Session Resumption` for more information. - * @return `true` if the session was reused, `false` otherwise. - */ - isSessionReused(): boolean; - - /** - * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. - * Returns `true` if setting the limit succeeded; `false` otherwise. - * - * Smaller fragment sizes decrease the buffering latency on the client: larger - * fragments are buffered by the TLS layer until the entire fragment is received - * and its integrity is verified; large fragments can span multiple roundtrips - * and their processing can be delayed due to packet loss or reordering. However, - * smaller fragments add extra TLS framing bytes and CPU overhead, which may - * decrease overall server throughput. - * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. - */ - setMaxSendFragment(size: number): boolean; - - /** - * Enable/disable the use of Nagle's algorithm. - * Only available for already connected sockets, will return false otherwise - * @param noDelay Default: `true` - * @returns true if is able to setNoDelay and false if it fails. - */ - setNoDelay(noDelay?: boolean): boolean; - - /** - * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. - * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. - * Only available for already connected sockets, will return false otherwise. - * - * Enabling the keep-alive functionality will set the following socket options: - * SO_KEEPALIVE=1 - * TCP_KEEPIDLE=initialDelay - * TCP_KEEPCNT=10 - * TCP_KEEPINTVL=1 - * @param enable Default: `false` - * @param initialDelay Default: `0` - * @returns true if is able to setNoDelay and false if it fails. - */ - setKeepAlive(enable?: boolean, initialDelay?: number): boolean; - - /** - * The number of bytes written to the socket. - */ - readonly bytesWritten: number; - } - - interface SocketListener extends Disposable { - stop(closeActiveConnections?: boolean): void; - ref(): void; - unref(): void; - reload(options: Pick, "socket">): void; - data: Data; - } - interface TCPSocketListener extends SocketListener { - readonly port: number; - readonly hostname: string; - } - interface UnixSocketListener extends SocketListener { - readonly unix: string; - } - - interface TCPSocket extends Socket {} - interface TLSSocket extends Socket {} - - interface BinaryTypeList { - arraybuffer: ArrayBuffer; - buffer: Buffer; - uint8array: Uint8Array; - // TODO: DataView - // dataview: DataView; - } - type BinaryType = keyof BinaryTypeList; - - interface SocketHandler< - Data = unknown, - DataBinaryType extends BinaryType = "buffer", - > { - /** - * Is called when the socket connects, or in case of TLS if no handshake is provided - * this will be called only after handshake - * @param socket - */ - open?(socket: Socket): void | Promise; - close?(socket: Socket): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - ): void | Promise; - drain?(socket: Socket): void | Promise; - - /** - * When handshake is completed, this functions is called. - * @param socket - * @param success Indicates if the server authorized despite the authorizationError. - * @param authorizationError Certificate Authorization Error or null. - */ - handshake?( - socket: Socket, - success: boolean, - authorizationError: Error | null, - ): void; - - /** - * When the socket has been shutdown from the other end, this function is - * called. This is a TCP FIN packet. - */ - end?(socket: Socket): void | Promise; - - /** - * When the socket fails to be created, this function is called. - * - * The promise returned by `Bun.connect` rejects **after** this function is - * called. - * - * When `connectError` is specified, the rejected promise will not be - * added to the promise rejection queue (so it won't be reported as an - * unhandled promise rejection, since connectError handles it). - * - * When `connectError` is not specified, the rejected promise will be added - * to the promise rejection queue. - */ - connectError?(socket: Socket, error: Error): void | Promise; - - /** - * Called when a message times out. - */ - timeout?(socket: Socket): void | Promise; - /** - * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. - * - * @default "buffer" - * - * @remarks - * This lets you select the desired binary type for the `data` callback. - * It's a small performance optimization to let you avoid creating extra - * ArrayBufferView objects when possible. - * - * Bun originally defaulted to `Uint8Array` but when dealing with network - * data, it's more useful to be able to directly read from the bytes which - * `Buffer` allows. - */ - binaryType?: BinaryType; - } - - interface SocketOptions { - socket: SocketHandler; - data?: Data; - } - // interface TCPSocketOptions extends SocketOptions { - // hostname: string; - // port: number; - // } - - interface TCPSocketListenOptions - extends SocketOptions { - hostname: string; - port: number; - tls?: TLSOptions; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface TCPSocketConnectOptions - extends SocketOptions { - hostname: string; - port: number; - tls?: boolean; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface UnixSocketOptions extends SocketOptions { - tls?: TLSOptions; - unix: string; - } - - interface FdSocketOptions extends SocketOptions { - tls?: TLSOptions; - fd: number; - } - - /** - * Create a TCP client that connects to a server - * - * @param options The options to use when creating the client - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function connect( - options: TCPSocketConnectOptions, - ): Promise>; - function connect( - options: UnixSocketOptions, - ): Promise>; - - /** - * Create a TCP server that listens on a port - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function listen( - options: TCPSocketListenOptions, - ): TCPSocketListener; - function listen( - options: UnixSocketOptions, - ): UnixSocketListener; - - namespace udp { - type Data = string | ArrayBufferView | ArrayBufferLike; - - export interface SocketHandler { - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: Socket): void | Promise; - error?( - socket: Socket, - error: Error, - ): void | Promise; - } - - export interface ConnectedSocketHandler { - data?( - socket: ConnectedSocket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: ConnectedSocket): void | Promise; - error?( - socket: ConnectedSocket, - error: Error, - ): void | Promise; - } - - export interface SocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: SocketHandler; - } - - export interface ConnectSocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: ConnectedSocketHandler; - connect: { - hostname: string; - port: number; - }; - } - - export interface BaseUDPSocket { - readonly hostname: string; - readonly port: number; - readonly address: SocketAddress; - readonly binaryType: BinaryType; - readonly closed: boolean; - ref(): void; - unref(): void; - close(): void; - } - - export interface ConnectedSocket - extends BaseUDPSocket { - readonly remoteAddress: SocketAddress; - sendMany(packets: readonly Data[]): number; - send(data: Data): boolean; - reload(handler: ConnectedSocketHandler): void; - } - - export interface Socket - extends BaseUDPSocket { - sendMany(packets: readonly (Data | string | number)[]): number; - send(data: Data, port: number, address: string): boolean; - reload(handler: SocketHandler): void; - } - } - - /** - * Create a UDP socket - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.hostname The hostname to listen on - * @param options.port The port to listen on - * @param options.binaryType The binary type to use for the socket - * @param options.connect The hostname and port to connect to - */ - export function udpSocket( - options: udp.SocketOptions, - ): Promise>; - export function udpSocket( - options: udp.ConnectSocketOptions, - ): Promise>; - - namespace SpawnOptions { - /** - * Option for stdout/stderr - */ - type Readable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number; - - /** - * Option for stdin - */ - type Writable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number - | ReadableStream - | Blob - | Response - | Request; - - interface OptionsObject< - In extends Writable = Writable, - Out extends Readable = Readable, - Err extends Readable = Readable, - > { - /** - * The current working directory of the process - * - * Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * The environment variables of the process - * - * Defaults to `process.env` as it was when the current Bun process launched. - * - * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. - */ - env?: Record; - - /** - * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. - * This overrides the `stdin`, `stdout`, and `stderr` properties. - * - * For stdin you may pass: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. - * - `number`: The process will read from the file descriptor - * - * For stdout and stdin you may pass: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default ["ignore", "pipe", "inherit"] for `spawn` - * ["ignore", "pipe", "pipe"] for `spawnSync` - */ - stdio?: [In, Out, Err]; - /** - * The file descriptor for the standard input. It may be: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`: The process will read from the buffer - * - `number`: The process will read from the file descriptor - * - * @default "ignore" - */ - stdin?: In; - /** - * The file descriptor for the standard output. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "pipe" - */ - stdout?: Out; - /** - * The file descriptor for the standard error. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "inherit" for `spawn` - * "pipe" for `spawnSync` - */ - stderr?: Err; - - /** - * Callback that runs when the {@link Subprocess} exits - * - * This is called even if the process exits with a non-zero exit code. - * - * Warning: this may run before the `Bun.spawn` function returns. - * - * A simple alternative is `await subprocess.exited`. - * - * @example - * - * ```ts - * const subprocess = spawn({ - * cmd: ["echo", "hello"], - * onExit: (subprocess, code) => { - * console.log(`Process exited with code ${code}`); - * }, - * }); - * ``` - */ - onExit?( - subprocess: Subprocess, - exitCode: number | null, - signalCode: number | null, - /** - * If an error occurred in the call to waitpid2, this will be the error. - */ - error?: ErrorLike, - ): void | Promise; - - /** - * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for - * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized - * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - * - * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, - * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. - * - * Currently, this is only compatible with processes that are other `bun` instances. - */ - ipc?( - message: any, - /** - * The {@link Subprocess} that sent the message - */ - subprocess: Subprocess, - ): void; - - /** - * The serialization format to use for IPC messages. Defaults to `"advanced"`. - * - * To communicate with Node.js processes, use `"json"`. - * - * When `ipc` is not specified, this is ignored. - */ - serialization?: "json" | "advanced"; - - /** - * If true, the subprocess will have a hidden window. - */ - windowsHide?: boolean; - - /** - * If true, no quoting or escaping of arguments is done on Windows. - */ - windowsVerbatimArguments?: boolean; - - /** - * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. - * - * One use-case for this is for applications which wrap other applications or to simulate a symlink. - * - * @default cmds[0] - */ - argv0?: string; - - /** - * An {@link AbortSignal} that can be used to abort the subprocess. - * - * This is useful for aborting a subprocess when some other part of the - * program is aborted, such as a `fetch` response. - * - * Internally, this works by calling `subprocess.kill(1)`. - * - * @example - * ```ts - * const controller = new AbortController(); - * const { signal } = controller; - * const start = performance.now(); - * const subprocess = Bun.spawn({ - * cmd: ["sleep", "100"], - * signal, - * }); - * await Bun.sleep(1); - * controller.abort(); - * await subprocess.exited; - * const end = performance.now(); - * console.log(end - start); // 1ms instead of 101ms - * ``` - */ - signal?: AbortSignal; - } - - type OptionsToSubprocess = - Opts extends OptionsObject - ? Subprocess< - // "Writable extends In" means "if In === Writable", - // aka if true that means the user didn't specify anything - Writable extends In ? "ignore" : In, - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "inherit" : Err - > - : Subprocess; - - type OptionsToSyncSubprocess = - Opts extends OptionsObject - ? SyncSubprocess< - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "pipe" : Err - > - : SyncSubprocess; - - type ReadableIO = ReadableStream | number | undefined; - - type ReadableToIO = X extends "pipe" | undefined - ? ReadableStream - : X extends BunFile | ArrayBufferView | number - ? number - : undefined; - - type ReadableToSyncIO = X extends "pipe" | undefined - ? Buffer - : undefined; - - type WritableIO = FileSink | number | undefined; - - type WritableToIO = X extends "pipe" - ? FileSink - : X extends BunFile | ArrayBufferView | Blob | Request | Response | number - ? number - : undefined; - } - - interface ResourceUsage { - /** - * The number of voluntary and involuntary context switches that the process made. - */ - contextSwitches: { - /** - * Voluntary context switches (context switches that the process initiated). - */ - voluntary: number; - /** - * Involuntary context switches (context switches initiated by the system scheduler). - */ - involuntary: number; - }; - - /** - * The amount of CPU time used by the process, in microseconds. - */ - cpuTime: { - /** - * User CPU time used by the process, in microseconds. - */ - user: number; - /** - * System CPU time used by the process, in microseconds. - */ - system: number; - /** - * Total CPU time used by the process, in microseconds. - */ - total: number; - }; - /** - * The maximum amount of resident set size (in bytes) used by the process during its lifetime. - */ - maxRSS: number; - - /** - * IPC messages sent and received by the process. - */ - messages: { - /** - * The number of IPC messages sent. - */ - sent: number; - /** - * The number of IPC messages received. - */ - received: number; - }; - /** - * The number of IO operations done by the process. - */ - ops: { - /** - * The number of input operations via the file system. - */ - in: number; - /** - * The number of output operations via the file system. - */ - out: number; - }; - /** - * The amount of shared memory that the process used. - */ - shmSize: number; - /** - * The number of signals delivered to the process. - */ - signalCount: number; - /** - * The number of times the process was swapped out of main memory. - */ - swapCount: number; - } - - /** - * A process created by {@link Bun.spawn}. - * - * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSubprocess} (any, pipe, pipe) - * - {@link WritableSubprocess} (pipe, any, any) - * - {@link PipedSubprocess} (pipe, pipe, pipe) - * - {@link NullSubprocess} (ignore, ignore, ignore) - */ - interface Subprocess< - In extends SpawnOptions.Writable = SpawnOptions.Writable, - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > extends AsyncDisposable { - readonly stdin: SpawnOptions.WritableToIO; - readonly stdout: SpawnOptions.ReadableToIO; - readonly stderr: SpawnOptions.ReadableToIO; - - /** - * This returns the same value as {@link Subprocess.stdout} - * - * It exists for compatibility with {@link ReadableStream.pipeThrough} - */ - readonly readable: SpawnOptions.ReadableToIO; - - /** - * The process ID of the child process - * @example - * ```ts - * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); - * console.log(pid); // 1234 - * ``` - */ - readonly pid: number; - /** - * The exit code of the process - * - * The promise will resolve when the process exits - */ - readonly exited: Promise; - - /** - * Synchronously get the exit code of the process - * - * If the process hasn't exited yet, this will return `null` - */ - readonly exitCode: number | null; - - /** - * Synchronously get the signal code of the process - * - * If the process never sent a signal code, this will return `null` - * - * To receive signal code changes, use the `onExit` callback. - * - * If the signal code is unknown, it will return the original signal code - * number, but that case should essentially never happen. - */ - readonly signalCode: NodeJS.Signals | null; - - /** - * Has the process exited? - */ - readonly killed: boolean; - - /** - * Kill the process - * @param exitCode The exitCode to send to the process - */ - kill(exitCode?: number | NodeJS.Signals): void; - - /** - * This method will tell Bun to wait for this process to exit after you already - * called `unref()`. - * - * Before shutting down, Bun will wait for all subprocesses to exit by default - */ - ref(): void; - - /** - * Before shutting down, Bun will wait for all subprocesses to exit by default - * - * This method will tell Bun to not wait for this process to exit before shutting down. - */ - unref(): void; - - /** - * Send a message to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option, and is another instance of `bun`. - * - * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - */ - send(message: any): void; - - /** - * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option. - */ - disconnect(): void; - - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - * - * Only available after the process has exited - * - * If the process hasn't exited yet, this will return `undefined` - */ - resourceUsage(): ResourceUsage | undefined; - } - - /** - * A process created by {@link Bun.spawnSync}. - * - * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSyncSubprocess} (pipe, pipe) - * - {@link NullSyncSubprocess} (ignore, ignore) - */ - interface SyncSubprocess< - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > { - stdout: SpawnOptions.ReadableToSyncIO; - stderr: SpawnOptions.ReadableToSyncIO; - exitCode: number; - success: boolean; - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - */ - resourceUsage: ResourceUsage; - - signalCode?: string; - } - - /** - * Spawn a new process - * - * ```js - * const subprocess = Bun.spawn({ - * cmd: ["echo", "hello"], - * stdout: "pipe", - * }); - * const text = await readableStreamToText(subprocess.stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmd: string[]; // to support dynamically constructed commands - }, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawn(["echo", "hello"]); - * const text = await readableStreamToText(stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync({ - * cmd: ["echo", "hello"], - * }); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); - * ``` - */ - cmd: string[]; - - onExit?: never; - }, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** - * Synchronously spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync(["echo", "hello"]); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ - type ReadableSubprocess = Subprocess; - /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ - type WritableSubprocess = Subprocess<"pipe", any, any>; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ - type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ - type NullSubprocess = Subprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ - type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ - type NullSyncSubprocess = SyncSubprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - - // Blocked on https://github.com/oven-sh/bun/issues/8329 - // /** - // * - // * Count the visible width of a string, as it would be displayed in a terminal. - // * - // * By default, strips ANSI escape codes before measuring the string. This is - // * because ANSI escape codes are not visible characters. If passed a non-string, - // * it will return 0. - // * - // * @param str The string to measure - // * @param options - // */ - // function stringWidth( - // str: string, - // options?: { - // /** - // * Whether to include ANSI escape codes in the width calculation - // * - // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. - // * @default false - // */ - // countAnsiEscapeCodes?: boolean; - // }, - // ): number; - - class FileSystemRouter { - /** - * Create a new {@link FileSystemRouter}. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: process.cwd() + "/pages", - * style: "nextjs", - * }); - * - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} - * ``` - * @param options The options to use when creating the router - * @param options.dir The root directory containing the files to route - * @param options.style The style of router to use (only "nextjs" supported - * for now) - */ - constructor(options: { - /** - * The root directory containing the files to route - * - * There is no default value for this option. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: - */ - dir: string; - style: "nextjs"; - - /** The base path to use when routing */ - assetPrefix?: string; - origin?: string; - /** Limit the pages to those with particular file extensions. */ - fileExtensions?: string[]; - }); - - // todo: URL - match(input: string | Request | Response): MatchedRoute | null; - - readonly assetPrefix: string; - readonly origin: string; - readonly style: string; - readonly routes: Record; - - reload(): void; - } - - interface MatchedRoute { - /** - * A map of the parameters from the route - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: "/path/to/files", - * style: "nextjs", - * }); - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params.year); // "2020" - * console.log(params.month); // "01" - * console.log(params.day); // "01" - * console.log(params.slug); // "hello-world" - * ``` - */ - readonly params: Record; - readonly filePath: string; - readonly pathname: string; - readonly query: Record; - readonly name: string; - readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; - readonly src: string; - } - - /** - * The current version of Bun - * @example - * "0.2.0" - */ - const version: string; - - /** - * The current version of Bun with the shortened commit sha of the build - * @example "v1.1.30 (d09df1af)" - */ - const version_with_sha: string; - - /** - * The git sha at the time the currently-running version of Bun was compiled - * @example - * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" - */ - const revision: string; - - /** - * Find the index of a newline character in potentially ill-formed UTF-8 text. - * - * This is sort of like readline() except without the IO. - */ - function indexOfLine( - buffer: ArrayBufferView | ArrayBufferLike, - offset?: number, - ): number; - - interface GlobScanOptions { - /** - * The root directory to start matching from. Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * Allow patterns to match entries that begin with a period (`.`). - * - * @default false - */ - dot?: boolean; - - /** - * Return the absolute path for entries. - * - * @default false - */ - absolute?: boolean; - - /** - * Indicates whether to traverse descendants of symbolic link directories. - * - * @default false - */ - followSymlinks?: boolean; - - /** - * Throw an error when symbolic link is broken - * - * @default false - */ - throwErrorOnBrokenSymlink?: boolean; - - /** - * Return only files. - * - * @default true - */ - onlyFiles?: boolean; - } - - /** - * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). - * - * The supported pattern syntax for is: - * - * - `?` - * Matches any single character. - * - `*` - * Matches zero or more characters, except for path separators ('/' or '\'). - * - `**` - * Matches zero or more characters, including path separators. - * Must match a complete path segment, i.e. followed by a path separator or - * at the end of the pattern. - * - `[ab]` - * Matches one of the characters contained in the brackets. - * Character ranges (e.g. "[a-z]") are also supported. - * Use "[!ab]" or "[^ab]" to match any character *except* those contained - * in the brackets. - * - `{a,b}` - * Match one of the patterns contained in the braces. - * Any of the wildcards listed above can be used in the sub patterns. - * Braces may be nested up to 10 levels deep. - * - `!` - * Negates the result when at the start of the pattern. - * Multiple "!" characters negate the pattern multiple times. - * - `\` - * Used to escape any of the special characters above. - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - */ - export class Glob { - constructor(pattern: string); - - /** - * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for await (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scan( - optionsOrCwd?: string | GlobScanOptions, - ): AsyncIterableIterator; - - /** - * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; - - /** - * Match the glob against a string - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * expect(glob.match('foo.ts')).toBeTrue(); - * ``` - */ - match(str: string): boolean; - } - - /** - * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. - * - * When the same timestamp is used multiple times, a monotonically increasing - * counter is appended to allow sorting. The final 8 bytes are - * cryptographically random. When the timestamp changes, the counter resets to - * a psuedo-random integer. - * - * @param encoding "hex" | "base64" | "base64url" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - * - * @example - * ```js - * import { randomUUIDv7 } from "bun"; - * const array = [ - * randomUUIDv7(), - * randomUUIDv7(), - * randomUUIDv7(), - * ] - * [ - * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", - * "0192ce07-8c4f-7d67-805f-0f71581b5622", - * "0192ce07-8c4f-7d68-8170-6816e4451a58" - * ] - * ``` - */ - function randomUUIDv7( - /** - * @default "hex" - */ - encoding?: "hex" | "base64" | "base64url", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): string; - - /** - * Generate a UUIDv7 as a Buffer - * - * @param encoding "buffer" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - */ - function randomUUIDv7( - encoding: "buffer", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): Buffer; - - /** - * Types for `bun.lock` - */ - type BunLockFile = { - lockfileVersion: 0 | 1; - workspaces: { - [workspace: string]: BunLockFileWorkspacePackage; - }; - overrides?: Record; - patchedDependencies?: Record; - trustedDependencies?: string[]; - - /** - * ``` - * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } - * - * // first index is resolution for each type of package - * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] - * symlink -> [ "name@link:path", INFO ] - * folder -> [ "name@file:path", INFO ] - * workspace -> [ "name@workspace:path" ] // workspace is only path - * tarball -> [ "name@tarball", INFO ] - * root -> [ "name@root:", { bin, binDir } ] - * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] - * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] - * ``` - * */ - packages: { - [pkg: string]: BunLockFilePackageArray; - }; - }; - - type BunLockFileBasePackageInfo = { - dependencies?: Record; - devDependencies?: Record; - optionalDependencies?: Record; - peerDependencies?: Record; - optionalPeers?: string[]; - bin?: string | Record; - binDir?: string; - }; - - type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { - name?: string; - version?: string; - }; - - type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { - os?: string | string[]; - cpu?: string | string[]; - bundled?: true; - }; - - /** @see {@link BunLockFile.packages} for more info */ - type BunLockFilePackageArray = - /** npm */ - | [ - pkg: string, - registry: string, - info: BunLockFilePackageInfo, - integrity: string, - ] - /** symlink, folder, tarball */ - | [pkg: string, info: BunLockFilePackageInfo] - /** workspace */ - | [pkg: string] - /** git, github */ - | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] - /** root */ - | [pkg: string, info: Pick]; + */ + function build(config: BuildConfig): Promise; + /** + * A status that represents the outcome of a sent message. + * + * - if **0**, the message was **dropped**. + * - if **-1**, there is **backpressure** of messages. + * - if **>0**, it represents the **number of bytes sent**. + * + * @example + * ```js + * const status = ws.send("Hello!"); + * if (status === 0) { + * console.log("Message was dropped"); + * } else if (status === -1) { + * console.log("Backpressure was applied"); + * } else { + * console.log(`Success! Sent ${status} bytes`); + * } + * ``` + */ + type ServerWebSocketSendStatus = number; + + /** + * A state that represents if a WebSocket is connected. + * + * - `WebSocket.CONNECTING` is `0`, the connection is pending. + * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. + * - `WebSocket.CLOSING` is `2`, the connection is closing. + * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState + */ + type WebSocketReadyState = 0 | 1 | 2 | 3; + + /** + * A fast WebSocket designed for servers. + * + * Features: + * - **Message compression** - Messages can be compressed + * - **Backpressure** - If the client is not ready to receive data, the server will tell you. + * - **Dropped messages** - If the client cannot receive data, the server will tell you. + * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics + * + * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. + * + * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). + * + * @example + * import { serve } from "bun"; + * + * serve({ + * websocket: { + * open(ws) { + * console.log("Connected", ws.remoteAddress); + * }, + * message(ws, data) { + * console.log("Received", data); + * ws.send(data); + * }, + * close(ws, code, reason) { + * console.log("Disconnected", code, reason); + * }, + * } + * }); + */ + interface ServerWebSocket { + /** + * Sends a message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + * ws.send(new Uint8Array([1, 2, 3, 4])); + */ + send(data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a text message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + */ + sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send(new TextEncoder().encode("Hello!")); + * ws.send(new Uint8Array([1, 2, 3, 4]), true); + */ + sendBinary(data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Closes the connection. + * + * Here is a list of close codes: + * - `1000` means "normal closure" **(default)** + * - `1009` means a message was too big and was rejected + * - `1011` means the server encountered an error + * - `1012` means the server is restarting + * - `1013` means the server is too busy or the client is rate-limited + * - `4000` through `4999` are reserved for applications (you can use it!) + * + * To close the connection abruptly, use `terminate()`. + * + * @param code The close code to send + * @param reason The close reason to send + */ + close(code?: number, reason?: string): void; + + /** + * Abruptly close the connection. + * + * To gracefully close the connection, use `close()`. + */ + terminate(): void; + + /** + * Sends a ping. + * + * @param data The data to send + */ + ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a pong. + * + * @param data The data to send + */ + pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); + */ + publish(topic: string, data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a text message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + */ + publishText(topic: string, data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", new TextEncoder().encode("Hello!")); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); + */ + publishBinary(topic: string, data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Subscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + */ + subscribe(topic: string): void; + + /** + * Unsubscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.unsubscribe("chat"); + */ + unsubscribe(topic: string): void; + + /** + * Is the client subscribed to a topic? + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + * console.log(ws.isSubscribed("chat")); // true + */ + isSubscribed(topic: string): boolean; + + /** + * Batches `send()` and `publish()` operations, which makes it faster to send data. + * + * The `message`, `open`, and `drain` callbacks are automatically corked, so + * you only need to call this if you are sending messages outside of those + * callbacks or in async functions. + * + * @param callback The callback to run. + * @example + * ws.cork((ctx) => { + * ctx.send("These messages"); + * ctx.sendText("are sent"); + * ctx.sendBinary(new TextEncoder().encode("together!")); + * }); + */ + cork(callback: (ws: ServerWebSocket) => T): T; + + /** + * The IP address of the client. + * + * @example + * console.log(socket.remoteAddress); // "127.0.0.1" + */ + readonly remoteAddress: string; + + /** + * The ready state of the client. + * + * - if `0`, the client is connecting. + * - if `1`, the client is connected. + * - if `2`, the client is closing. + * - if `3`, the client is closed. + * + * @example + * console.log(socket.readyState); // 1 + */ + readonly readyState: WebSocketReadyState; + + /** + * Sets how binary data is returned in events. + * + * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** + * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. + * - if `uint8array`, binary data is returned as `Uint8Array` objects. + * + * @example + * let ws: WebSocket; + * ws.binaryType = "uint8array"; + * ws.addEventListener("message", ({ data }) => { + * console.log(data instanceof Uint8Array); // true + * }); + */ + binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; + + /** + * Custom data that you can assign to a client, can be read and written at any time. + * + * @example + * import { serve } from "bun"; + * + * serve({ + * fetch(request, server) { + * const data = { + * accessToken: request.headers.get("Authorization"), + * }; + * if (server.upgrade(request, { data })) { + * return; + * } + * return new Response(); + * }, + * websocket: { + * open(ws) { + * console.log(ws.data.accessToken); + * } + * } + * }); + */ + data: T; + + getBufferedAmount(): number; + } + + /** + * Compression options for WebSocket messages. + */ + type WebSocketCompressor = + | "disable" + | "shared" + | "dedicated" + | "3KB" + | "4KB" + | "8KB" + | "16KB" + | "32KB" + | "64KB" + | "128KB" + | "256KB"; + + /** + * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} + * + * @example + * ```ts + * import { websocket, serve } from "bun"; + * + * serve<{name: string}>({ + * port: 3000, + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log(`${ws.data.name}: ${message}`); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req, { + * data: { + * name: new URL(req.url).searchParams.get("name"), + * }, + * }); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * return; + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + */ + interface WebSocketHandler { + /** + * Called when the server receives an incoming message. + * + * If the message is not a `string`, its type is based on the value of `binaryType`. + * - if `nodebuffer`, then the message is a `Buffer`. + * - if `arraybuffer`, then the message is an `ArrayBuffer`. + * - if `uint8array`, then the message is a `Uint8Array`. + * + * @param ws The websocket that sent the message + * @param message The message received + */ + message(ws: ServerWebSocket, message: string | Buffer): void | Promise; + + /** + * Called when a connection is opened. + * + * @param ws The websocket that was opened + */ + open?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection was previously under backpressure, + * meaning it had too many queued messages, but is now ready to receive more data. + * + * @param ws The websocket that is ready for more data + */ + drain?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection is closed. + * + * @param ws The websocket that was closed + * @param code The close code + * @param message The close message + */ + close?(ws: ServerWebSocket, code: number, reason: string): void | Promise; + + /** + * Called when a ping is sent. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + ping?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Called when a pong is received. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + pong?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Sets the maximum size of messages in bytes. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + maxPayloadLength?: number; + + /** + * Sets the maximum number of bytes that can be buffered on a single connection. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + backpressureLimit?: number; + + /** + * Sets if the connection should be closed if `backpressureLimit` is reached. + * + * Default is `false`. + */ + closeOnBackpressureLimit?: boolean; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to no messages or pings. + * + * Default is 2 minutes, or `120` in seconds. + */ + idleTimeout?: number; + + /** + * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? + * + * Default is `false`. + */ + publishToSelf?: boolean; + + /** + * Should the server automatically send and respond to pings to clients? + * + * Default is `true`. + */ + sendPings?: boolean; + + /** + * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. + * + * Default is `false`. + */ + perMessageDeflate?: + | boolean + | { + /** + * Sets the compression level. + */ + compress?: WebSocketCompressor | boolean; + /** + * Sets the decompression level. + */ + decompress?: WebSocketCompressor | boolean; + }; + } + + namespace RouterTypes { + type ExtractRouteParams = T extends `${string}:${infer Param}/${infer Rest}` + ? { [K in Param]: string } & ExtractRouteParams + : T extends `${string}:${infer Param}` + ? { [K in Param]: string } + : T extends `${string}*` + ? {} + : {}; + + type RouteHandler = (req: BunRequest, server: Server) => Response | Promise; + + type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; + + type RouteHandlerObject = { + [K in HTTPMethod]?: RouteHandler; + }; + + type RouteValue = Response | false | RouteHandler | RouteHandlerObject; + } + + interface BunRequest extends Request { + params: RouterTypes.ExtractRouteParams; + } + + interface GenericServeOptions { + /** + * What URI should be used to make {@link Request.url} absolute? + * + * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one + * + * @example + * ```js + * "http://my-app.com" + * ``` + * + * @example + * ```js + * "https://wongmjane.com/" + * ``` + * + * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. + * + * @example + * "http://localhost:3000" + */ + // baseURI?: string; + + /** + * What is the maximum size of a request body? (in bytes) + * @default 1024 * 1024 * 128 // 128MB + */ + maxRequestBodySize?: number; + + /** + * Render contextual errors? This enables bun's error page + * @default process.env.NODE_ENV !== 'production' + */ + development?: + | boolean + | { + /** + * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) + * + * @default true if process.env.NODE_ENV !== 'production' + * + */ + hmr?: boolean; + }; + + error?: (this: Server, error: ErrorLike) => Response | Promise | undefined | Promise; + + /** + * Uniquely identify a server instance with an ID + * + * ### When bun is started with the `--hot` flag + * + * This string will be used to hot reload the server without interrupting + * pending requests or websockets. If not provided, a value will be + * generated. To disable hot reloading, set this value to `null`. + * + * ### When bun is not started with the `--hot` flag + * + * This string will currently do nothing. But in the future it could be useful for logs or metrics. + */ + id?: string | null; + } + + interface ServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * Whether the `SO_REUSEPORT` flag should be set. + * + * This allows multiple processes to bind to the same port, which is useful for load balancing. + * + * @default false + */ + reusePort?: boolean; + + /** + * Whether the `IPV6_V6ONLY` flag should be set. + * @default false + */ + ipv6Only?: boolean; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix?: never; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to inactivity. + * + * Default is `10` seconds. + */ + idleTimeout?: number; + + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | Promise; + } + + interface UnixServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | Promise; + } + + interface WebSocketServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | void | Promise; + } + + interface UnixWebSocketServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | undefined | Promise; + } + + interface TLSWebSocketServeOptions + extends WebSocketServeOptions, + TLSOptionsAsDeprecated { + unix?: never; + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSWebSocketServeOptions + extends UnixWebSocketServeOptions, + TLSOptionsAsDeprecated { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + tls?: TLSOptions | TLSOptions[]; + } + + interface ErrorLike extends Error { + code?: string; + errno?: number; + syscall?: string; + } + + interface TLSOptions { + /** + * Passphrase for the TLS key + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: string | Buffer | BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: string | Buffer | BunFile | Array | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: string | Buffer | BunFile | Array | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + // Note for contributors: TLSOptionsAsDeprecated should be considered immutable + // and new TLS option keys should only be supported on the `.tls` property (which comes + // from the TLSOptions interface above). + /** + * This exists because Bun.serve() extends the TLSOptions object, but + * they're now considered deprecated. You should be passing the + * options on `.tls` instead. + * + * @example + * ```ts + * //// OLD //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * passphrase: "secret", + * }); + * + * //// NEW //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * tls: { + * passphrase: "secret", + * }, + * }); + * ``` + */ + interface TLSOptionsAsDeprecated { + /** + * Passphrase for the TLS key + * + * @deprecated Use `.tls.passphrase` instead + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + * + * @deprecated Use `.tls.dhParamsFile` instead + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + * + * @deprecated Use `.tls.serverName` instead + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + * + * @deprecated Use `.tls.lowMemoryMode` instead + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + * + * @deprecated Use `.tls.rejectUnauthorized` instead + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + * + * @deprecated Use `.tls.requestCert` instead + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + * + * @deprecated Use `.tls.ca` instead + */ + ca?: string | Buffer | BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + * + * @deprecated Use `.tls.cert` instead + */ + cert?: string | Buffer | BunFile | Array | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + * + * @deprecated Use `.tls.key` instead + */ + key?: string | Buffer | BunFile | Array | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + * + * @deprecated `Use .tls.secureOptions` instead + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSServeOptions extends UnixServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface SocketAddress { + /** + * The IP address of the client. + */ + address: string; + /** + * The port of the client. + */ + port: number; + /** + * The IP family ("IPv4" or "IPv6"). + */ + family: "IPv4" | "IPv6"; + } + + /** + * HTTP & HTTPS Server + * + * To start the server, see {@link serve} + * + * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. + * That means starting a new server allocates about 500 KB of memory. Try to + * avoid starting and stopping the server often (unless it's a new instance of bun). + * + * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. + */ + interface Server extends Disposable { + /** + * Stop listening to prevent new connections from being accepted. + * + * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. + * + * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. + * @default false + */ + stop(closeActiveConnections?: boolean): Promise; + + /** + * Update the `fetch` and `error` handlers without restarting the server. + * + * This is useful if you want to change the behavior of your server without + * restarting it or for hot reloading. + * + * @example + * + * ```js + * // create the server + * const server = Bun.serve({ + * fetch(request) { + * return new Response("Hello World v1") + * } + * }); + * + * // Update the server to return a different response + * server.reload({ + * fetch(request) { + * return new Response("Hello World v2") + * } + * }); + * ``` + * + * Passing other options such as `port` or `hostname` won't do anything. + */ + reload }>( + options: ( + | (Omit & { + routes: R; + fetch?: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | (Omit & { + routes?: never; + fetch: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. + */ + static?: R; + }, + ): Server; + + /** + * Mock the fetch handler for a running server. + * + * This feature is not fully implemented yet. It doesn't normalize URLs + * consistently in all cases and it doesn't yet call the `error` handler + * consistently. This needs to be fixed + */ + fetch(request: Request | string): Response | Promise; + + /** + * Upgrade a {@link Request} to a {@link ServerWebSocket} + * + * @param request The {@link Request} to upgrade + * @param options Pass headers or attach data to the {@link ServerWebSocket} + * + * @returns `true` if the upgrade was successful and `false` if it failed + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * What you pass to `data` is available on the {@link ServerWebSocket.data} property + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + upgrade( + request: Request, + options?: { + /** + * Send any additional headers while upgrading, like cookies + */ + headers?: Bun.HeadersInit; + /** + * This value is passed to the {@link ServerWebSocket.data} property + */ + data?: T; + }, + ): boolean; + + /** + * Send a message to all connected {@link ServerWebSocket} subscribed to a topic + * + * @param topic The topic to publish to + * @param data The data to send + * @param compress Should the data be compressed? Ignored if the client does not support compression. + * + * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. + * + * @example + * + * ```js + * server.publish("chat", "Hello World"); + * ``` + * + * @example + * ```js + * server.publish("chat", new Uint8Array([1, 2, 3, 4])); + * ``` + * + * @example + * ```js + * server.publish("chat", new ArrayBuffer(4), true); + * ``` + * + * @example + * ```js + * server.publish("chat", new DataView(new ArrayBuffer(4))); + * ``` + */ + publish( + topic: string, + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * A count of connections subscribed to a given topic + * + * This operation will loop through each topic internally to get the count. + * + * @param topic the websocket topic to check how many subscribers are connected to + * @returns the number of subscribers + */ + subscriberCount(topic: string): number; + + /** + * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * return new Response(server.requestIP(request)); + * } + * } + * ``` + */ + requestIP(request: Request): SocketAddress | null; + + /** + * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * server.timeout(request, 60); + * await Bun.sleep(30000); + * return new Response("30 seconds have passed"); + * } + * } + * ``` + */ + timeout(request: Request, seconds: number): void; + /** + * Undo a call to {@link Server.unref} + * + * If the Server has already been stopped, this does nothing. + * + * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. + */ + ref(): void; + + /** + * Don't keep the process alive if this server is the only thing left. + * Active connections may continue to keep the process alive. + * + * By default, the server is ref'd. + * + * To prevent new connections from being accepted, use {@link Server.stop} + */ + unref(): void; + + /** + * How many requests are in-flight right now? + */ + readonly pendingRequests: number; + + /** + * How many {@link ServerWebSocket}s are in-flight right now? + */ + readonly pendingWebSockets: number; + + readonly url: URL; + + readonly port: number; + /** + * The hostname the server is listening on. Does not include the port + * @example + * ```js + * "localhost" + * ``` + */ + readonly hostname: string; + /** + * Is the server running in development mode? + * + * In development mode, `Bun.serve()` returns rendered error messages with + * stack traces instead of a generic 500 error. This makes debugging easier, + * but development mode shouldn't be used in production or you will risk + * leaking sensitive information. + */ + readonly development: boolean; + + /** + * An identifier of the server instance + * + * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. + * + * When bun is not started with the `--hot` flag, this ID is currently unused. + */ + readonly id: string; + } + + type Serve = + | ServeOptions + | TLSServeOptions + | UnixServeOptions + | UnixTLSServeOptions + | WebSocketServeOptions + | TLSWebSocketServeOptions + | UnixWebSocketServeOptions + | UnixTLSWebSocketServeOptions; + + /** + Bun.serve provides a high-performance HTTP server with built-in routing support. + It enables both function-based and object-based route handlers with type-safe + parameters and method-specific handling. + + @example Basic Usage + ```ts + Bun.serve({ + port: 3000, + fetch(req) { + return new Response("Hello World"); + } + }); + ``` + + @example Route-based Handlers + ```ts + Bun.serve({ + routes: { + // Static responses + "/": new Response("Home page"), + + // Function handlers with type-safe parameters + "/users/:id": (req) => { + // req.params.id is typed as string + return new Response(`User ${req.params.id}`); + }, + + // Method-specific handlers + "/api/posts": { + GET: () => new Response("Get posts"), + POST: async (req) => { + const body = await req.json(); + return new Response("Created post"); + }, + DELETE: (req) => new Response("Deleted post") + }, + + // Wildcard routes + "/static/*": (req) => { + // Handle any path under /static/ + return new Response("Static file"); + }, + + // Disable route (fall through to fetch handler) + "/api/legacy": false + }, + + // Fallback handler for unmatched routes + fetch(req) { + return new Response("Not Found", { status: 404 }); + } + }); + ``` + + @example Path Parameters + ```ts + Bun.serve({ + routes: { + // Single parameter + "/users/:id": (req: BunRequest<"/users/:id">) => { + return new Response(`User ID: ${req.params.id}`); + }, + + // Multiple parameters + "/posts/:postId/comments/:commentId": ( + req: BunRequest<"/posts/:postId/comments/:commentId"> + ) => { + return new Response(JSON.stringify(req.params)); + // Output: {"postId": "123", "commentId": "456"} + } + } + }); + ``` + + @example Route Precedence + ```ts + // Routes are matched in the following order: + // 1. Exact static routes ("/about") + // 2. Parameter routes ("/users/:id") + // 3. Wildcard routes ("/api/*") + + Bun.serve({ + routes: { + "/api/users": () => new Response("Users list"), + "/api/users/:id": (req) => new Response(`User ${req.params.id}`), + "/api/*": () => new Response("API catchall"), + "/*": () => new Response("Root catchall") + } + }); + ``` + + @example Error Handling + ```ts + Bun.serve({ + routes: { + "/error": () => { + throw new Error("Something went wrong"); + } + }, + error(error) { + // Custom error handler + console.error(error); + return new Response(`Error: ${error.message}`, { + status: 500 + }); + } + }); + ``` + + @example Server Lifecycle + ```ts + const server = Bun.serve({ + // Server config... + }); + + // Update routes at runtime + server.reload({ + routes: { + "/": () => new Response("Updated route") + } + }); + + // Stop the server + server.stop(); + ``` + + @example Development Mode + ```ts + Bun.serve({ + development: true, // Enable hot reloading + routes: { + // Routes will auto-reload on changes + } + }); + ``` + + @example Type-Safe Request Handling + ```ts + type Post = { + id: string; + title: string; + }; + + Bun.serve({ + routes: { + "/api/posts/:id": async ( + req: BunRequest<"/api/posts/:id"> + ) => { + if (req.method === "POST") { + const body: Post = await req.json(); + return Response.json(body); + } + return new Response("Method not allowed", { + status: 405 + }); + } + } + }); + ``` + @param options - Server configuration options + @param options.routes - Route definitions mapping paths to handlers + */ + function serve }>( + options: ( + | (DistributedOmit & { + routes: R; + fetch?: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | (DistributedOmit & { + routes?: never; + fetch: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for a while though. + */ + static?: R; + }, + ): Server; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * - `type` is auto-set based on the file extension when possible + * + * @example + * ```js + * const file = Bun.file("./hello.json"); + * console.log(file.type); // "application/json" + * console.log(await file.json()); // { hello: "world" } + * ``` + * + * @example + * ```js + * await Bun.write( + * Bun.file("./hello.txt"), + * "Hello, world!" + * ); + * ``` + * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: string | URL, options?: BlobPropertyBag): BunFile; + + /** + * A list of files embedded into the standalone executable. Lexigraphically sorted by name. + * + * If the process is not a standalone executable, this returns an empty array. + */ + const embeddedFiles: ReadonlyArray; + + /** + * `Blob` that leverages the fastest system calls available to operate on files. + * + * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. + * + * `Blob.size` will not be valid until the contents of the file are read at least once. + * `Blob.type` will have a default set based on the file extension + * + * @example + * ```js + * const file = Bun.file(new TextEncoder.encode("./hello.json")); + * console.log(file.type); // "application/json" + * ``` + * + * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * + * @example + * ```js + * const file = Bun.file(fd); + * ``` + * + * @param fileDescriptor The file descriptor of the file + */ + // tslint:disable-next-line:unified-signatures + function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; + + /** + * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. + * + * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. + */ + function allocUnsafe(size: number): Uint8Array; + + interface BunInspectOptions { + colors?: boolean; + depth?: number; + sorted?: boolean; + compact?: boolean; + } + + /** + * Pretty-print an object the same as {@link console.log} to a `string` + * + * Supports JSX + * + * @param args + */ + function inspect(arg: any, options?: BunInspectOptions): string; + namespace inspect { + /** + * That can be used to declare custom inspect functions. + */ + const custom: typeof import("util").inspect.custom; + + /** + * Pretty-print an object or array as a table + * + * Like {@link console.table}, except it returns a string + */ + function table(tabularData: object | unknown[], properties?: string[], options?: { colors?: boolean }): string; + function table(tabularData: object | unknown[], options?: { colors?: boolean }): string; + } + + interface MMapOptions { + /** + * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. + */ + sync?: boolean; + /** + * Allow other processes to see results instantly? + * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. + * @default true + */ + shared?: boolean; + } + /** + * Open a file as a live-updating `Uint8Array` without copying memory + * - Writing to the array writes to the file. + * - Reading from the array reads from the file. + * + * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. + * + * --- + * + * This API inherently has some rough edges: + * - It does not support empty files. It will throw a `SystemError` with `EINVAL` + * - Usage on shared/networked filesystems is discouraged. It will be very slow. + * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. + * + * --- + * + * To close the file, set the array to `null` and it will be garbage collected eventually. + */ + function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; + + /** Write to stdout */ + const stdout: BunFile; + /** Write to stderr */ + const stderr: BunFile; + /** + * Read from stdin + * + * This is read-only + */ + const stdin: BunFile; + + type StringLike = string | { toString(): string }; + + type ColorInput = + | { r: number; g: number; b: number; a?: number } + | [number, number, number] + | [number, number, number, number] + | Uint8Array + | Uint8ClampedArray + | Float32Array + | Float64Array + | string + | number + | { toString(): string }; + + function color( + input: ColorInput, + outputFormat?: /** + * True color ANSI color string, for use in terminals + * @example \x1b[38;2;100;200;200m + */ + | "ansi" + | "ansi-16" + | "ansi-16m" + /** + * 256 color ANSI color string, for use in terminals which don't support true color + * + * Tries to match closest 24-bit color to 256 color palette + */ + | "ansi-256" + /** + * Picks the format that produces the shortest output + */ + | "css" + /** + * Lowercase hex color string without alpha + * @example #ff9800 + */ + | "hex" + /** + * Uppercase hex color string without alpha + * @example #FF9800 + */ + | "HEX" + /** + * @example hsl(35.764706, 1, 0.5) + */ + | "hsl" + /** + * @example lab(0.72732764, 33.938198, -25.311619) + */ + | "lab" + /** + * @example 16750592 + */ + | "number" + /** + * RGB color string without alpha + * @example rgb(255, 152, 0) + */ + | "rgb" + /** + * RGB color string with alpha + * @example rgba(255, 152, 0, 1) + */ + | "rgba", + ): string | null; + + function color( + input: ColorInput, + /** + * An array of numbers representing the RGB color + * @example [100, 200, 200] + */ + outputFormat: "[rgb]", + ): [number, number, number] | null; + function color( + input: ColorInput, + /** + * An array of numbers representing the RGBA color + * @example [100, 200, 200, 255] + */ + outputFormat: "[rgba]", + ): [number, number, number, number] | null; + function color( + input: ColorInput, + /** + * An object representing the RGB color + * @example { r: 100, g: 200, b: 200 } + */ + outputFormat: "{rgb}", + ): { r: number; g: number; b: number } | null; + function color( + input: ColorInput, + /** + * An object representing the RGBA color + * @example { r: 100, g: 200, b: 200, a: 0.5 } + */ + outputFormat: "{rgba}", + ): { r: number; g: number; b: number; a: number } | null; + function color(input: ColorInput, outputFormat: "number"): number | null; + + interface Semver { + /** + * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. + */ + satisfies(version: StringLike, range: StringLike): boolean; + + /** + * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. + * Throws an error if either version is invalid. + */ + order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; + } + var semver: Semver; + + interface Unsafe { + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. + * + * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; + + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` + * + * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + // tslint:disable-next-line:unified-signatures + arrayBufferToString(buffer: Uint16Array): string; + + /** Mock bun's segfault handler. You probably don't want to use this */ + segfault(): void; + + /** + * Force the garbage collector to run extremely often, + * especially inside `bun:test`. + * + * - `0`: default, disable + * - `1`: asynchronously call the garbage collector more often + * - `2`: synchronously call the garbage collector more often. + * + * This is a global setting. It's useful for debugging seemingly random crashes. + * + * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. + * + * @param level + * @returns The previous level + */ + gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; + } + const unsafe: Unsafe; + + type DigestEncoding = "utf8" | "ucs2" | "utf16le" | "latin1" | "ascii" | "base64" | "base64url" | "hex"; + + /** + * Are ANSI colors enabled for stdin and stdout? + * + * Used for {@link console.log} + */ + const enableANSIColors: boolean; + + /** + * What script launched bun? + * + * Absolute file path + * + * @example "/never-gonna-give-you-up.js" + */ + const main: string; + + /** + * Manually trigger the garbage collector + * + * This does two things: + * 1. It tells JavaScriptCore to run the garbage collector + * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. + * + * @param force Synchronously run the garbage collector + */ + function gc(force: boolean): void; + + /** + * JavaScriptCore engine's internal heap snapshot + * + * I don't know how to make this something Chrome or Safari can read. + * + * If you have any ideas, please file an issue https://github.com/oven-sh/bun + */ + interface HeapSnapshot { + /** 2 */ + version: number; + + /** "Inspector" */ + type: string; + + nodes: number[]; + + nodeClassNames: string[]; + edges: number[]; + edgeTypes: string[]; + edgeNames: string[]; + } + + /** + * Returns the number of nanoseconds since the process was started. + * + * This function uses a high-resolution monotonic system timer to provide precise time measurements. + * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), + * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). + * + * Due to this limitation, while the internal counter may continue beyond this point, + * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond + * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but + * with reduced precision, which might affect time calculations and comparisons in long-running applications. + * + * @returns {number} The number of nanoseconds since the process was started, with precise values up to + * Number.MAX_SAFE_INTEGER. + */ + function nanoseconds(): number; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector + */ + function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code + * + * This is a JSON string that can be saved to a file. + * ```ts + * const snapshot = Bun.generateHeapSnapshot("v8"); + * await Bun.write("heap.heapsnapshot", snapshot); + * ``` + */ + function generateHeapSnapshot(format: "v8"): string; + + /** + * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. + */ + function shrink(): void; + + /** + * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` + * + * @param path path to open + */ + function openInEditor(path: string, options?: EditorOptions): void; + + var fetch: typeof globalThis.fetch & { + preconnect(url: string): void; + }; + + interface EditorOptions { + editor?: "vscode" | "subl"; + line?: number; + column?: number; + } + + /** + * This class only exists in types + */ + abstract class CryptoHashInterface { + /** + * Update the hash with data + * + * @param data + */ + update(data: Bun.BlobOrStringOrBuffer): T; + + /** + * Finalize the hash + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash(input: Bun.BlobOrStringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash(input: Bun.BlobOrStringOrBuffer, encoding: DigestEncoding): string; + } + + type SupportedCryptoAlgorithms = + | "blake2b256" + | "blake2b512" + | "md4" + | "md5" + | "ripemd160" + | "sha1" + | "sha224" + | "sha256" + | "sha384" + | "sha512" + | "sha512-224" + | "sha512-256" + | "sha3-224" + | "sha3-256" + | "sha3-384" + | "sha3-512" + | "shake128" + | "shake256"; + + /** + * Hardware-accelerated cryptographic hash functions + * + * Used for `crypto.createHash()` + */ + class CryptoHasher { + /** + * The algorithm chosen to hash the data + */ + readonly algorithm: SupportedCryptoAlgorithms; + + /** + * The length of the output hash in bytes + */ + readonly byteLength: number; + + /** + * Create a new hasher + * + * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms + * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. + */ + constructor(algorithm: SupportedCryptoAlgorithms, hmacKey?: string | NodeJS.TypedArray); + + /** + * Update the hash with data + * + * @param input + */ + update(input: Bun.BlobOrStringOrBuffer, inputEncoding?: CryptoEncoding): CryptoHasher; + + /** + * Perform a deep copy of the hasher + */ + copy(): CryptoHasher; + + /** + * Finalize the hash. Resets the CryptoHasher so it can be reused. + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(): Buffer; + digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash(algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer): Buffer; + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + hashInto: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + + /** + * List of supported hash algorithms + * + * These are hardware accelerated with BoringSSL + */ + static readonly algorithms: SupportedCryptoAlgorithms[]; + } + + /** + * Resolve a `Promise` after milliseconds. This is like + * {@link setTimeout} except it returns a `Promise`. + * + * @param ms milliseconds to delay resolving the promise. This is a minimum + * number. It may take longer. If a {@link Date} is passed, it will sleep until the + * {@link Date} is reached. + * + * @example + * ## Sleep for 1 second + * ```ts + * import { sleep } from "bun"; + * + * await sleep(1000); + * ``` + * ## Sleep for 10 milliseconds + * ```ts + * await Bun.sleep(10); + * ``` + * ## Sleep until `Date` + * + * ```ts + * const target = new Date(); + * target.setSeconds(target.getSeconds() + 1); + * await Bun.sleep(target); + * ``` + * Internally, `Bun.sleep` is the equivalent of + * ```ts + * await new Promise((resolve) => setTimeout(resolve, ms)); + * ``` + * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. + */ + function sleep(ms: number | Date): Promise; + + /** + * Sleep the thread for a given number of milliseconds + * + * This is a blocking function. + * + * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) + */ + function sleepSync(ms: number): void; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param encoding `DigestEncoding` to return the hash in + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; + + /** + * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} + * + * Consider using the ugly-named {@link SHA512_256} instead + */ + class SHA1 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 20; + } + class MD5 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class MD4 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class SHA224 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 28; + } + class SHA512 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 64; + } + class SHA384 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 48; + } + class SHA256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + /** + * See also {@link sha} + */ + class SHA512_256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + + /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ + interface ZlibCompressionOptions { + /** + * The compression level to use. Must be between `-1` and `9`. + * - A value of `-1` uses the default compression level (Currently `6`) + * - A value of `0` gives no compression + * - A value of `1` gives least compression, fastest speed + * - A value of `9` gives best compression, slowest speed + */ + level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * How much memory should be allocated for the internal compression state. + * + * A value of `1` uses minimum memory but is slow and reduces compression ratio. + * + * A value of `9` uses maximum memory for optimal speed. The default is `8`. + */ + memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * The base 2 logarithm of the window size (the size of the history buffer). + * + * Larger values of this parameter result in better compression at the expense of memory usage. + * + * The following value ranges are supported: + * - `9..15`: The output will have a zlib header and footer (Deflate) + * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) + * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) + * + * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. + */ + windowBits?: + | -9 + | -10 + | -11 + | -12 + | -13 + | -14 + | -15 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 25 + | 26 + | 27 + | 28 + | 29 + | 30 + | 31; + /** + * Tunes the compression algorithm. + * + * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** + * - `Z_FILTERED`: For data produced by a filter or predictor + * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) + * - `Z_RLE`: Limit match distances to one (run-length encoding) + * - `Z_FIXED` prevents the use of dynamic Huffman codes + * + * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. + * + * `Z_FILTERED` forces more Huffman coding and less string matching, it is + * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. + * Filtered data consists mostly of small values with a somewhat random distribution. + */ + strategy?: number; + + library?: "zlib"; + } + + interface LibdeflateCompressionOptions { + level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; + library?: "libdeflate"; + } + + /** + * Compresses a chunk of data with `zlib` DEFLATE algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function deflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Compresses a chunk of data with `zlib` GZIP algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function gzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` INFLATE algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function inflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` GUNZIP algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function gunzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + + type Target = + /** + * For generating bundles that are intended to be run by the Bun runtime. In many cases, + * it isn't necessary to bundle server-side code; you can directly execute the source code + * without modification. However, bundling your server code can reduce startup times and + * improve running performance. + * + * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which + * indicates to the Bun runtime that there's no need to re-transpile the file before execution. + */ + | "bun" + /** + * The plugin will be applied to Node.js builds + */ + | "node" + /** + * The plugin will be applied to browser builds + */ + | "browser"; + + /** https://bun.sh/docs/bundler/loaders */ + type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "file" | "napi" | "wasm" | "text" | "css" | "html"; + + interface PluginConstraints { + /** + * Only apply the plugin when the import specifier matches this regular expression + * + * @example + * ```ts + * // Only apply the plugin when the import specifier matches the regex + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { + * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; + * }); + * } + * }) + * ``` + */ + filter: RegExp; + + /** + * Only apply the plugin when the import specifier has a namespace matching + * this string + * + * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` + * has the namespace `"bun"`. + * + * The default namespace is `"file"` and it can be omitted from import + * specifiers. + */ + namespace?: string; + } + + interface OnLoadResultSourceCode { + /** + * The source code of the module + */ + contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; + /** + * The loader to use for this file + * + * "css" will be added in a future version of Bun. + */ + loader?: Loader; + } + + interface OnLoadResultObject { + /** + * The object to use as the module + * @example + * ```ts + * // In your loader + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * + * // In your script + * import {foo} from "hello:world"; + * console.log(foo); // "bar" + * ``` + */ + exports: Record; + /** + * The loader to use for this file + */ + loader: "object"; + } + + interface OnLoadArgs { + /** + * The resolved import specifier of the module being loaded + * @example + * ```ts + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * console.log(args.path); // "hello:world" + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * ``` + */ + path: string; + /** + * The namespace of the module being loaded + */ + namespace: string; + /** + * The default loader for this file extension + */ + loader: Loader; + /** + * Defer the execution of this callback until all other modules have been parsed. + * + * @returns Promise which will be resolved when all modules have been parsed + */ + defer: () => Promise; + } + + type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject | undefined | void; + type OnLoadCallback = (args: OnLoadArgs) => OnLoadResult | Promise; + type OnStartCallback = () => void | Promise; + + interface OnResolveArgs { + /** + * The import specifier of the module being loaded + */ + path: string; + /** + * The module that imported the module being resolved + */ + importer: string; + /** + * The namespace of the importer. + */ + namespace: string; + /** + * The directory to perform file-based resolutions in. + */ + resolveDir: string; + /** + * The kind of import this resolve is for. + */ + kind: ImportKind; + // resolveDir: string; + // pluginData: any; + } + + interface OnResolveResult { + /** + * The destination of the import + */ + path: string; + /** + * The namespace of the destination + * It will be concatenated with `path` to form the final import specifier + * @example + * ```ts + * "foo" // "foo:bar" + * ``` + */ + namespace?: string; + external?: boolean; + } + + type OnResolveCallback = ( + args: OnResolveArgs, + ) => OnResolveResult | Promise | undefined | null; + + type FFIFunctionCallable = Function & { + // Making a nominally typed function so that the user must get it from dlopen + readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + + interface PluginBuilder { + /** + * Register a callback which will be invoked when bundling starts. When + * using hot module reloading, this is called at the start of each + * incremental rebuild. + * + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onStart(() => { + * console.log("bundle just started!!") + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onStart(callback: OnStartCallback): this; + onBeforeParse( + constraints: PluginConstraints, + callback: { + napiModule: unknown; + symbol: string; + external?: unknown | undefined; + }, + ): this; + /** + * Register a callback to load imports with a specific import specifier + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; + /** + * Register a callback to resolve imports matching a filter and/or namespace + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onResolve({ filter: /^wat$/ }, (args) => { + * return { path: "/tmp/woah.js" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onResolve(constraints: PluginConstraints, callback: OnResolveCallback): this; + /** + * The config object passed to `Bun.build` as is. Can be mutated. + */ + config: BuildConfig & { plugins: BunPlugin[] }; + + /** + * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules + * + * @param specifier The module specifier to register the callback for + * @param callback The function to run when the module is imported or required + * + * ### Example + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.module("hello:world", () => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * + * // sometime later + * const { foo } = await import("hello:world"); + * console.log(foo); // "bar" + * + * // or + * const { foo } = require("hello:world"); + * console.log(foo); // "bar" + * ``` + * + * @returns `this` for method chaining + */ + module(specifier: string, callback: () => OnLoadResult | Promise): this; + } + + interface BunPlugin { + /** + * Human-readable name of the plugin + * + * In a future version of Bun, this will be used in error messages. + */ + name: string; + + /** + * The target JavaScript environment the plugin should be applied to. + * - `bun`: The default environment when using `bun run` or `bun` to load a script + * - `browser`: The plugin will be applied to browser builds + * - `node`: The plugin will be applied to Node.js builds + * + * If unspecified, it is assumed that the plugin is compatible with all targets. + * + * This field is not read by {@link Bun.plugin} + */ + target?: Target; + /** + * A function that will be called when the plugin is loaded. + * + * This function may be called in the same tick that it is registered, or it + * may be called later. It could potentially be called multiple times for + * different targets. + */ + setup( + /** + * A builder object that can be used to register plugin hooks + * @example + * ```ts + * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), + * })); + * ``` + */ + build: PluginBuilder, + ): void | Promise; + } + + /** + * Extend Bun's module resolution and loading behavior + * + * Plugins are applied in the order they are defined. + * + * Today, there are two kinds of hooks: + * - `onLoad` lets you return source code or an object that will become the module's exports + * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. + * + * Plugin hooks must define a `filter` RegExp and will only be matched if the + * import specifier contains a "." or a ":". + * + * ES Module resolution semantics mean that plugins may be initialized _after_ + * a module is resolved. You might need to load plugins at the very beginning + * of the application and then use a dynamic import to load the rest of the + * application. A future version of Bun may also support specifying plugins + * via `bunfig.toml`. + * + * @example + * A YAML loader plugin + * + * ```js + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) + * })); + * }); + * + * // You can use require() + * const {foo} = require("./file.yaml"); + * + * // Or import + * await import("./file.yaml"); + * + * ``` + */ + interface BunRegisterPlugin { + (options: T): ReturnType; + + /** + * Deactivate all plugins + * + * This prevents registered plugins from being applied to future builds. + */ + clearAll(): void; + } + + const plugin: BunRegisterPlugin; + + /** + * Is the current global scope the main thread? + */ + const isMainThread: boolean; + + /** + * Used when importing an HTML file at runtime. + * + * @example + * + * ```ts + * import app from "./index.html"; + * ``` + * + * Bun.build support for this isn't imlpemented yet. + */ + interface HTMLBundle { + index: string; + } + + interface Socket extends Disposable { + /** + * Write `data` to the socket + * + * @param data The data to write to the socket + * @param byteOffset The offset in the buffer to start writing from (defaults to 0) + * @param byteLength The number of bytes to write (defaults to the length of the buffer) + * + * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. + * + * This is unbuffered as of Bun v0.2.2. That means individual write() calls + * will be slow. In the future, Bun will buffer writes and flush them at the + * end of the tick, when the event loop is idle, or sooner if the buffer is full. + */ + write(data: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; + + /** + * The data context for the socket. + */ + data: Data; + + /** + * Like {@link Socket.write} except it includes a TCP FIN packet + * + * Use it to send your last message and close the connection. + */ + end(data?: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; + + /** + * Close the socket immediately + */ + end(): void; + + /** + * Keep Bun's process alive at least until this socket is closed + * + * After the socket has closed, the socket is unref'd, the process may exit, + * and this becomes a no-op + */ + ref(): void; + + /** + * Set a timeout until the socket automatically closes. + * + * To reset the timeout, call this function again. + * + * When a timeout happens, the `timeout` callback is called and the socket is closed. + */ + timeout(seconds: number): void; + + /** + * Forcefully close the socket. The other end may not receive all data, and + * the socket will be closed immediately. + * + * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to + * `0` and then calls `close(2)`. + */ + terminate(): void; + + /** + * Shutdown writes to a socket + * + * This makes the socket a half-closed socket. It can still receive data. + * + * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally + */ + shutdown(halfClose?: boolean): void; + + readonly readyState: "open" | "closing" | "closed"; + + /** + * Allow Bun's process to exit even if this socket is still open + * + * After the socket has closed, this function does nothing. + */ + unref(): void; + + /** + * Flush any buffered data to the socket + */ + flush(): void; + + /** + * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. + * + * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. + */ + reload(handler: SocketHandler): void; + + /** + * Get the server that created this socket + * + * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. + */ + readonly listener?: SocketListener; + + /** + * Remote IP address connected to the socket + */ + readonly remoteAddress: string; + + /** + * local port connected to the socket + */ + readonly localPort: number; + + /** + * This property is `true` if the peer certificate was signed by one of the CAs + * specified when creating the `Socket` instance, otherwise `false`. + */ + readonly authorized: boolean; + + /** + * String containing the selected ALPN protocol. + * Before a handshake has completed, this value is always null. + * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. + */ + readonly alpnProtocol: string | false | null; + + /** + * Disables TLS renegotiation for this `Socket` instance. Once called, attempts + * to renegotiate will trigger an `error` handler on the `Socket`. + * + * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) + */ + disableRenegotiation(): void; + + /** + * Keying material is used for validations to prevent different kind of attacks in + * network protocols, for example in the specifications of IEEE 802.1X. + * + * Example + * + * ```js + * const keyingMaterial = socket.exportKeyingMaterial( + * 128, + * 'client finished'); + * + * /* + * Example return value of keyingMaterial: + * + * + * ``` + * + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the [IANA Exporter Label + * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context Optionally provide a context. + * @return requested bytes of the keying material + */ + exportKeyingMaterial(length: number, label: string, context: Buffer): Buffer; + + /** + * Returns the reason why the peer's certificate was not been verified. This + * property is set only when `socket.authorized === false`. + */ + getAuthorizationError(): Error | null; + + /** + * Returns an object representing the local certificate. The returned object has + * some properties corresponding to the fields of the certificate. + * + * If there is no local certificate, an empty object will be returned. If the + * socket has been destroyed, `null` will be returned. + */ + getCertificate(): PeerCertificate | object | null; + getX509Certificate(): X509Certificate | undefined; + + /** + * Returns an object containing information on the negotiated cipher suite. + * + * For example, a TLSv1.2 protocol with AES256-SHA cipher: + * + * ```json + * { + * "name": "AES256-SHA", + * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", + * "version": "SSLv3" + * } + * ``` + * + */ + getCipher(): CipherNameAndProtocol; + + /** + * Returns an object representing the type, name, and size of parameter of + * an ephemeral key exchange in `perfect forward secrecy` on a client + * connection. It returns an empty object when the key exchange is not + * ephemeral. As this is only supported on a client socket; `null` is returned + * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. + * + * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. + */ + getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; + + /** + * Returns an object representing the peer's certificate. If the peer does not + * provide a certificate, an empty object will be returned. If the socket has been + * destroyed, `null` will be returned. + * + * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's + * certificate. + * @return A certificate object. + */ + getPeerCertificate(): PeerCertificate; + getPeerX509Certificate(): X509Certificate; + + /** + * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. + * @since v12.11.0 + * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. + */ + getSharedSigalgs(): string[]; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. + */ + getTLSFinishedMessage(): Buffer | undefined; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so + * far. + */ + getTLSPeerFinishedMessage(): Buffer | undefined; + + /** + * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. + * + * It may be useful for debugging. + * + * See `Session Resumption` for more information. + */ + getTLSTicket(): Buffer | undefined; + + /** + * Returns a string containing the negotiated SSL/TLS protocol version of the + * current connection. The value `'unknown'` will be returned for connected + * sockets that have not completed the handshaking process. The value `null` will + * be returned for server sockets or disconnected client sockets. + * + * Protocol versions are: + * + * * `'SSLv3'` + * * `'TLSv1'` + * * `'TLSv1.1'` + * * `'TLSv1.2'` + * * `'TLSv1.3'` + * + */ + getTLSVersion(): string; + + /** + * See `Session Resumption` for more information. + * @return `true` if the session was reused, `false` otherwise. + */ + isSessionReused(): boolean; + + /** + * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. + * Returns `true` if setting the limit succeeded; `false` otherwise. + * + * Smaller fragment sizes decrease the buffering latency on the client: larger + * fragments are buffered by the TLS layer until the entire fragment is received + * and its integrity is verified; large fragments can span multiple roundtrips + * and their processing can be delayed due to packet loss or reordering. However, + * smaller fragments add extra TLS framing bytes and CPU overhead, which may + * decrease overall server throughput. + * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. + */ + setMaxSendFragment(size: number): boolean; + + /** + * Enable/disable the use of Nagle's algorithm. + * Only available for already connected sockets, will return false otherwise + * @param noDelay Default: `true` + * @returns true if is able to setNoDelay and false if it fails. + */ + setNoDelay(noDelay?: boolean): boolean; + + /** + * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. + * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. + * Only available for already connected sockets, will return false otherwise. + * + * Enabling the keep-alive functionality will set the following socket options: + * SO_KEEPALIVE=1 + * TCP_KEEPIDLE=initialDelay + * TCP_KEEPCNT=10 + * TCP_KEEPINTVL=1 + * @param enable Default: `false` + * @param initialDelay Default: `0` + * @returns true if is able to setNoDelay and false if it fails. + */ + setKeepAlive(enable?: boolean, initialDelay?: number): boolean; + + /** + * The number of bytes written to the socket. + */ + readonly bytesWritten: number; + } + + interface SocketListener extends Disposable { + stop(closeActiveConnections?: boolean): void; + ref(): void; + unref(): void; + reload(options: Pick, "socket">): void; + data: Data; + } + interface TCPSocketListener extends SocketListener { + readonly port: number; + readonly hostname: string; + } + interface UnixSocketListener extends SocketListener { + readonly unix: string; + } + + interface TCPSocket extends Socket {} + interface TLSSocket extends Socket {} + + interface BinaryTypeList { + arraybuffer: ArrayBuffer; + buffer: Buffer; + uint8array: Uint8Array; + // TODO: DataView + // dataview: DataView; + } + type BinaryType = keyof BinaryTypeList; + + interface SocketHandler { + /** + * Is called when the socket connects, or in case of TLS if no handshake is provided + * this will be called only after handshake + * @param socket + */ + open?(socket: Socket): void | Promise; + close?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + data?(socket: Socket, data: BinaryTypeList[DataBinaryType]): void | Promise; + drain?(socket: Socket): void | Promise; + + /** + * When handshake is completed, this functions is called. + * @param socket + * @param success Indicates if the server authorized despite the authorizationError. + * @param authorizationError Certificate Authorization Error or null. + */ + handshake?(socket: Socket, success: boolean, authorizationError: Error | null): void; + + /** + * When the socket has been shutdown from the other end, this function is + * called. This is a TCP FIN packet. + */ + end?(socket: Socket): void | Promise; + + /** + * When the socket fails to be created, this function is called. + * + * The promise returned by `Bun.connect` rejects **after** this function is + * called. + * + * When `connectError` is specified, the rejected promise will not be + * added to the promise rejection queue (so it won't be reported as an + * unhandled promise rejection, since connectError handles it). + * + * When `connectError` is not specified, the rejected promise will be added + * to the promise rejection queue. + */ + connectError?(socket: Socket, error: Error): void | Promise; + + /** + * Called when a message times out. + */ + timeout?(socket: Socket): void | Promise; + /** + * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. + * + * @default "buffer" + * + * @remarks + * This lets you select the desired binary type for the `data` callback. + * It's a small performance optimization to let you avoid creating extra + * ArrayBufferView objects when possible. + * + * Bun originally defaulted to `Uint8Array` but when dealing with network + * data, it's more useful to be able to directly read from the bytes which + * `Buffer` allows. + */ + binaryType?: BinaryType; + } + + interface SocketOptions { + socket: SocketHandler; + data?: Data; + } + // interface TCPSocketOptions extends SocketOptions { + // hostname: string; + // port: number; + // } + + interface TCPSocketListenOptions extends SocketOptions { + hostname: string; + port: number; + tls?: TLSOptions; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface TCPSocketConnectOptions extends SocketOptions { + hostname: string; + port: number; + tls?: boolean; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface UnixSocketOptions extends SocketOptions { + tls?: TLSOptions; + unix: string; + } + + interface FdSocketOptions extends SocketOptions { + tls?: TLSOptions; + fd: number; + } + + /** + * Create a TCP client that connects to a server + * + * @param options The options to use when creating the client + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function connect(options: TCPSocketConnectOptions): Promise>; + function connect(options: UnixSocketOptions): Promise>; + + /** + * Create a TCP server that listens on a port + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function listen(options: TCPSocketListenOptions): TCPSocketListener; + function listen(options: UnixSocketOptions): UnixSocketListener; + + namespace udp { + type Data = string | ArrayBufferView | ArrayBufferLike; + + export interface SocketHandler { + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + } + + export interface ConnectedSocketHandler { + data?( + socket: ConnectedSocket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: ConnectedSocket): void | Promise; + error?(socket: ConnectedSocket, error: Error): void | Promise; + } + + export interface SocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: SocketHandler; + } + + export interface ConnectSocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: ConnectedSocketHandler; + connect: { + hostname: string; + port: number; + }; + } + + export interface BaseUDPSocket { + readonly hostname: string; + readonly port: number; + readonly address: SocketAddress; + readonly binaryType: BinaryType; + readonly closed: boolean; + ref(): void; + unref(): void; + close(): void; + } + + export interface ConnectedSocket extends BaseUDPSocket { + readonly remoteAddress: SocketAddress; + sendMany(packets: readonly Data[]): number; + send(data: Data): boolean; + reload(handler: ConnectedSocketHandler): void; + } + + export interface Socket extends BaseUDPSocket { + sendMany(packets: readonly (Data | string | number)[]): number; + send(data: Data, port: number, address: string): boolean; + reload(handler: SocketHandler): void; + } + } + + /** + * Create a UDP socket + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.hostname The hostname to listen on + * @param options.port The port to listen on + * @param options.binaryType The binary type to use for the socket + * @param options.connect The hostname and port to connect to + */ + export function udpSocket( + options: udp.SocketOptions, + ): Promise>; + export function udpSocket( + options: udp.ConnectSocketOptions, + ): Promise>; + + namespace SpawnOptions { + /** + * Option for stdout/stderr + */ + type Readable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number; + + /** + * Option for stdin + */ + type Writable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number + | ReadableStream + | Blob + | Response + | Request; + + interface OptionsObject< + In extends Writable = Writable, + Out extends Readable = Readable, + Err extends Readable = Readable, + > { + /** + * The current working directory of the process + * + * Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * The environment variables of the process + * + * Defaults to `process.env` as it was when the current Bun process launched. + * + * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. + */ + env?: Record; + + /** + * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. + * This overrides the `stdin`, `stdout`, and `stderr` properties. + * + * For stdin you may pass: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. + * - `number`: The process will read from the file descriptor + * + * For stdout and stdin you may pass: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default ["ignore", "pipe", "inherit"] for `spawn` + * ["ignore", "pipe", "pipe"] for `spawnSync` + */ + stdio?: [In, Out, Err]; + /** + * The file descriptor for the standard input. It may be: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`: The process will read from the buffer + * - `number`: The process will read from the file descriptor + * + * @default "ignore" + */ + stdin?: In; + /** + * The file descriptor for the standard output. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "pipe" + */ + stdout?: Out; + /** + * The file descriptor for the standard error. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "inherit" for `spawn` + * "pipe" for `spawnSync` + */ + stderr?: Err; + + /** + * Callback that runs when the {@link Subprocess} exits + * + * This is called even if the process exits with a non-zero exit code. + * + * Warning: this may run before the `Bun.spawn` function returns. + * + * A simple alternative is `await subprocess.exited`. + * + * @example + * + * ```ts + * const subprocess = spawn({ + * cmd: ["echo", "hello"], + * onExit: (subprocess, code) => { + * console.log(`Process exited with code ${code}`); + * }, + * }); + * ``` + */ + onExit?( + subprocess: Subprocess, + exitCode: number | null, + signalCode: number | null, + /** + * If an error occurred in the call to waitpid2, this will be the error. + */ + error?: ErrorLike, + ): void | Promise; + + /** + * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for + * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized + * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + * + * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, + * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. + * + * Currently, this is only compatible with processes that are other `bun` instances. + */ + ipc?( + message: any, + /** + * The {@link Subprocess} that sent the message + */ + subprocess: Subprocess, + ): void; + + /** + * The serialization format to use for IPC messages. Defaults to `"advanced"`. + * + * To communicate with Node.js processes, use `"json"`. + * + * When `ipc` is not specified, this is ignored. + */ + serialization?: "json" | "advanced"; + + /** + * If true, the subprocess will have a hidden window. + */ + windowsHide?: boolean; + + /** + * If true, no quoting or escaping of arguments is done on Windows. + */ + windowsVerbatimArguments?: boolean; + + /** + * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. + * + * One use-case for this is for applications which wrap other applications or to simulate a symlink. + * + * @default cmds[0] + */ + argv0?: string; + + /** + * An {@link AbortSignal} that can be used to abort the subprocess. + * + * This is useful for aborting a subprocess when some other part of the + * program is aborted, such as a `fetch` response. + * + * Internally, this works by calling `subprocess.kill(1)`. + * + * @example + * ```ts + * const controller = new AbortController(); + * const { signal } = controller; + * const start = performance.now(); + * const subprocess = Bun.spawn({ + * cmd: ["sleep", "100"], + * signal, + * }); + * await Bun.sleep(1); + * controller.abort(); + * await subprocess.exited; + * const end = performance.now(); + * console.log(end - start); // 1ms instead of 101ms + * ``` + */ + signal?: AbortSignal; + } + + type OptionsToSubprocess = + Opts extends OptionsObject + ? Subprocess< + // "Writable extends In" means "if In === Writable", + // aka if true that means the user didn't specify anything + Writable extends In ? "ignore" : In, + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "inherit" : Err + > + : Subprocess; + + type OptionsToSyncSubprocess = + Opts extends OptionsObject + ? SyncSubprocess + : SyncSubprocess; + + type ReadableIO = ReadableStream | number | undefined; + + type ReadableToIO = X extends "pipe" | undefined + ? ReadableStream + : X extends BunFile | ArrayBufferView | number + ? number + : undefined; + + type ReadableToSyncIO = X extends "pipe" | undefined ? Buffer : undefined; + + type WritableIO = FileSink | number | undefined; + + type WritableToIO = X extends "pipe" + ? FileSink + : X extends BunFile | ArrayBufferView | Blob | Request | Response | number + ? number + : undefined; + } + + interface ResourceUsage { + /** + * The number of voluntary and involuntary context switches that the process made. + */ + contextSwitches: { + /** + * Voluntary context switches (context switches that the process initiated). + */ + voluntary: number; + /** + * Involuntary context switches (context switches initiated by the system scheduler). + */ + involuntary: number; + }; + + /** + * The amount of CPU time used by the process, in microseconds. + */ + cpuTime: { + /** + * User CPU time used by the process, in microseconds. + */ + user: number; + /** + * System CPU time used by the process, in microseconds. + */ + system: number; + /** + * Total CPU time used by the process, in microseconds. + */ + total: number; + }; + /** + * The maximum amount of resident set size (in bytes) used by the process during its lifetime. + */ + maxRSS: number; + + /** + * IPC messages sent and received by the process. + */ + messages: { + /** + * The number of IPC messages sent. + */ + sent: number; + /** + * The number of IPC messages received. + */ + received: number; + }; + /** + * The number of IO operations done by the process. + */ + ops: { + /** + * The number of input operations via the file system. + */ + in: number; + /** + * The number of output operations via the file system. + */ + out: number; + }; + /** + * The amount of shared memory that the process used. + */ + shmSize: number; + /** + * The number of signals delivered to the process. + */ + signalCount: number; + /** + * The number of times the process was swapped out of main memory. + */ + swapCount: number; + } + + /** + * A process created by {@link Bun.spawn}. + * + * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSubprocess} (any, pipe, pipe) + * - {@link WritableSubprocess} (pipe, any, any) + * - {@link PipedSubprocess} (pipe, pipe, pipe) + * - {@link NullSubprocess} (ignore, ignore, ignore) + */ + interface Subprocess< + In extends SpawnOptions.Writable = SpawnOptions.Writable, + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > extends AsyncDisposable { + readonly stdin: SpawnOptions.WritableToIO; + readonly stdout: SpawnOptions.ReadableToIO; + readonly stderr: SpawnOptions.ReadableToIO; + + /** + * This returns the same value as {@link Subprocess.stdout} + * + * It exists for compatibility with {@link ReadableStream.pipeThrough} + */ + readonly readable: SpawnOptions.ReadableToIO; + + /** + * The process ID of the child process + * @example + * ```ts + * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); + * console.log(pid); // 1234 + * ``` + */ + readonly pid: number; + /** + * The exit code of the process + * + * The promise will resolve when the process exits + */ + readonly exited: Promise; + + /** + * Synchronously get the exit code of the process + * + * If the process hasn't exited yet, this will return `null` + */ + readonly exitCode: number | null; + + /** + * Synchronously get the signal code of the process + * + * If the process never sent a signal code, this will return `null` + * + * To receive signal code changes, use the `onExit` callback. + * + * If the signal code is unknown, it will return the original signal code + * number, but that case should essentially never happen. + */ + readonly signalCode: NodeJS.Signals | null; + + /** + * Has the process exited? + */ + readonly killed: boolean; + + /** + * Kill the process + * @param exitCode The exitCode to send to the process + */ + kill(exitCode?: number | NodeJS.Signals): void; + + /** + * This method will tell Bun to wait for this process to exit after you already + * called `unref()`. + * + * Before shutting down, Bun will wait for all subprocesses to exit by default + */ + ref(): void; + + /** + * Before shutting down, Bun will wait for all subprocesses to exit by default + * + * This method will tell Bun to not wait for this process to exit before shutting down. + */ + unref(): void; + + /** + * Send a message to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option, and is another instance of `bun`. + * + * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + */ + send(message: any): void; + + /** + * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option. + */ + disconnect(): void; + + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + * + * Only available after the process has exited + * + * If the process hasn't exited yet, this will return `undefined` + */ + resourceUsage(): ResourceUsage | undefined; + } + + /** + * A process created by {@link Bun.spawnSync}. + * + * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSyncSubprocess} (pipe, pipe) + * - {@link NullSyncSubprocess} (ignore, ignore) + */ + interface SyncSubprocess< + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > { + stdout: SpawnOptions.ReadableToSyncIO; + stderr: SpawnOptions.ReadableToSyncIO; + exitCode: number; + success: boolean; + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + */ + resourceUsage: ResourceUsage; + + signalCode?: string; + } + + /** + * Spawn a new process + * + * ```js + * const subprocess = Bun.spawn({ + * cmd: ["echo", "hello"], + * stdout: "pipe", + * }); + * const text = await readableStreamToText(subprocess.stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmd: string[]; // to support dynamically constructed commands + }, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawn(["echo", "hello"]); + * const text = await readableStreamToText(stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync({ + * cmd: ["echo", "hello"], + * }); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); + * ``` + */ + cmd: string[]; + + onExit?: never; + }, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** + * Synchronously spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync(["echo", "hello"]); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ + type ReadableSubprocess = Subprocess; + /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ + type WritableSubprocess = Subprocess<"pipe", any, any>; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ + type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ + type NullSubprocess = Subprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ + type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ + type NullSyncSubprocess = SyncSubprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + + // Blocked on https://github.com/oven-sh/bun/issues/8329 + // /** + // * + // * Count the visible width of a string, as it would be displayed in a terminal. + // * + // * By default, strips ANSI escape codes before measuring the string. This is + // * because ANSI escape codes are not visible characters. If passed a non-string, + // * it will return 0. + // * + // * @param str The string to measure + // * @param options + // */ + // function stringWidth( + // str: string, + // options?: { + // /** + // * Whether to include ANSI escape codes in the width calculation + // * + // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. + // * @default false + // */ + // countAnsiEscapeCodes?: boolean; + // }, + // ): number; + + class FileSystemRouter { + /** + * Create a new {@link FileSystemRouter}. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: process.cwd() + "/pages", + * style: "nextjs", + * }); + * + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} + * ``` + * @param options The options to use when creating the router + * @param options.dir The root directory containing the files to route + * @param options.style The style of router to use (only "nextjs" supported + * for now) + */ + constructor(options: { + /** + * The root directory containing the files to route + * + * There is no default value for this option. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: + */ + dir: string; + style: "nextjs"; + + /** The base path to use when routing */ + assetPrefix?: string; + origin?: string; + /** Limit the pages to those with particular file extensions. */ + fileExtensions?: string[]; + }); + + // todo: URL + match(input: string | Request | Response): MatchedRoute | null; + + readonly assetPrefix: string; + readonly origin: string; + readonly style: string; + readonly routes: Record; + + reload(): void; + } + + interface MatchedRoute { + /** + * A map of the parameters from the route + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: "/path/to/files", + * style: "nextjs", + * }); + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params.year); // "2020" + * console.log(params.month); // "01" + * console.log(params.day); // "01" + * console.log(params.slug); // "hello-world" + * ``` + */ + readonly params: Record; + readonly filePath: string; + readonly pathname: string; + readonly query: Record; + readonly name: string; + readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; + readonly src: string; + } + + /** + * The current version of Bun + * @example + * "0.2.0" + */ + const version: string; + + /** + * The current version of Bun with the shortened commit sha of the build + * @example "v1.1.30 (d09df1af)" + */ + const version_with_sha: string; + + /** + * The git sha at the time the currently-running version of Bun was compiled + * @example + * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" + */ + const revision: string; + + /** + * Find the index of a newline character in potentially ill-formed UTF-8 text. + * + * This is sort of like readline() except without the IO. + */ + function indexOfLine(buffer: ArrayBufferView | ArrayBufferLike, offset?: number): number; + + interface GlobScanOptions { + /** + * The root directory to start matching from. Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * Allow patterns to match entries that begin with a period (`.`). + * + * @default false + */ + dot?: boolean; + + /** + * Return the absolute path for entries. + * + * @default false + */ + absolute?: boolean; + + /** + * Indicates whether to traverse descendants of symbolic link directories. + * + * @default false + */ + followSymlinks?: boolean; + + /** + * Throw an error when symbolic link is broken + * + * @default false + */ + throwErrorOnBrokenSymlink?: boolean; + + /** + * Return only files. + * + * @default true + */ + onlyFiles?: boolean; + } + + /** + * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). + * + * The supported pattern syntax for is: + * + * - `?` + * Matches any single character. + * - `*` + * Matches zero or more characters, except for path separators ('/' or '\'). + * - `**` + * Matches zero or more characters, including path separators. + * Must match a complete path segment, i.e. followed by a path separator or + * at the end of the pattern. + * - `[ab]` + * Matches one of the characters contained in the brackets. + * Character ranges (e.g. "[a-z]") are also supported. + * Use "[!ab]" or "[^ab]" to match any character *except* those contained + * in the brackets. + * - `{a,b}` + * Match one of the patterns contained in the braces. + * Any of the wildcards listed above can be used in the sub patterns. + * Braces may be nested up to 10 levels deep. + * - `!` + * Negates the result when at the start of the pattern. + * Multiple "!" characters negate the pattern multiple times. + * - `\` + * Used to escape any of the special characters above. + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + */ + export class Glob { + constructor(pattern: string); + + /** + * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for await (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scan(optionsOrCwd?: string | GlobScanOptions): AsyncIterableIterator; + + /** + * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; + + /** + * Match the glob against a string + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * expect(glob.match('foo.ts')).toBeTrue(); + * ``` + */ + match(str: string): boolean; + } + + /** + * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. + * + * When the same timestamp is used multiple times, a monotonically increasing + * counter is appended to allow sorting. The final 8 bytes are + * cryptographically random. When the timestamp changes, the counter resets to + * a psuedo-random integer. + * + * @param encoding "hex" | "base64" | "base64url" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + * + * @example + * ```js + * import { randomUUIDv7 } from "bun"; + * const array = [ + * randomUUIDv7(), + * randomUUIDv7(), + * randomUUIDv7(), + * ] + * [ + * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", + * "0192ce07-8c4f-7d67-805f-0f71581b5622", + * "0192ce07-8c4f-7d68-8170-6816e4451a58" + * ] + * ``` + */ + function randomUUIDv7( + /** + * @default "hex" + */ + encoding?: "hex" | "base64" | "base64url", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): string; + + /** + * Generate a UUIDv7 as a Buffer + * + * @param encoding "buffer" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + */ + function randomUUIDv7( + encoding: "buffer", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): Buffer; + + /** + * Types for `bun.lock` + */ + type BunLockFile = { + lockfileVersion: 0 | 1; + workspaces: { + [workspace: string]: BunLockFileWorkspacePackage; + }; + overrides?: Record; + patchedDependencies?: Record; + trustedDependencies?: string[]; + + /** + * ``` + * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } + * + * // first index is resolution for each type of package + * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] + * symlink -> [ "name@link:path", INFO ] + * folder -> [ "name@file:path", INFO ] + * workspace -> [ "name@workspace:path" ] // workspace is only path + * tarball -> [ "name@tarball", INFO ] + * root -> [ "name@root:", { bin, binDir } ] + * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] + * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] + * ``` + * */ + packages: { + [pkg: string]: BunLockFilePackageArray; + }; + }; + + type BunLockFileBasePackageInfo = { + dependencies?: Record; + devDependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; + optionalPeers?: string[]; + bin?: string | Record; + binDir?: string; + }; + + type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { + name?: string; + version?: string; + }; + + type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { + os?: string | string[]; + cpu?: string | string[]; + bundled?: true; + }; + + /** @see {@link BunLockFile.packages} for more info */ + type BunLockFilePackageArray = + /** npm */ + | [pkg: string, registry: string, info: BunLockFilePackageInfo, integrity: string] + /** symlink, folder, tarball */ + | [pkg: string, info: BunLockFilePackageInfo] + /** workspace */ + | [pkg: string] + /** git, github */ + | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] + /** root */ + | [pkg: string, info: Pick]; } diff --git a/packages/bun-types/deprecated.d.ts b/packages/bun-types/deprecated.d.ts index 3eb174db4ded5a..5a90164689ded8 100644 --- a/packages/bun-types/deprecated.d.ts +++ b/packages/bun-types/deprecated.d.ts @@ -1,71 +1,66 @@ declare module "bun" { - /** - * @deprecated Renamed to `ErrorLike` - */ - type Errorlike = ErrorLike; - interface TLSOptions { - /** - * File path to a TLS key - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. - */ - keyFile?: string; - /** - * File path to a TLS certificate - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. - */ - certFile?: string; - /** - * File path to a .pem file for a custom root CA - * - * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. - */ - caFile?: string; - } + /** + * @deprecated Renamed to `ErrorLike` + */ + type Errorlike = ErrorLike; + interface TLSOptions { + /** + * File path to a TLS key + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. + */ + keyFile?: string; + /** + * File path to a TLS certificate + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. + */ + certFile?: string; + /** + * File path to a .pem file for a custom root CA + * + * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. + */ + caFile?: string; + } } declare namespace NodeJS { - interface Process { - /** - * @deprecated This is deprecated; use the "node:assert" module instead. - */ - assert(value: unknown, message?: string | Error): asserts value; - } + interface Process { + /** + * @deprecated This is deprecated; use the "node:assert" module instead. + */ + assert(value: unknown, message?: string | Error): asserts value; + } } declare namespace Bun { - interface MessageEvent { - /** @deprecated */ - initMessageEvent( - type: string, - bubbles?: boolean, - cancelable?: boolean, - data?: any, - origin?: string, - lastEventId?: string, - source?: null, - ): void; - } + interface MessageEvent { + /** @deprecated */ + initMessageEvent( + type: string, + bubbles?: boolean, + cancelable?: boolean, + data?: any, + origin?: string, + lastEventId?: string, + source?: null, + ): void; + } } interface CustomEvent { - /** @deprecated */ - initCustomEvent( - type: string, - bubbles?: boolean, - cancelable?: boolean, - detail?: T, - ): void; + /** @deprecated */ + initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void; } interface DOMException { - /** @deprecated */ - readonly code: number; + /** @deprecated */ + readonly code: number; } /** diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 599ffa198190b9..58e138bbad8c93 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,119 +1,114 @@ interface Headers { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; } var Headers: { - prototype: Headers; - new (init?: Bun.HeadersInit): Headers; + prototype: Headers; + new (init?: Bun.HeadersInit): Headers; }; interface Request { - headers: Headers; + headers: Headers; } var Request: { - prototype: Request; - new (requestInfo: string, requestInit?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, requestInit?: RequestInit): Request; + prototype: Request; + new (requestInfo: string, requestInit?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, requestInit?: RequestInit): Request; }; var Response: { - new ( - body?: Bun.BodyInit | null | undefined, - init?: Bun.ResponseInit | undefined, - ): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: Bun.ResponseInit | number): Response; + new (body?: Bun.BodyInit | null | undefined, init?: Bun.ResponseInit | undefined): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, options?: Bun.ResponseInit | number): Response; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, status?: number): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, status?: number): Response; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, options?: Bun.ResponseInit): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, options?: Bun.ResponseInit): Response; - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; }; type _BunTLSOptions = import("bun").TLSOptions; interface BunFetchRequestInitTLS extends _BunTLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable< - import("node:tls").ConnectionOptions["checkServerIdentity"] - >; + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable; } /** @@ -124,46 +119,43 @@ interface BunFetchRequestInitTLS extends _BunTLSOptions { * if passed to `new Request()`. This is why it's a separate type. */ interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; + /** + * Override the default TLS options + */ + tls?: BunFetchRequestInitTLS; } var fetch: { - /** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ - (request: Request, init?: BunFetchRequestInit): Promise; + /** + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ + (request: Request, init?: BunFetchRequestInit): Promise; - /** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ - (url: string | URL | Request, init?: BunFetchRequestInit): Promise; + /** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ + (url: string | URL | Request, init?: BunFetchRequestInit): Promise; - ( - input: string | URL | globalThis.Request, - init?: BunFetchRequestInit, - ): Promise; + (input: string | URL | globalThis.Request, init?: BunFetchRequestInit): Promise; - /** - * Start the DNS resolution, TCP connection, and TLS handshake for a request - * before the request is actually sent. - * - * This can reduce the latency of a request when you know there's some - * long-running task that will delay the request starting. - * - * This is a bun-specific API and is not part of the Fetch API specification. - */ - preconnect(url: string | URL): void; + /** + * Start the DNS resolution, TCP connection, and TLS handshake for a request + * before the request is actually sent. + * + * This can reduce the latency of a request when you know there's some + * long-running task that will delay the request starting. + * + * This is a bun-specific API and is not part of the Fetch API specification. + */ + preconnect(url: string | URL): void; }; diff --git a/packages/bun-types/ffi.d.ts b/packages/bun-types/ffi.d.ts index db21b4d03aa3d7..6a684678e209d3 100644 --- a/packages/bun-types/ffi.d.ts +++ b/packages/bun-types/ffi.d.ts @@ -15,1154 +15,1136 @@ * goes to Fabrice Bellard and TinyCC maintainers for making this possible. */ declare module "bun:ffi" { - enum FFIType { - char = 0, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int8_t = 1, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i8 = 1, + enum FFIType { + char = 0, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int8_t = 1, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i8 = 1, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint8_t = 2, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u8 = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint8_t = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u8 = 2, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int16_t = 3, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i16 = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int16_t = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i16 = 3, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint16_t = 4, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u16 = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint16_t = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u16 = 4, - /** - * 32-bit signed integer - */ - int32_t = 5, + /** + * 32-bit signed integer + */ + int32_t = 5, - /** - * 32-bit signed integer - * - * Alias of {@link FFIType.int32_t} - */ - i32 = 5, - /** - * 32-bit signed integer - * - * The same as `int` in C - * - * ```c - * int - * ``` - */ - int = 5, + /** + * 32-bit signed integer + * + * Alias of {@link FFIType.int32_t} + */ + i32 = 5, + /** + * 32-bit signed integer + * + * The same as `int` in C + * + * ```c + * int + * ``` + */ + int = 5, - /** - * 32-bit unsigned integer - * - * The same as `unsigned int` in C (on x64 & arm64) - * - * C: - * ```c - * unsigned int - * ``` - * JavaScript: - * ```js - * ptr(new Uint32Array(1)) - * ``` - */ - uint32_t = 6, - /** - * 32-bit unsigned integer - * - * Alias of {@link FFIType.uint32_t} - */ - u32 = 6, + /** + * 32-bit unsigned integer + * + * The same as `unsigned int` in C (on x64 & arm64) + * + * C: + * ```c + * unsigned int + * ``` + * JavaScript: + * ```js + * ptr(new Uint32Array(1)) + * ``` + */ + uint32_t = 6, + /** + * 32-bit unsigned integer + * + * Alias of {@link FFIType.uint32_t} + */ + u32 = 6, - /** - * int64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - int64_t = 7, - /** - * i64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - i64 = 7, + /** + * int64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + int64_t = 7, + /** + * i64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + i64 = 7, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - uint64_t = 8, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - u64 = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + uint64_t = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + u64 = 8, - /** - * Doubles are not supported yet! - */ - double = 9, - /** - * Doubles are not supported yet! - */ - f64 = 9, - /** - * Floats are not supported yet! - */ - float = 10, - /** - * Floats are not supported yet! - */ - f32 = 10, + /** + * Doubles are not supported yet! + */ + double = 9, + /** + * Doubles are not supported yet! + */ + f64 = 9, + /** + * Floats are not supported yet! + */ + float = 10, + /** + * Floats are not supported yet! + */ + f32 = 10, - /** - * Boolean value - * - * Must be `true` or `false`. `0` and `1` type coercion is not supported. - * - * In C, this corresponds to: - * ```c - * bool - * _Bool - * ``` - */ - bool = 11, + /** + * Boolean value + * + * Must be `true` or `false`. `0` and `1` type coercion is not supported. + * + * In C, this corresponds to: + * ```c + * bool + * _Bool + * ``` + */ + bool = 11, - /** - * Pointer value - * - * See {@link Bun.FFI.ptr} for more information - * - * In C: - * ```c - * void* - * ``` - * - * In JavaScript: - * ```js - * ptr(new Uint8Array(1)) - * ``` - */ - ptr = 12, - /** - * Pointer value - * - * alias of {@link FFIType.ptr} - */ - pointer = 12, + /** + * Pointer value + * + * See {@link Bun.FFI.ptr} for more information + * + * In C: + * ```c + * void* + * ``` + * + * In JavaScript: + * ```js + * ptr(new Uint8Array(1)) + * ``` + */ + ptr = 12, + /** + * Pointer value + * + * alias of {@link FFIType.ptr} + */ + pointer = 12, - /** - * void value - * - * void arguments are not supported - * - * void return type is the default return type - * - * In C: - * ```c - * void - * ``` - */ - void = 13, + /** + * void value + * + * void arguments are not supported + * + * void return type is the default return type + * + * In C: + * ```c + * void + * ``` + */ + void = 13, - /** - * When used as a `returns`, this will automatically become a {@link CString}. - * - * When used in `args` it is equivalent to {@link FFIType.pointer} - */ - cstring = 14, + /** + * When used as a `returns`, this will automatically become a {@link CString}. + * + * When used in `args` it is equivalent to {@link FFIType.pointer} + */ + cstring = 14, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `int64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - i64_fast = 15, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `int64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + i64_fast = 15, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `uint64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - u64_fast = 16, - function = 17, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `uint64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + u64_fast = 16, + function = 17, - napi_env = 18, - napi_value = 19, - buffer = 20, - } + napi_env = 18, + napi_value = 19, + buffer = 20, + } - type Pointer = number & { __pointer__: null }; + type Pointer = number & { __pointer__: null }; - interface FFITypeToArgsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: number | bigint; - [FFIType.i64]: number | bigint; - [FFIType.uint64_t]: number | bigint; - [FFIType.u64]: number | bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.void]: undefined; - [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | JSCallback; // cannot be null - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeToReturnsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: bigint; - [FFIType.i64]: bigint; - [FFIType.uint64_t]: bigint; - [FFIType.u64]: bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: Pointer | null; - [FFIType.pointer]: Pointer | null; - [FFIType.void]: undefined; - [FFIType.cstring]: CString; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | null; - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeStringToType { - ["char"]: FFIType.char; - ["int8_t"]: FFIType.int8_t; - ["i8"]: FFIType.i8; - ["uint8_t"]: FFIType.uint8_t; - ["u8"]: FFIType.u8; - ["int16_t"]: FFIType.int16_t; - ["i16"]: FFIType.i16; - ["uint16_t"]: FFIType.uint16_t; - ["u16"]: FFIType.u16; - ["int32_t"]: FFIType.int32_t; - ["i32"]: FFIType.i32; - ["int"]: FFIType.int; - ["uint32_t"]: FFIType.uint32_t; - ["u32"]: FFIType.u32; - ["int64_t"]: FFIType.int64_t; - ["i64"]: FFIType.i64; - ["uint64_t"]: FFIType.uint64_t; - ["u64"]: FFIType.u64; - ["double"]: FFIType.double; - ["f64"]: FFIType.f64; - ["float"]: FFIType.float; - ["f32"]: FFIType.f32; - ["bool"]: FFIType.bool; - ["ptr"]: FFIType.ptr; - ["pointer"]: FFIType.pointer; - ["void"]: FFIType.void; - ["cstring"]: FFIType.cstring; - ["function"]: FFIType.pointer; // for now - ["usize"]: FFIType.uint64_t; // for now - ["callback"]: FFIType.pointer; // for now - ["napi_env"]: FFIType.napi_env; - ["napi_value"]: FFIType.napi_value; - ["buffer"]: FFIType.buffer; - } + interface FFITypeToArgsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: number | bigint; + [FFIType.i64]: number | bigint; + [FFIType.uint64_t]: number | bigint; + [FFIType.u64]: number | bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.void]: undefined; + [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | JSCallback; // cannot be null + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeToReturnsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: bigint; + [FFIType.i64]: bigint; + [FFIType.uint64_t]: bigint; + [FFIType.u64]: bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: Pointer | null; + [FFIType.pointer]: Pointer | null; + [FFIType.void]: undefined; + [FFIType.cstring]: CString; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | null; + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeStringToType { + ["char"]: FFIType.char; + ["int8_t"]: FFIType.int8_t; + ["i8"]: FFIType.i8; + ["uint8_t"]: FFIType.uint8_t; + ["u8"]: FFIType.u8; + ["int16_t"]: FFIType.int16_t; + ["i16"]: FFIType.i16; + ["uint16_t"]: FFIType.uint16_t; + ["u16"]: FFIType.u16; + ["int32_t"]: FFIType.int32_t; + ["i32"]: FFIType.i32; + ["int"]: FFIType.int; + ["uint32_t"]: FFIType.uint32_t; + ["u32"]: FFIType.u32; + ["int64_t"]: FFIType.int64_t; + ["i64"]: FFIType.i64; + ["uint64_t"]: FFIType.uint64_t; + ["u64"]: FFIType.u64; + ["double"]: FFIType.double; + ["f64"]: FFIType.f64; + ["float"]: FFIType.float; + ["f32"]: FFIType.f32; + ["bool"]: FFIType.bool; + ["ptr"]: FFIType.ptr; + ["pointer"]: FFIType.pointer; + ["void"]: FFIType.void; + ["cstring"]: FFIType.cstring; + ["function"]: FFIType.pointer; // for now + ["usize"]: FFIType.uint64_t; // for now + ["callback"]: FFIType.pointer; // for now + ["napi_env"]: FFIType.napi_env; + ["napi_value"]: FFIType.napi_value; + ["buffer"]: FFIType.buffer; + } - type FFITypeOrString = FFIType | keyof FFITypeStringToType; + type FFITypeOrString = FFIType | keyof FFITypeStringToType; - interface FFIFunction { - /** - * Arguments to a FFI function (C ABI) - * - * Defaults to an empty array, which means no arguments. - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, FFIType, suffix } from "bun:ffi" - * - * const lib = dlopen(`adder.${suffix}`, { - * add: { - * // FFIType can be used or you can pass string labels. - * args: [FFIType.i32, "i32"], - * returns: "i32", - * }, - * }) - * lib.symbols.add(1, 2) - * ``` - * In C: - * ```c - * int add(int a, int b) { - * return a + b; - * } - * ``` - */ - readonly args?: readonly FFITypeOrString[]; - /** - * Return type to a FFI function (C ABI) - * - * Defaults to {@link FFIType.void} - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, CString } from "bun:ffi" - * - * const lib = dlopen('z', { - * version: { - * returns: "ptr", - * } - * }); - * console.log(new CString(lib.symbols.version())); - * ``` - * In C: - * ```c - * char* version() - * { - * return "1.0.0"; - * } - * ``` - */ - readonly returns?: FFITypeOrString; + interface FFIFunction { + /** + * Arguments to a FFI function (C ABI) + * + * Defaults to an empty array, which means no arguments. + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, FFIType, suffix } from "bun:ffi" + * + * const lib = dlopen(`adder.${suffix}`, { + * add: { + * // FFIType can be used or you can pass string labels. + * args: [FFIType.i32, "i32"], + * returns: "i32", + * }, + * }) + * lib.symbols.add(1, 2) + * ``` + * In C: + * ```c + * int add(int a, int b) { + * return a + b; + * } + * ``` + */ + readonly args?: readonly FFITypeOrString[]; + /** + * Return type to a FFI function (C ABI) + * + * Defaults to {@link FFIType.void} + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, CString } from "bun:ffi" + * + * const lib = dlopen('z', { + * version: { + * returns: "ptr", + * } + * }); + * console.log(new CString(lib.symbols.version())); + * ``` + * In C: + * ```c + * char* version() + * { + * return "1.0.0"; + * } + * ``` + */ + readonly returns?: FFITypeOrString; - /** - * Function pointer to the native function - * - * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. - * This pointer should not be null (0). - * - * This is useful if the library has already been loaded - * or if the module is also using Node-API. - */ - readonly ptr?: Pointer | bigint; + /** + * Function pointer to the native function + * + * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. + * This pointer should not be null (0). + * + * This is useful if the library has already been loaded + * or if the module is also using Node-API. + */ + readonly ptr?: Pointer | bigint; - /** - * Can C/FFI code call this function from a separate thread? - * - * Only supported with {@link JSCallback}. - * - * This does not make the function run in a separate thread. It is still up to the application/library - * to run their code in a separate thread. - * - * By default, {@link JSCallback} calls are not thread-safe. Turning this on - * incurs a small performance penalty for every function call. That small - * performance penalty needs to be less than the performance gain from - * running the function in a separate thread. - * - * @default false - */ - readonly threadsafe?: boolean; - } + /** + * Can C/FFI code call this function from a separate thread? + * + * Only supported with {@link JSCallback}. + * + * This does not make the function run in a separate thread. It is still up to the application/library + * to run their code in a separate thread. + * + * By default, {@link JSCallback} calls are not thread-safe. Turning this on + * incurs a small performance penalty for every function call. That small + * performance penalty needs to be less than the performance gain from + * running the function in a separate thread. + * + * @default false + */ + readonly threadsafe?: boolean; + } - type Symbols = Readonly>; + type Symbols = Readonly>; - interface Library { - symbols: ConvertFns; + interface Library { + symbols: ConvertFns; - /** - * `dlclose` the library, unloading the symbols and freeing allocated memory. - * - * Once called, the library is no longer usable. - * - * Calling a function from a library that has been closed is undefined behavior. - */ - close(): void; - } + /** + * `dlclose` the library, unloading the symbols and freeing allocated memory. + * + * Once called, the library is no longer usable. + * + * Calling a function from a library that has been closed is undefined behavior. + */ + close(): void; + } - type ToFFIType = T extends FFIType - ? T - : T extends string - ? FFITypeStringToType[T] - : never; + type ToFFIType = T extends FFIType ? T : T extends string ? FFITypeStringToType[T] : never; - const FFIFunctionCallableSymbol: unique symbol; - type ConvertFns = { - [K in keyof Fns]: { - ( - ...args: Fns[K]["args"] extends infer A extends - readonly FFITypeOrString[] - ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } - : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [unknown] extends [Fns[K]["args"]] - ? [] - : never - ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - ? undefined - : FFITypeToReturnsType[ToFFIType>]; - __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - }; + const FFIFunctionCallableSymbol: unique symbol; + type ConvertFns = { + [K in keyof Fns]: { + ( + ...args: Fns[K]["args"] extends infer A extends readonly FFITypeOrString[] + ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } + : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [unknown] extends [Fns[K]["args"]] + ? [] + : never + ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + ? undefined + : FFITypeToReturnsType[ToFFIType>]; + __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + }; - /** - * Open a library using `"bun:ffi"` - * - * @param name The name of the library or file path. This will be passed to `dlopen()` - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import {dlopen} from 'bun:ffi'; - * - * const lib = dlopen("duckdb.dylib", { - * get_version: { - * returns: "cstring", - * args: [], - * }, - * }); - * lib.symbols.get_version(); - * // "1.0.0" - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function dlopen>( - name: string | import("bun").BunFile | URL, - symbols: Fns, - ): Library; + /** + * Open a library using `"bun:ffi"` + * + * @param name The name of the library or file path. This will be passed to `dlopen()` + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import {dlopen} from 'bun:ffi'; + * + * const lib = dlopen("duckdb.dylib", { + * get_version: { + * returns: "cstring", + * args: [], + * }, + * }); + * lib.symbols.get_version(); + * // "1.0.0" + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function dlopen>( + name: string | import("bun").BunFile | URL, + symbols: Fns, + ): Library; - /** - * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. - * - * @param options - * @returns Library - * - * @example - * ## Hello, World! - * - * JavaScript: - * ```js - * import { cc } from "bun:ffi"; - * import hello from "./hello.c" with {type: "file"}; - * const {symbols: {hello}} = cc({ - * source: hello, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * // "Hello, World!" - * console.log(hello()); - * ``` - * - * `./hello.c`: - * ```c - * #include - * const char* hello() { - * return "Hello, World!"; - * } - * ``` - */ - function cc>(options: { - /** - * File path to an ISO C11 source file to compile and link - */ - source: string | import("bun").BunFile | URL; + /** + * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. + * + * @param options + * @returns Library + * + * @example + * ## Hello, World! + * + * JavaScript: + * ```js + * import { cc } from "bun:ffi"; + * import hello from "./hello.c" with {type: "file"}; + * const {symbols: {hello}} = cc({ + * source: hello, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * // "Hello, World!" + * console.log(hello()); + * ``` + * + * `./hello.c`: + * ```c + * #include + * const char* hello() { + * return "Hello, World!"; + * } + * ``` + */ + function cc>(options: { + /** + * File path to an ISO C11 source file to compile and link + */ + source: string | import("bun").BunFile | URL; - /** - * Library names to link against - * - * Equivalent to `-l` option in gcc/clang. - */ - library?: string[] | string; + /** + * Library names to link against + * + * Equivalent to `-l` option in gcc/clang. + */ + library?: string[] | string; - /** - * Include directories to pass to the compiler - * - * Equivalent to `-I` option in gcc/clang. - */ - include?: string[] | string; + /** + * Include directories to pass to the compiler + * + * Equivalent to `-I` option in gcc/clang. + */ + include?: string[] | string; - /** - * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - */ - symbols: Fns; + /** + * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + */ + symbols: Fns; - /** - * Map of symbols to define where the key is the symbol name and the value is the symbol value - * - * Equivalent to `-D` option in gcc/clang. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * define: { - * "NDEBUG": "1", - * }, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - define?: Record; + /** + * Map of symbols to define where the key is the symbol name and the value is the symbol value + * + * Equivalent to `-D` option in gcc/clang. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * define: { + * "NDEBUG": "1", + * }, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + define?: Record; - /** - * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. - * - * @default "-std=c11 -Wl,--export-all-symbols -g -O2" - * - * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * flags: ["-framework CoreFoundation", "-framework Security"], - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - flags?: string | string[]; - }): Library; + /** + * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. + * + * @default "-std=c11 -Wl,--export-all-symbols -g -O2" + * + * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * flags: ["-framework CoreFoundation", "-framework Security"], + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + flags?: string | string[]; + }): Library; - /** - * Turn a native library's function pointer into a JavaScript function - * - * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. - * - * @param fn {@link FFIFunction} declaration. `ptr` is required - * - * @example - * - * ```js - * import {CFunction} from 'bun:ffi'; - * - * const getVersion = new CFunction({ - * returns: "cstring", - * args: [], - * ptr: myNativeLibraryGetVersion, - * }); - * getVersion(); - * getVersion.close(); - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { - /** - * Free the memory allocated by the wrapping function - */ - close(): void; - }; + /** + * Turn a native library's function pointer into a JavaScript function + * + * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. + * + * @param fn {@link FFIFunction} declaration. `ptr` is required + * + * @example + * + * ```js + * import {CFunction} from 'bun:ffi'; + * + * const getVersion = new CFunction({ + * returns: "cstring", + * args: [], + * ptr: myNativeLibraryGetVersion, + * }); + * getVersion(); + * getVersion.close(); + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { + /** + * Free the memory allocated by the wrapping function + */ + close(): void; + }; - /** - * Link a map of symbols to JavaScript functions - * - * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. - * - * You could use this with Node-API to skip loading a second time. - * - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import { linkSymbols } from "bun:ffi"; - * - * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); - * - * const lib = linkSymbols({ - * // Unlike with dlopen(), the names here can be whatever you want - * getMajor: { - * returns: "cstring", - * args: [], - * - * // Since this doesn't use dlsym(), you have to provide a valid ptr - * // That ptr could be a number or a bigint - * // An invalid pointer will crash your program. - * ptr: majorPtr, - * }, - * getMinor: { - * returns: "cstring", - * args: [], - * ptr: minorPtr, - * }, - * getPatch: { - * returns: "cstring", - * args: [], - * ptr: patchPtr, - * }, - * }); - * - * const [major, minor, patch] = [ - * lib.symbols.getMajor(), - * lib.symbols.getMinor(), - * lib.symbols.getPatch(), - * ]; - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function linkSymbols>( - symbols: Fns, - ): Library; + /** + * Link a map of symbols to JavaScript functions + * + * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. + * + * You could use this with Node-API to skip loading a second time. + * + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import { linkSymbols } from "bun:ffi"; + * + * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); + * + * const lib = linkSymbols({ + * // Unlike with dlopen(), the names here can be whatever you want + * getMajor: { + * returns: "cstring", + * args: [], + * + * // Since this doesn't use dlsym(), you have to provide a valid ptr + * // That ptr could be a number or a bigint + * // An invalid pointer will crash your program. + * ptr: majorPtr, + * }, + * getMinor: { + * returns: "cstring", + * args: [], + * ptr: minorPtr, + * }, + * getPatch: { + * returns: "cstring", + * args: [], + * ptr: patchPtr, + * }, + * }); + * + * const [major, minor, patch] = [ + * lib.symbols.getMajor(), + * lib.symbols.getMinor(), + * lib.symbols.getPatch(), + * ]; + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function linkSymbols>(symbols: Fns): Library; - /** - * Read a pointer as a {@link Buffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toBuffer( - ptr: Pointer, - byteOffset?: number, - byteLength?: number, - ): Buffer; + /** + * Read a pointer as a {@link Buffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): Buffer; - /** - * Read a pointer as an {@link ArrayBuffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toArrayBuffer( - ptr: Pointer, - byteOffset?: number, - byteLength?: number, - ): ArrayBuffer; + /** + * Read a pointer as an {@link ArrayBuffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toArrayBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): ArrayBuffer; - namespace read { - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f64(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function ptr(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function intptr(ptr: Pointer, byteOffset?: number): number; - } + namespace read { + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f64(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function ptr(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function intptr(ptr: Pointer, byteOffset?: number): number; + } - /** - * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} - * - * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. - * - * This is for use with FFI functions. For performance reasons, FFI will - * not automatically convert typed arrays to C pointers. - * - * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for - * @param {number} byteOffset optional offset into the view in bytes - * - * @example - * - * From JavaScript: - * ```js - * const array = new Uint8Array(10); - * const rawPtr = ptr(array); - * myFFIFunction(rawPtr); - * ``` - * To C: - * ```c - * void myFFIFunction(char* rawPtr) { - * // Do something with rawPtr - * } - * ``` - */ - function ptr( - view: NodeJS.TypedArray | ArrayBufferLike | DataView, - byteOffset?: number, - ): Pointer; + /** + * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} + * + * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. + * + * This is for use with FFI functions. For performance reasons, FFI will + * not automatically convert typed arrays to C pointers. + * + * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for + * @param {number} byteOffset optional offset into the view in bytes + * + * @example + * + * From JavaScript: + * ```js + * const array = new Uint8Array(10); + * const rawPtr = ptr(array); + * myFFIFunction(rawPtr); + * ``` + * To C: + * ```c + * void myFFIFunction(char* rawPtr) { + * // Do something with rawPtr + * } + * ``` + */ + function ptr(view: NodeJS.TypedArray | ArrayBufferLike | DataView, byteOffset?: number): Pointer; - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ - class CString extends String { - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @param ptr The pointer to the C string - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); + class CString extends String { + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @param ptr The pointer to the C string + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); - /** - * The ptr to the C string - * - * This `CString` instance is a clone of the string, so it - * is safe to continue using this instance after the `ptr` has been - * freed. - */ - ptr: Pointer; - byteOffset?: number; - byteLength?: number; + /** + * The ptr to the C string + * + * This `CString` instance is a clone of the string, so it + * is safe to continue using this instance after the `ptr` has been + * freed. + */ + ptr: Pointer; + byteOffset?: number; + byteLength?: number; - /** - * Get the {@link ptr} as an `ArrayBuffer` - * - * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 - */ - get arrayBuffer(): ArrayBuffer; - } + /** + * Get the {@link ptr} as an `ArrayBuffer` + * + * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 + */ + get arrayBuffer(): ArrayBuffer; + } - /** - * Pass a JavaScript function to FFI (Foreign Function Interface) - */ - class JSCallback { - /** - * Enable a JavaScript callback function to be passed to C with bun:ffi - * - * @param callback The JavaScript function to be called - * @param definition The C function definition - */ - constructor(callback: (...args: any[]) => any, definition: FFIFunction); + /** + * Pass a JavaScript function to FFI (Foreign Function Interface) + */ + class JSCallback { + /** + * Enable a JavaScript callback function to be passed to C with bun:ffi + * + * @param callback The JavaScript function to be called + * @param definition The C function definition + */ + constructor(callback: (...args: any[]) => any, definition: FFIFunction); - /** - * The pointer to the C function - * - * Becomes `null` once {@link JSCallback.prototype.close} is called - */ - readonly ptr: Pointer | null; + /** + * The pointer to the C function + * + * Becomes `null` once {@link JSCallback.prototype.close} is called + */ + readonly ptr: Pointer | null; - /** - * Can the callback be called from a different thread? - */ - readonly threadsafe: boolean; + /** + * Can the callback be called from a different thread? + */ + readonly threadsafe: boolean; - /** - * Free the memory allocated for the callback - * - * If called multiple times, does nothing after the first call. - */ - close(): void; - } + /** + * Free the memory allocated for the callback + * + * If called multiple times, does nothing after the first call. + */ + close(): void; + } - /** - * View the generated C code for FFI bindings - * - * You probably won't need this unless there's a bug in the FFI bindings - * generator or you're just curious. - */ - function viewSource(symbols: Symbols, is_callback?: false): string[]; - function viewSource(callback: FFIFunction, is_callback: true): string; + /** + * View the generated C code for FFI bindings + * + * You probably won't need this unless there's a bug in the FFI bindings + * generator or you're just curious. + */ + function viewSource(symbols: Symbols, is_callback?: false): string[]; + function viewSource(callback: FFIFunction, is_callback: true): string; - /** - * Platform-specific file extension name for dynamic libraries - * - * "." is not included - * - * @example - * ```js - * "dylib" // macOS - * ``` - * - * @example - * ```js - * "so" // linux - * ``` - */ - const suffix: string; + /** + * Platform-specific file extension name for dynamic libraries + * + * "." is not included + * + * @example + * ```js + * "dylib" // macOS + * ``` + * + * @example + * ```js + * "so" // linux + * ``` + */ + const suffix: string; } diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 7263946b604113..09708e33339903 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1,1310 +1,1266 @@ export {}; type _Event = { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly bubbles: boolean; + /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ + cancelBubble: () => void; + /** True if the event was created with the cancelable option */ + readonly cancelable: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly composed: boolean; + /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ + composedPath(): [EventTarget?]; + /** Alias for event.target. */ + readonly currentTarget: EventTarget | null; + /** Is true if cancelable is true and event.preventDefault() has been called. */ + readonly defaultPrevented: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly eventPhase: 0 | 2; + /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ + readonly isTrusted: boolean; + /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ + preventDefault(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + returnValue: boolean; + /** Alias for event.target. */ + readonly srcElement: EventTarget | null; + /** Stops the invocation of event listeners after the current one completes. */ + stopImmediatePropagation(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + stopPropagation(): void; + /** The `EventTarget` dispatching the event */ + readonly target: EventTarget | null; + /** The millisecond timestamp when the Event object was created. */ + readonly timeStamp: number; + /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ + readonly type: string; }; type _EventTarget = { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; + /** + * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. + * + * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. + * + * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. + * Specifically, the `capture` option is used as part of the key when registering a `listener`. + * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. + */ + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ + dispatchEvent(event: Event): boolean; + /** Removes the event listener in target's event listener list with the same type, callback, and options. */ + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; }; declare global { - var Bun: typeof import("bun"); - - namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - - /** Whether you are using Bun */ - isBun: true; - /** The current git sha of Bun **/ - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - } - - type _ReadableStream = import("stream/web").ReadableStream; - interface ReadableStream extends _ReadableStream {} - var ReadableStream: { - prototype: ReadableStream; - new ( - underlyingSource?: Bun.UnderlyingSource, - strategy?: QueuingStrategy, - ): ReadableStream; - new ( - underlyingSource?: Bun.DirectUnderlyingSource, - strategy?: QueuingStrategy, - ): ReadableStream; - }; - - type _WritableStream = import("stream/web").WritableStream; - interface WritableStream extends _WritableStream {} - var WritableStream: { - prototype: WritableStream; - new ( - underlyingSink?: Bun.UnderlyingSink, - strategy?: QueuingStrategy, - ): WritableStream; - }; - - type _Worker = import("worker_threads").Worker; - interface Worker extends _Worker {} - var Worker: { - prototype: Worker; - new ( - scriptURL: string | URL, - options?: Bun.WorkerOptions | undefined, - ): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; - }; - - var WebSocket: typeof import("ws").WebSocket; - - type _Crypto = import("crypto").webcrypto.Crypto; - interface Crypto extends _Crypto {} - var Crypto: { - prototype: Crypto; - new (): Crypto; - }; - - var crypto: Crypto; - - /** - * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All - * instances of `TextEncoder` only support UTF-8 encoding. - * - * ```js - * const encoder = new TextEncoder(); - * const uint8array = encoder.encode('this is some data'); - * ``` - */ - interface TextEncoder extends Bun.TextEncoder {} - var TextEncoder: typeof TextEncoder; - - interface TextDecoder extends Bun.TextDecoder {} - var TextDecoder: typeof TextDecoder; - - type _Performance = import("perf_hooks").Performance; - interface Performance extends _Performance {} - var performance: Performance; - - interface Event extends _Event {} - var Event: { - prototype: Event; - new (type: string, eventInitDict?: Bun.EventInit): Event; - }; - - interface EventTarget extends _EventTarget {} - var EventTarget: { - prototype: EventTarget; - new (): EventTarget; - }; - - interface File extends Blob { - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new ( - parts: Bun.BlobPart[], - name: string, - options?: BlobPropertyBag & { lastModified?: Date | number }, - ): File; - readonly lastModified: number; - readonly name: string; - } - - var File: typeof File; - - type _RequestInit = import("undici-types").RequestInit; - interface RequestInit extends _RequestInit { - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: import("bun").S3Options; - } - - /** - * ShadowRealms are a distinct global environment, with its own global object - * containing its own intrinsics and built-ins (standard objects that are not - * bound to global variables, like the initial value of Object.prototype). - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - interface ShadowRealm { - /** - * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; - } - - var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; - }; - - function queueMicrotask(callback: (...args: any[]) => void): void; - /** - * Log an error using the default exception handler - * @param error Error or string - */ - function reportError(error: any): void; - - interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; - - [Symbol.toPrimitive](): number; - } - - /** - * Cancel a repeating timer by its timer ID. - * @param id timer id - */ - function clearInterval(id?: number | Timer): void; - /** - * Cancel a delayed function call by its timer ID. - * @param id timer id - */ - function clearTimeout(id?: number | Timer): void; - /** - * Cancel an immediate function call by its immediate ID. - * @param id immediate id - */ - function clearImmediate(id?: number | Timer): void; - /** - * Run a function immediately after main event loop is vacant - * @param handler function to call - */ - function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; - /** - * Run a function every `interval` milliseconds - * @param handler function to call - * @param interval milliseconds to wait between calls - */ - function setInterval( - handler: Bun.TimerHandler, - interval?: number, - ...arguments: any[] - ): Timer; - /** - * Run a function after `timeout` (milliseconds) - * @param handler function to call - * @param timeout milliseconds to wait between calls - */ - function setTimeout( - handler: Bun.TimerHandler, - timeout?: number, - ...arguments: any[] - ): Timer; - - function addEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - function addEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - function removeEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | Bun.EventListenerOptions, - ): void; - function removeEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | Bun.EventListenerOptions, - ): void; - - /** - * Events providing information related to errors in scripts or in files. - */ - interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; - } - - var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; - }; - - /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ - interface CloseEvent extends Event { - /** Returns the WebSocket connection close code provided by the server. */ - readonly code: number; - /** Returns the WebSocket connection close reason provided by the server. */ - readonly reason: string; - /** Returns true if the connection closed cleanly; false otherwise. */ - readonly wasClean: boolean; - } - - var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; - }; - - interface MessageEvent extends Bun.MessageEvent {} - var MessageEvent: { - prototype: MessageEvent; - new ( - type: string, - eventInitDict?: Bun.MessageEventInit, - ): MessageEvent; - }; - - interface CustomEvent extends Event { - /** Returns any custom data event was created with. Typically used for synthetic events. */ - readonly detail: T; - } - - var CustomEvent: { - prototype: CustomEvent; - new ( - type: string, - eventInitDict?: Bun.CustomEventInit, - ): CustomEvent; - }; - - // /** - // * The URL interface represents an object providing static methods used for - // * creating object URLs. - // */ - // interface URL extends _URL { - // new (url: string | URL, base?: string | URL): URL; - // /** Not implemented yet */ - // createObjectURL(obj: Blob): string; - // /** Not implemented yet */ - // revokeObjectURL(url: string): void; - - // /** - // * Check if `url` is a valid URL string - // * - // * @param url URL string to parse - // * @param base URL to resolve against - // */ - // canParse(url: string, base?: string): boolean; - // } - - interface EventListener { - (evt: Event): void; - } - - interface EventListenerObject { - handleEvent(object: Event): void; - } - - interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; - - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; - } - - interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; - // exit: Event; - } - - interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; - } - - /** - * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) - * - * Before using this, be aware of a few things: - * - * **Using this incorrectly will crash your application**. - * - * This API may change any time JavaScriptCore is updated. - * - * Bun may rewrite ESM import specifiers to point to bundled code. This will - * be confusing when using this API, as it will return a string like - * "/node_modules.server.bun". - * - * Bun may inject additional imports into your code. This usually has a `bun:` prefix. - */ - var Loader: { - /** - * ESM module registry - * - * This lets you implement live reload in Bun. If you - * delete a module specifier from this map, the next time it's imported, it - * will be re-transpiled and loaded again. - * - * The keys are the module specifiers and the - * values are metadata about the module. - * - * The keys are an implementation detail for Bun that will change between - * versions. - * - * - Userland modules are an absolute file path - * - Virtual modules have a `bun:` prefix or `node:` prefix - * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill - * - If you have a `node_modules.bun` file, many modules will point to that file - * - * Virtual modules and JS polyfills are embedded in bun's binary. They don't - * point to anywhere in your local filesystem. - */ - registry: Map< - string, - { - key: string; - /** - * This refers to the state the ESM module is in - * - * TODO: make an enum for this number - */ - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array< - (typeof Loader)["registry"] extends Map ? V : any - >; - /** - * Your application will probably crash if you mess with this. - */ - module: { - dependenciesMap: (typeof Loader)["registry"]; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - /** - * For an already-evaluated module, return the dependencies as module specifiers - * - * This list is already sorted and uniqued. - * - * @example - * - * For this code: - * ```js - * // /foo.js - * import classNames from 'classnames'; - * import React from 'react'; - * import {createElement} from 'react'; - * ``` - * - * This would return: - * ```js - * Loader.dependencyKeysIfEvaluated("/foo.js") - * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] - * ``` - * - * @param specifier - module specifier as it appears in transpiled source code - */ - dependencyKeysIfEvaluated: (specifier: string) => string[]; - /** - * The function JavaScriptCore internally calls when you use an import statement. - * - * This may return a path to `node_modules.server.bun`, which will be confusing. - * - * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} - * instead. - * - * @param specifier - module specifier as it appears in transpiled source code - * @param referrer - module specifier that is resolving this specifier - */ - resolve: (specifier: string, referrer: string) => string; - }; - - interface QueuingStrategy { - highWaterMark?: number; - size?: QueuingStrategySize; - } - - interface QueuingStrategyInit { - /** - * Creates a new ByteLengthQueuingStrategy with the provided high water mark. - * - * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. - */ - highWaterMark: number; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface ByteLengthQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - // changed from QueuingStrategySize - // to avoid conflict with lib.dom.d.ts - readonly size: QueuingStrategySize; - } - - var ByteLengthQueuingStrategy: { - prototype: ByteLengthQueuingStrategy; - new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; - }; - - interface ReadableStreamDefaultController { - readonly desiredSize: number | null; - close(): void; - enqueue(chunk?: R): void; - error(e?: any): void; - } - - interface ReadableStreamDirectController { - close(error?: Error): void; - write( - data: Bun.BufferSource | ArrayBuffer | string, - ): number | Promise; - end(): number | Promise; - flush(): number | Promise; - start(): void; - } - - var ReadableStreamDefaultController: { - prototype: ReadableStreamDefaultController; - new (): ReadableStreamDefaultController; - }; - - interface ReadableStreamDefaultReader - extends ReadableStreamGenericReader { - read(): Promise>; - /** - * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. - * Will only return a promise if the data is not immediately available. - */ - readMany(): - | Promise> - | Bun.ReadableStreamDefaultReadManyResult; - releaseLock(): void; - } - - var ReadableStreamDefaultReader: { - prototype: ReadableStreamDefaultReader; - new (stream: ReadableStream): ReadableStreamDefaultReader; - }; - - interface ReadableStreamGenericReader { - readonly closed: Promise; - cancel(reason?: any): Promise; - } - - interface ReadableStreamDefaultReadDoneResult { - done: true; - value?: undefined; - } - - interface ReadableStreamDefaultReadValueResult { - done: false; - value: T; - } - - interface ReadableWritablePair { - readable: ReadableStream; - /** - * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - */ - writable: WritableStream; - } - - interface WritableStreamDefaultController { - error(e?: any): void; - } - - var WritableStreamDefaultController: { - prototype: WritableStreamDefaultController; - new (): WritableStreamDefaultController; - }; - - /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ - interface WritableStreamDefaultWriter { - readonly closed: Promise; - readonly desiredSize: number | null; - readonly ready: Promise; - abort(reason?: any): Promise; - close(): Promise; - releaseLock(): void; - write(chunk?: W): Promise; - } - - var WritableStreamDefaultWriter: { - prototype: WritableStreamDefaultWriter; - new (stream: WritableStream): WritableStreamDefaultWriter; - }; - - interface TransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; - } - - var TransformStream: { - prototype: TransformStream; - new ( - transformer?: Transformer, - writableStrategy?: QueuingStrategy, - readableStrategy?: QueuingStrategy, - ): TransformStream; - }; - - interface TransformStreamDefaultController { - readonly desiredSize: number | null; - enqueue(chunk?: O): void; - error(reason?: any): void; - terminate(): void; - } - - var TransformStreamDefaultController: { - prototype: TransformStreamDefaultController; - new (): TransformStreamDefaultController; - }; - - interface StreamPipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - /** - * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - * - * Errors and closures of the source and destination streams propagate as follows: - * - * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. - * - * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. - * - * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. - * - * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. - * - * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. - */ - preventClose?: boolean; - signal?: AbortSignal; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface CountQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - readonly size: QueuingStrategySize; - } - - var CountQueuingStrategy: { - prototype: CountQueuingStrategy; - new (init: QueuingStrategyInit): CountQueuingStrategy; - }; - - interface QueuingStrategySize { - (chunk?: T): number; - } - - interface Transformer { - flush?: Bun.TransformerFlushCallback; - readableType?: undefined; - start?: Bun.TransformerStartCallback; - transform?: Bun.TransformerTransformCallback; - writableType?: undefined; - } - - interface Dict { - [key: string]: T | undefined; - } - - interface ReadOnlyDict { - readonly [key: string]: T | undefined; - } - - interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; - } - - /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ - interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; - } - - var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; - }; - - function alert(message?: string): void; - function confirm(message?: string): boolean; - function prompt(message?: string, _default?: string): string | null; - - type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; - var SubtleCrypto: { - prototype: _SubtleCrypto; - new (): _SubtleCrypto; - }; - - type _CryptoKey = import("crypto").webcrypto.CryptoKey; - interface CryptoKey extends _CryptoKey {} - var CryptoKey: { - prototype: CryptoKey; - new (): CryptoKey; - }; - - interface Position { - lineText: string; - file: string; - namespace: string; - line: number; - column: number; - length: number; - offset: number; - } - - class ResolveMessage { - readonly name: "ResolveMessage"; - readonly position: Position | null; - readonly code: string; - readonly message: string; - readonly referrer: string; - readonly specifier: string; - readonly importKind: - | "entry_point" - | "stmt" - | "require" - | "import" - | "dynamic" - | "require_resolve" - | "at" - | "at_conditional" - | "url" - | "internal"; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - - toString(): string; - } - - class BuildMessage { - readonly name: "BuildMessage"; - readonly position: Position | null; - readonly message: string; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - } - - // Declare "static" methods in Error - interface ErrorConstructor { - /** Create .stack property on a target object */ - // eslint-disable-next-line @typescript-eslint/ban-types - captureStackTrace(targetObject: object, constructorOpt?: Function): void; - - /** - * Optional override for formatting stack traces - * - * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces - */ - prepareStackTrace?: - | ((err: Error, stackTraces: NodeJS.CallSite[]) => any) - | undefined; - - stackTraceLimit: number; - } - - interface ArrayBufferConstructor { - new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; - } - - interface ArrayBuffer { - /** - * Read-only. The length of the ArrayBuffer (in bytes). - */ - readonly byteLength: number; - /** - * Resize an ArrayBuffer in-place. - */ - resize(byteLength: number): ArrayBuffer; - - /** - * Returns a section of an ArrayBuffer. - */ - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; - } - - interface SharedArrayBuffer { - /** - * Grow the SharedArrayBuffer in-place. - */ - grow(size: number): SharedArrayBuffer; - } - - interface ArrayConstructor { - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - ): Promise[]>; - - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. Results of the map function are also awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * await Array.fromAsync([1], (n) => n + 1); // [2] - * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. - * @param thisArg - The `this` to which `mapFn` is bound. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; - } - - interface ConsoleOptions { - stdout: import("stream").Writable; - stderr?: import("stream").Writable; - ignoreErrors?: boolean; - colorMode?: boolean | "auto"; - inspectOptions?: import("util").InspectOptions; - groupIndentation?: number; - } - - interface Console { - /** - * Asynchronously read lines from standard input (fd 0) - * - * ```ts - * for await (const line of console) { - * console.log(line); - * } - * ``` - */ - [Symbol.asyncIterator](): AsyncIterableIterator; - - /** - * Write text or bytes to stdout - * - * Unlike {@link console.log}, this does no formatting and doesn't add a - * newline or spaces between arguments. You can pass it strings or bytes or - * any combination of the two. - * - * ```ts - * console.write("hello world!", "\n"); // "hello world\n" - * ``` - * - * @param data - The data to write - * @returns The number of bytes written - * - * This function is not available in the browser. - */ - write(...data: Array): number; - - /** - * Clear the console - */ - clear(): void; - - assert(condition?: boolean, ...data: any[]): void; - - /** - * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) - * @param label label counter - */ - count(label?: string): void; - countReset(label?: string): void; - debug(...data: any[]): void; - dir(item?: any, options?: any): void; - dirxml(...data: any[]): void; - /** - * Log to stderr in your terminal - * - * Appears in red - * - * @param data something to display - */ - error(...data: any[]): void; - /** Does nothing currently */ - group(...data: any[]): void; - /** Does nothing currently */ - groupCollapsed(...data: any[]): void; - /** Does nothing currently */ - groupEnd(): void; - info(...data: any[]): void; - log(...data: any[]): void; - /** - * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just - * logging the argument if it can't be parsed as tabular. - * - * ```js - * // These can't be parsed as tabular data - * console.table(Symbol()); - * // Symbol() - * - * console.table(undefined); - * // undefined - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ b โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * ``` - * @param properties Alternate properties for constructing the table. - */ - table(tabularData?: any, properties?: string[]): void; - /** - * Begin a timer to log with {@link console.timeEnd} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - time(label?: string): void; - /** - * End a timer to log with {@link console.time} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - timeEnd(label?: string): void; - timeLog(label?: string, ...data: any[]): void; - timeStamp(label?: string): void; - trace(...data: any[]): void; - warn(...data: any[]): void; - - /** - * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. - */ - // Console: { - // new (options: ConsoleOptions): Console; - // new ( - // stdout: import("stream").Writable, - // stderr?: import("stream").Writable, - // ignoreErrors?: boolean, - // ): Console; - // }; - } - - var console: Console; - - interface ImportMeta { - /** - * `file://` url string for the current module. - * - * @example - * ```ts - * console.log(import.meta.url); - * "file:///Users/me/projects/my-app/src/my-app.ts" - * ``` - */ - url: string; - /** - * Absolute path to the source file - */ - readonly path: string; - /** - * Absolute path to the directory containing the source file. - * - * Does not have a trailing slash - */ - readonly dir: string; - /** - * Filename of the source file - */ - readonly file: string; - /** - * The environment variables of the process - * - * ```ts - * import.meta.env === process.env - * ``` - */ - readonly env: NodeJS.ProcessEnv; - - /** - * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead - * - * Resolve a module ID the same as if you imported it - * - * The `parent` argument is optional, and defaults to the current module's path. - */ - resolveSync(moduleId: string, parent?: string): string; - - /** - * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all - * calls to `require` with `import.meta.require` when transpiling ES Modules - * for the runtime. - * - * Warning: **This API is not stable** and may change or be removed in the - * future. Use at your own risk. - */ - require: NodeJS.Require; - - /** - * Did the current file start the process? - * - * @example - * ```ts - * if (import.meta.main) { - * console.log("I started the process!"); - * } - * ``` - * - * @example - * ```ts - * console.log( - * import.meta.main === (import.meta.path === Bun.main) - * ) - * ``` - */ - readonly main: boolean; - - /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ - dirname: string; - - /** Alias of `import.meta.path`. Exists for Node.js compatibility */ - filename: string; - } - - /** - * NodeJS-style `require` function - * - * @param moduleId - The module ID to resolve - */ - var require: NodeJS.Require; - - /** Same as module.exports */ - var exports: any; - - interface NodeModule { - exports: any; - } - - var module: NodeModule; - - /** - * Creates a deep clone of an object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) - */ - function structuredClone( - value: T, - options?: Bun.StructuredSerializeOptions, - ): T; - - /** - * Post a message to the parent thread. - * - * Only useful in a worker thread; calling this from the main thread does nothing. - */ - function postMessage(message: any, transfer?: Bun.Transferable[]): void; - - interface EventSourceInit { - withCredentials?: boolean; - } - - interface PromiseConstructor { - /** - * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called - * separately. - * - * This is useful when you want to return a Promise and have code outside the Promise - * resolve or reject it. - * - * ## Example - * ```ts - * const { promise, resolve, reject } = Promise.withResolvers(); - * - * setTimeout(() => { - * resolve("Hello world!"); - * }, 1000); - * - * await promise; // "Hello world!" - * ``` - * - * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). - */ - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; - } - - interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; - } - - var navigator: Navigator; - - interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; - } - - interface Blob { - /** - * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - */ - new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; - /** - * Read the data from the blob as a JSON object. - * - * This first decodes the data from UTF-8, then parses it as JSON. - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - json(): Promise; - - /** - * Read the data from the blob as a {@link FormData} object. - * - * This first decodes the data from UTF-8, then parses it as a - * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. - * - * The `type` property of the blob is used to determine the format of the - * body. - * - * This is a non-standard addition to the `Blob` API, to make it conform more - * closely to the `BodyMixin` API. - */ - formData(): Promise; - - arrayBuffer(): Promise; - - /** - * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` - */ - bytes(): Promise; - } - - var Blob: typeof Blob; + var Bun: typeof import("bun"); + + namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; + + /** Whether you are using Bun */ + isBun: true; + /** The current git sha of Bun **/ + revision: string; + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + } + + type _ReadableStream = import("stream/web").ReadableStream; + interface ReadableStream extends _ReadableStream {} + var ReadableStream: { + prototype: ReadableStream; + new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + }; + + type _WritableStream = import("stream/web").WritableStream; + interface WritableStream extends _WritableStream {} + var WritableStream: { + prototype: WritableStream; + new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; + }; + + type _Worker = import("worker_threads").Worker; + interface Worker extends _Worker {} + var Worker: { + prototype: Worker; + new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; + }; + + var WebSocket: typeof import("ws").WebSocket; + + type _Crypto = import("crypto").webcrypto.Crypto; + interface Crypto extends _Crypto {} + var Crypto: { + prototype: Crypto; + new (): Crypto; + }; + + var crypto: Crypto; + + /** + * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All + * instances of `TextEncoder` only support UTF-8 encoding. + * + * ```js + * const encoder = new TextEncoder(); + * const uint8array = encoder.encode('this is some data'); + * ``` + */ + interface TextEncoder extends Bun.TextEncoder {} + var TextEncoder: typeof TextEncoder; + + interface TextDecoder extends Bun.TextDecoder {} + var TextDecoder: typeof TextDecoder; + + type _Performance = import("perf_hooks").Performance; + interface Performance extends _Performance {} + var performance: Performance; + + interface Event extends _Event {} + var Event: { + prototype: Event; + new (type: string, eventInitDict?: Bun.EventInit): Event; + }; + + interface EventTarget extends _EventTarget {} + var EventTarget: { + prototype: EventTarget; + new (): EventTarget; + }; + + interface File extends Blob { + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; + readonly lastModified: number; + readonly name: string; + } + + var File: typeof File; + + type _RequestInit = import("undici-types").RequestInit; + interface RequestInit extends _RequestInit { + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: import("bun").S3Options; + } + + /** + * ShadowRealms are a distinct global environment, with its own global object + * containing its own intrinsics and built-ins (standard objects that are not + * bound to global variables, like the initial value of Object.prototype). + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + interface ShadowRealm { + /** + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; + } + + var ShadowRealm: { + prototype: ShadowRealm; + new (): ShadowRealm; + }; + + function queueMicrotask(callback: (...args: any[]) => void): void; + /** + * Log an error using the default exception handler + * @param error Error or string + */ + function reportError(error: any): void; + + interface Timer { + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; + + [Symbol.toPrimitive](): number; + } + + /** + * Cancel a repeating timer by its timer ID. + * @param id timer id + */ + function clearInterval(id?: number | Timer): void; + /** + * Cancel a delayed function call by its timer ID. + * @param id timer id + */ + function clearTimeout(id?: number | Timer): void; + /** + * Cancel an immediate function call by its immediate ID. + * @param id immediate id + */ + function clearImmediate(id?: number | Timer): void; + /** + * Run a function immediately after main event loop is vacant + * @param handler function to call + */ + function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; + /** + * Run a function every `interval` milliseconds + * @param handler function to call + * @param interval milliseconds to wait between calls + */ + function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; + /** + * Run a function after `timeout` (milliseconds) + * @param handler function to call + * @param timeout milliseconds to wait between calls + */ + function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; + + function addEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + function addEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + function removeEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | Bun.EventListenerOptions, + ): void; + function removeEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | Bun.EventListenerOptions, + ): void; + + /** + * Events providing information related to errors in scripts or in files. + */ + interface ErrorEvent extends Event { + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; + } + + var ErrorEvent: { + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; + }; + + /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ + interface CloseEvent extends Event { + /** Returns the WebSocket connection close code provided by the server. */ + readonly code: number; + /** Returns the WebSocket connection close reason provided by the server. */ + readonly reason: string; + /** Returns true if the connection closed cleanly; false otherwise. */ + readonly wasClean: boolean; + } + + var CloseEvent: { + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; + }; + + interface MessageEvent extends Bun.MessageEvent {} + var MessageEvent: { + prototype: MessageEvent; + new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; + }; + + interface CustomEvent extends Event { + /** Returns any custom data event was created with. Typically used for synthetic events. */ + readonly detail: T; + } + + var CustomEvent: { + prototype: CustomEvent; + new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; + }; + + // /** + // * The URL interface represents an object providing static methods used for + // * creating object URLs. + // */ + // interface URL extends _URL { + // new (url: string | URL, base?: string | URL): URL; + // /** Not implemented yet */ + // createObjectURL(obj: Blob): string; + // /** Not implemented yet */ + // revokeObjectURL(url: string): void; + + // /** + // * Check if `url` is a valid URL string + // * + // * @param url URL string to parse + // * @param base URL to resolve against + // */ + // canParse(url: string, base?: string): boolean; + // } + + interface EventListener { + (evt: Event): void; + } + + interface EventListenerObject { + handleEvent(object: Event): void; + } + + interface FetchEvent extends Event { + readonly request: Request; + readonly url: string; + + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; + } + + interface EventMap { + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; + // exit: Event; + } + + interface AddEventListenerOptions extends Bun.EventListenerOptions { + once?: boolean; + passive?: boolean; + signal?: AbortSignal; + } + + /** + * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) + * + * Before using this, be aware of a few things: + * + * **Using this incorrectly will crash your application**. + * + * This API may change any time JavaScriptCore is updated. + * + * Bun may rewrite ESM import specifiers to point to bundled code. This will + * be confusing when using this API, as it will return a string like + * "/node_modules.server.bun". + * + * Bun may inject additional imports into your code. This usually has a `bun:` prefix. + */ + var Loader: { + /** + * ESM module registry + * + * This lets you implement live reload in Bun. If you + * delete a module specifier from this map, the next time it's imported, it + * will be re-transpiled and loaded again. + * + * The keys are the module specifiers and the + * values are metadata about the module. + * + * The keys are an implementation detail for Bun that will change between + * versions. + * + * - Userland modules are an absolute file path + * - Virtual modules have a `bun:` prefix or `node:` prefix + * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill + * - If you have a `node_modules.bun` file, many modules will point to that file + * + * Virtual modules and JS polyfills are embedded in bun's binary. They don't + * point to anywhere in your local filesystem. + */ + registry: Map< + string, + { + key: string; + /** + * This refers to the state the ESM module is in + * + * TODO: make an enum for this number + */ + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; + /** + * Your application will probably crash if you mess with this. + */ + module: { + dependenciesMap: (typeof Loader)["registry"]; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; + /** + * For an already-evaluated module, return the dependencies as module specifiers + * + * This list is already sorted and uniqued. + * + * @example + * + * For this code: + * ```js + * // /foo.js + * import classNames from 'classnames'; + * import React from 'react'; + * import {createElement} from 'react'; + * ``` + * + * This would return: + * ```js + * Loader.dependencyKeysIfEvaluated("/foo.js") + * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] + * ``` + * + * @param specifier - module specifier as it appears in transpiled source code + */ + dependencyKeysIfEvaluated: (specifier: string) => string[]; + /** + * The function JavaScriptCore internally calls when you use an import statement. + * + * This may return a path to `node_modules.server.bun`, which will be confusing. + * + * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} + * instead. + * + * @param specifier - module specifier as it appears in transpiled source code + * @param referrer - module specifier that is resolving this specifier + */ + resolve: (specifier: string, referrer: string) => string; + }; + + interface QueuingStrategy { + highWaterMark?: number; + size?: QueuingStrategySize; + } + + interface QueuingStrategyInit { + /** + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. + */ + highWaterMark: number; + } + + /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ + interface ByteLengthQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + // changed from QueuingStrategySize + // to avoid conflict with lib.dom.d.ts + readonly size: QueuingStrategySize; + } + + var ByteLengthQueuingStrategy: { + prototype: ByteLengthQueuingStrategy; + new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; + }; + + interface ReadableStreamDefaultController { + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; + } + + interface ReadableStreamDirectController { + close(error?: Error): void; + write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; + end(): number | Promise; + flush(): number | Promise; + start(): void; + } + + var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; + }; + + interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { + read(): Promise>; + /** + * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. + * Will only return a promise if the data is not immediately available. + */ + readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; + releaseLock(): void; + } + + var ReadableStreamDefaultReader: { + prototype: ReadableStreamDefaultReader; + new (stream: ReadableStream): ReadableStreamDefaultReader; + }; + + interface ReadableStreamGenericReader { + readonly closed: Promise; + cancel(reason?: any): Promise; + } + + interface ReadableStreamDefaultReadDoneResult { + done: true; + value?: undefined; + } + + interface ReadableStreamDefaultReadValueResult { + done: false; + value: T; + } + + interface ReadableWritablePair { + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; + } + + interface WritableStreamDefaultController { + error(e?: any): void; + } + + var WritableStreamDefaultController: { + prototype: WritableStreamDefaultController; + new (): WritableStreamDefaultController; + }; + + /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ + interface WritableStreamDefaultWriter { + readonly closed: Promise; + readonly desiredSize: number | null; + readonly ready: Promise; + abort(reason?: any): Promise; + close(): Promise; + releaseLock(): void; + write(chunk?: W): Promise; + } + + var WritableStreamDefaultWriter: { + prototype: WritableStreamDefaultWriter; + new (stream: WritableStream): WritableStreamDefaultWriter; + }; + + interface TransformStream { + readonly readable: ReadableStream; + readonly writable: WritableStream; + } + + var TransformStream: { + prototype: TransformStream; + new ( + transformer?: Transformer, + writableStrategy?: QueuingStrategy, + readableStrategy?: QueuingStrategy, + ): TransformStream; + }; + + interface TransformStreamDefaultController { + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; + } + + var TransformStreamDefaultController: { + prototype: TransformStreamDefaultController; + new (): TransformStreamDefaultController; + }; + + interface StreamPipeOptions { + preventAbort?: boolean; + preventCancel?: boolean; + /** + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + * + * Errors and closures of the source and destination streams propagate as follows: + * + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. + * + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. + * + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. + * + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. + */ + preventClose?: boolean; + signal?: AbortSignal; + } + + /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ + interface CountQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + readonly size: QueuingStrategySize; + } + + var CountQueuingStrategy: { + prototype: CountQueuingStrategy; + new (init: QueuingStrategyInit): CountQueuingStrategy; + }; + + interface QueuingStrategySize { + (chunk?: T): number; + } + + interface Transformer { + flush?: Bun.TransformerFlushCallback; + readableType?: undefined; + start?: Bun.TransformerStartCallback; + transform?: Bun.TransformerTransformCallback; + writableType?: undefined; + } + + interface Dict { + [key: string]: T | undefined; + } + + interface ReadOnlyDict { + readonly [key: string]: T | undefined; + } + + interface ErrnoException extends Error { + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; + } + + /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ + interface DOMException extends Error { + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; + } + + var DOMException: { + prototype: DOMException; + new (message?: string, name?: string): DOMException; + }; + + function alert(message?: string): void; + function confirm(message?: string): boolean; + function prompt(message?: string, _default?: string): string | null; + + type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; + var SubtleCrypto: { + prototype: _SubtleCrypto; + new (): _SubtleCrypto; + }; + + type _CryptoKey = import("crypto").webcrypto.CryptoKey; + interface CryptoKey extends _CryptoKey {} + var CryptoKey: { + prototype: CryptoKey; + new (): CryptoKey; + }; + + interface Position { + lineText: string; + file: string; + namespace: string; + line: number; + column: number; + length: number; + offset: number; + } + + class ResolveMessage { + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; + } + + class BuildMessage { + readonly name: "BuildMessage"; + readonly position: Position | null; + readonly message: string; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + } + + // Declare "static" methods in Error + interface ErrorConstructor { + /** Create .stack property on a target object */ + + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; + + stackTraceLimit: number; + } + + interface ArrayBufferConstructor { + new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; + } + + interface ArrayBuffer { + /** + * Read-only. The length of the ArrayBuffer (in bytes). + */ + readonly byteLength: number; + /** + * Resize an ArrayBuffer in-place. + */ + resize(byteLength: number): ArrayBuffer; + + /** + * Returns a section of an ArrayBuffer. + */ + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; + } + + interface SharedArrayBuffer { + /** + * Grow the SharedArrayBuffer in-place. + */ + grow(size: number): SharedArrayBuffer; + } + + interface ArrayConstructor { + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; + + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. Results of the map function are also awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * await Array.fromAsync([1], (n) => n + 1); // [2] + * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. + * @param thisArg - The `this` to which `mapFn` is bound. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; + } + + interface ConsoleOptions { + stdout: import("stream").Writable; + stderr?: import("stream").Writable; + ignoreErrors?: boolean; + colorMode?: boolean | "auto"; + inspectOptions?: import("util").InspectOptions; + groupIndentation?: number; + } + + interface Console { + /** + * Asynchronously read lines from standard input (fd 0) + * + * ```ts + * for await (const line of console) { + * console.log(line); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterableIterator; + + /** + * Write text or bytes to stdout + * + * Unlike {@link console.log}, this does no formatting and doesn't add a + * newline or spaces between arguments. You can pass it strings or bytes or + * any combination of the two. + * + * ```ts + * console.write("hello world!", "\n"); // "hello world\n" + * ``` + * + * @param data - The data to write + * @returns The number of bytes written + * + * This function is not available in the browser. + */ + write(...data: Array): number; + + /** + * Clear the console + */ + clear(): void; + + assert(condition?: boolean, ...data: any[]): void; + + /** + * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) + * @param label label counter + */ + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: any): void; + dirxml(...data: any[]): void; + /** + * Log to stderr in your terminal + * + * Appears in red + * + * @param data something to display + */ + error(...data: any[]): void; + /** Does nothing currently */ + group(...data: any[]): void; + /** Does nothing currently */ + groupCollapsed(...data: any[]): void; + /** Does nothing currently */ + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + /** + * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just + * logging the argument if it can't be parsed as tabular. + * + * ```js + * // These can't be parsed as tabular data + * console.table(Symbol()); + * // Symbol() + * + * console.table(undefined); + * // undefined + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ b โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * ``` + * @param properties Alternate properties for constructing the table. + */ + table(tabularData?: any, properties?: string[]): void; + /** + * Begin a timer to log with {@link console.timeEnd} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + time(label?: string): void; + /** + * End a timer to log with {@link console.time} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + timeStamp(label?: string): void; + trace(...data: any[]): void; + warn(...data: any[]): void; + + /** + * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. + */ + // Console: { + // new (options: ConsoleOptions): Console; + // new ( + // stdout: import("stream").Writable, + // stderr?: import("stream").Writable, + // ignoreErrors?: boolean, + // ): Console; + // }; + } + + var console: Console; + + interface ImportMeta { + /** + * `file://` url string for the current module. + * + * @example + * ```ts + * console.log(import.meta.url); + * "file:///Users/me/projects/my-app/src/my-app.ts" + * ``` + */ + url: string; + /** + * Absolute path to the source file + */ + readonly path: string; + /** + * Absolute path to the directory containing the source file. + * + * Does not have a trailing slash + */ + readonly dir: string; + /** + * Filename of the source file + */ + readonly file: string; + /** + * The environment variables of the process + * + * ```ts + * import.meta.env === process.env + * ``` + */ + readonly env: NodeJS.ProcessEnv; + + /** + * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead + * + * Resolve a module ID the same as if you imported it + * + * The `parent` argument is optional, and defaults to the current module's path. + */ + resolveSync(moduleId: string, parent?: string): string; + + /** + * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all + * calls to `require` with `import.meta.require` when transpiling ES Modules + * for the runtime. + * + * Warning: **This API is not stable** and may change or be removed in the + * future. Use at your own risk. + */ + require: NodeJS.Require; + + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; + + /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ + dirname: string; + + /** Alias of `import.meta.path`. Exists for Node.js compatibility */ + filename: string; + } + + /** + * NodeJS-style `require` function + * + * @param moduleId - The module ID to resolve + */ + var require: NodeJS.Require; + + /** Same as module.exports */ + var exports: any; + + interface NodeModule { + exports: any; + } + + var module: NodeModule; + + /** + * Creates a deep clone of an object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) + */ + function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; + + /** + * Post a message to the parent thread. + * + * Only useful in a worker thread; calling this from the main thread does nothing. + */ + function postMessage(message: any, transfer?: Bun.Transferable[]): void; + + interface EventSourceInit { + withCredentials?: boolean; + } + + interface PromiseConstructor { + /** + * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called + * separately. + * + * This is useful when you want to return a Promise and have code outside the Promise + * resolve or reject it. + * + * ## Example + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); + * + * setTimeout(() => { + * resolve("Hello world!"); + * }, 1000); + * + * await promise; // "Hello world!" + * ``` + * + * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). + */ + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; + } + + interface Navigator { + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; + } + + var navigator: Navigator; + + interface BlobPropertyBag { + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; + } + + interface Blob { + /** + * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + */ + new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; + /** + * Read the data from the blob as a JSON object. + * + * This first decodes the data from UTF-8, then parses it as JSON. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + json(): Promise; + + /** + * Read the data from the blob as a {@link FormData} object. + * + * This first decodes the data from UTF-8, then parses it as a + * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. + * + * The `type` property of the blob is used to determine the format of the + * body. + * + * This is a non-standard addition to the `Blob` API, to make it conform more + * closely to the `BodyMixin` API. + */ + formData(): Promise; + + arrayBuffer(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + */ + bytes(): Promise; + } + + var Blob: typeof Blob; } diff --git a/packages/bun-types/html-rewriter.d.ts b/packages/bun-types/html-rewriter.d.ts index 6bec7fea979ab2..4b2b2954cff397 100644 --- a/packages/bun-types/html-rewriter.d.ts +++ b/packages/bun-types/html-rewriter.d.ts @@ -1,129 +1,129 @@ declare namespace HTMLRewriterTypes { - interface HTMLRewriterElementContentHandlers { - element?(element: Element): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - } + interface HTMLRewriterElementContentHandlers { + element?(element: Element): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + } - interface HTMLRewriterDocumentContentHandlers { - doctype?(doctype: Doctype): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - end?(end: DocumentEnd): void | Promise; - } + interface HTMLRewriterDocumentContentHandlers { + doctype?(doctype: Doctype): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + end?(end: DocumentEnd): void | Promise; + } - interface Text { - /** The text content */ - readonly text: string; - /** Whether this chunk is the last piece of text in a text node */ - readonly lastInTextNode: boolean; - /** Whether this chunk was removed */ - readonly removed: boolean; - /** Insert content before this chunk */ - before(content: Content, options?: ContentOptions): Text; - /** Insert content after this chunk */ - after(content: Content, options?: ContentOptions): Text; - /** Replace this chunk with new content */ - replace(content: Content, options?: ContentOptions): Text; - /** Remove this chunk */ - remove(): Text; - } + interface Text { + /** The text content */ + readonly text: string; + /** Whether this chunk is the last piece of text in a text node */ + readonly lastInTextNode: boolean; + /** Whether this chunk was removed */ + readonly removed: boolean; + /** Insert content before this chunk */ + before(content: Content, options?: ContentOptions): Text; + /** Insert content after this chunk */ + after(content: Content, options?: ContentOptions): Text; + /** Replace this chunk with new content */ + replace(content: Content, options?: ContentOptions): Text; + /** Remove this chunk */ + remove(): Text; + } - interface Doctype { - /** The doctype name (e.g. "html" for ) */ - readonly name: string | null; - /** The doctype public identifier */ - readonly publicId: string | null; - /** The doctype system identifier */ - readonly systemId: string | null; - /** Whether this doctype was removed */ - readonly removed: boolean; - /** Remove this doctype */ - remove(): Doctype; - } + interface Doctype { + /** The doctype name (e.g. "html" for ) */ + readonly name: string | null; + /** The doctype public identifier */ + readonly publicId: string | null; + /** The doctype system identifier */ + readonly systemId: string | null; + /** Whether this doctype was removed */ + readonly removed: boolean; + /** Remove this doctype */ + remove(): Doctype; + } - interface DocumentEnd { - /** Append content at the end of the document */ - append(content: Content, options?: ContentOptions): DocumentEnd; - } + interface DocumentEnd { + /** Append content at the end of the document */ + append(content: Content, options?: ContentOptions): DocumentEnd; + } - interface ContentOptions { - /** Whether to parse the content as HTML */ - html?: boolean; - } + interface ContentOptions { + /** Whether to parse the content as HTML */ + html?: boolean; + } - type Content = string; + type Content = string; - interface Comment { - /** The comment text */ - text: string; - /** Whether this comment was removed */ - readonly removed: boolean; - /** Insert content before this comment */ - before(content: Content, options?: ContentOptions): Comment; - /** Insert content after this comment */ - after(content: Content, options?: ContentOptions): Comment; - /** Replace this comment with new content */ - replace(content: Content, options?: ContentOptions): Comment; - /** Remove this comment */ - remove(): Comment; - } + interface Comment { + /** The comment text */ + text: string; + /** Whether this comment was removed */ + readonly removed: boolean; + /** Insert content before this comment */ + before(content: Content, options?: ContentOptions): Comment; + /** Insert content after this comment */ + after(content: Content, options?: ContentOptions): Comment; + /** Replace this comment with new content */ + replace(content: Content, options?: ContentOptions): Comment; + /** Remove this comment */ + remove(): Comment; + } - interface Element { - /** The tag name in lowercase (e.g. "div", "span") */ - tagName: string; - /** Iterator for the element's attributes */ - readonly attributes: IterableIterator<[string, string]>; - /** Whether this element was removed */ - readonly removed: boolean; - /** Whether the element is explicitly self-closing, e.g. */ - readonly selfClosing: boolean; - /** - * Whether the element can have inner content. Returns `true` unless - * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) - * - or it's self-closing in a foreign context (eg. in SVG, MathML). - */ - readonly canHaveContent: boolean; - /** The element's namespace URI */ - readonly namespaceURI: string; - /** Get an attribute value by name */ - getAttribute(name: string): string | null; - /** Check if an attribute exists */ - hasAttribute(name: string): boolean; - /** Set an attribute value */ - setAttribute(name: string, value: string): Element; - /** Remove an attribute */ - removeAttribute(name: string): Element; - /** Insert content before this element */ - before(content: Content, options?: ContentOptions): Element; - /** Insert content after this element */ - after(content: Content, options?: ContentOptions): Element; - /** Insert content at the start of this element */ - prepend(content: Content, options?: ContentOptions): Element; - /** Insert content at the end of this element */ - append(content: Content, options?: ContentOptions): Element; - /** Replace this element with new content */ - replace(content: Content, options?: ContentOptions): Element; - /** Remove this element and its contents */ - remove(): Element; - /** Remove this element but keep its contents */ - removeAndKeepContent(): Element; - /** Set the inner content of this element */ - setInnerContent(content: Content, options?: ContentOptions): Element; - /** Add a handler for the end tag of this element */ - onEndTag(handler: (tag: EndTag) => void | Promise): void; - } + interface Element { + /** The tag name in lowercase (e.g. "div", "span") */ + tagName: string; + /** Iterator for the element's attributes */ + readonly attributes: IterableIterator<[string, string]>; + /** Whether this element was removed */ + readonly removed: boolean; + /** Whether the element is explicitly self-closing, e.g. */ + readonly selfClosing: boolean; + /** + * Whether the element can have inner content. Returns `true` unless + * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) + * - or it's self-closing in a foreign context (eg. in SVG, MathML). + */ + readonly canHaveContent: boolean; + /** The element's namespace URI */ + readonly namespaceURI: string; + /** Get an attribute value by name */ + getAttribute(name: string): string | null; + /** Check if an attribute exists */ + hasAttribute(name: string): boolean; + /** Set an attribute value */ + setAttribute(name: string, value: string): Element; + /** Remove an attribute */ + removeAttribute(name: string): Element; + /** Insert content before this element */ + before(content: Content, options?: ContentOptions): Element; + /** Insert content after this element */ + after(content: Content, options?: ContentOptions): Element; + /** Insert content at the start of this element */ + prepend(content: Content, options?: ContentOptions): Element; + /** Insert content at the end of this element */ + append(content: Content, options?: ContentOptions): Element; + /** Replace this element with new content */ + replace(content: Content, options?: ContentOptions): Element; + /** Remove this element and its contents */ + remove(): Element; + /** Remove this element but keep its contents */ + removeAndKeepContent(): Element; + /** Set the inner content of this element */ + setInnerContent(content: Content, options?: ContentOptions): Element; + /** Add a handler for the end tag of this element */ + onEndTag(handler: (tag: EndTag) => void | Promise): void; + } - interface EndTag { - /** The tag name in lowercase */ - name: string; - /** Insert content before this end tag */ - before(content: Content, options?: ContentOptions): EndTag; - /** Insert content after this end tag */ - after(content: Content, options?: ContentOptions): EndTag; - /** Remove this end tag */ - remove(): EndTag; - } + interface EndTag { + /** The tag name in lowercase */ + name: string; + /** Insert content before this end tag */ + before(content: Content, options?: ContentOptions): EndTag; + /** Insert content after this end tag */ + after(content: Content, options?: ContentOptions): EndTag; + /** Remove this end tag */ + remove(): EndTag; + } } /** @@ -149,41 +149,36 @@ declare namespace HTMLRewriterTypes { * ``` */ declare class HTMLRewriter { - constructor(); - /** - * Add handlers for elements matching a CSS selector - * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") - * @param handlers - Object containing handler functions for elements, comments, and text nodes - */ - on( - selector: string, - handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers, - ): HTMLRewriter; + constructor(); + /** + * Add handlers for elements matching a CSS selector + * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") + * @param handlers - Object containing handler functions for elements, comments, and text nodes + */ + on(selector: string, handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers): HTMLRewriter; - /** - * Add handlers for document-level events - * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end - */ - onDocument( - handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers, - ): HTMLRewriter; + /** + * Add handlers for document-level events + * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end + */ + onDocument(handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers): HTMLRewriter; - /** - * Transform HTML content - * @param input - The HTML to transform - * @returns A new {@link Response} with the transformed HTML - */ - transform(input: Response | Blob | Bun.BufferSource): Response; - /** - * Transform HTML content - * @param input - The HTML string to transform - * @returns A new {@link String} containing the transformed HTML - */ - transform(input: string): string; - /** - * Transform HTML content - * @param input - The HTML to transform as a {@link ArrayBuffer} - * @returns A new {@link ArrayBuffer} with the transformed HTML - */ - transform(input: ArrayBuffer): ArrayBuffer; + /** + * Transform HTML content + * @param input - The HTML to transform + * @returns A new {@link Response} with the transformed HTML + */ + transform(input: Response | Blob | Bun.BufferSource): Response; + /** + * Transform HTML content + * @param input - The HTML string to transform + * @returns A new {@link String} containing the transformed HTML + */ + transform(input: string): string; + /** + * Transform HTML content + * @param input - The HTML to transform as a {@link ArrayBuffer} + * @returns A new {@link ArrayBuffer} with the transformed HTML + */ + transform(input: ArrayBuffer): ArrayBuffer; } diff --git a/packages/bun-types/jsc.d.ts b/packages/bun-types/jsc.d.ts index c5942da2813fb5..2a07534586516c 100644 --- a/packages/bun-types/jsc.d.ts +++ b/packages/bun-types/jsc.d.ts @@ -1,243 +1,229 @@ declare module "bun:jsc" { - /** - * This used to be called "describe" but it could be confused with the test runner. - */ - function jscDescribe(value: any): string; - function jscDescribeArray(args: any[]): string; - function gcAndSweep(): number; - function fullGC(): number; - function edenGC(): number; - function heapSize(): number; - function heapStats(): { - heapSize: number; - heapCapacity: number; - extraMemorySize: number; - objectCount: number; - protectedObjectCount: number; - globalObjectCount: number; - protectedGlobalObjectCount: number; - objectTypeCounts: Record; - protectedObjectTypeCounts: Record; - }; - function memoryUsage(): { - current: number; - peak: number; - currentCommit: number; - peakCommit: number; - pageFaults: number; - }; - function getRandomSeed(): number; - function setRandomSeed(value: number): void; - function isRope(input: string): boolean; - function callerSourceOrigin(): string; - function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; - function noOSRExitFuzzing( - func: (...args: any[]) => any, - ): (...args: any[]) => any; - function optimizeNextInvocation(func: (...args: any[]) => any): void; - function numberOfDFGCompiles(func: (...args: any[]) => any): number; - function releaseWeakRefs(): void; - function totalCompileTime(func: (...args: any[]) => any): number; - function reoptimizationRetryCount(func: (...args: any[]) => any): number; - function drainMicrotasks(): void; + /** + * This used to be called "describe" but it could be confused with the test runner. + */ + function jscDescribe(value: any): string; + function jscDescribeArray(args: any[]): string; + function gcAndSweep(): number; + function fullGC(): number; + function edenGC(): number; + function heapSize(): number; + function heapStats(): { + heapSize: number; + heapCapacity: number; + extraMemorySize: number; + objectCount: number; + protectedObjectCount: number; + globalObjectCount: number; + protectedGlobalObjectCount: number; + objectTypeCounts: Record; + protectedObjectTypeCounts: Record; + }; + function memoryUsage(): { + current: number; + peak: number; + currentCommit: number; + peakCommit: number; + pageFaults: number; + }; + function getRandomSeed(): number; + function setRandomSeed(value: number): void; + function isRope(input: string): boolean; + function callerSourceOrigin(): string; + function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; + function noOSRExitFuzzing(func: (...args: any[]) => any): (...args: any[]) => any; + function optimizeNextInvocation(func: (...args: any[]) => any): void; + function numberOfDFGCompiles(func: (...args: any[]) => any): number; + function releaseWeakRefs(): void; + function totalCompileTime(func: (...args: any[]) => any): number; + function reoptimizationRetryCount(func: (...args: any[]) => any): number; + function drainMicrotasks(): void; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A SharedArrayBuffer that can be sent to another Bun instance. - */ - function serialize( - value: any, - options?: { binaryType?: "arraybuffer" }, - ): SharedArrayBuffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A SharedArrayBuffer that can be sent to another Bun instance. + */ + function serialize(value: any, options?: { binaryType?: "arraybuffer" }): SharedArrayBuffer; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A Buffer that can be sent to another Bun instance. - */ - function serialize( - value: any, - options?: { binaryType: "nodebuffer" }, - ): Buffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A Buffer that can be sent to another Bun instance. + */ + function serialize(value: any, options?: { binaryType: "nodebuffer" }): Buffer; - /** - * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. - * - * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. - */ - function deserialize( - value: ArrayBufferLike | NodeJS.TypedArray | Buffer, - ): any; + /** + * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. + * + * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. + */ + function deserialize(value: ArrayBufferLike | NodeJS.TypedArray | Buffer): any; - /** - * Set the timezone used by Intl, Date, etc. - * - * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" - * - * @returns The normalized time zone string - * - * You can also set process.env.TZ to the time zone you want to use. - * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` - */ - function setTimeZone(timeZone: string): string; + /** + * Set the timezone used by Intl, Date, etc. + * + * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" + * + * @returns The normalized time zone string + * + * You can also set process.env.TZ to the time zone you want to use. + * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` + */ + function setTimeZone(timeZone: string): string; - interface SamplingProfile { - /** - * A formatted summary of the top functions - * - * Example output: - * ```js - * - * Sampling rate: 100.000000 microseconds. Total samples: 6858 - * Top functions as - * 2948 '#:8' - * 393 'visit#:8' - * 263 'push#:8' - * 164 'scan_ref_scoped#:8' - * 164 'walk#:8' - * 144 'pop#:8' - * 107 'extract_candidates#:8' - * 94 'get#:8' - * 82 'Function#:4294967295' - * 79 'set#:8' - * 67 'forEach#:5' - * 58 'collapse#:8' - * ``` - */ - functions: string; - /** - * A formatted summary of the top bytecodes - * - * Example output: - * ```js - * Tier breakdown: - * ----------------------------------- - * LLInt: 106 (1.545640%) - * Baseline: 2355 (34.339458%) - * DFG: 3290 (47.973170%) - * FTL: 833 (12.146398%) - * js builtin: 132 (1.924759%) - * Wasm: 0 (0.000000%) - * Host: 111 (1.618548%) - * RegExp: 15 (0.218723%) - * C/C++: 0 (0.000000%) - * Unknown Executable: 148 (2.158064%) - * - * Hottest bytecodes as - * 273 'visit#:DFG:bc#63' - * 121 'walk#:DFG:bc#7' - * 119 '#:Baseline:bc#1' - * 82 'Function#:None:' - * 66 '#:DFG:bc#11' - * 65 '#:DFG:bc#33' - * 58 '#:Baseline:bc#7' - * 53 '#:Baseline:bc#23' - * 50 'forEach#:DFG:bc#83' - * 49 'pop#:FTL:bc#65' - * 47 '#:DFG:bc#99' - * 45 '#:DFG:bc#16' - * 44 '#:DFG:bc#7' - * 44 '#:Baseline:bc#30' - * 44 'push#:FTL:bc#214' - * 41 '#:DFG:bc#50' - * 39 'get#:DFG:bc#27' - * 39 '#:Baseline:bc#0' - * 36 '#:DFG:bc#27' - * 36 'Dictionary#:DFG:bc#41' - * 36 'visit#:DFG:bc#81' - * 36 'get#:FTL:bc#11' - * 32 'push#:FTL:bc#49' - * 31 '#:DFG:bc#76' - * 31 '#:DFG:bc#10' - * 31 '#:DFG:bc#73' - * 29 'set#:DFG:bc#28' - * 28 'in_boolean_context#:DFG:bc#104' - * 28 '#:Baseline:' - * 28 'regExpSplitFast#:None:' - * 26 'visit#:DFG:bc#95' - * 26 'pop#:FTL:bc#120' - * 25 '#:DFG:bc#23' - * 25 'push#:FTL:bc#152' - * 24 'push#:FTL:bc#262' - * 24 '#:FTL:bc#10' - * 23 'is_identifier_char#:DFG:bc#22' - * 23 'visit#:DFG:bc#22' - * 22 '#:FTL:bc#27' - * 22 'indexOf#:None:' - * ``` - */ - bytecodes: string; + interface SamplingProfile { + /** + * A formatted summary of the top functions + * + * Example output: + * ```js + * + * Sampling rate: 100.000000 microseconds. Total samples: 6858 + * Top functions as + * 2948 '#:8' + * 393 'visit#:8' + * 263 'push#:8' + * 164 'scan_ref_scoped#:8' + * 164 'walk#:8' + * 144 'pop#:8' + * 107 'extract_candidates#:8' + * 94 'get#:8' + * 82 'Function#:4294967295' + * 79 'set#:8' + * 67 'forEach#:5' + * 58 'collapse#:8' + * ``` + */ + functions: string; + /** + * A formatted summary of the top bytecodes + * + * Example output: + * ```js + * Tier breakdown: + * ----------------------------------- + * LLInt: 106 (1.545640%) + * Baseline: 2355 (34.339458%) + * DFG: 3290 (47.973170%) + * FTL: 833 (12.146398%) + * js builtin: 132 (1.924759%) + * Wasm: 0 (0.000000%) + * Host: 111 (1.618548%) + * RegExp: 15 (0.218723%) + * C/C++: 0 (0.000000%) + * Unknown Executable: 148 (2.158064%) + * + * Hottest bytecodes as + * 273 'visit#:DFG:bc#63' + * 121 'walk#:DFG:bc#7' + * 119 '#:Baseline:bc#1' + * 82 'Function#:None:' + * 66 '#:DFG:bc#11' + * 65 '#:DFG:bc#33' + * 58 '#:Baseline:bc#7' + * 53 '#:Baseline:bc#23' + * 50 'forEach#:DFG:bc#83' + * 49 'pop#:FTL:bc#65' + * 47 '#:DFG:bc#99' + * 45 '#:DFG:bc#16' + * 44 '#:DFG:bc#7' + * 44 '#:Baseline:bc#30' + * 44 'push#:FTL:bc#214' + * 41 '#:DFG:bc#50' + * 39 'get#:DFG:bc#27' + * 39 '#:Baseline:bc#0' + * 36 '#:DFG:bc#27' + * 36 'Dictionary#:DFG:bc#41' + * 36 'visit#:DFG:bc#81' + * 36 'get#:FTL:bc#11' + * 32 'push#:FTL:bc#49' + * 31 '#:DFG:bc#76' + * 31 '#:DFG:bc#10' + * 31 '#:DFG:bc#73' + * 29 'set#:DFG:bc#28' + * 28 'in_boolean_context#:DFG:bc#104' + * 28 '#:Baseline:' + * 28 'regExpSplitFast#:None:' + * 26 'visit#:DFG:bc#95' + * 26 'pop#:FTL:bc#120' + * 25 '#:DFG:bc#23' + * 25 'push#:FTL:bc#152' + * 24 'push#:FTL:bc#262' + * 24 '#:FTL:bc#10' + * 23 'is_identifier_char#:DFG:bc#22' + * 23 'visit#:DFG:bc#22' + * 22 '#:FTL:bc#27' + * 22 'indexOf#:None:' + * ``` + */ + bytecodes: string; - /** - * Stack traces of the top functions - */ - stackTraces: string[]; - } + /** + * Stack traces of the top functions + */ + stackTraces: string[]; + } - /** - * Run JavaScriptCore's sampling profiler for a particular function - * - * This is pretty low-level. - * - * Things to know: - * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation - * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile - * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile - * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile - */ - function profile any>( - callback: T, - sampleInterval?: number, - ...args: Parameters - ): ReturnType extends Promise - ? Promise - : SamplingProfile; + /** + * Run JavaScriptCore's sampling profiler for a particular function + * + * This is pretty low-level. + * + * Things to know: + * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation + * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile + * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile + * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile + */ + function profile any>( + callback: T, + sampleInterval?: number, + ...args: Parameters + ): ReturnType extends Promise ? Promise : SamplingProfile; - /** - * This returns objects which native code has explicitly protected from being - * garbage collected - * - * By calling this function you create another reference to the object, which - * will further prevent it from being garbage collected - * - * This function is mostly a debugging tool for bun itself. - * - * Warning: not all objects returned are supposed to be observable from JavaScript - */ - function getProtectedObjects(): any[]; + /** + * This returns objects which native code has explicitly protected from being + * garbage collected + * + * By calling this function you create another reference to the object, which + * will further prevent it from being garbage collected + * + * This function is mostly a debugging tool for bun itself. + * + * Warning: not all objects returned are supposed to be observable from JavaScript + */ + function getProtectedObjects(): any[]; - /** - * Start a remote debugging socket server on the given port. - * - * This exposes JavaScriptCore's built-in debugging server. - * - * This is untested. May not be supported yet on macOS - */ - function startRemoteDebugger(host?: string, port?: number): void; + /** + * Start a remote debugging socket server on the given port. + * + * This exposes JavaScriptCore's built-in debugging server. + * + * This is untested. May not be supported yet on macOS + */ + function startRemoteDebugger(host?: string, port?: number): void; - /** - * Run JavaScriptCore's sampling profiler - */ - function startSamplingProfiler(optionalDirectory?: string): void; + /** + * Run JavaScriptCore's sampling profiler + */ + function startSamplingProfiler(optionalDirectory?: string): void; - /** - * Non-recursively estimate the memory usage of an object, excluding the memory usage of - * properties or other objects it references. For more accurate per-object - * memory usage, use {@link Bun.generateHeapSnapshot}. - * - * This is a best-effort estimate. It may not be 100% accurate. When it's - * wrong, it may mean the memory is non-contiguous (such as a large array). - * - * Passing a primitive type that isn't heap allocated returns 0. - */ - function estimateShallowMemoryUsageOf( - value: object | CallableFunction | bigint | symbol | string, - ): number; + /** + * Non-recursively estimate the memory usage of an object, excluding the memory usage of + * properties or other objects it references. For more accurate per-object + * memory usage, use {@link Bun.generateHeapSnapshot}. + * + * This is a best-effort estimate. It may not be 100% accurate. When it's + * wrong, it may mean the memory is non-contiguous (such as a large array). + * + * Passing a primitive type that isn't heap allocated returns 0. + */ + function estimateShallowMemoryUsageOf(value: object | CallableFunction | bigint | symbol | string): number; } diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 2eab4c3e4cd897..d49d89cd5ceb86 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -14,2814 +14,2684 @@ * This module aliases `globalThis.Bun`. */ declare module "bun" { - type DistributedOmit = T extends T - ? Omit - : never; - type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; - type ArrayBufferView = NodeJS.TypedArray | DataView; - type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; - type ReadableStreamController = ReadableStreamDefaultController; - type ReadableStreamDefaultReadResult = - | ReadableStreamDefaultReadValueResult - | ReadableStreamDefaultReadDoneResult; - type ReadableStreamReader = ReadableStreamDefaultReader; - type Transferable = ArrayBuffer | import("worker_threads").MessagePort; - type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; - type DOMHighResTimeStamp = number; - type EventListenerOrEventListenerObject = EventListener | EventListenerObject; - - type BlobOrStringOrBuffer = - | string - | NodeJS.TypedArray - | ArrayBufferLike - | Blob; - - type Platform = - | "aix" - | "android" - | "darwin" - | "freebsd" - | "haiku" - | "linux" - | "openbsd" - | "sunos" - | "win32" - | "cygwin" - | "netbsd"; - type Architecture = - | "arm" - | "arm64" - | "ia32" - | "mips" - | "mipsel" - | "ppc" - | "ppc64" - | "s390" - | "s390x" - | "x64"; - - 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. - */ - type UnhandledRejectionListener = ( - reason: unknown, - promise: Promise, - ) => void; - - type MultipleResolveListener = ( - type: MultipleResolveType, - promise: Promise, - value: unknown, - ) => void; - - type ResponseType = - | "basic" - | "cors" - | "default" - | "error" - | "opaque" - | "opaqueredirect"; - - type _TextEncoder = import("util").TextEncoder; - interface TextEncoder extends _TextEncoder { - new ( - encoding?: Bun.Encoding, - options?: { fatal?: boolean; ignoreBOM?: boolean }, - ): TextEncoder; - /** - * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object - * containing the read Unicode code units and written UTF-8 bytes. - * - * ```js - * const encoder = new TextEncoder(); - * const src = 'this is some data'; - * const dest = new Uint8Array(10); - * const { read, written } = encoder.encodeInto(src, dest); - * ``` - * @param src The text to encode. - * @param dest The array to hold the encode result. - */ - encodeInto( - src?: string, - dest?: Bun.BufferSource, - ): import("util").EncodeIntoResult; - } - - type _TextDecoder = import("util").TextDecoder; - interface TextDecoder extends _TextDecoder { - new ( - encoding?: Bun.Encoding, - options?: { fatal?: boolean; ignoreBOM?: boolean }, - ): TextDecoder; - } - - 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 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 extends Bun.EventInit { - detail?: T; - } - - /** A message received by a target object. */ - interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; - readonly source: Bun.MessageEventSource | null; - } - - interface ReadableStreamDefaultReadManyResult { - done: boolean; - /** Number of bytes */ - size: number; - value: T[]; - } - - interface ResponseInit { - headers?: HeadersInit; - /** @default 200 */ - status?: number; - - /** @default "OK" */ - statusText?: string; - } - - interface EventSourceEventMap { - error: Event; - message: MessageEvent; - open: Event; - } - - interface EventInit { - bubbles?: boolean; - cancelable?: boolean; - composed?: boolean; - } - - interface EventListenerOptions { - /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ - capture?: boolean; - } - - 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): void; - respondWith(response: Response | Promise): 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( - 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( - 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 { - (controller: TransformStreamDefaultController): void | PromiseLike; - } - - interface TransformerStartCallback { - (controller: TransformStreamDefaultController): any; - } - - interface TransformerTransformCallback { - ( - chunk: I, - controller: TransformStreamDefaultController, - ): void | PromiseLike; - } - - interface UnderlyingSinkAbortCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSinkCloseCallback { - (): void | PromiseLike; - } - - interface UnderlyingSinkStartCallback { - (controller: WritableStreamDefaultController): any; - } - - interface UnderlyingSinkWriteCallback { - ( - chunk: W, - controller: WritableStreamDefaultController, - ): void | PromiseLike; - } - - interface UnderlyingSourceCancelCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSink { - abort?: UnderlyingSinkAbortCallback; - close?: UnderlyingSinkCloseCallback; - start?: UnderlyingSinkStartCallback; - type?: undefined | "default" | "bytes"; - write?: UnderlyingSinkWriteCallback; - } - - interface UnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull?: UnderlyingSourcePullCallback; - start?: UnderlyingSourceStartCallback; - /** - * Mode "bytes" is not currently supported. - */ - type?: undefined; - } - - interface DirectUnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull: ( - controller: ReadableStreamDirectController, - ) => void | PromiseLike; - type: "direct"; - } - - interface UnderlyingSourcePullCallback { - (controller: ReadableStreamController): void | PromiseLike; - } - - interface UnderlyingSourceStartCallback { - (controller: ReadableStreamController): 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( - type: K, - listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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 - | 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( - type: K, - listener: (this: Worker, ev: WorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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 BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; - } - - 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; - - type ShellFunction = (input: Uint8Array) => Uint8Array; - - type ShellExpression = - | { toString(): string } - | Array - | string - | { raw: string } - | Subprocess - | SpawnOptions.Readable - | SpawnOptions.Writable - | ReadableStream; - - class ShellPromise extends Promise { - 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 | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - } - - 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): 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 Shell: ShellConstructor; - - readonly ShellPromise: { - prototype: ShellPromise; - new (args: unknown, throws: boolean): ShellPromise; - }; - - readonly ShellError: { - prototype: ShellError; - new (): ShellError; - }; - } - - interface ShellError extends Error { - 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; - - bytes(): Uint8Array; - } - - 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; - } - - 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; - - /** - * 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; - - /** - * 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 | 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; - - /** - * 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; - - /** - * 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: 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; - - /** - * 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; - - /** - * 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: 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; - - 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, - maxLength?: number, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - maxLength: number, - asUint8Array: false, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - 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, - ): Promise | 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, - ): Promise | 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; - - /** - * 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, - multipartBoundaryExcludingDashes?: - | string - | NodeJS.TypedArray - | ArrayBufferView, - ): Promise; - - /** - * 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; - - /** - * 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; - - /** - * 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( - stream: ReadableStream, - ): Promise | T[]; - - /** - * Escape the following characters in a string: - * - * - `"` 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. - * - * @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 { - (promise: T | Promise): Promise | T; - status( - promise: T | Promise, - ): "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; - - /** - * - * **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; - }; - - ADDRCONFIG: number; - ALL: number; - 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 - * - * @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 { - /**.p - * 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; - - /** - * 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; - - /** - * Deletes the file. - */ - unlink(): Promise; - - /** - * Deletes the file. ( same as unlink ) - */ - delete(): Promise; - - /** - * Provides useful information about the file. - */ - stat(): Promise; - } - - /** - * Configuration options for SQL client connection and behavior - * @example - * const config: SQLOptions = { - * host: 'localhost', - * port: 5432, - * user: 'dbuser', - * password: 'secretpass', - * database: 'myapp', - * idleTimeout: 30000, - * max: 20, - * onconnect: (client) => { - * console.log('Connected to database'); - * } - * }; - */ - type 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); - /** Database password for authentication (alias for password) */ - pass?: string | (() => Promise); - /** 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 extends Promise { - /** Indicates if the query is currently executing */ - active: boolean; - /** Indicates if the query has been cancelled */ - cancelled: boolean; - /** Cancels the executing query */ - cancel(): SQLQuery; - /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ - simple(): SQLQuery; - /** Executes the query */ - execute(): SQLQuery; - /** Returns the raw query result */ - raw(): SQLQuery; - /** Returns only the values from the query result */ - values(): SQLQuery; - } - - /** - * Callback function type for transaction contexts - * @param sql Function to execute SQL queries within the transaction - */ - type SQLTransactionContextCallback = ( - sql: TransactionSQL, - ) => Promise | Array; - /** - * Callback function type for savepoint contexts - * @param sql Function to execute SQL queries within the savepoint - */ - type SQLSavepointContextCallback = ( - sql: SavepointSQL, - ) => Promise | Array; - - /** - * Main SQL client interface providing connection and transaction management - */ - interface SQL { - /** Creates a new SQL client instance - * @example - * const sql = new SQL("postgres://localhost:5432/mydb"); - * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); - */ - new (connectionString: string | URL): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); - */ - new (connectionString: string | URL, options: SQLOptions): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); - */ - new (options?: SQLOptions): SQL; - /** Executes a SQL query using template literals - * @example - * const [user] = await sql`select * from users where id = ${1}`; - */ - (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; - /** - * Helper function to allow easy use to insert values into a query - * @example - * const result = await sql`insert into users ${sql(users)} RETURNING *`; - */ - (obj: any): SQLQuery; - /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.commitDistributed("my_distributed_transaction"); - */ - commitDistributed(name: string): Promise; - /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.rollbackDistributed("my_distributed_transaction"); - */ - rollbackDistributed(name: string): Promise; - /** Waits for the database connection to be established - * @example - * await sql.connect(); - */ - connect(): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @example - * await sql.close({ timeout: 1 }); - */ - close(options?: { timeout?: number }): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @alias close - * @example - * await sql.end({ timeout: 1 }); - */ - end(options?: { timeout?: number }): Promise; - /** Flushes any pending operations */ - flush(): void; - /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. - * This can be used for running queries on an isolated connection. - * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). - * @example - * const reserved = await sql.reserve(); - * await reserved`select * from users`; - * await reserved.release(); - * // with in a production scenario would be something more like - * const reserved = await sql.reserve(); - * try { - * // ... queries - * } finally { - * await reserved.release(); - * } - * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose - * { - * // always release after context (safer) - * using reserved = await sql.reserve() - * await reserved`select * from users` - * } - */ - reserve(): Promise; - /** Begins a new transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(fn: SQLTransactionContextCallback): Promise; - /** Begins a new transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(options: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction( - options: string, - fn: SQLTransactionContextCallback, - ): Promise; - /** Begins a distributed transaction - * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. - * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. - * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. - * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. - * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. - * @example - * await sql.beginDistributed("numbers", async sql => { - * await sql`create table if not exists numbers (a int)`; - * await sql`insert into numbers values(1)`; - * }); - * // later you can call - * await sql.commitDistributed("numbers"); - * // or await sql.rollbackDistributed("numbers"); - */ - beginDistributed( - name: string, - fn: SQLTransactionContextCallback, - ): Promise; - /** Alternative method to begin a distributed transaction - * @alias beginDistributed - */ - distributed(name: string, fn: SQLTransactionContextCallback): Promise; - /**If you know what you're doing, you can use unsafe to pass any string you'd like. - * Please note that this can lead to SQL injection if you're not careful. - * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. - * @example - * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) - */ - unsafe(string: string, values?: any[]): SQLQuery; - /** - * Reads a file and uses the contents as a query. - * Optional parameters can be used if the file includes $1, $2, etc - * @example - * const result = await sql.file("query.sql", [1, 2, 3]); - */ - file(filename: string, values?: any[]): SQLQuery; - - /** Current client options */ - options: SQLOptions; - - [Symbol.asyncDispose](): Promise; - } - - /** - * Represents a reserved connection from the connection pool - * Extends SQL with additional release functionality - */ - interface ReservedSQL extends SQL { - /** Releases the client back to the connection pool */ - release(): void; - [Symbol.dispose](): void; - } - - /** - * Represents a client within a transaction context - * Extends SQL with savepoint functionality - */ - interface TransactionSQL extends SQL { - /** Creates a savepoint within the current transaction */ - savepoint(name: string, fn: SQLSavepointContextCallback): Promise; - savepoint(fn: SQLSavepointContextCallback): Promise; - } - /** - * Represents a savepoint within a transaction - */ - interface SavepointSQL extends SQL {} - - var sql: SQL; - var postgres: SQL; - var SQL: SQL; - - /** - * This lets you use macros as regular imports - * @example - * ``` - * { - * "react-relay": { - * "graphql": "bun-macro-relay/bun-macro-relay.tsx" - * } - * } - * ``` - */ - type MacroMap = Record>; - - /** - * 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; - } - - 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; - 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; - - /** 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; - }; - 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 = () =>
Hello World
; - * 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; - /** - * 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-run" - | "entry-point-build"; - - interface Import { - path: string; - kind: ImportKind; - } - - /** - * @see [Bun.build API docs](https://bun.sh/docs/bundler#api) - */ - interface BuildConfig { - entrypoints: string[]; // list of file path - outdir?: string; // output directory - /** - * @default "browser" - */ - 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?: /** + type DistributedOmit = T extends T ? Omit : never; + type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; + type ArrayBufferView = NodeJS.TypedArray | DataView; + type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; + type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; + type ReadableStreamController = ReadableStreamDefaultController; + type ReadableStreamDefaultReadResult = + | ReadableStreamDefaultReadValueResult + | ReadableStreamDefaultReadDoneResult; + type ReadableStreamReader = ReadableStreamDefaultReader; + type Transferable = ArrayBuffer | import("worker_threads").MessagePort; + type 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) => 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 BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; + type DOMHighResTimeStamp = number; + type EventListenerOrEventListenerObject = EventListener | EventListenerObject; + + type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob; + + type Platform = + | "aix" + | "android" + | "darwin" + | "freebsd" + | "haiku" + | "linux" + | "openbsd" + | "sunos" + | "win32" + | "cygwin" + | "netbsd"; + type Architecture = "arm" | "arm64" | "ia32" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x" | "x64"; + + 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. + */ + type UnhandledRejectionListener = (reason: unknown, promise: Promise) => void; + + type MultipleResolveListener = (type: MultipleResolveType, promise: Promise, value: unknown) => void; + + type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; + + type _TextEncoder = import("util").TextEncoder; + interface TextEncoder extends _TextEncoder { + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; + /** + * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object + * containing the read Unicode code units and written UTF-8 bytes. + * + * ```js + * const encoder = new TextEncoder(); + * const src = 'this is some data'; + * const dest = new Uint8Array(10); + * const { read, written } = encoder.encodeInto(src, dest); + * ``` + * @param src The text to encode. + * @param dest The array to hold the encode result. + */ + encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; + } + + type _TextDecoder = import("util").TextDecoder; + interface TextDecoder extends _TextDecoder { + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextDecoder; + } + + 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 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 extends Bun.EventInit { + detail?: T; + } + + /** A message received by a target object. */ + interface MessageEvent 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 (typeof MessagePort)[]; // ReadonlyArray; + readonly source: Bun.MessageEventSource | null; + } + + interface ReadableStreamDefaultReadManyResult { + done: boolean; + /** Number of bytes */ + size: number; + value: T[]; + } + + interface ResponseInit { + headers?: HeadersInit; + /** @default 200 */ + status?: number; + + /** @default "OK" */ + statusText?: string; + } + + interface EventSourceEventMap { + error: Event; + message: MessageEvent; + open: Event; + } + + interface EventInit { + bubbles?: boolean; + cancelable?: boolean; + composed?: boolean; + } + + interface EventListenerOptions { + /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ + capture?: boolean; + } + + 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): void; + respondWith(response: Response | Promise): 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( + 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( + 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 { + (controller: TransformStreamDefaultController): void | PromiseLike; + } + + interface TransformerStartCallback { + (controller: TransformStreamDefaultController): any; + } + + interface TransformerTransformCallback { + (chunk: I, controller: TransformStreamDefaultController): void | PromiseLike; + } + + interface UnderlyingSinkAbortCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSinkCloseCallback { + (): void | PromiseLike; + } + + interface UnderlyingSinkStartCallback { + (controller: WritableStreamDefaultController): any; + } + + interface UnderlyingSinkWriteCallback { + (chunk: W, controller: WritableStreamDefaultController): void | PromiseLike; + } + + interface UnderlyingSourceCancelCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSink { + abort?: UnderlyingSinkAbortCallback; + close?: UnderlyingSinkCloseCallback; + start?: UnderlyingSinkStartCallback; + type?: undefined | "default" | "bytes"; + write?: UnderlyingSinkWriteCallback; + } + + interface UnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull?: UnderlyingSourcePullCallback; + start?: UnderlyingSourceStartCallback; + /** + * Mode "bytes" is not currently supported. + */ + type?: undefined; + } + + interface DirectUnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull: (controller: ReadableStreamDirectController) => void | PromiseLike; + type: "direct"; + } + + interface UnderlyingSourcePullCallback { + (controller: ReadableStreamController): void | PromiseLike; + } + + interface UnderlyingSourceStartCallback { + (controller: ReadableStreamController): 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( + type: K, + listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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 | (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( + type: K, + listener: (this: Worker, ev: WorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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 BlobPropertyBag { + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; + } + + 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; + + type ShellFunction = (input: Uint8Array) => Uint8Array; + + type ShellExpression = + | { toString(): string } + | Array + | string + | { raw: string } + | Subprocess + | SpawnOptions.Readable + | SpawnOptions.Writable + | ReadableStream; + + class ShellPromise extends Promise { + 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 | 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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; + } + + 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): 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 Shell: ShellConstructor; + + readonly ShellPromise: { + prototype: ShellPromise; + new (args: unknown, throws: boolean): ShellPromise; + }; + + readonly ShellError: { + prototype: ShellError; + new (): ShellError; + }; + } + + interface ShellError extends Error { + 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; + + bytes(): Uint8Array; + } + + 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; + } + + 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; + + /** + * 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; + + /** + * 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 | 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; + + /** + * 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; + + /** + * 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: 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; + + /** + * 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; + + /** + * 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: 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; + + 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, maxLength?: number): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + maxLength: number, + asUint8Array: false, + ): ArrayBuffer; + function concatArrayBuffers( + buffers: Array, + 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, + ): Promise | 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, + ): Promise | 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; + + /** + * 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, + multipartBoundaryExcludingDashes?: string | NodeJS.TypedArray | ArrayBufferView, + ): Promise; + + /** + * 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; + + /** + * 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; + + /** + * 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(stream: ReadableStream): Promise | T[]; + + /** + * Escape the following characters in a string: + * + * - `"` 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. + * + * @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 { + (promise: T | Promise): Promise | T; + status(promise: T | Promise): "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; + + /** + * + * **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; + }; + + ADDRCONFIG: number; + ALL: number; + 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 + * + * @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 { + /**.p + * 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; + + /** + * 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; + + /** + * Deletes the file. + */ + unlink(): Promise; + + /** + * Deletes the file. ( same as unlink ) + */ + delete(): Promise; + + /** + * Provides useful information about the file. + */ + stat(): Promise; + } + + /** + * Configuration options for SQL client connection and behavior + * @example + * const config: SQLOptions = { + * host: 'localhost', + * port: 5432, + * user: 'dbuser', + * password: 'secretpass', + * database: 'myapp', + * idleTimeout: 30000, + * max: 20, + * onconnect: (client) => { + * console.log('Connected to database'); + * } + * }; + */ + type 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); + /** Database password for authentication (alias for password) */ + pass?: string | (() => Promise); + /** 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 extends Promise { + /** Indicates if the query is currently executing */ + active: boolean; + /** Indicates if the query has been cancelled */ + cancelled: boolean; + /** Cancels the executing query */ + cancel(): SQLQuery; + /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ + simple(): SQLQuery; + /** Executes the query */ + execute(): SQLQuery; + /** Returns the raw query result */ + raw(): SQLQuery; + /** Returns only the values from the query result */ + values(): SQLQuery; + } + + /** + * Callback function type for transaction contexts + * @param sql Function to execute SQL queries within the transaction + */ + type SQLTransactionContextCallback = (sql: TransactionSQL) => Promise | Array; + /** + * Callback function type for savepoint contexts + * @param sql Function to execute SQL queries within the savepoint + */ + type SQLSavepointContextCallback = (sql: SavepointSQL) => Promise | Array; + + /** + * Main SQL client interface providing connection and transaction management + */ + interface SQL { + /** Creates a new SQL client instance + * @example + * const sql = new SQL("postgres://localhost:5432/mydb"); + * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); + */ + new (connectionString: string | URL): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); + */ + new (connectionString: string | URL, options: SQLOptions): SQL; + /** Creates a new SQL client instance with options + * @example + * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); + */ + new (options?: SQLOptions): SQL; + /** Executes a SQL query using template literals + * @example + * const [user] = await sql`select * from users where id = ${1}`; + */ + (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; + /** + * Helper function to allow easy use to insert values into a query + * @example + * const result = await sql`insert into users ${sql(users)} RETURNING *`; + */ + (obj: any): SQLQuery; + /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.commitDistributed("my_distributed_transaction"); + */ + commitDistributed(name: string): Promise; + /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL + * @example + * await sql.rollbackDistributed("my_distributed_transaction"); + */ + rollbackDistributed(name: string): Promise; + /** Waits for the database connection to be established + * @example + * await sql.connect(); + */ + connect(): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @example + * await sql.close({ timeout: 1 }); + */ + close(options?: { timeout?: number }): Promise; + /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. + * @alias close + * @example + * await sql.end({ timeout: 1 }); + */ + end(options?: { timeout?: number }): Promise; + /** Flushes any pending operations */ + flush(): void; + /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. + * This can be used for running queries on an isolated connection. + * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). + * @example + * const reserved = await sql.reserve(); + * await reserved`select * from users`; + * await reserved.release(); + * // with in a production scenario would be something more like + * const reserved = await sql.reserve(); + * try { + * // ... queries + * } finally { + * await reserved.release(); + * } + * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose + * { + * // always release after context (safer) + * using reserved = await sql.reserve() + * await reserved`select * from users` + * } + */ + reserve(): Promise; + /** Begins a new transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(fn: SQLTransactionContextCallback): Promise; + /** Begins a new transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @example + * const [user, account] = await sql.begin("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + begin(options: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction(async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a transaction with options + * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. + * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. + * @alias begin + * @example + * const [user, account] = await sql.transaction("read write", async sql => { + * const [user] = await sql` + * insert into users ( + * name + * ) values ( + * 'Murray' + * ) + * returning * + * ` + * const [account] = await sql` + * insert into accounts ( + * user_id + * ) values ( + * ${ user.user_id } + * ) + * returning * + * ` + * return [user, account] + * }) + */ + transaction(options: string, fn: SQLTransactionContextCallback): Promise; + /** Begins a distributed transaction + * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. + * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. + * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. + * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. + * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. + * @example + * await sql.beginDistributed("numbers", async sql => { + * await sql`create table if not exists numbers (a int)`; + * await sql`insert into numbers values(1)`; + * }); + * // later you can call + * await sql.commitDistributed("numbers"); + * // or await sql.rollbackDistributed("numbers"); + */ + beginDistributed(name: string, fn: SQLTransactionContextCallback): Promise; + /** Alternative method to begin a distributed transaction + * @alias beginDistributed + */ + distributed(name: string, fn: SQLTransactionContextCallback): Promise; + /**If you know what you're doing, you can use unsafe to pass any string you'd like. + * Please note that this can lead to SQL injection if you're not careful. + * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. + * @example + * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) + */ + unsafe(string: string, values?: any[]): SQLQuery; + /** + * Reads a file and uses the contents as a query. + * Optional parameters can be used if the file includes $1, $2, etc + * @example + * const result = await sql.file("query.sql", [1, 2, 3]); + */ + file(filename: string, values?: any[]): SQLQuery; + + /** Current client options */ + options: SQLOptions; + + [Symbol.asyncDispose](): Promise; + } + + /** + * Represents a reserved connection from the connection pool + * Extends SQL with additional release functionality + */ + interface ReservedSQL extends SQL { + /** Releases the client back to the connection pool */ + release(): void; + [Symbol.dispose](): void; + } + + /** + * Represents a client within a transaction context + * Extends SQL with savepoint functionality + */ + interface TransactionSQL extends SQL { + /** Creates a savepoint within the current transaction */ + savepoint(name: string, fn: SQLSavepointContextCallback): Promise; + savepoint(fn: SQLSavepointContextCallback): Promise; + } + /** + * Represents a savepoint within a transaction + */ + interface SavepointSQL extends SQL {} + + var sql: SQL; + var postgres: SQL; + var SQL: SQL; + + /** + * This lets you use macros as regular imports + * @example + * ``` + * { + * "react-relay": { + * "graphql": "bun-macro-relay/bun-macro-relay.tsx" + * } + * } + * ``` + */ + type MacroMap = Record>; + + /** + * 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; + } + + 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; + 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; + + /** 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; + }; + 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 = () =>
Hello World
; + * 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; + /** + * 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-run" + | "entry-point-build"; + + interface Import { + path: string; + kind: ImportKind; + } + + /** + * @see [Bun.build API docs](https://bun.sh/docs/bundler#api) + */ + interface BuildConfig { + entrypoints: string[]; // list of file path + outdir?: string; // output directory + /** + * @default "browser" + */ + 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; - // origin?: string; // e.g. http://mydomain.com - loader?: { [k in string]: Loader }; - /** - * Specifies if and how to generate source maps. - * - * - `"none"` - No source maps are generated - * - `"linked"` - A separate `*.ext.map` file is generated alongside each - * `*.ext` file. A `//# sourceMappingURL` comment is added to the output - * file to link the two. Requires `outdir` to be set. - * - `"inline"` - an inline source map is appended to the output file. - * - `"external"` - Generate a separate source map file for each input file. - * No `//# sourceMappingURL` comment is added to the output file. - * - * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. - * - * @default "none" - * - * @see {@link outdir} required for `"linked"` maps - * @see {@link publicPath} to customize the base url of linked source maps - */ - sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; - /** - * 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; - - /** - * Controls how environment variables are handled during bundling. - * - * Can be one of: - * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` - * references to string literals containing the actual environment variable values - * - `"disable"`: Disables environment variable injection entirely - * - A string ending in `*`: Inlines environment variables that match the given prefix. - * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" - * - * @example - * ```ts - * Bun.build({ - * env: "MY_PUBLIC_*", - * entrypoints: ["src/index.ts"], - * }) - * ``` - */ - env?: "inline" | "disable" | `${string}*`; - /** - * Whether to enable minification. - * - * Use `true`/`false` to enable/disable all minification options. Alternatively, - * you can pass an object for granular control over certain minifications. - * - * @default false - */ - 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; - - /** - * Drop function calls to matching property accesses. - */ - drop?: string[]; - - /** - * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. - * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. - * This defaults to `true`. - */ - throw?: boolean; - } - - 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 password. - * If empty, always returns false - */ - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - * - * If specified and the algorithm does not match the hash, this function - * throws an error. - */ - algorithm?: Password.AlgorithmLabel, - ): Promise; - /** - * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. - * - * @returns A promise that resolves to the hashed password - * - * ## Example with argon2 - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world"); - * console.log(hash); // $argon2id$v=1... - * const verify = await password.verify("hello world", hash); - * ``` - * ## Example with bcrypt - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world", "bcrypt"); - * console.log(hash); // $2b$10$... - * const verify = await password.verify("hello world", hash); - * ``` - */ - hash( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before - */ - algorithm?: - | Password.AlgorithmLabel - | Password.Argon2Algorithm - | Password.BCryptAlgorithm, - ): Promise; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.verify} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - verifySync( - password: Bun.StringOrBuffer, - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - */ - algorithm?: Password.AlgorithmLabel, - ): boolean; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.hash} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - hashSync( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before - */ - algorithm?: - | Password.AlgorithmLabel - | Password.Argon2Algorithm - | Password.BCryptAlgorithm, - ): string; - }; - - interface BuildArtifact extends Blob { - path: string; - loader: Loader; - hash: string | null; - kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; - sourcemap: BuildArtifact | null; - } - - interface BuildOutput { - outputs: BuildArtifact[]; - success: boolean; - logs: Array; - } - - /** + | "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; + // origin?: string; // e.g. http://mydomain.com + loader?: { [k in string]: Loader }; + /** + * Specifies if and how to generate source maps. + * + * - `"none"` - No source maps are generated + * - `"linked"` - A separate `*.ext.map` file is generated alongside each + * `*.ext` file. A `//# sourceMappingURL` comment is added to the output + * file to link the two. Requires `outdir` to be set. + * - `"inline"` - an inline source map is appended to the output file. + * - `"external"` - Generate a separate source map file for each input file. + * No `//# sourceMappingURL` comment is added to the output file. + * + * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. + * + * @default "none" + * + * @see {@link outdir} required for `"linked"` maps + * @see {@link publicPath} to customize the base url of linked source maps + */ + sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; + /** + * 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; + + /** + * Controls how environment variables are handled during bundling. + * + * Can be one of: + * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` + * references to string literals containing the actual environment variable values + * - `"disable"`: Disables environment variable injection entirely + * - A string ending in `*`: Inlines environment variables that match the given prefix. + * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" + * + * @example + * ```ts + * Bun.build({ + * env: "MY_PUBLIC_*", + * entrypoints: ["src/index.ts"], + * }) + * ``` + */ + env?: "inline" | "disable" | `${string}*`; + /** + * Whether to enable minification. + * + * Use `true`/`false` to enable/disable all minification options. Alternatively, + * you can pass an object for granular control over certain minifications. + * + * @default false + */ + 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; + + /** + * Drop function calls to matching property accesses. + */ + drop?: string[]; + + /** + * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. + * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. + * This defaults to `true`. + */ + throw?: boolean; + } + + 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 password. + * If empty, always returns false + */ + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + * + * If specified and the algorithm does not match the hash, this function + * throws an error. + */ + algorithm?: Password.AlgorithmLabel, + ): Promise; + /** + * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. + * + * @returns A promise that resolves to the hashed password + * + * ## Example with argon2 + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world"); + * console.log(hash); // $argon2id$v=1... + * const verify = await password.verify("hello world", hash); + * ``` + * ## Example with bcrypt + * ```ts + * import {password} from "bun"; + * const hash = await password.hash("hello world", "bcrypt"); + * console.log(hash); // $2b$10$... + * const verify = await password.verify("hello world", hash); + * ``` + */ + hash( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before + */ + algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, + ): Promise; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.verify} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + verifySync( + password: Bun.StringOrBuffer, + hash: Bun.StringOrBuffer, + /** + * If not specified, the algorithm will be inferred from the hash. + */ + algorithm?: Password.AlgorithmLabel, + ): boolean; + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.hash} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig contributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + hashSync( + /** + * The password to hash + * + * If empty, this function throws an error. It is usually a programming + * mistake to hash an empty password. + */ + password: Bun.StringOrBuffer, + /** + * @default "argon2id" + * + * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before + */ + algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, + ): string; + }; + + interface BuildArtifact extends Blob { + path: string; + loader: Loader; + hash: string | null; + kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; + sourcemap: BuildArtifact | null; + } + + interface BuildOutput { + outputs: BuildArtifact[]; + success: boolean; + logs: Array; + } + + /** * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. * * @param {Object} config - Build configuration options @@ -3042,1377 +2912,1280 @@ declare module "bun" { }); ``` */ - function build(config: BuildConfig): Promise; - /** - * A status that represents the outcome of a sent message. - * - * - if **0**, the message was **dropped**. - * - if **-1**, there is **backpressure** of messages. - * - if **>0**, it represents the **number of bytes sent**. - * - * @example - * ```js - * const status = ws.send("Hello!"); - * if (status === 0) { - * console.log("Message was dropped"); - * } else if (status === -1) { - * console.log("Backpressure was applied"); - * } else { - * console.log(`Success! Sent ${status} bytes`); - * } - * ``` - */ - type ServerWebSocketSendStatus = number; - - /** - * A state that represents if a WebSocket is connected. - * - * - `WebSocket.CONNECTING` is `0`, the connection is pending. - * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. - * - `WebSocket.CLOSING` is `2`, the connection is closing. - * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState - */ - type WebSocketReadyState = 0 | 1 | 2 | 3; - - /** - * A fast WebSocket designed for servers. - * - * Features: - * - **Message compression** - Messages can be compressed - * - **Backpressure** - If the client is not ready to receive data, the server will tell you. - * - **Dropped messages** - If the client cannot receive data, the server will tell you. - * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics - * - * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. - * - * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). - * - * @example - * import { serve } from "bun"; - * - * serve({ - * websocket: { - * open(ws) { - * console.log("Connected", ws.remoteAddress); - * }, - * message(ws, data) { - * console.log("Received", data); - * ws.send(data); - * }, - * close(ws, code, reason) { - * console.log("Disconnected", code, reason); - * }, - * } - * }); - */ - interface ServerWebSocket { - /** - * Sends a message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - * ws.send(new Uint8Array([1, 2, 3, 4])); - */ - send( - data: string | BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a text message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - */ - sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send(new TextEncoder().encode("Hello!")); - * ws.send(new Uint8Array([1, 2, 3, 4]), true); - */ - sendBinary( - data: BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Closes the connection. - * - * Here is a list of close codes: - * - `1000` means "normal closure" **(default)** - * - `1009` means a message was too big and was rejected - * - `1011` means the server encountered an error - * - `1012` means the server is restarting - * - `1013` means the server is too busy or the client is rate-limited - * - `4000` through `4999` are reserved for applications (you can use it!) - * - * To close the connection abruptly, use `terminate()`. - * - * @param code The close code to send - * @param reason The close reason to send - */ - close(code?: number, reason?: string): void; - - /** - * Abruptly close the connection. - * - * To gracefully close the connection, use `close()`. - */ - terminate(): void; - - /** - * Sends a ping. - * - * @param data The data to send - */ - ping(data?: string | BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a pong. - * - * @param data The data to send - */ - pong(data?: string | BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); - */ - publish( - topic: string, - data: string | BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a text message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - */ - publishText( - topic: string, - data: string, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Sends a binary message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", new TextEncoder().encode("Hello!")); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); - */ - publishBinary( - topic: string, - data: BufferSource, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * Subscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - */ - subscribe(topic: string): void; - - /** - * Unsubscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.unsubscribe("chat"); - */ - unsubscribe(topic: string): void; - - /** - * Is the client subscribed to a topic? - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - * console.log(ws.isSubscribed("chat")); // true - */ - isSubscribed(topic: string): boolean; - - /** - * Batches `send()` and `publish()` operations, which makes it faster to send data. - * - * The `message`, `open`, and `drain` callbacks are automatically corked, so - * you only need to call this if you are sending messages outside of those - * callbacks or in async functions. - * - * @param callback The callback to run. - * @example - * ws.cork((ctx) => { - * ctx.send("These messages"); - * ctx.sendText("are sent"); - * ctx.sendBinary(new TextEncoder().encode("together!")); - * }); - */ - cork(callback: (ws: ServerWebSocket) => T): T; - - /** - * The IP address of the client. - * - * @example - * console.log(socket.remoteAddress); // "127.0.0.1" - */ - readonly remoteAddress: string; - - /** - * The ready state of the client. - * - * - if `0`, the client is connecting. - * - if `1`, the client is connected. - * - if `2`, the client is closing. - * - if `3`, the client is closed. - * - * @example - * console.log(socket.readyState); // 1 - */ - readonly readyState: WebSocketReadyState; - - /** - * Sets how binary data is returned in events. - * - * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** - * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. - * - if `uint8array`, binary data is returned as `Uint8Array` objects. - * - * @example - * let ws: WebSocket; - * ws.binaryType = "uint8array"; - * ws.addEventListener("message", ({ data }) => { - * console.log(data instanceof Uint8Array); // true - * }); - */ - binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; - - /** - * Custom data that you can assign to a client, can be read and written at any time. - * - * @example - * import { serve } from "bun"; - * - * serve({ - * fetch(request, server) { - * const data = { - * accessToken: request.headers.get("Authorization"), - * }; - * if (server.upgrade(request, { data })) { - * return; - * } - * return new Response(); - * }, - * websocket: { - * open(ws) { - * console.log(ws.data.accessToken); - * } - * } - * }); - */ - data: T; - - getBufferedAmount(): number; - } - - /** - * Compression options for WebSocket messages. - */ - type WebSocketCompressor = - | "disable" - | "shared" - | "dedicated" - | "3KB" - | "4KB" - | "8KB" - | "16KB" - | "32KB" - | "64KB" - | "128KB" - | "256KB"; - - /** - * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} - * - * @example - * ```ts - * import { websocket, serve } from "bun"; - * - * serve<{name: string}>({ - * port: 3000, - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log(`${ws.data.name}: ${message}`); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req, { - * data: { - * name: new URL(req.url).searchParams.get("name"), - * }, - * }); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * return; - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - */ - interface WebSocketHandler { - /** - * Called when the server receives an incoming message. - * - * If the message is not a `string`, its type is based on the value of `binaryType`. - * - if `nodebuffer`, then the message is a `Buffer`. - * - if `arraybuffer`, then the message is an `ArrayBuffer`. - * - if `uint8array`, then the message is a `Uint8Array`. - * - * @param ws The websocket that sent the message - * @param message The message received - */ - message( - ws: ServerWebSocket, - message: string | Buffer, - ): void | Promise; - - /** - * Called when a connection is opened. - * - * @param ws The websocket that was opened - */ - open?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection was previously under backpressure, - * meaning it had too many queued messages, but is now ready to receive more data. - * - * @param ws The websocket that is ready for more data - */ - drain?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection is closed. - * - * @param ws The websocket that was closed - * @param code The close code - * @param message The close message - */ - close?( - ws: ServerWebSocket, - code: number, - reason: string, - ): void | Promise; - - /** - * Called when a ping is sent. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - ping?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Called when a pong is received. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - pong?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Sets the maximum size of messages in bytes. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - maxPayloadLength?: number; - - /** - * Sets the maximum number of bytes that can be buffered on a single connection. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - backpressureLimit?: number; - - /** - * Sets if the connection should be closed if `backpressureLimit` is reached. - * - * Default is `false`. - */ - closeOnBackpressureLimit?: boolean; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to no messages or pings. - * - * Default is 2 minutes, or `120` in seconds. - */ - idleTimeout?: number; - - /** - * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? - * - * Default is `false`. - */ - publishToSelf?: boolean; - - /** - * Should the server automatically send and respond to pings to clients? - * - * Default is `true`. - */ - sendPings?: boolean; - - /** - * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. - * - * Default is `false`. - */ - perMessageDeflate?: - | boolean - | { - /** - * Sets the compression level. - */ - compress?: WebSocketCompressor | boolean; - /** - * Sets the decompression level. - */ - decompress?: WebSocketCompressor | boolean; - }; - } - - namespace RouterTypes { - type ExtractRouteParams = - T extends `${string}:${infer Param}/${infer Rest}` - ? { [K in Param]: string } & ExtractRouteParams - : T extends `${string}:${infer Param}` - ? { [K in Param]: string } - : T extends `${string}*` - ? {} - : {}; - - type RouteHandler = ( - req: BunRequest, - server: Server, - ) => Response | Promise; - - type HTTPMethod = - | "GET" - | "POST" - | "PUT" - | "DELETE" - | "PATCH" - | "HEAD" - | "OPTIONS"; - - type RouteHandlerObject = { - [K in HTTPMethod]?: RouteHandler; - }; - - type RouteValue = - | Response - | false - | RouteHandler - | RouteHandlerObject; - } - - interface BunRequest extends Request { - params: RouterTypes.ExtractRouteParams; - } - - interface GenericServeOptions { - /** - * What URI should be used to make {@link Request.url} absolute? - * - * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one - * - * @example - * ```js - * "http://my-app.com" - * ``` - * - * @example - * ```js - * "https://wongmjane.com/" - * ``` - * - * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. - * - * @example - * "http://localhost:3000" - */ - // baseURI?: string; - - /** - * What is the maximum size of a request body? (in bytes) - * @default 1024 * 1024 * 128 // 128MB - */ - maxRequestBodySize?: number; - - /** - * Render contextual errors? This enables bun's error page - * @default process.env.NODE_ENV !== 'production' - */ - development?: - | boolean - | { - /** - * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) - * - * @default true if process.env.NODE_ENV !== 'production' - * - */ - hmr?: boolean; - }; - - error?: ( - this: Server, - error: ErrorLike, - ) => Response | Promise | undefined | Promise; - - /** - * Uniquely identify a server instance with an ID - * - * ### When bun is started with the `--hot` flag - * - * This string will be used to hot reload the server without interrupting - * pending requests or websockets. If not provided, a value will be - * generated. To disable hot reloading, set this value to `null`. - * - * ### When bun is not started with the `--hot` flag - * - * This string will currently do nothing. But in the future it could be useful for logs or metrics. - */ - id?: string | null; - } - - interface ServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * Whether the `SO_REUSEPORT` flag should be set. - * - * This allows multiple processes to bind to the same port, which is useful for load balancing. - * - * @default false - */ - reusePort?: boolean; - - /** - * Whether the `IPV6_V6ONLY` flag should be set. - * @default false - */ - ipv6Only?: boolean; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix?: never; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to inactivity. - * - * Default is `10` seconds. - */ - idleTimeout?: number; - - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | Promise; - } - - interface UnixServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | Promise; - } - - interface WebSocketServeOptions - extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | void | Promise; - } - - interface UnixWebSocketServeOptions - extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | Promise; - } - - interface TLSWebSocketServeOptions - extends WebSocketServeOptions, - TLSOptionsAsDeprecated { - unix?: never; - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSWebSocketServeOptions - extends UnixWebSocketServeOptions, - TLSOptionsAsDeprecated { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - tls?: TLSOptions | TLSOptions[]; - } - - interface ErrorLike extends Error { - code?: string; - errno?: number; - syscall?: string; - } - - interface TLSOptions { - /** - * Passphrase for the TLS key - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - // Note for contributors: TLSOptionsAsDeprecated should be considered immutable - // and new TLS option keys should only be supported on the `.tls` property (which comes - // from the TLSOptions interface above). - /** - * This exists because Bun.serve() extends the TLSOptions object, but - * they're now considered deprecated. You should be passing the - * options on `.tls` instead. - * - * @example - * ```ts - * //// OLD //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * passphrase: "secret", - * }); - * - * //// NEW //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * tls: { - * passphrase: "secret", - * }, - * }); - * ``` - */ - interface TLSOptionsAsDeprecated { - /** - * Passphrase for the TLS key - * - * @deprecated Use `.tls.passphrase` instead - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - * - * @deprecated Use `.tls.dhParamsFile` instead - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - * - * @deprecated Use `.tls.serverName` instead - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - * - * @deprecated Use `.tls.lowMemoryMode` instead - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - * - * @deprecated Use `.tls.rejectUnauthorized` instead - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - * - * @deprecated Use `.tls.requestCert` instead - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - * - * @deprecated Use `.tls.ca` instead - */ - ca?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - * - * @deprecated Use `.tls.cert` instead - */ - cert?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - * - * @deprecated Use `.tls.key` instead - */ - key?: - | string - | Buffer - | BunFile - | Array - | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - * - * @deprecated `Use .tls.secureOptions` instead - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSServeOptions - extends UnixServeOptions, - TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface SocketAddress { - /** - * The IP address of the client. - */ - address: string; - /** - * The port of the client. - */ - port: number; - /** - * The IP family ("IPv4" or "IPv6"). - */ - family: "IPv4" | "IPv6"; - } - - /** - * HTTP & HTTPS Server - * - * To start the server, see {@link serve} - * - * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. - * That means starting a new server allocates about 500 KB of memory. Try to - * avoid starting and stopping the server often (unless it's a new instance of bun). - * - * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. - */ - interface Server extends Disposable { - /** - * Stop listening to prevent new connections from being accepted. - * - * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. - * - * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. - * @default false - */ - stop(closeActiveConnections?: boolean): Promise; - - /** - * Update the `fetch` and `error` handlers without restarting the server. - * - * This is useful if you want to change the behavior of your server without - * restarting it or for hot reloading. - * - * @example - * - * ```js - * // create the server - * const server = Bun.serve({ - * fetch(request) { - * return new Response("Hello World v1") - * } - * }); - * - * // Update the server to return a different response - * server.reload({ - * fetch(request) { - * return new Response("Hello World v2") - * } - * }); - * ``` - * - * Passing other options such as `port` or `hostname` won't do anything. - */ - reload }>( - options: ( - | (Omit & { - routes: R; - fetch?: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | (Omit & { - routes?: never; - fetch: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. - */ - static?: R; - }, - ): Server; - - /** - * Mock the fetch handler for a running server. - * - * This feature is not fully implemented yet. It doesn't normalize URLs - * consistently in all cases and it doesn't yet call the `error` handler - * consistently. This needs to be fixed - */ - fetch(request: Request | string): Response | Promise; - - /** - * Upgrade a {@link Request} to a {@link ServerWebSocket} - * - * @param request The {@link Request} to upgrade - * @param options Pass headers or attach data to the {@link ServerWebSocket} - * - * @returns `true` if the upgrade was successful and `false` if it failed - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * What you pass to `data` is available on the {@link ServerWebSocket.data} property - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - upgrade( - request: Request, - options?: { - /** - * Send any additional headers while upgrading, like cookies - */ - headers?: HeadersInit; - /** - * This value is passed to the {@link ServerWebSocket.data} property - */ - data?: T; - }, - ): boolean; - - /** - * Send a message to all connected {@link ServerWebSocket} subscribed to a topic - * - * @param topic The topic to publish to - * @param data The data to send - * @param compress Should the data be compressed? Ignored if the client does not support compression. - * - * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. - * - * @example - * - * ```js - * server.publish("chat", "Hello World"); - * ``` - * - * @example - * ```js - * server.publish("chat", new Uint8Array([1, 2, 3, 4])); - * ``` - * - * @example - * ```js - * server.publish("chat", new ArrayBuffer(4), true); - * ``` - * - * @example - * ```js - * server.publish("chat", new DataView(new ArrayBuffer(4))); - * ``` - */ - publish( - topic: string, - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * A count of connections subscribed to a given topic - * - * This operation will loop through each topic internally to get the count. - * - * @param topic the websocket topic to check how many subscribers are connected to - * @returns the number of subscribers - */ - subscriberCount(topic: string): number; - - /** - * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * return new Response(server.requestIP(request)); - * } - * } - * ``` - */ - requestIP(request: Request): SocketAddress | null; - - /** - * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * server.timeout(request, 60); - * await Bun.sleep(30000); - * return new Response("30 seconds have passed"); - * } - * } - * ``` - */ - timeout(request: Request, seconds: number): void; - /** - * Undo a call to {@link Server.unref} - * - * If the Server has already been stopped, this does nothing. - * - * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. - */ - ref(): void; - - /** - * Don't keep the process alive if this server is the only thing left. - * Active connections may continue to keep the process alive. - * - * By default, the server is ref'd. - * - * To prevent new connections from being accepted, use {@link Server.stop} - */ - unref(): void; - - /** - * How many requests are in-flight right now? - */ - readonly pendingRequests: number; - - /** - * How many {@link ServerWebSocket}s are in-flight right now? - */ - readonly pendingWebSockets: number; - - readonly url: URL; - - readonly port: number; - /** - * The hostname the server is listening on. Does not include the port - * @example - * ```js - * "localhost" - * ``` - */ - readonly hostname: string; - /** - * Is the server running in development mode? - * - * In development mode, `Bun.serve()` returns rendered error messages with - * stack traces instead of a generic 500 error. This makes debugging easier, - * but development mode shouldn't be used in production or you will risk - * leaking sensitive information. - */ - readonly development: boolean; - - /** - * An identifier of the server instance - * - * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. - * - * When bun is not started with the `--hot` flag, this ID is currently unused. - */ - readonly id: string; - } - - type Serve = - | ServeOptions - | TLSServeOptions - | UnixServeOptions - | UnixTLSServeOptions - | WebSocketServeOptions - | TLSWebSocketServeOptions - | UnixWebSocketServeOptions - | UnixTLSWebSocketServeOptions; - - /** - Bun.serve provides a high-performance HTTP server with built-in routing support. - It enables both function-based and object-based route handlers with type-safe - parameters and method-specific handling. + function build(config: BuildConfig): Promise; + /** + * A status that represents the outcome of a sent message. + * + * - if **0**, the message was **dropped**. + * - if **-1**, there is **backpressure** of messages. + * - if **>0**, it represents the **number of bytes sent**. + * + * @example + * ```js + * const status = ws.send("Hello!"); + * if (status === 0) { + * console.log("Message was dropped"); + * } else if (status === -1) { + * console.log("Backpressure was applied"); + * } else { + * console.log(`Success! Sent ${status} bytes`); + * } + * ``` + */ + type ServerWebSocketSendStatus = number; + + /** + * A state that represents if a WebSocket is connected. + * + * - `WebSocket.CONNECTING` is `0`, the connection is pending. + * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. + * - `WebSocket.CLOSING` is `2`, the connection is closing. + * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState + */ + type WebSocketReadyState = 0 | 1 | 2 | 3; - @example Basic Usage - ```ts - Bun.serve({ - port: 3000, - fetch(req) { - return new Response("Hello World"); + /** + * A fast WebSocket designed for servers. + * + * Features: + * - **Message compression** - Messages can be compressed + * - **Backpressure** - If the client is not ready to receive data, the server will tell you. + * - **Dropped messages** - If the client cannot receive data, the server will tell you. + * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics + * + * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. + * + * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). + * + * @example + * import { serve } from "bun"; + * + * serve({ + * websocket: { + * open(ws) { + * console.log("Connected", ws.remoteAddress); + * }, + * message(ws, data) { + * console.log("Received", data); + * ws.send(data); + * }, + * close(ws, code, reason) { + * console.log("Disconnected", code, reason); + * }, + * } + * }); + */ + interface ServerWebSocket { + /** + * Sends a message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + * ws.send(new Uint8Array([1, 2, 3, 4])); + */ + send(data: string | BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a text message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send("Hello!"); + * ws.send("Compress this.", true); + */ + sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to the client. + * + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.send(new TextEncoder().encode("Hello!")); + * ws.send(new Uint8Array([1, 2, 3, 4]), true); + */ + sendBinary(data: BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Closes the connection. + * + * Here is a list of close codes: + * - `1000` means "normal closure" **(default)** + * - `1009` means a message was too big and was rejected + * - `1011` means the server encountered an error + * - `1012` means the server is restarting + * - `1013` means the server is too busy or the client is rate-limited + * - `4000` through `4999` are reserved for applications (you can use it!) + * + * To close the connection abruptly, use `terminate()`. + * + * @param code The close code to send + * @param reason The close reason to send + */ + close(code?: number, reason?: string): void; + + /** + * Abruptly close the connection. + * + * To gracefully close the connection, use `close()`. + */ + terminate(): void; + + /** + * Sends a ping. + * + * @param data The data to send + */ + ping(data?: string | BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a pong. + * + * @param data The data to send + */ + pong(data?: string | BufferSource): ServerWebSocketSendStatus; + + /** + * Sends a message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); + */ + publish(topic: string, data: string | BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a text message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", "Hello!"); + * ws.publish("chat", "Compress this.", true); + */ + publishText(topic: string, data: string, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Sends a binary message to subscribers of the topic. + * + * @param topic The topic name. + * @param data The data to send. + * @param compress Should the data be compressed? If the client does not support compression, this is ignored. + * @example + * ws.publish("chat", new TextEncoder().encode("Hello!")); + * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); + */ + publishBinary(topic: string, data: BufferSource, compress?: boolean): ServerWebSocketSendStatus; + + /** + * Subscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + */ + subscribe(topic: string): void; + + /** + * Unsubscribes a client to the topic. + * + * @param topic The topic name. + * @example + * ws.unsubscribe("chat"); + */ + unsubscribe(topic: string): void; + + /** + * Is the client subscribed to a topic? + * + * @param topic The topic name. + * @example + * ws.subscribe("chat"); + * console.log(ws.isSubscribed("chat")); // true + */ + isSubscribed(topic: string): boolean; + + /** + * Batches `send()` and `publish()` operations, which makes it faster to send data. + * + * The `message`, `open`, and `drain` callbacks are automatically corked, so + * you only need to call this if you are sending messages outside of those + * callbacks or in async functions. + * + * @param callback The callback to run. + * @example + * ws.cork((ctx) => { + * ctx.send("These messages"); + * ctx.sendText("are sent"); + * ctx.sendBinary(new TextEncoder().encode("together!")); + * }); + */ + cork(callback: (ws: ServerWebSocket) => T): T; + + /** + * The IP address of the client. + * + * @example + * console.log(socket.remoteAddress); // "127.0.0.1" + */ + readonly remoteAddress: string; + + /** + * The ready state of the client. + * + * - if `0`, the client is connecting. + * - if `1`, the client is connected. + * - if `2`, the client is closing. + * - if `3`, the client is closed. + * + * @example + * console.log(socket.readyState); // 1 + */ + readonly readyState: WebSocketReadyState; + + /** + * Sets how binary data is returned in events. + * + * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** + * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. + * - if `uint8array`, binary data is returned as `Uint8Array` objects. + * + * @example + * let ws: WebSocket; + * ws.binaryType = "uint8array"; + * ws.addEventListener("message", ({ data }) => { + * console.log(data instanceof Uint8Array); // true + * }); + */ + binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; + + /** + * Custom data that you can assign to a client, can be read and written at any time. + * + * @example + * import { serve } from "bun"; + * + * serve({ + * fetch(request, server) { + * const data = { + * accessToken: request.headers.get("Authorization"), + * }; + * if (server.upgrade(request, { data })) { + * return; + * } + * return new Response(); + * }, + * websocket: { + * open(ws) { + * console.log(ws.data.accessToken); + * } + * } + * }); + */ + data: T; + + getBufferedAmount(): number; + } + + /** + * Compression options for WebSocket messages. + */ + type WebSocketCompressor = + | "disable" + | "shared" + | "dedicated" + | "3KB" + | "4KB" + | "8KB" + | "16KB" + | "32KB" + | "64KB" + | "128KB" + | "256KB"; + + /** + * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} + * + * @example + * ```ts + * import { websocket, serve } from "bun"; + * + * serve<{name: string}>({ + * port: 3000, + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log(`${ws.data.name}: ${message}`); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req, { + * data: { + * name: new URL(req.url).searchParams.get("name"), + * }, + * }); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * return; + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + */ + interface WebSocketHandler { + /** + * Called when the server receives an incoming message. + * + * If the message is not a `string`, its type is based on the value of `binaryType`. + * - if `nodebuffer`, then the message is a `Buffer`. + * - if `arraybuffer`, then the message is an `ArrayBuffer`. + * - if `uint8array`, then the message is a `Uint8Array`. + * + * @param ws The websocket that sent the message + * @param message The message received + */ + message(ws: ServerWebSocket, message: string | Buffer): void | Promise; + + /** + * Called when a connection is opened. + * + * @param ws The websocket that was opened + */ + open?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection was previously under backpressure, + * meaning it had too many queued messages, but is now ready to receive more data. + * + * @param ws The websocket that is ready for more data + */ + drain?(ws: ServerWebSocket): void | Promise; + + /** + * Called when a connection is closed. + * + * @param ws The websocket that was closed + * @param code The close code + * @param message The close message + */ + close?(ws: ServerWebSocket, code: number, reason: string): void | Promise; + + /** + * Called when a ping is sent. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + ping?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Called when a pong is received. + * + * @param ws The websocket that received the ping + * @param data The data sent with the ping + */ + pong?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** + * Sets the maximum size of messages in bytes. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + maxPayloadLength?: number; + + /** + * Sets the maximum number of bytes that can be buffered on a single connection. + * + * Default is 16 MB, or `1024 * 1024 * 16` in bytes. + */ + backpressureLimit?: number; + + /** + * Sets if the connection should be closed if `backpressureLimit` is reached. + * + * Default is `false`. + */ + closeOnBackpressureLimit?: boolean; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to no messages or pings. + * + * Default is 2 minutes, or `120` in seconds. + */ + idleTimeout?: number; + + /** + * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? + * + * Default is `false`. + */ + publishToSelf?: boolean; + + /** + * Should the server automatically send and respond to pings to clients? + * + * Default is `true`. + */ + sendPings?: boolean; + + /** + * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. + * + * Default is `false`. + */ + perMessageDeflate?: + | boolean + | { + /** + * Sets the compression level. + */ + compress?: WebSocketCompressor | boolean; + /** + * Sets the decompression level. + */ + decompress?: WebSocketCompressor | boolean; + }; + } + + namespace RouterTypes { + type ExtractRouteParams = T extends `${string}:${infer Param}/${infer Rest}` + ? { [K in Param]: string } & ExtractRouteParams + : T extends `${string}:${infer Param}` + ? { [K in Param]: string } + : T extends `${string}*` + ? {} + : {}; + + type RouteHandler = (req: BunRequest, server: Server) => Response | Promise; + + type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; + + type RouteHandlerObject = { + [K in HTTPMethod]?: RouteHandler; + }; + + type RouteValue = Response | false | RouteHandler | RouteHandlerObject; + } + + interface BunRequest extends Request { + params: RouterTypes.ExtractRouteParams; + } + + interface GenericServeOptions { + /** + * What URI should be used to make {@link Request.url} absolute? + * + * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one + * + * @example + * ```js + * "http://my-app.com" + * ``` + * + * @example + * ```js + * "https://wongmjane.com/" + * ``` + * + * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. + * + * @example + * "http://localhost:3000" + */ + // baseURI?: string; + + /** + * What is the maximum size of a request body? (in bytes) + * @default 1024 * 1024 * 128 // 128MB + */ + maxRequestBodySize?: number; + + /** + * Render contextual errors? This enables bun's error page + * @default process.env.NODE_ENV !== 'production' + */ + development?: + | boolean + | { + /** + * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) + * + * @default true if process.env.NODE_ENV !== 'production' + * + */ + hmr?: boolean; + }; + + error?: (this: Server, error: ErrorLike) => Response | Promise | undefined | Promise; + + /** + * Uniquely identify a server instance with an ID + * + * ### When bun is started with the `--hot` flag + * + * This string will be used to hot reload the server without interrupting + * pending requests or websockets. If not provided, a value will be + * generated. To disable hot reloading, set this value to `null`. + * + * ### When bun is not started with the `--hot` flag + * + * This string will currently do nothing. But in the future it could be useful for logs or metrics. + */ + id?: string | null; + } + + interface ServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * Whether the `SO_REUSEPORT` flag should be set. + * + * This allows multiple processes to bind to the same port, which is useful for load balancing. + * + * @default false + */ + reusePort?: boolean; + + /** + * Whether the `IPV6_V6ONLY` flag should be set. + * @default false + */ + ipv6Only?: boolean; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix?: never; + + /** + * Sets the the number of seconds to wait before timing out a connection + * due to inactivity. + * + * Default is `10` seconds. + */ + idleTimeout?: number; + + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | Promise; + } + + interface UnixServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + /** + * Handle HTTP requests + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | Promise; + } + + interface WebSocketServeOptions extends GenericServeOptions { + /** + * What port should the server listen on? + * @default process.env.PORT || "3000" + */ + port?: string | number; + + /** + * What hostname should the server listen on? + * + * @default + * ```js + * "0.0.0.0" // listen on all interfaces + * ``` + * @example + * ```js + * "127.0.0.1" // Only listen locally + * ``` + * @example + * ```js + * "remix.run" // Only listen on remix.run + * ```` + * + * note: hostname should not include a {@link port} + */ + hostname?: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch( + this: Server, + request: Request, + server: Server, + ): Response | undefined | void | Promise; + } + + interface UnixWebSocketServeOptions extends GenericServeOptions { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + + /** + * Enable websockets with {@link Bun.serve} + * + * For simpler type safety, see {@link Bun.websocket} + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} + * + * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property + */ + websocket: WebSocketHandler; + + /** + * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} + * + * Respond to {@link Request} objects with a {@link Response} object. + */ + fetch(this: Server, request: Request, server: Server): Response | undefined | Promise; + } + + interface TLSWebSocketServeOptions + extends WebSocketServeOptions, + TLSOptionsAsDeprecated { + unix?: never; + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSWebSocketServeOptions + extends UnixWebSocketServeOptions, + TLSOptionsAsDeprecated { + /** + * If set, the HTTP server will listen on a unix socket instead of a port. + * (Cannot be used with hostname+port) + */ + unix: string; + tls?: TLSOptions | TLSOptions[]; + } + + interface ErrorLike extends Error { + code?: string; + errno?: number; + syscall?: string; + } + + interface TLSOptions { + /** + * Passphrase for the TLS key + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: string | Buffer | BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: string | Buffer | BunFile | Array | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: string | Buffer | BunFile | Array | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + // Note for contributors: TLSOptionsAsDeprecated should be considered immutable + // and new TLS option keys should only be supported on the `.tls` property (which comes + // from the TLSOptions interface above). + /** + * This exists because Bun.serve() extends the TLSOptions object, but + * they're now considered deprecated. You should be passing the + * options on `.tls` instead. + * + * @example + * ```ts + * //// OLD //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * passphrase: "secret", + * }); + * + * //// NEW //// + * Bun.serve({ + * fetch: () => new Response("Hello World"), + * tls: { + * passphrase: "secret", + * }, + * }); + * ``` + */ + interface TLSOptionsAsDeprecated { + /** + * Passphrase for the TLS key + * + * @deprecated Use `.tls.passphrase` instead + */ + passphrase?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + * + * @deprecated Use `.tls.dhParamsFile` instead + */ + dhParamsFile?: string; + + /** + * Explicitly set a server name + * + * @deprecated Use `.tls.serverName` instead + */ + serverName?: string; + + /** + * This sets `OPENSSL_RELEASE_BUFFERS` to 1. + * It reduces overall performance but saves some memory. + * @default false + * + * @deprecated Use `.tls.lowMemoryMode` instead + */ + lowMemoryMode?: boolean; + + /** + * If set to `false`, any certificate is accepted. + * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. + * + * @deprecated Use `.tls.rejectUnauthorized` instead + */ + rejectUnauthorized?: boolean; + + /** + * If set to `true`, the server will request a client certificate. + * + * Default is `false`. + * + * @deprecated Use `.tls.requestCert` instead + */ + requestCert?: boolean; + + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + * + * @deprecated Use `.tls.ca` instead + */ + ca?: string | Buffer | BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + * + * @deprecated Use `.tls.cert` instead + */ + cert?: string | Buffer | BunFile | Array | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + * + * @deprecated Use `.tls.key` instead + */ + key?: string | Buffer | BunFile | Array | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + * + * @deprecated `Use .tls.secureOptions` instead + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + } + + interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface UnixTLSServeOptions extends UnixServeOptions, TLSOptionsAsDeprecated { + tls?: TLSOptions | TLSOptions[]; + } + + interface SocketAddress { + /** + * The IP address of the client. + */ + address: string; + /** + * The port of the client. + */ + port: number; + /** + * The IP family ("IPv4" or "IPv6"). + */ + family: "IPv4" | "IPv6"; + } + + /** + * HTTP & HTTPS Server + * + * To start the server, see {@link serve} + * + * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. + * That means starting a new server allocates about 500 KB of memory. Try to + * avoid starting and stopping the server often (unless it's a new instance of bun). + * + * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. + */ + interface Server extends Disposable { + /** + * Stop listening to prevent new connections from being accepted. + * + * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. + * + * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. + * @default false + */ + stop(closeActiveConnections?: boolean): Promise; + + /** + * Update the `fetch` and `error` handlers without restarting the server. + * + * This is useful if you want to change the behavior of your server without + * restarting it or for hot reloading. + * + * @example + * + * ```js + * // create the server + * const server = Bun.serve({ + * fetch(request) { + * return new Response("Hello World v1") + * } + * }); + * + * // Update the server to return a different response + * server.reload({ + * fetch(request) { + * return new Response("Hello World v2") + * } + * }); + * ``` + * + * Passing other options such as `port` or `hostname` won't do anything. + */ + reload }>( + options: ( + | (Omit & { + routes: R; + fetch?: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | (Omit & { + routes?: never; + fetch: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. + */ + static?: R; + }, + ): Server; + + /** + * Mock the fetch handler for a running server. + * + * This feature is not fully implemented yet. It doesn't normalize URLs + * consistently in all cases and it doesn't yet call the `error` handler + * consistently. This needs to be fixed + */ + fetch(request: Request | string): Response | Promise; + + /** + * Upgrade a {@link Request} to a {@link ServerWebSocket} + * + * @param request The {@link Request} to upgrade + * @param options Pass headers or attach data to the {@link ServerWebSocket} + * + * @returns `true` if the upgrade was successful and `false` if it failed + * + * @example + * ```js + * import { serve } from "bun"; + * serve({ + * websocket: { + * open: (ws) => { + * console.log("Client connected"); + * }, + * message: (ws, message) => { + * console.log("Client sent message", message); + * }, + * close: (ws) => { + * console.log("Client disconnected"); + * }, + * }, + * fetch(req, server) { + * const url = new URL(req.url); + * if (url.pathname === "/chat") { + * const upgraded = server.upgrade(req); + * if (!upgraded) { + * return new Response("Upgrade failed", { status: 400 }); + * } + * } + * return new Response("Hello World"); + * }, + * }); + * ``` + * What you pass to `data` is available on the {@link ServerWebSocket.data} property + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + upgrade( + request: Request, + options?: { + /** + * Send any additional headers while upgrading, like cookies + */ + headers?: HeadersInit; + /** + * This value is passed to the {@link ServerWebSocket.data} property + */ + data?: T; + }, + ): boolean; + + /** + * Send a message to all connected {@link ServerWebSocket} subscribed to a topic + * + * @param topic The topic to publish to + * @param data The data to send + * @param compress Should the data be compressed? Ignored if the client does not support compression. + * + * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. + * + * @example + * + * ```js + * server.publish("chat", "Hello World"); + * ``` + * + * @example + * ```js + * server.publish("chat", new Uint8Array([1, 2, 3, 4])); + * ``` + * + * @example + * ```js + * server.publish("chat", new ArrayBuffer(4), true); + * ``` + * + * @example + * ```js + * server.publish("chat", new DataView(new ArrayBuffer(4))); + * ``` + */ + publish( + topic: string, + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * A count of connections subscribed to a given topic + * + * This operation will loop through each topic internally to get the count. + * + * @param topic the websocket topic to check how many subscribers are connected to + * @returns the number of subscribers + */ + subscriberCount(topic: string): number; + + /** + * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * return new Response(server.requestIP(request)); + * } + * } + * ``` + */ + requestIP(request: Request): SocketAddress | null; + + /** + * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. + * + * @example + * ```js + * export default { + * async fetch(request, server) { + * server.timeout(request, 60); + * await Bun.sleep(30000); + * return new Response("30 seconds have passed"); + * } + * } + * ``` + */ + timeout(request: Request, seconds: number): void; + /** + * Undo a call to {@link Server.unref} + * + * If the Server has already been stopped, this does nothing. + * + * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. + */ + ref(): void; + + /** + * Don't keep the process alive if this server is the only thing left. + * Active connections may continue to keep the process alive. + * + * By default, the server is ref'd. + * + * To prevent new connections from being accepted, use {@link Server.stop} + */ + unref(): void; + + /** + * How many requests are in-flight right now? + */ + readonly pendingRequests: number; + + /** + * How many {@link ServerWebSocket}s are in-flight right now? + */ + readonly pendingWebSockets: number; + + readonly url: URL; + + readonly port: number; + /** + * The hostname the server is listening on. Does not include the port + * @example + * ```js + * "localhost" + * ``` + */ + readonly hostname: string; + /** + * Is the server running in development mode? + * + * In development mode, `Bun.serve()` returns rendered error messages with + * stack traces instead of a generic 500 error. This makes debugging easier, + * but development mode shouldn't be used in production or you will risk + * leaking sensitive information. + */ + readonly development: boolean; + + /** + * An identifier of the server instance + * + * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. + * + * When bun is not started with the `--hot` flag, this ID is currently unused. + */ + readonly id: string; + } + + type Serve = + | ServeOptions + | TLSServeOptions + | UnixServeOptions + | UnixTLSServeOptions + | WebSocketServeOptions + | TLSWebSocketServeOptions + | UnixWebSocketServeOptions + | UnixTLSWebSocketServeOptions; + + /** + Bun.serve provides a high-performance HTTP server with built-in routing support. + It enables both function-based and object-based route handlers with type-safe + parameters and method-specific handling. + + @example Basic Usage + ```ts + Bun.serve({ + port: 3000, + fetch(req) { + return new Response("Hello World"); } }); ``` @@ -4565,2911 +4338,2781 @@ declare module "bun" { @param options - Server configuration options @param options.routes - Route definitions mapping paths to handlers */ - function serve< - T, - R extends { [K in keyof R]: RouterTypes.RouteValue }, - >( - options: ( - | (DistributedOmit & { - routes: R; - fetch?: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | (DistributedOmit & { - routes?: never; - fetch: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise; - }) - | WebSocketServeOptions - ) & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for a while though. - */ - static?: R; - }, - ): Server; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - `type` is auto-set based on the file extension when possible - * - * @example - * ```js - * const file = Bun.file("./hello.json"); - * console.log(file.type); // "application/json" - * console.log(await file.json()); // { hello: "world" } - * ``` - * - * @example - * ```js - * await Bun.write( - * Bun.file("./hello.txt"), - * "Hello, world!" - * ); - * ``` - * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file(path: string | URL, options?: BlobPropertyBag): BunFile; - - /** - * A list of files embedded into the standalone executable. Lexigraphically sorted by name. - * - * If the process is not a standalone executable, this returns an empty array. - */ - const embeddedFiles: ReadonlyArray; - - /** - * `Blob` that leverages the fastest system calls available to operate on files. - * - * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. - * - * `Blob.size` will not be valid until the contents of the file are read at least once. - * `Blob.type` will have a default set based on the file extension - * - * @example - * ```js - * const file = Bun.file(new TextEncoder.encode("./hello.json")); - * console.log(file.type); // "application/json" - * ``` - * - * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} - */ - // tslint:disable-next-line:unified-signatures - function file( - path: ArrayBufferLike | Uint8Array, - options?: BlobPropertyBag, - ): BunFile; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - * @example - * ```js - * const file = Bun.file(fd); - * ``` - * - * @param fileDescriptor The file descriptor of the file - */ - // tslint:disable-next-line:unified-signatures - function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; - - /** - * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. - * - * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. - */ - function allocUnsafe(size: number): Uint8Array; - - interface BunInspectOptions { - colors?: boolean; - depth?: number; - sorted?: boolean; - compact?: boolean; - } - - /** - * Pretty-print an object the same as {@link console.log} to a `string` - * - * Supports JSX - * - * @param args - */ - function inspect(arg: any, options?: BunInspectOptions): string; - namespace inspect { - /** - * That can be used to declare custom inspect functions. - */ - const custom: typeof import("util").inspect.custom; - - /** - * Pretty-print an object or array as a table - * - * Like {@link console.table}, except it returns a string - */ - function table( - tabularData: object | unknown[], - properties?: string[], - options?: { colors?: boolean }, - ): string; - function table( - tabularData: object | unknown[], - options?: { colors?: boolean }, - ): string; - } - - interface MMapOptions { - /** - * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. - */ - sync?: boolean; - /** - * Allow other processes to see results instantly? - * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. - * @default true - */ - shared?: boolean; - } - /** - * Open a file as a live-updating `Uint8Array` without copying memory - * - Writing to the array writes to the file. - * - Reading from the array reads from the file. - * - * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. - * - * --- - * - * This API inherently has some rough edges: - * - It does not support empty files. It will throw a `SystemError` with `EINVAL` - * - Usage on shared/networked filesystems is discouraged. It will be very slow. - * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. - * - * --- - * - * To close the file, set the array to `null` and it will be garbage collected eventually. - */ - function mmap(path: PathLike, opts?: MMapOptions): Uint8Array; - - /** Write to stdout */ - const stdout: BunFile; - /** Write to stderr */ - const stderr: BunFile; - /** - * Read from stdin - * - * This is read-only - */ - const stdin: BunFile; - - type StringLike = string | { toString(): string }; - - type ColorInput = - | { r: number; g: number; b: number; a?: number } - | [number, number, number] - | [number, number, number, number] - | Uint8Array - | Uint8ClampedArray - | Float32Array - | Float64Array - | string - | number - | { toString(): string }; - - function color( - input: ColorInput, - outputFormat?: /** - * True color ANSI color string, for use in terminals - * @example \x1b[38;2;100;200;200m - */ - | "ansi" - | "ansi-16" - | "ansi-16m" - /** - * 256 color ANSI color string, for use in terminals which don't support true color - * - * Tries to match closest 24-bit color to 256 color palette - */ - | "ansi-256" - /** - * Picks the format that produces the shortest output - */ - | "css" - /** - * Lowercase hex color string without alpha - * @example #ff9800 - */ - | "hex" - /** - * Uppercase hex color string without alpha - * @example #FF9800 - */ - | "HEX" - /** - * @example hsl(35.764706, 1, 0.5) - */ - | "hsl" - /** - * @example lab(0.72732764, 33.938198, -25.311619) - */ - | "lab" - /** - * @example 16750592 - */ - | "number" - /** - * RGB color string without alpha - * @example rgb(255, 152, 0) - */ - | "rgb" - /** - * RGB color string with alpha - * @example rgba(255, 152, 0, 1) - */ - | "rgba", - ): string | null; - - function color( - input: ColorInput, - /** - * An array of numbers representing the RGB color - * @example [100, 200, 200] - */ - outputFormat: "[rgb]", - ): [number, number, number] | null; - function color( - input: ColorInput, - /** - * An array of numbers representing the RGBA color - * @example [100, 200, 200, 255] - */ - outputFormat: "[rgba]", - ): [number, number, number, number] | null; - function color( - input: ColorInput, - /** - * An object representing the RGB color - * @example { r: 100, g: 200, b: 200 } - */ - outputFormat: "{rgb}", - ): { r: number; g: number; b: number } | null; - function color( - input: ColorInput, - /** - * An object representing the RGBA color - * @example { r: 100, g: 200, b: 200, a: 0.5 } - */ - outputFormat: "{rgba}", - ): { r: number; g: number; b: number; a: number } | null; - function color(input: ColorInput, outputFormat: "number"): number | null; - - interface Semver { - /** - * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. - */ - satisfies(version: StringLike, range: StringLike): boolean; - - /** - * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. - * Throws an error if either version is invalid. - */ - order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; - } - var semver: Semver; - - interface Unsafe { - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. - * - * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; - - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` - * - * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - // tslint:disable-next-line:unified-signatures - arrayBufferToString(buffer: Uint16Array): string; - - /** - * Force the garbage collector to run extremely often, - * especially inside `bun:test`. - * - * - `0`: default, disable - * - `1`: asynchronously call the garbage collector more often - * - `2`: synchronously call the garbage collector more often. - * - * This is a global setting. It's useful for debugging seemingly random crashes. - * - * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. - * - * @param level - * @returns The previous level - */ - gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; - - /** - * Dump the mimalloc heap to the console - */ - mimallocDump(): void; - } - const unsafe: Unsafe; - - type DigestEncoding = - | "utf8" - | "ucs2" - | "utf16le" - | "latin1" - | "ascii" - | "base64" - | "base64url" - | "hex"; - - /** - * Are ANSI colors enabled for stdin and stdout? - * - * Used for {@link console.log} - */ - const enableANSIColors: boolean; - - /** - * What script launched Bun? - * - * Absolute file path - * - * @example "/never-gonna-give-you-up.js" - */ - const main: string; - - /** - * Manually trigger the garbage collector - * - * This does two things: - * 1. It tells JavaScriptCore to run the garbage collector - * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. - * - * @param force Synchronously run the garbage collector - */ - function gc(force: boolean): void; - - /** - * JavaScriptCore engine's internal heap snapshot - * - * I don't know how to make this something Chrome or Safari can read. - * - * If you have any ideas, please file an issue https://github.com/oven-sh/bun - */ - interface HeapSnapshot { - /** 2 */ - version: number; - - /** "Inspector" */ - type: string; - - nodes: number[]; - - nodeClassNames: string[]; - edges: number[]; - edgeTypes: string[]; - edgeNames: string[]; - } - - /** - * Returns the number of nanoseconds since the process was started. - * - * This function uses a high-resolution monotonic system timer to provide precise time measurements. - * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), - * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). - * - * Due to this limitation, while the internal counter may continue beyond this point, - * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond - * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but - * with reduced precision, which might affect time calculations and comparisons in long-running applications. - * - * @returns {number} The number of nanoseconds since the process was started, with precise values up to - * Number.MAX_SAFE_INTEGER. - */ - function nanoseconds(): number; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector - */ - function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code - * - * This is a JSON string that can be saved to a file. - * ```ts - * const snapshot = Bun.generateHeapSnapshot("v8"); - * await Bun.write("heap.heapsnapshot", snapshot); - * ``` - */ - function generateHeapSnapshot(format: "v8"): string; - - /** - * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. - */ - function shrink(): void; - - /** - * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` - * - * @param path path to open - */ - function openInEditor(path: string, options?: EditorOptions): void; - - var fetch: typeof globalThis.fetch; - - interface EditorOptions { - editor?: "vscode" | "subl"; - line?: number; - column?: number; - } - - /** - * This class only exists in types - */ - abstract class CryptoHashInterface { - /** - * Update the hash with data - * - * @param data - */ - update(data: Bun.BlobOrStringOrBuffer): T; - - /** - * Finalize the hash - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash( - input: Bun.BlobOrStringOrBuffer, - hashInto?: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - } - - type SupportedCryptoAlgorithms = - | "blake2b256" - | "blake2b512" - | "md4" - | "md5" - | "ripemd160" - | "sha1" - | "sha224" - | "sha256" - | "sha384" - | "sha512" - | "sha512-224" - | "sha512-256" - | "sha3-224" - | "sha3-256" - | "sha3-384" - | "sha3-512" - | "shake128" - | "shake256"; - - /** - * Hardware-accelerated cryptographic hash functions - * - * Used for `crypto.createHash()` - */ - class CryptoHasher { - /** - * The algorithm chosen to hash the data - */ - readonly algorithm: SupportedCryptoAlgorithms; - - /** - * The length of the output hash in bytes - */ - readonly byteLength: number; - - /** - * Create a new hasher - * - * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms - * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. - */ - constructor( - algorithm: SupportedCryptoAlgorithms, - hmacKey?: string | NodeJS.TypedArray, - ); - - /** - * Update the hash with data - * - * @param input - */ - update( - input: Bun.BlobOrStringOrBuffer, - inputEncoding?: import("crypto").Encoding, - ): CryptoHasher; - - /** - * Perform a deep copy of the hasher - */ - copy(): CryptoHasher; - - /** - * Finalize the hash. Resets the CryptoHasher so it can be reused. - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(): Buffer; - digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - ): Buffer; - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - hashInto: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - - /** - * List of supported hash algorithms - * - * These are hardware accelerated with BoringSSL - */ - static readonly algorithms: SupportedCryptoAlgorithms[]; - } - - /** - * Resolve a `Promise` after milliseconds. This is like - * {@link setTimeout} except it returns a `Promise`. - * - * @param ms milliseconds to delay resolving the promise. This is a minimum - * number. It may take longer. If a {@link Date} is passed, it will sleep until the - * {@link Date} is reached. - * - * @example - * ## Sleep for 1 second - * ```ts - * import { sleep } from "bun"; - * - * await sleep(1000); - * ``` - * ## Sleep for 10 milliseconds - * ```ts - * await Bun.sleep(10); - * ``` - * ## Sleep until `Date` - * - * ```ts - * const target = new Date(); - * target.setSeconds(target.getSeconds() + 1); - * await Bun.sleep(target); - * ``` - * Internally, `Bun.sleep` is the equivalent of - * ```ts - * await new Promise((resolve) => setTimeout(resolve, ms)); - * ``` - * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. - */ - function sleep(ms: number | Date): Promise; - - /** - * Sleep the thread for a given number of milliseconds - * - * This is a blocking function. - * - * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) - */ - function sleepSync(ms: number): void; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha( - input: Bun.StringOrBuffer, - hashInto?: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param encoding `DigestEncoding` to return the hash in - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; - - /** - * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} - * - * Consider using the ugly-named {@link SHA512_256} instead - */ - class SHA1 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 20; - } - class MD5 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class MD4 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class SHA224 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 28; - } - class SHA512 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 64; - } - class SHA384 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 48; - } - class SHA256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - /** - * See also {@link sha} - */ - class SHA512_256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - - /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ - interface ZlibCompressionOptions { - /** - * The compression level to use. Must be between `-1` and `9`. - * - A value of `-1` uses the default compression level (Currently `6`) - * - A value of `0` gives no compression - * - A value of `1` gives least compression, fastest speed - * - A value of `9` gives best compression, slowest speed - */ - level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * How much memory should be allocated for the internal compression state. - * - * A value of `1` uses minimum memory but is slow and reduces compression ratio. - * - * A value of `9` uses maximum memory for optimal speed. The default is `8`. - */ - memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * The base 2 logarithm of the window size (the size of the history buffer). - * - * Larger values of this parameter result in better compression at the expense of memory usage. - * - * The following value ranges are supported: - * - `9..15`: The output will have a zlib header and footer (Deflate) - * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) - * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) - * - * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. - */ - windowBits?: - | -9 - | -10 - | -11 - | -12 - | -13 - | -14 - | -15 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 25 - | 26 - | 27 - | 28 - | 29 - | 30 - | 31; - /** - * Tunes the compression algorithm. - * - * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** - * - `Z_FILTERED`: For data produced by a filter or predictor - * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) - * - `Z_RLE`: Limit match distances to one (run-length encoding) - * - `Z_FIXED` prevents the use of dynamic Huffman codes - * - * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. - * - * `Z_FILTERED` forces more Huffman coding and less string matching, it is - * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. - * Filtered data consists mostly of small values with a somewhat random distribution. - */ - strategy?: number; - - library?: "zlib"; - } - - interface LibdeflateCompressionOptions { - level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; - library?: "libdeflate"; - } - - /** - * Compresses a chunk of data with `zlib` DEFLATE algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function deflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Compresses a chunk of data with `zlib` GZIP algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function gzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` INFLATE algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function inflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` GUNZIP algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function gunzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - - type Target = - /** - * For generating bundles that are intended to be run by the Bun runtime. In many cases, - * it isn't necessary to bundle server-side code; you can directly execute the source code - * without modification. However, bundling your server code can reduce startup times and - * improve running performance. - * - * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which - * indicates to the Bun runtime that there's no need to re-transpile the file before execution. - */ - | "bun" - /** - * The plugin will be applied to Node.js builds - */ - | "node" - /** - * The plugin will be applied to browser builds - */ - | "browser"; - - /** https://bun.sh/docs/bundler/loaders */ - type Loader = - | "js" - | "jsx" - | "ts" - | "tsx" - | "json" - | "toml" - | "file" - | "napi" - | "wasm" - | "text" - | "css" - | "html"; - - interface PluginConstraints { - /** - * Only apply the plugin when the import specifier matches this regular expression - * - * @example - * ```ts - * // Only apply the plugin when the import specifier matches the regex - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { - * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; - * }); - * } - * }) - * ``` - */ - filter: RegExp; - - /** - * Only apply the plugin when the import specifier has a namespace matching - * this string - * - * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` - * has the namespace `"bun"`. - * - * The default namespace is `"file"` and it can be omitted from import - * specifiers. - */ - namespace?: string; - } - - interface OnLoadResultSourceCode { - /** - * The source code of the module - */ - contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; - /** - * The loader to use for this file - * - * "css" will be added in a future version of Bun. - */ - loader?: Loader; - } - - interface OnLoadResultObject { - /** - * The object to use as the module - * @example - * ```ts - * // In your loader - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * - * // In your script - * import {foo} from "hello:world"; - * console.log(foo); // "bar" - * ``` - */ - exports: Record; - /** - * The loader to use for this file - */ - loader: "object"; - } - - interface OnLoadArgs { - /** - * The resolved import specifier of the module being loaded - * @example - * ```ts - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * console.log(args.path); // "hello:world" - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * ``` - */ - path: string; - /** - * The namespace of the module being loaded - */ - namespace: string; - /** - * The default loader for this file extension - */ - loader: Loader; - /** - * Defer the execution of this callback until all other modules have been parsed. - * - * @returns Promise which will be resolved when all modules have been parsed - */ - defer: () => Promise; - } - - type OnLoadResult = - | OnLoadResultSourceCode - | OnLoadResultObject - | undefined - | void; - type OnLoadCallback = ( - args: OnLoadArgs, - ) => OnLoadResult | Promise; - type OnStartCallback = () => void | Promise; - - interface OnResolveArgs { - /** - * The import specifier of the module being loaded - */ - path: string; - /** - * The module that imported the module being resolved - */ - importer: string; - /** - * The namespace of the importer. - */ - namespace: string; - /** - * The directory to perform file-based resolutions in. - */ - resolveDir: string; - /** - * The kind of import this resolve is for. - */ - kind: ImportKind; - // resolveDir: string; - // pluginData: any; - } - - interface OnResolveResult { - /** - * The destination of the import - */ - path: string; - /** - * The namespace of the destination - * It will be concatenated with `path` to form the final import specifier - * @example - * ```ts - * "foo" // "foo:bar" - * ``` - */ - namespace?: string; - external?: boolean; - } - - type OnResolveCallback = ( - args: OnResolveArgs, - ) => - | OnResolveResult - | Promise - | undefined - | null; - - type FFIFunctionCallable = Function & { - // Making a nominally typed function so that the user must get it from dlopen - readonly __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol; - }; - - interface PluginBuilder { - /** - * Register a callback which will be invoked when bundling starts. When - * using hot module reloading, this is called at the start of each - * incremental rebuild. - * - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onStart(() => { - * console.log("bundle just started!!") - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onStart(callback: OnStartCallback): this; - onBeforeParse( - constraints: PluginConstraints, - callback: { - napiModule: unknown; - symbol: string; - external?: unknown | undefined; - }, - ): this; - /** - * Register a callback to load imports with a specific import specifier - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; - /** - * Register a callback to resolve imports matching a filter and/or namespace - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onResolve({ filter: /^wat$/ }, (args) => { - * return { path: "/tmp/woah.js" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onResolve( - constraints: PluginConstraints, - callback: OnResolveCallback, - ): this; - /** - * The config object passed to `Bun.build` as is. Can be mutated. - */ - config: BuildConfig & { plugins: BunPlugin[] }; - - /** - * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules - * - * @param specifier The module specifier to register the callback for - * @param callback The function to run when the module is imported or required - * - * ### Example - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.module("hello:world", () => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * - * // sometime later - * const { foo } = await import("hello:world"); - * console.log(foo); // "bar" - * - * // or - * const { foo } = require("hello:world"); - * console.log(foo); // "bar" - * ``` - * - * @returns `this` for method chaining - */ - module( - specifier: string, - callback: () => OnLoadResult | Promise, - ): this; - } - - interface BunPlugin { - /** - * Human-readable name of the plugin - * - * In a future version of Bun, this will be used in error messages. - */ - name: string; - - /** - * The target JavaScript environment the plugin should be applied to. - * - `bun`: The default environment when using `bun run` or `bun` to load a script - * - `browser`: The plugin will be applied to browser builds - * - `node`: The plugin will be applied to Node.js builds - * - * If unspecified, it is assumed that the plugin is compatible with all targets. - * - * This field is not read by {@link Bun.plugin} - */ - target?: Target; - /** - * A function that will be called when the plugin is loaded. - * - * This function may be called in the same tick that it is registered, or it - * may be called later. It could potentially be called multiple times for - * different targets. - */ - setup( - /** - * A builder object that can be used to register plugin hooks - * @example - * ```ts - * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), - * })); - * ``` - */ - build: PluginBuilder, - ): void | Promise; - } - - /** - * Extend Bun's module resolution and loading behavior - * - * Plugins are applied in the order they are defined. - * - * Today, there are two kinds of hooks: - * - `onLoad` lets you return source code or an object that will become the module's exports - * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. - * - * Plugin hooks must define a `filter` RegExp and will only be matched if the - * import specifier contains a "." or a ":". - * - * ES Module resolution semantics mean that plugins may be initialized _after_ - * a module is resolved. You might need to load plugins at the very beginning - * of the application and then use a dynamic import to load the rest of the - * application. A future version of Bun may also support specifying plugins - * via `bunfig.toml`. - * - * @example - * A YAML loader plugin - * - * ```js - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) - * })); - * }); - * - * // You can use require() - * const {foo} = require("./file.yaml"); - * - * // Or import - * await import("./file.yaml"); - * - * ``` - */ - interface BunRegisterPlugin { - (options: T): ReturnType; - - /** - * Deactivate all plugins - * - * This prevents registered plugins from being applied to future builds. - */ - clearAll(): void; - } - - const plugin: BunRegisterPlugin; - - /** - * Is the current global scope the main thread? - */ - const isMainThread: boolean; - - /** - * Used when importing an HTML file at runtime. - * - * @example - * - * ```ts - * import app from "./index.html"; - * ``` - * - * Bun.build support for this isn't imlpemented yet. - */ - interface HTMLBundle { - index: string; - } - - interface Socket extends Disposable { - /** - * Write `data` to the socket - * - * @param data The data to write to the socket - * @param byteOffset The offset in the buffer to start writing from (defaults to 0) - * @param byteLength The number of bytes to write (defaults to the length of the buffer) - * - * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. - * - * This is unbuffered as of Bun v0.2.2. That means individual write() calls - * will be slow. In the future, Bun will buffer writes and flush them at the - * end of the tick, when the event loop is idle, or sooner if the buffer is full. - */ - write( - data: string | BufferSource, - byteOffset?: number, - byteLength?: number, - ): number; - - /** - * The data context for the socket. - */ - data: Data; - - /** - * Like {@link Socket.write} except it includes a TCP FIN packet - * - * Use it to send your last message and close the connection. - */ - end( - data?: string | BufferSource, - byteOffset?: number, - byteLength?: number, - ): number; - - /** - * Close the socket immediately - */ - end(): void; - - /** - * Keep Bun's process alive at least until this socket is closed - * - * After the socket has closed, the socket is unref'd, the process may exit, - * and this becomes a no-op - */ - ref(): void; - - /** - * Set a timeout until the socket automatically closes. - * - * To reset the timeout, call this function again. - * - * When a timeout happens, the `timeout` callback is called and the socket is closed. - */ - timeout(seconds: number): void; - - /** - * Forcefully close the socket. The other end may not receive all data, and - * the socket will be closed immediately. - * - * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to - * `0` and then calls `close(2)`. - */ - terminate(): void; - - /** - * Shutdown writes to a socket - * - * This makes the socket a half-closed socket. It can still receive data. - * - * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally - */ - shutdown(halfClose?: boolean): void; - - readonly readyState: "open" | "closing" | "closed"; - - /** - * Allow Bun's process to exit even if this socket is still open - * - * After the socket has closed, this function does nothing. - */ - unref(): void; - - /** - * Flush any buffered data to the socket - */ - flush(): void; - - /** - * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. - * - * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. - */ - reload(handler: SocketHandler): void; - - /** - * Get the server that created this socket - * - * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. - */ - readonly listener?: SocketListener; - - /** - * Remote IP address connected to the socket - */ - readonly remoteAddress: string; - - /** - * local port connected to the socket - */ - readonly localPort: number; - - /** - * This property is `true` if the peer certificate was signed by one of the CAs - * specified when creating the `Socket` instance, otherwise `false`. - */ - readonly authorized: boolean; - - /** - * String containing the selected ALPN protocol. - * Before a handshake has completed, this value is always null. - * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. - */ - readonly alpnProtocol: string | false | null; - - /** - * Disables TLS renegotiation for this `Socket` instance. Once called, attempts - * to renegotiate will trigger an `error` handler on the `Socket`. - * - * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) - */ - disableRenegotiation(): void; - - /** - * Keying material is used for validations to prevent different kind of attacks in - * network protocols, for example in the specifications of IEEE 802.1X. - * - * Example - * - * ```js - * const keyingMaterial = socket.exportKeyingMaterial( - * 128, - * 'client finished'); - * - * /* - * Example return value of keyingMaterial: - * - * - * ``` - * - * @param length number of bytes to retrieve from keying material - * @param label an application specific label, typically this will be a value from the [IANA Exporter Label - * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). - * @param context Optionally provide a context. - * @return requested bytes of the keying material - */ - exportKeyingMaterial( - length: number, - label: string, - context: Buffer, - ): Buffer; - - /** - * Returns the reason why the peer's certificate was not been verified. This - * property is set only when `socket.authorized === false`. - */ - getAuthorizationError(): Error | null; - - /** - * Returns an object representing the local certificate. The returned object has - * some properties corresponding to the fields of the certificate. - * - * If there is no local certificate, an empty object will be returned. If the - * socket has been destroyed, `null` will be returned. - */ - getCertificate(): import("tls").PeerCertificate | object | null; - getX509Certificate(): import("node:crypto").X509Certificate | undefined; - - /** - * Returns an object containing information on the negotiated cipher suite. - * - * For example, a TLSv1.2 protocol with AES256-SHA cipher: - * - * ```json - * { - * "name": "AES256-SHA", - * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", - * "version": "SSLv3" - * } - * ``` - * - */ - getCipher(): import("tls").CipherNameAndProtocol; - - /** - * Returns an object representing the type, name, and size of parameter of - * an ephemeral key exchange in `perfect forward secrecy` on a client - * connection. It returns an empty object when the key exchange is not - * ephemeral. As this is only supported on a client socket; `null` is returned - * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. - * - * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. - */ - getEphemeralKeyInfo(): import("tls").EphemeralKeyInfo | object | null; - - /** - * Returns an object representing the peer's certificate. If the peer does not - * provide a certificate, an empty object will be returned. If the socket has been - * destroyed, `null` will be returned. - * - * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's - * certificate. - * @return A certificate object. - */ - getPeerCertificate(): import("tls").PeerCertificate; - getPeerX509Certificate(): import("node:crypto").X509Certificate; - - /** - * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. - * @since v12.11.0 - * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. - */ - getSharedSigalgs(): string[]; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. - */ - getTLSFinishedMessage(): Buffer | undefined; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so - * far. - */ - getTLSPeerFinishedMessage(): Buffer | undefined; - - /** - * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. - * - * It may be useful for debugging. - * - * See `Session Resumption` for more information. - */ - getTLSTicket(): Buffer | undefined; - - /** - * Returns a string containing the negotiated SSL/TLS protocol version of the - * current connection. The value `'unknown'` will be returned for connected - * sockets that have not completed the handshaking process. The value `null` will - * be returned for server sockets or disconnected client sockets. - * - * Protocol versions are: - * - * * `'SSLv3'` - * * `'TLSv1'` - * * `'TLSv1.1'` - * * `'TLSv1.2'` - * * `'TLSv1.3'` - * - */ - getTLSVersion(): string; - - /** - * See `Session Resumption` for more information. - * @return `true` if the session was reused, `false` otherwise. - */ - isSessionReused(): boolean; - - /** - * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. - * Returns `true` if setting the limit succeeded; `false` otherwise. - * - * Smaller fragment sizes decrease the buffering latency on the client: larger - * fragments are buffered by the TLS layer until the entire fragment is received - * and its integrity is verified; large fragments can span multiple roundtrips - * and their processing can be delayed due to packet loss or reordering. However, - * smaller fragments add extra TLS framing bytes and CPU overhead, which may - * decrease overall server throughput. - * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. - */ - setMaxSendFragment(size: number): boolean; - - /** - * Enable/disable the use of Nagle's algorithm. - * Only available for already connected sockets, will return false otherwise - * @param noDelay Default: `true` - * @returns true if is able to setNoDelay and false if it fails. - */ - setNoDelay(noDelay?: boolean): boolean; - - /** - * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. - * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. - * Only available for already connected sockets, will return false otherwise. - * - * Enabling the keep-alive functionality will set the following socket options: - * SO_KEEPALIVE=1 - * TCP_KEEPIDLE=initialDelay - * TCP_KEEPCNT=10 - * TCP_KEEPINTVL=1 - * @param enable Default: `false` - * @param initialDelay Default: `0` - * @returns true if is able to setNoDelay and false if it fails. - */ - setKeepAlive(enable?: boolean, initialDelay?: number): boolean; - - /** - * The number of bytes written to the socket. - */ - readonly bytesWritten: number; - } - - interface SocketListener extends Disposable { - stop(closeActiveConnections?: boolean): void; - ref(): void; - unref(): void; - reload(options: Pick, "socket">): void; - data: Data; - } - interface TCPSocketListener extends SocketListener { - readonly port: number; - readonly hostname: string; - } - interface UnixSocketListener extends SocketListener { - readonly unix: string; - } - - interface TCPSocket extends Socket {} - interface TLSSocket extends Socket {} - - interface BinaryTypeList { - arraybuffer: ArrayBuffer; - buffer: Buffer; - uint8array: Uint8Array; - // TODO: DataView - // dataview: DataView; - } - type BinaryType = keyof BinaryTypeList; - - interface SocketHandler< - Data = unknown, - DataBinaryType extends BinaryType = "buffer", - > { - /** - * Is called when the socket connects, or in case of TLS if no handshake is provided - * this will be called only after handshake - * @param socket - */ - open?(socket: Socket): void | Promise; - close?(socket: Socket): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - ): void | Promise; - drain?(socket: Socket): void | Promise; - - /** - * When handshake is completed, this functions is called. - * @param socket - * @param success Indicates if the server authorized despite the authorizationError. - * @param authorizationError Certificate Authorization Error or null. - */ - handshake?( - socket: Socket, - success: boolean, - authorizationError: Error | null, - ): void; - - /** - * When the socket has been shutdown from the other end, this function is - * called. This is a TCP FIN packet. - */ - end?(socket: Socket): void | Promise; - - /** - * When the socket fails to be created, this function is called. - * - * The promise returned by `Bun.connect` rejects **after** this function is - * called. - * - * When `connectError` is specified, the rejected promise will not be - * added to the promise rejection queue (so it won't be reported as an - * unhandled promise rejection, since connectError handles it). - * - * When `connectError` is not specified, the rejected promise will be added - * to the promise rejection queue. - */ - connectError?(socket: Socket, error: Error): void | Promise; - - /** - * Called when a message times out. - */ - timeout?(socket: Socket): void | Promise; - /** - * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. - * - * @default "buffer" - * - * @remarks - * This lets you select the desired binary type for the `data` callback. - * It's a small performance optimization to let you avoid creating extra - * ArrayBufferView objects when possible. - * - * Bun originally defaulted to `Uint8Array` but when dealing with network - * data, it's more useful to be able to directly read from the bytes which - * `Buffer` allows. - */ - binaryType?: BinaryType; - } - - interface SocketOptions { - socket: SocketHandler; - data?: Data; - } - // interface TCPSocketOptions extends SocketOptions { - // hostname: string; - // port: number; - // } - - interface TCPSocketListenOptions - extends SocketOptions { - hostname: string; - port: number; - tls?: TLSOptions; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface TCPSocketConnectOptions - extends SocketOptions { - hostname: string; - port: number; - tls?: boolean; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface UnixSocketOptions extends SocketOptions { - tls?: TLSOptions; - unix: string; - } - - interface FdSocketOptions extends SocketOptions { - tls?: TLSOptions; - fd: number; - } - - /** - * Create a TCP client that connects to a server - * - * @param options The options to use when creating the client - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function connect( - options: TCPSocketConnectOptions, - ): Promise>; - function connect( - options: UnixSocketOptions, - ): Promise>; - - /** - * Create a TCP server that listens on a port - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function listen( - options: TCPSocketListenOptions, - ): TCPSocketListener; - function listen( - options: UnixSocketOptions, - ): UnixSocketListener; - - namespace udp { - type Data = string | ArrayBufferView | ArrayBufferLike; - - export interface SocketHandler { - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: Socket): void | Promise; - error?( - socket: Socket, - error: Error, - ): void | Promise; - } - - export interface ConnectedSocketHandler { - data?( - socket: ConnectedSocket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: ConnectedSocket): void | Promise; - error?( - socket: ConnectedSocket, - error: Error, - ): void | Promise; - } - - export interface SocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: SocketHandler; - } - - export interface ConnectSocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: ConnectedSocketHandler; - connect: { - hostname: string; - port: number; - }; - } - - export interface BaseUDPSocket { - readonly hostname: string; - readonly port: number; - readonly address: SocketAddress; - readonly binaryType: BinaryType; - readonly closed: boolean; - ref(): void; - unref(): void; - close(): void; - } - - export interface ConnectedSocket - extends BaseUDPSocket { - readonly remoteAddress: SocketAddress; - sendMany(packets: readonly Data[]): number; - send(data: Data): boolean; - reload(handler: ConnectedSocketHandler): void; - } - - export interface Socket - extends BaseUDPSocket { - sendMany(packets: readonly (Data | string | number)[]): number; - send(data: Data, port: number, address: string): boolean; - reload(handler: SocketHandler): void; - } - } - - /** - * Create a UDP socket - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.hostname The hostname to listen on - * @param options.port The port to listen on - * @param options.binaryType The binary type to use for the socket - * @param options.connect The hostname and port to connect to - */ - export function udpSocket( - options: udp.SocketOptions, - ): Promise>; - export function udpSocket( - options: udp.ConnectSocketOptions, - ): Promise>; - - namespace SpawnOptions { - /** - * Option for stdout/stderr - */ - type Readable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number; - - /** - * Option for stdin - */ - type Writable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number - | ReadableStream - | Blob - | Response - | Request; - - interface OptionsObject< - In extends Writable = Writable, - Out extends Readable = Readable, - Err extends Readable = Readable, - > { - /** - * The current working directory of the process - * - * Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * The environment variables of the process - * - * Defaults to `process.env` as it was when the current Bun process launched. - * - * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. - */ - env?: Record; - - /** - * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. - * This overrides the `stdin`, `stdout`, and `stderr` properties. - * - * For stdin you may pass: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. - * - `number`: The process will read from the file descriptor - * - * For stdout and stdin you may pass: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default ["ignore", "pipe", "inherit"] for `spawn` - * ["ignore", "pipe", "pipe"] for `spawnSync` - */ - stdio?: [In, Out, Err]; - /** - * The file descriptor for the standard input. It may be: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`: The process will read from the buffer - * - `number`: The process will read from the file descriptor - * - * @default "ignore" - */ - stdin?: In; - /** - * The file descriptor for the standard output. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "pipe" - */ - stdout?: Out; - /** - * The file descriptor for the standard error. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "inherit" for `spawn` - * "pipe" for `spawnSync` - */ - stderr?: Err; - - /** - * Callback that runs when the {@link Subprocess} exits - * - * This is called even if the process exits with a non-zero exit code. - * - * Warning: this may run before the `Bun.spawn` function returns. - * - * A simple alternative is `await subprocess.exited`. - * - * @example - * - * ```ts - * const subprocess = spawn({ - * cmd: ["echo", "hello"], - * onExit: (subprocess, code) => { - * console.log(`Process exited with code ${code}`); - * }, - * }); - * ``` - */ - onExit?( - subprocess: Subprocess, - exitCode: number | null, - signalCode: number | null, - /** - * If an error occurred in the call to waitpid2, this will be the error. - */ - error?: ErrorLike, - ): void | Promise; - - /** - * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for - * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized - * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - * - * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, - * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. - * - * Currently, this is only compatible with processes that are other `bun` instances. - */ - ipc?( - message: any, - /** - * The {@link Subprocess} that sent the message - */ - subprocess: Subprocess, - ): void; - - /** - * The serialization format to use for IPC messages. Defaults to `"advanced"`. - * - * To communicate with Node.js processes, use `"json"`. - * - * When `ipc` is not specified, this is ignored. - */ - serialization?: "json" | "advanced"; - - /** - * If true, the subprocess will have a hidden window. - */ - windowsHide?: boolean; - - /** - * If true, no quoting or escaping of arguments is done on Windows. - */ - windowsVerbatimArguments?: boolean; - - /** - * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. - * - * One use-case for this is for applications which wrap other applications or to simulate a symlink. - * - * @default cmds[0] - */ - argv0?: string; - - /** - * An {@link AbortSignal} that can be used to abort the subprocess. - * - * This is useful for aborting a subprocess when some other part of the - * program is aborted, such as a `fetch` response. - * - * Internally, this works by calling `subprocess.kill(1)`. - * - * @example - * ```ts - * const controller = new AbortController(); - * const { signal } = controller; - * const start = performance.now(); - * const subprocess = Bun.spawn({ - * cmd: ["sleep", "100"], - * signal, - * }); - * await Bun.sleep(1); - * controller.abort(); - * await subprocess.exited; - * const end = performance.now(); - * console.log(end - start); // 1ms instead of 101ms - * ``` - */ - signal?: AbortSignal; - } - - type OptionsToSubprocess = - Opts extends OptionsObject - ? Subprocess< - // "Writable extends In" means "if In === Writable", - // aka if true that means the user didn't specify anything - Writable extends In ? "ignore" : In, - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "inherit" : Err - > - : Subprocess; - - type OptionsToSyncSubprocess = - Opts extends OptionsObject - ? SyncSubprocess< - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "pipe" : Err - > - : SyncSubprocess; - - type ReadableIO = ReadableStream | number | undefined; - - type ReadableToIO = X extends "pipe" | undefined - ? ReadableStream - : X extends BunFile | ArrayBufferView | number - ? number - : undefined; - - type ReadableToSyncIO = X extends "pipe" | undefined - ? Buffer - : undefined; - - type WritableIO = FileSink | number | undefined; - - type WritableToIO = X extends "pipe" - ? FileSink - : X extends BunFile | ArrayBufferView | Blob | Request | Response | number - ? number - : undefined; - } - - interface ResourceUsage { - /** - * The number of voluntary and involuntary context switches that the process made. - */ - contextSwitches: { - /** - * Voluntary context switches (context switches that the process initiated). - */ - voluntary: number; - /** - * Involuntary context switches (context switches initiated by the system scheduler). - */ - involuntary: number; - }; - - /** - * The amount of CPU time used by the process, in microseconds. - */ - cpuTime: { - /** - * User CPU time used by the process, in microseconds. - */ - user: number; - /** - * System CPU time used by the process, in microseconds. - */ - system: number; - /** - * Total CPU time used by the process, in microseconds. - */ - total: number; - }; - /** - * The maximum amount of resident set size (in bytes) used by the process during its lifetime. - */ - maxRSS: number; - - /** - * IPC messages sent and received by the process. - */ - messages: { - /** - * The number of IPC messages sent. - */ - sent: number; - /** - * The number of IPC messages received. - */ - received: number; - }; - /** - * The number of IO operations done by the process. - */ - ops: { - /** - * The number of input operations via the file system. - */ - in: number; - /** - * The number of output operations via the file system. - */ - out: number; - }; - /** - * The amount of shared memory that the process used. - */ - shmSize: number; - /** - * The number of signals delivered to the process. - */ - signalCount: number; - /** - * The number of times the process was swapped out of main memory. - */ - swapCount: number; - } - - /** - * A process created by {@link Bun.spawn}. - * - * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSubprocess} (any, pipe, pipe) - * - {@link WritableSubprocess} (pipe, any, any) - * - {@link PipedSubprocess} (pipe, pipe, pipe) - * - {@link NullSubprocess} (ignore, ignore, ignore) - */ - interface Subprocess< - In extends SpawnOptions.Writable = SpawnOptions.Writable, - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > extends AsyncDisposable { - readonly stdin: SpawnOptions.WritableToIO; - readonly stdout: SpawnOptions.ReadableToIO; - readonly stderr: SpawnOptions.ReadableToIO; - - /** - * This returns the same value as {@link Subprocess.stdout} - * - * It exists for compatibility with {@link ReadableStream.pipeThrough} - */ - readonly readable: SpawnOptions.ReadableToIO; - - /** - * The process ID of the child process - * @example - * ```ts - * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); - * console.log(pid); // 1234 - * ``` - */ - readonly pid: number; - /** - * The exit code of the process - * - * The promise will resolve when the process exits - */ - readonly exited: Promise; - - /** - * Synchronously get the exit code of the process - * - * If the process hasn't exited yet, this will return `null` - */ - readonly exitCode: number | null; - - /** - * Synchronously get the signal code of the process - * - * If the process never sent a signal code, this will return `null` - * - * To receive signal code changes, use the `onExit` callback. - * - * If the signal code is unknown, it will return the original signal code - * number, but that case should essentially never happen. - */ - readonly signalCode: NodeJS.Signals | null; - - /** - * Has the process exited? - */ - readonly killed: boolean; - - /** - * Kill the process - * @param exitCode The exitCode to send to the process - */ - kill(exitCode?: number | NodeJS.Signals): void; - - /** - * This method will tell Bun to wait for this process to exit after you already - * called `unref()`. - * - * Before shutting down, Bun will wait for all subprocesses to exit by default - */ - ref(): void; - - /** - * Before shutting down, Bun will wait for all subprocesses to exit by default - * - * This method will tell Bun to not wait for this process to exit before shutting down. - */ - unref(): void; - - /** - * Send a message to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option, and is another instance of `bun`. - * - * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - */ - send(message: any): void; - - /** - * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option. - */ - disconnect(): void; - - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - * - * Only available after the process has exited - * - * If the process hasn't exited yet, this will return `undefined` - */ - resourceUsage(): ResourceUsage | undefined; - } - - /** - * A process created by {@link Bun.spawnSync}. - * - * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSyncSubprocess} (pipe, pipe) - * - {@link NullSyncSubprocess} (ignore, ignore) - */ - interface SyncSubprocess< - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > { - stdout: SpawnOptions.ReadableToSyncIO; - stderr: SpawnOptions.ReadableToSyncIO; - exitCode: number; - success: boolean; - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - */ - resourceUsage: ResourceUsage; - - signalCode?: string; - } - - /** - * Spawn a new process - * - * ```js - * const subprocess = Bun.spawn({ - * cmd: ["echo", "hello"], - * stdout: "pipe", - * }); - * const text = await readableStreamToText(subprocess.stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmd: string[]; // to support dynamically constructed commands - }, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawn(["echo", "hello"]); - * const text = await readableStreamToText(stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync({ - * cmd: ["echo", "hello"], - * }); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); - * ``` - */ - cmd: string[]; - - onExit?: never; - }, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** - * Synchronously spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync(["echo", "hello"]); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ - type ReadableSubprocess = Subprocess; - /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ - type WritableSubprocess = Subprocess<"pipe", any, any>; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ - type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ - type NullSubprocess = Subprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ - type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ - type NullSyncSubprocess = SyncSubprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - - // Blocked on https://github.com/oven-sh/bun/issues/8329 - // /** - // * - // * Count the visible width of a string, as it would be displayed in a terminal. - // * - // * By default, strips ANSI escape codes before measuring the string. This is - // * because ANSI escape codes are not visible characters. If passed a non-string, - // * it will return 0. - // * - // * @param str The string to measure - // * @param options - // */ - // function stringWidth( - // str: string, - // options?: { - // /** - // * Whether to include ANSI escape codes in the width calculation - // * - // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. - // * @default false - // */ - // countAnsiEscapeCodes?: boolean; - // }, - // ): number; - - class FileSystemRouter { - /** - * Create a new {@link FileSystemRouter}. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: process.cwd() + "/pages", - * style: "nextjs", - * }); - * - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} - * ``` - * @param options The options to use when creating the router - * @param options.dir The root directory containing the files to route - * @param options.style The style of router to use (only "nextjs" supported - * for now) - */ - constructor(options: { - /** - * The root directory containing the files to route - * - * There is no default value for this option. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: - */ - dir: string; - style: "nextjs"; - - /** The base path to use when routing */ - assetPrefix?: string; - origin?: string; - /** Limit the pages to those with particular file extensions. */ - fileExtensions?: string[]; - }); - - // todo: URL - match(input: string | Request | Response): MatchedRoute | null; - - readonly assetPrefix: string; - readonly origin: string; - readonly style: string; - readonly routes: Record; - - reload(): void; - } - - interface MatchedRoute { - /** - * A map of the parameters from the route - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: "/path/to/files", - * style: "nextjs", - * }); - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params.year); // "2020" - * console.log(params.month); // "01" - * console.log(params.day); // "01" - * console.log(params.slug); // "hello-world" - * ``` - */ - readonly params: Record; - readonly filePath: string; - readonly pathname: string; - readonly query: Record; - readonly name: string; - readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; - readonly src: string; - } - - /** - * The current version of Bun - * @example - * "0.2.0" - */ - const version: string; - - /** - * The current version of Bun with the shortened commit sha of the build - * @example "v1.1.30 (d09df1af)" - */ - const version_with_sha: string; - - /** - * The git sha at the time the currently-running version of Bun was compiled - * @example - * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" - */ - const revision: string; - - /** - * Find the index of a newline character in potentially ill-formed UTF-8 text. - * - * This is sort of like readline() except without the IO. - */ - function indexOfLine( - buffer: ArrayBufferView | ArrayBufferLike, - offset?: number, - ): number; - - interface GlobScanOptions { - /** - * The root directory to start matching from. Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * Allow patterns to match entries that begin with a period (`.`). - * - * @default false - */ - dot?: boolean; - - /** - * Return the absolute path for entries. - * - * @default false - */ - absolute?: boolean; - - /** - * Indicates whether to traverse descendants of symbolic link directories. - * - * @default false - */ - followSymlinks?: boolean; - - /** - * Throw an error when symbolic link is broken - * - * @default false - */ - throwErrorOnBrokenSymlink?: boolean; - - /** - * Return only files. - * - * @default true - */ - onlyFiles?: boolean; - } - - /** - * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). - * - * The supported pattern syntax for is: - * - * - `?` - * Matches any single character. - * - `*` - * Matches zero or more characters, except for path separators ('/' or '\'). - * - `**` - * Matches zero or more characters, including path separators. - * Must match a complete path segment, i.e. followed by a path separator or - * at the end of the pattern. - * - `[ab]` - * Matches one of the characters contained in the brackets. - * Character ranges (e.g. "[a-z]") are also supported. - * Use "[!ab]" or "[^ab]" to match any character *except* those contained - * in the brackets. - * - `{a,b}` - * Match one of the patterns contained in the braces. - * Any of the wildcards listed above can be used in the sub patterns. - * Braces may be nested up to 10 levels deep. - * - `!` - * Negates the result when at the start of the pattern. - * Multiple "!" characters negate the pattern multiple times. - * - `\` - * Used to escape any of the special characters above. - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - */ - export class Glob { - constructor(pattern: string); - - /** - * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for await (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scan( - optionsOrCwd?: string | GlobScanOptions, - ): AsyncIterableIterator; - - /** - * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; - - /** - * Match the glob against a string - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * expect(glob.match('foo.ts')).toBeTrue(); - * ``` - */ - match(str: string): boolean; - } - - /** - * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. - * - * When the same timestamp is used multiple times, a monotonically increasing - * counter is appended to allow sorting. The final 8 bytes are - * cryptographically random. When the timestamp changes, the counter resets to - * a psuedo-random integer. - * - * @param encoding "hex" | "base64" | "base64url" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - * - * @example - * ```js - * import { randomUUIDv7 } from "bun"; - * const array = [ - * randomUUIDv7(), - * randomUUIDv7(), - * randomUUIDv7(), - * ] - * [ - * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", - * "0192ce07-8c4f-7d67-805f-0f71581b5622", - * "0192ce07-8c4f-7d68-8170-6816e4451a58" - * ] - * ``` - */ - function randomUUIDv7( - /** - * @default "hex" - */ - encoding?: "hex" | "base64" | "base64url", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): string; - - /** - * Generate a UUIDv7 as a Buffer - * - * @param encoding "buffer" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - */ - function randomUUIDv7( - encoding: "buffer", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): Buffer; - - /** - * Types for `bun.lock` - */ - type BunLockFile = { - lockfileVersion: 0 | 1; - workspaces: { - [workspace: string]: BunLockFileWorkspacePackage; - }; - overrides?: Record; - patchedDependencies?: Record; - trustedDependencies?: string[]; - - /** - * ``` - * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } - * - * // first index is resolution for each type of package - * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] - * symlink -> [ "name@link:path", INFO ] - * folder -> [ "name@file:path", INFO ] - * workspace -> [ "name@workspace:path" ] // workspace is only path - * tarball -> [ "name@tarball", INFO ] - * root -> [ "name@root:", { bin, binDir } ] - * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] - * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] - * ``` - * */ - packages: { - [pkg: string]: BunLockFilePackageArray; - }; - }; - - type BunLockFileBasePackageInfo = { - dependencies?: Record; - devDependencies?: Record; - optionalDependencies?: Record; - peerDependencies?: Record; - optionalPeers?: string[]; - bin?: string | Record; - binDir?: string; - }; - - type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { - name?: string; - version?: string; - }; - - type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { - os?: string | string[]; - cpu?: string | string[]; - bundled?: true; - }; - - /** @see {@link BunLockFile.packages} for more info */ - type BunLockFilePackageArray = - /** npm */ - | [ - pkg: string, - registry: string, - info: BunLockFilePackageInfo, - integrity: string, - ] - /** symlink, folder, tarball */ - | [pkg: string, info: BunLockFilePackageInfo] - /** workspace */ - | [pkg: string] - /** git, github */ - | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] - /** root */ - | [pkg: string, info: Pick]; + function serve }>( + options: ( + | (DistributedOmit & { + routes: R; + fetch?: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | (DistributedOmit & { + routes?: never; + fetch: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | WebSocketServeOptions + ) & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for a while though. + */ + static?: R; + }, + ): Server; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * - `type` is auto-set based on the file extension when possible + * + * @example + * ```js + * const file = Bun.file("./hello.json"); + * console.log(file.type); // "application/json" + * console.log(await file.json()); // { hello: "world" } + * ``` + * + * @example + * ```js + * await Bun.write( + * Bun.file("./hello.txt"), + * "Hello, world!" + * ); + * ``` + * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: string | URL, options?: BlobPropertyBag): BunFile; + + /** + * A list of files embedded into the standalone executable. Lexigraphically sorted by name. + * + * If the process is not a standalone executable, this returns an empty array. + */ + const embeddedFiles: ReadonlyArray; + + /** + * `Blob` that leverages the fastest system calls available to operate on files. + * + * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. + * + * `Blob.size` will not be valid until the contents of the file are read at least once. + * `Blob.type` will have a default set based on the file extension + * + * @example + * ```js + * const file = Bun.file(new TextEncoder.encode("./hello.json")); + * console.log(file.type); // "application/json" + * ``` + * + * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} + */ + // tslint:disable-next-line:unified-signatures + function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; + + /** + * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. + * + * This Blob is lazy. That means it won't do any work until you read from it. + * + * - `size` will not be valid until the contents of the file are read at least once. + * + * @example + * ```js + * const file = Bun.file(fd); + * ``` + * + * @param fileDescriptor The file descriptor of the file + */ + // tslint:disable-next-line:unified-signatures + function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; + + /** + * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. + * + * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. + */ + function allocUnsafe(size: number): Uint8Array; + + interface BunInspectOptions { + colors?: boolean; + depth?: number; + sorted?: boolean; + compact?: boolean; + } + + /** + * Pretty-print an object the same as {@link console.log} to a `string` + * + * Supports JSX + * + * @param args + */ + function inspect(arg: any, options?: BunInspectOptions): string; + namespace inspect { + /** + * That can be used to declare custom inspect functions. + */ + const custom: typeof import("util").inspect.custom; + + /** + * Pretty-print an object or array as a table + * + * Like {@link console.table}, except it returns a string + */ + function table(tabularData: object | unknown[], properties?: string[], options?: { colors?: boolean }): string; + function table(tabularData: object | unknown[], options?: { colors?: boolean }): string; + } + + interface MMapOptions { + /** + * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. + */ + sync?: boolean; + /** + * Allow other processes to see results instantly? + * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. + * @default true + */ + shared?: boolean; + } + /** + * Open a file as a live-updating `Uint8Array` without copying memory + * - Writing to the array writes to the file. + * - Reading from the array reads from the file. + * + * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. + * + * --- + * + * This API inherently has some rough edges: + * - It does not support empty files. It will throw a `SystemError` with `EINVAL` + * - Usage on shared/networked filesystems is discouraged. It will be very slow. + * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. + * + * --- + * + * To close the file, set the array to `null` and it will be garbage collected eventually. + */ + function mmap(path: PathLike, opts?: MMapOptions): Uint8Array; + + /** Write to stdout */ + const stdout: BunFile; + /** Write to stderr */ + const stderr: BunFile; + /** + * Read from stdin + * + * This is read-only + */ + const stdin: BunFile; + + type StringLike = string | { toString(): string }; + + type ColorInput = + | { r: number; g: number; b: number; a?: number } + | [number, number, number] + | [number, number, number, number] + | Uint8Array + | Uint8ClampedArray + | Float32Array + | Float64Array + | string + | number + | { toString(): string }; + + function color( + input: ColorInput, + outputFormat?: /** + * True color ANSI color string, for use in terminals + * @example \x1b[38;2;100;200;200m + */ + | "ansi" + | "ansi-16" + | "ansi-16m" + /** + * 256 color ANSI color string, for use in terminals which don't support true color + * + * Tries to match closest 24-bit color to 256 color palette + */ + | "ansi-256" + /** + * Picks the format that produces the shortest output + */ + | "css" + /** + * Lowercase hex color string without alpha + * @example #ff9800 + */ + | "hex" + /** + * Uppercase hex color string without alpha + * @example #FF9800 + */ + | "HEX" + /** + * @example hsl(35.764706, 1, 0.5) + */ + | "hsl" + /** + * @example lab(0.72732764, 33.938198, -25.311619) + */ + | "lab" + /** + * @example 16750592 + */ + | "number" + /** + * RGB color string without alpha + * @example rgb(255, 152, 0) + */ + | "rgb" + /** + * RGB color string with alpha + * @example rgba(255, 152, 0, 1) + */ + | "rgba", + ): string | null; + + function color( + input: ColorInput, + /** + * An array of numbers representing the RGB color + * @example [100, 200, 200] + */ + outputFormat: "[rgb]", + ): [number, number, number] | null; + function color( + input: ColorInput, + /** + * An array of numbers representing the RGBA color + * @example [100, 200, 200, 255] + */ + outputFormat: "[rgba]", + ): [number, number, number, number] | null; + function color( + input: ColorInput, + /** + * An object representing the RGB color + * @example { r: 100, g: 200, b: 200 } + */ + outputFormat: "{rgb}", + ): { r: number; g: number; b: number } | null; + function color( + input: ColorInput, + /** + * An object representing the RGBA color + * @example { r: 100, g: 200, b: 200, a: 0.5 } + */ + outputFormat: "{rgba}", + ): { r: number; g: number; b: number; a: number } | null; + function color(input: ColorInput, outputFormat: "number"): number | null; + + interface Semver { + /** + * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. + */ + satisfies(version: StringLike, range: StringLike): boolean; + + /** + * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. + * Throws an error if either version is invalid. + */ + order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; + } + var semver: Semver; + + interface Unsafe { + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. + * + * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; + + /** + * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` + * + * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. + * + * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. + */ + // tslint:disable-next-line:unified-signatures + arrayBufferToString(buffer: Uint16Array): string; + + /** + * Force the garbage collector to run extremely often, + * especially inside `bun:test`. + * + * - `0`: default, disable + * - `1`: asynchronously call the garbage collector more often + * - `2`: synchronously call the garbage collector more often. + * + * This is a global setting. It's useful for debugging seemingly random crashes. + * + * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. + * + * @param level + * @returns The previous level + */ + gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; + + /** + * Dump the mimalloc heap to the console + */ + mimallocDump(): void; + } + const unsafe: Unsafe; + + type DigestEncoding = "utf8" | "ucs2" | "utf16le" | "latin1" | "ascii" | "base64" | "base64url" | "hex"; + + /** + * Are ANSI colors enabled for stdin and stdout? + * + * Used for {@link console.log} + */ + const enableANSIColors: boolean; + + /** + * What script launched Bun? + * + * Absolute file path + * + * @example "/never-gonna-give-you-up.js" + */ + const main: string; + + /** + * Manually trigger the garbage collector + * + * This does two things: + * 1. It tells JavaScriptCore to run the garbage collector + * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. + * + * @param force Synchronously run the garbage collector + */ + function gc(force: boolean): void; + + /** + * JavaScriptCore engine's internal heap snapshot + * + * I don't know how to make this something Chrome or Safari can read. + * + * If you have any ideas, please file an issue https://github.com/oven-sh/bun + */ + interface HeapSnapshot { + /** 2 */ + version: number; + + /** "Inspector" */ + type: string; + + nodes: number[]; + + nodeClassNames: string[]; + edges: number[]; + edgeTypes: string[]; + edgeNames: string[]; + } + + /** + * Returns the number of nanoseconds since the process was started. + * + * This function uses a high-resolution monotonic system timer to provide precise time measurements. + * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), + * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). + * + * Due to this limitation, while the internal counter may continue beyond this point, + * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond + * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but + * with reduced precision, which might affect time calculations and comparisons in long-running applications. + * + * @returns {number} The number of nanoseconds since the process was started, with precise values up to + * Number.MAX_SAFE_INTEGER. + */ + function nanoseconds(): number; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector + */ + function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; + + /** + * Show precise statistics about memory usage of your application + * + * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code + * + * This is a JSON string that can be saved to a file. + * ```ts + * const snapshot = Bun.generateHeapSnapshot("v8"); + * await Bun.write("heap.heapsnapshot", snapshot); + * ``` + */ + function generateHeapSnapshot(format: "v8"): string; + + /** + * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. + */ + function shrink(): void; + + /** + * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` + * + * @param path path to open + */ + function openInEditor(path: string, options?: EditorOptions): void; + + var fetch: typeof globalThis.fetch; + + interface EditorOptions { + editor?: "vscode" | "subl"; + line?: number; + column?: number; + } + + /** + * This class only exists in types + */ + abstract class CryptoHashInterface { + /** + * Update the hash with data + * + * @param data + */ + update(data: Bun.BlobOrStringOrBuffer): T; + + /** + * Finalize the hash + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash(input: Bun.BlobOrStringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash(input: Bun.BlobOrStringOrBuffer, encoding: DigestEncoding): string; + } + + type SupportedCryptoAlgorithms = + | "blake2b256" + | "blake2b512" + | "md4" + | "md5" + | "ripemd160" + | "sha1" + | "sha224" + | "sha256" + | "sha384" + | "sha512" + | "sha512-224" + | "sha512-256" + | "sha3-224" + | "sha3-256" + | "sha3-384" + | "sha3-512" + | "shake128" + | "shake256"; + + /** + * Hardware-accelerated cryptographic hash functions + * + * Used for `crypto.createHash()` + */ + class CryptoHasher { + /** + * The algorithm chosen to hash the data + */ + readonly algorithm: SupportedCryptoAlgorithms; + + /** + * The length of the output hash in bytes + */ + readonly byteLength: number; + + /** + * Create a new hasher + * + * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms + * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. + */ + constructor(algorithm: SupportedCryptoAlgorithms, hmacKey?: string | NodeJS.TypedArray); + + /** + * Update the hash with data + * + * @param input + */ + update(input: Bun.BlobOrStringOrBuffer, inputEncoding?: import("crypto").Encoding): CryptoHasher; + + /** + * Perform a deep copy of the hasher + */ + copy(): CryptoHasher; + + /** + * Finalize the hash. Resets the CryptoHasher so it can be reused. + * + * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. + */ + digest(encoding: DigestEncoding): string; + + /** + * Finalize the hash + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + digest(): Buffer; + digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time + */ + static hash(algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer): Buffer; + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + hashInto: NodeJS.TypedArray, + ): NodeJS.TypedArray; + + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + * + * @param encoding `DigestEncoding` to return the hash in + */ + static hash( + algorithm: SupportedCryptoAlgorithms, + input: Bun.BlobOrStringOrBuffer, + encoding: DigestEncoding, + ): string; + + /** + * List of supported hash algorithms + * + * These are hardware accelerated with BoringSSL + */ + static readonly algorithms: SupportedCryptoAlgorithms[]; + } + + /** + * Resolve a `Promise` after milliseconds. This is like + * {@link setTimeout} except it returns a `Promise`. + * + * @param ms milliseconds to delay resolving the promise. This is a minimum + * number. It may take longer. If a {@link Date} is passed, it will sleep until the + * {@link Date} is reached. + * + * @example + * ## Sleep for 1 second + * ```ts + * import { sleep } from "bun"; + * + * await sleep(1000); + * ``` + * ## Sleep for 10 milliseconds + * ```ts + * await Bun.sleep(10); + * ``` + * ## Sleep until `Date` + * + * ```ts + * const target = new Date(); + * target.setSeconds(target.getSeconds() + 1); + * await Bun.sleep(target); + * ``` + * Internally, `Bun.sleep` is the equivalent of + * ```ts + * await new Promise((resolve) => setTimeout(resolve, ms)); + * ``` + * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. + */ + function sleep(ms: number | Date): Promise; + + /** + * Sleep the thread for a given number of milliseconds + * + * This is a blocking function. + * + * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) + */ + function sleepSync(ms: number): void; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; + + /** + * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster + * @param encoding `DigestEncoding` to return the hash in + * + * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. + * + * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) + * + * The equivalent `openssl` command is: + * + * ```bash + * # You will need OpenSSL 3 or later + * openssl sha512-256 /path/to/file + * ``` + */ + function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; + + /** + * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} + * + * Consider using the ugly-named {@link SHA512_256} instead + */ + class SHA1 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 20; + } + class MD5 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class MD4 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 16; + } + class SHA224 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 28; + } + class SHA512 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 64; + } + class SHA384 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 48; + } + class SHA256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + /** + * See also {@link sha} + */ + class SHA512_256 extends CryptoHashInterface { + constructor(); + + /** + * The number of bytes the hash will produce + */ + static readonly byteLength: 32; + } + + /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ + interface ZlibCompressionOptions { + /** + * The compression level to use. Must be between `-1` and `9`. + * - A value of `-1` uses the default compression level (Currently `6`) + * - A value of `0` gives no compression + * - A value of `1` gives least compression, fastest speed + * - A value of `9` gives best compression, slowest speed + */ + level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * How much memory should be allocated for the internal compression state. + * + * A value of `1` uses minimum memory but is slow and reduces compression ratio. + * + * A value of `9` uses maximum memory for optimal speed. The default is `8`. + */ + memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; + /** + * The base 2 logarithm of the window size (the size of the history buffer). + * + * Larger values of this parameter result in better compression at the expense of memory usage. + * + * The following value ranges are supported: + * - `9..15`: The output will have a zlib header and footer (Deflate) + * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) + * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) + * + * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. + */ + windowBits?: + | -9 + | -10 + | -11 + | -12 + | -13 + | -14 + | -15 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 25 + | 26 + | 27 + | 28 + | 29 + | 30 + | 31; + /** + * Tunes the compression algorithm. + * + * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** + * - `Z_FILTERED`: For data produced by a filter or predictor + * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) + * - `Z_RLE`: Limit match distances to one (run-length encoding) + * - `Z_FIXED` prevents the use of dynamic Huffman codes + * + * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. + * + * `Z_FILTERED` forces more Huffman coding and less string matching, it is + * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. + * Filtered data consists mostly of small values with a somewhat random distribution. + */ + strategy?: number; + + library?: "zlib"; + } + + interface LibdeflateCompressionOptions { + level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; + library?: "libdeflate"; + } + + /** + * Compresses a chunk of data with `zlib` DEFLATE algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function deflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Compresses a chunk of data with `zlib` GZIP algorithm. + * @param data The buffer of data to compress + * @param options Compression options to use + * @returns The output buffer with the compressed data + */ + function gzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` INFLATE algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function inflateSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + /** + * Decompresses a chunk of data with `zlib` GUNZIP algorithm. + * @param data The buffer of data to decompress + * @returns The output buffer with the decompressed data + */ + function gunzipSync( + data: Uint8Array | string | ArrayBuffer, + options?: ZlibCompressionOptions | LibdeflateCompressionOptions, + ): Uint8Array; + + type Target = + /** + * For generating bundles that are intended to be run by the Bun runtime. In many cases, + * it isn't necessary to bundle server-side code; you can directly execute the source code + * without modification. However, bundling your server code can reduce startup times and + * improve running performance. + * + * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which + * indicates to the Bun runtime that there's no need to re-transpile the file before execution. + */ + | "bun" + /** + * The plugin will be applied to Node.js builds + */ + | "node" + /** + * The plugin will be applied to browser builds + */ + | "browser"; + + /** https://bun.sh/docs/bundler/loaders */ + type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "file" | "napi" | "wasm" | "text" | "css" | "html"; + + interface PluginConstraints { + /** + * Only apply the plugin when the import specifier matches this regular expression + * + * @example + * ```ts + * // Only apply the plugin when the import specifier matches the regex + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { + * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; + * }); + * } + * }) + * ``` + */ + filter: RegExp; + + /** + * Only apply the plugin when the import specifier has a namespace matching + * this string + * + * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` + * has the namespace `"bun"`. + * + * The default namespace is `"file"` and it can be omitted from import + * specifiers. + */ + namespace?: string; + } + + interface OnLoadResultSourceCode { + /** + * The source code of the module + */ + contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; + /** + * The loader to use for this file + * + * "css" will be added in a future version of Bun. + */ + loader?: Loader; + } + + interface OnLoadResultObject { + /** + * The object to use as the module + * @example + * ```ts + * // In your loader + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * + * // In your script + * import {foo} from "hello:world"; + * console.log(foo); // "bar" + * ``` + */ + exports: Record; + /** + * The loader to use for this file + */ + loader: "object"; + } + + interface OnLoadArgs { + /** + * The resolved import specifier of the module being loaded + * @example + * ```ts + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * console.log(args.path); // "hello:world" + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * ``` + */ + path: string; + /** + * The namespace of the module being loaded + */ + namespace: string; + /** + * The default loader for this file extension + */ + loader: Loader; + /** + * Defer the execution of this callback until all other modules have been parsed. + * + * @returns Promise which will be resolved when all modules have been parsed + */ + defer: () => Promise; + } + + type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject | undefined | void; + type OnLoadCallback = (args: OnLoadArgs) => OnLoadResult | Promise; + type OnStartCallback = () => void | Promise; + + interface OnResolveArgs { + /** + * The import specifier of the module being loaded + */ + path: string; + /** + * The module that imported the module being resolved + */ + importer: string; + /** + * The namespace of the importer. + */ + namespace: string; + /** + * The directory to perform file-based resolutions in. + */ + resolveDir: string; + /** + * The kind of import this resolve is for. + */ + kind: ImportKind; + // resolveDir: string; + // pluginData: any; + } + + interface OnResolveResult { + /** + * The destination of the import + */ + path: string; + /** + * The namespace of the destination + * It will be concatenated with `path` to form the final import specifier + * @example + * ```ts + * "foo" // "foo:bar" + * ``` + */ + namespace?: string; + external?: boolean; + } + + type OnResolveCallback = ( + args: OnResolveArgs, + ) => OnResolveResult | Promise | undefined | null; + + type FFIFunctionCallable = Function & { + // Making a nominally typed function so that the user must get it from dlopen + readonly __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol; + }; + + interface PluginBuilder { + /** + * Register a callback which will be invoked when bundling starts. When + * using hot module reloading, this is called at the start of each + * incremental rebuild. + * + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onStart(() => { + * console.log("bundle just started!!") + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onStart(callback: OnStartCallback): this; + onBeforeParse( + constraints: PluginConstraints, + callback: { + napiModule: unknown; + symbol: string; + external?: unknown | undefined; + }, + ): this; + /** + * Register a callback to load imports with a specific import specifier + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /^hello:world$/ }, (args) => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; + /** + * Register a callback to resolve imports matching a filter and/or namespace + * @param constraints The constraints to apply the plugin to + * @param callback The callback to handle the import + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.onResolve({ filter: /^wat$/ }, (args) => { + * return { path: "/tmp/woah.js" }; + * }); + * }, + * }); + * ``` + * + * @returns `this` for method chaining + */ + onResolve(constraints: PluginConstraints, callback: OnResolveCallback): this; + /** + * The config object passed to `Bun.build` as is. Can be mutated. + */ + config: BuildConfig & { plugins: BunPlugin[] }; + + /** + * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules + * + * @param specifier The module specifier to register the callback for + * @param callback The function to run when the module is imported or required + * + * ### Example + * @example + * ```ts + * Bun.plugin({ + * setup(builder) { + * builder.module("hello:world", () => { + * return { exports: { foo: "bar" }, loader: "object" }; + * }); + * }, + * }); + * + * // sometime later + * const { foo } = await import("hello:world"); + * console.log(foo); // "bar" + * + * // or + * const { foo } = require("hello:world"); + * console.log(foo); // "bar" + * ``` + * + * @returns `this` for method chaining + */ + module(specifier: string, callback: () => OnLoadResult | Promise): this; + } + + interface BunPlugin { + /** + * Human-readable name of the plugin + * + * In a future version of Bun, this will be used in error messages. + */ + name: string; + + /** + * The target JavaScript environment the plugin should be applied to. + * - `bun`: The default environment when using `bun run` or `bun` to load a script + * - `browser`: The plugin will be applied to browser builds + * - `node`: The plugin will be applied to Node.js builds + * + * If unspecified, it is assumed that the plugin is compatible with all targets. + * + * This field is not read by {@link Bun.plugin} + */ + target?: Target; + /** + * A function that will be called when the plugin is loaded. + * + * This function may be called in the same tick that it is registered, or it + * may be called later. It could potentially be called multiple times for + * different targets. + */ + setup( + /** + * A builder object that can be used to register plugin hooks + * @example + * ```ts + * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), + * })); + * ``` + */ + build: PluginBuilder, + ): void | Promise; + } + + /** + * Extend Bun's module resolution and loading behavior + * + * Plugins are applied in the order they are defined. + * + * Today, there are two kinds of hooks: + * - `onLoad` lets you return source code or an object that will become the module's exports + * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. + * + * Plugin hooks must define a `filter` RegExp and will only be matched if the + * import specifier contains a "." or a ":". + * + * ES Module resolution semantics mean that plugins may be initialized _after_ + * a module is resolved. You might need to load plugins at the very beginning + * of the application and then use a dynamic import to load the rest of the + * application. A future version of Bun may also support specifying plugins + * via `bunfig.toml`. + * + * @example + * A YAML loader plugin + * + * ```js + * Bun.plugin({ + * setup(builder) { + * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ + * loader: "object", + * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) + * })); + * }); + * + * // You can use require() + * const {foo} = require("./file.yaml"); + * + * // Or import + * await import("./file.yaml"); + * + * ``` + */ + interface BunRegisterPlugin { + (options: T): ReturnType; + + /** + * Deactivate all plugins + * + * This prevents registered plugins from being applied to future builds. + */ + clearAll(): void; + } + + const plugin: BunRegisterPlugin; + + /** + * Is the current global scope the main thread? + */ + const isMainThread: boolean; + + /** + * Used when importing an HTML file at runtime. + * + * @example + * + * ```ts + * import app from "./index.html"; + * ``` + * + * Bun.build support for this isn't imlpemented yet. + */ + interface HTMLBundle { + index: string; + } + + interface Socket extends Disposable { + /** + * Write `data` to the socket + * + * @param data The data to write to the socket + * @param byteOffset The offset in the buffer to start writing from (defaults to 0) + * @param byteLength The number of bytes to write (defaults to the length of the buffer) + * + * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. + * + * This is unbuffered as of Bun v0.2.2. That means individual write() calls + * will be slow. In the future, Bun will buffer writes and flush them at the + * end of the tick, when the event loop is idle, or sooner if the buffer is full. + */ + write(data: string | BufferSource, byteOffset?: number, byteLength?: number): number; + + /** + * The data context for the socket. + */ + data: Data; + + /** + * Like {@link Socket.write} except it includes a TCP FIN packet + * + * Use it to send your last message and close the connection. + */ + end(data?: string | BufferSource, byteOffset?: number, byteLength?: number): number; + + /** + * Close the socket immediately + */ + end(): void; + + /** + * Keep Bun's process alive at least until this socket is closed + * + * After the socket has closed, the socket is unref'd, the process may exit, + * and this becomes a no-op + */ + ref(): void; + + /** + * Set a timeout until the socket automatically closes. + * + * To reset the timeout, call this function again. + * + * When a timeout happens, the `timeout` callback is called and the socket is closed. + */ + timeout(seconds: number): void; + + /** + * Forcefully close the socket. The other end may not receive all data, and + * the socket will be closed immediately. + * + * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to + * `0` and then calls `close(2)`. + */ + terminate(): void; + + /** + * Shutdown writes to a socket + * + * This makes the socket a half-closed socket. It can still receive data. + * + * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally + */ + shutdown(halfClose?: boolean): void; + + readonly readyState: "open" | "closing" | "closed"; + + /** + * Allow Bun's process to exit even if this socket is still open + * + * After the socket has closed, this function does nothing. + */ + unref(): void; + + /** + * Flush any buffered data to the socket + */ + flush(): void; + + /** + * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. + * + * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. + */ + reload(handler: SocketHandler): void; + + /** + * Get the server that created this socket + * + * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. + */ + readonly listener?: SocketListener; + + /** + * Remote IP address connected to the socket + */ + readonly remoteAddress: string; + + /** + * local port connected to the socket + */ + readonly localPort: number; + + /** + * This property is `true` if the peer certificate was signed by one of the CAs + * specified when creating the `Socket` instance, otherwise `false`. + */ + readonly authorized: boolean; + + /** + * String containing the selected ALPN protocol. + * Before a handshake has completed, this value is always null. + * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. + */ + readonly alpnProtocol: string | false | null; + + /** + * Disables TLS renegotiation for this `Socket` instance. Once called, attempts + * to renegotiate will trigger an `error` handler on the `Socket`. + * + * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) + */ + disableRenegotiation(): void; + + /** + * Keying material is used for validations to prevent different kind of attacks in + * network protocols, for example in the specifications of IEEE 802.1X. + * + * Example + * + * ```js + * const keyingMaterial = socket.exportKeyingMaterial( + * 128, + * 'client finished'); + * + * /* + * Example return value of keyingMaterial: + * + * + * ``` + * + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the [IANA Exporter Label + * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context Optionally provide a context. + * @return requested bytes of the keying material + */ + exportKeyingMaterial(length: number, label: string, context: Buffer): Buffer; + + /** + * Returns the reason why the peer's certificate was not been verified. This + * property is set only when `socket.authorized === false`. + */ + getAuthorizationError(): Error | null; + + /** + * Returns an object representing the local certificate. The returned object has + * some properties corresponding to the fields of the certificate. + * + * If there is no local certificate, an empty object will be returned. If the + * socket has been destroyed, `null` will be returned. + */ + getCertificate(): import("tls").PeerCertificate | object | null; + getX509Certificate(): import("node:crypto").X509Certificate | undefined; + + /** + * Returns an object containing information on the negotiated cipher suite. + * + * For example, a TLSv1.2 protocol with AES256-SHA cipher: + * + * ```json + * { + * "name": "AES256-SHA", + * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", + * "version": "SSLv3" + * } + * ``` + * + */ + getCipher(): import("tls").CipherNameAndProtocol; + + /** + * Returns an object representing the type, name, and size of parameter of + * an ephemeral key exchange in `perfect forward secrecy` on a client + * connection. It returns an empty object when the key exchange is not + * ephemeral. As this is only supported on a client socket; `null` is returned + * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. + * + * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. + */ + getEphemeralKeyInfo(): import("tls").EphemeralKeyInfo | object | null; + + /** + * Returns an object representing the peer's certificate. If the peer does not + * provide a certificate, an empty object will be returned. If the socket has been + * destroyed, `null` will be returned. + * + * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's + * certificate. + * @return A certificate object. + */ + getPeerCertificate(): import("tls").PeerCertificate; + getPeerX509Certificate(): import("node:crypto").X509Certificate; + + /** + * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. + * @since v12.11.0 + * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. + */ + getSharedSigalgs(): string[]; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. + */ + getTLSFinishedMessage(): Buffer | undefined; + + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so + * far. + */ + getTLSPeerFinishedMessage(): Buffer | undefined; + + /** + * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. + * + * It may be useful for debugging. + * + * See `Session Resumption` for more information. + */ + getTLSTicket(): Buffer | undefined; + + /** + * Returns a string containing the negotiated SSL/TLS protocol version of the + * current connection. The value `'unknown'` will be returned for connected + * sockets that have not completed the handshaking process. The value `null` will + * be returned for server sockets or disconnected client sockets. + * + * Protocol versions are: + * + * * `'SSLv3'` + * * `'TLSv1'` + * * `'TLSv1.1'` + * * `'TLSv1.2'` + * * `'TLSv1.3'` + * + */ + getTLSVersion(): string; + + /** + * See `Session Resumption` for more information. + * @return `true` if the session was reused, `false` otherwise. + */ + isSessionReused(): boolean; + + /** + * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. + * Returns `true` if setting the limit succeeded; `false` otherwise. + * + * Smaller fragment sizes decrease the buffering latency on the client: larger + * fragments are buffered by the TLS layer until the entire fragment is received + * and its integrity is verified; large fragments can span multiple roundtrips + * and their processing can be delayed due to packet loss or reordering. However, + * smaller fragments add extra TLS framing bytes and CPU overhead, which may + * decrease overall server throughput. + * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. + */ + setMaxSendFragment(size: number): boolean; + + /** + * Enable/disable the use of Nagle's algorithm. + * Only available for already connected sockets, will return false otherwise + * @param noDelay Default: `true` + * @returns true if is able to setNoDelay and false if it fails. + */ + setNoDelay(noDelay?: boolean): boolean; + + /** + * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. + * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. + * Only available for already connected sockets, will return false otherwise. + * + * Enabling the keep-alive functionality will set the following socket options: + * SO_KEEPALIVE=1 + * TCP_KEEPIDLE=initialDelay + * TCP_KEEPCNT=10 + * TCP_KEEPINTVL=1 + * @param enable Default: `false` + * @param initialDelay Default: `0` + * @returns true if is able to setNoDelay and false if it fails. + */ + setKeepAlive(enable?: boolean, initialDelay?: number): boolean; + + /** + * The number of bytes written to the socket. + */ + readonly bytesWritten: number; + } + + interface SocketListener extends Disposable { + stop(closeActiveConnections?: boolean): void; + ref(): void; + unref(): void; + reload(options: Pick, "socket">): void; + data: Data; + } + interface TCPSocketListener extends SocketListener { + readonly port: number; + readonly hostname: string; + } + interface UnixSocketListener extends SocketListener { + readonly unix: string; + } + + interface TCPSocket extends Socket {} + interface TLSSocket extends Socket {} + + interface BinaryTypeList { + arraybuffer: ArrayBuffer; + buffer: Buffer; + uint8array: Uint8Array; + // TODO: DataView + // dataview: DataView; + } + type BinaryType = keyof BinaryTypeList; + + interface SocketHandler { + /** + * Is called when the socket connects, or in case of TLS if no handshake is provided + * this will be called only after handshake + * @param socket + */ + open?(socket: Socket): void | Promise; + close?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + data?(socket: Socket, data: BinaryTypeList[DataBinaryType]): void | Promise; + drain?(socket: Socket): void | Promise; + + /** + * When handshake is completed, this functions is called. + * @param socket + * @param success Indicates if the server authorized despite the authorizationError. + * @param authorizationError Certificate Authorization Error or null. + */ + handshake?(socket: Socket, success: boolean, authorizationError: Error | null): void; + + /** + * When the socket has been shutdown from the other end, this function is + * called. This is a TCP FIN packet. + */ + end?(socket: Socket): void | Promise; + + /** + * When the socket fails to be created, this function is called. + * + * The promise returned by `Bun.connect` rejects **after** this function is + * called. + * + * When `connectError` is specified, the rejected promise will not be + * added to the promise rejection queue (so it won't be reported as an + * unhandled promise rejection, since connectError handles it). + * + * When `connectError` is not specified, the rejected promise will be added + * to the promise rejection queue. + */ + connectError?(socket: Socket, error: Error): void | Promise; + + /** + * Called when a message times out. + */ + timeout?(socket: Socket): void | Promise; + /** + * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. + * + * @default "buffer" + * + * @remarks + * This lets you select the desired binary type for the `data` callback. + * It's a small performance optimization to let you avoid creating extra + * ArrayBufferView objects when possible. + * + * Bun originally defaulted to `Uint8Array` but when dealing with network + * data, it's more useful to be able to directly read from the bytes which + * `Buffer` allows. + */ + binaryType?: BinaryType; + } + + interface SocketOptions { + socket: SocketHandler; + data?: Data; + } + // interface TCPSocketOptions extends SocketOptions { + // hostname: string; + // port: number; + // } + + interface TCPSocketListenOptions extends SocketOptions { + hostname: string; + port: number; + tls?: TLSOptions; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface TCPSocketConnectOptions extends SocketOptions { + hostname: string; + port: number; + tls?: boolean; + exclusive?: boolean; + allowHalfOpen?: boolean; + } + + interface UnixSocketOptions extends SocketOptions { + tls?: TLSOptions; + unix: string; + } + + interface FdSocketOptions extends SocketOptions { + tls?: TLSOptions; + fd: number; + } + + /** + * Create a TCP client that connects to a server + * + * @param options The options to use when creating the client + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function connect(options: TCPSocketConnectOptions): Promise>; + function connect(options: UnixSocketOptions): Promise>; + + /** + * Create a TCP server that listens on a port + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.data The per-instance data context + * @param options.hostname The hostname to connect to + * @param options.port The port to connect to + * @param options.tls The TLS configuration object + * @param options.unix The unix socket to connect to + */ + function listen(options: TCPSocketListenOptions): TCPSocketListener; + function listen(options: UnixSocketOptions): UnixSocketListener; + + namespace udp { + type Data = string | ArrayBufferView | ArrayBufferLike; + + export interface SocketHandler { + data?( + socket: Socket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: Socket): void | Promise; + error?(socket: Socket, error: Error): void | Promise; + } + + export interface ConnectedSocketHandler { + data?( + socket: ConnectedSocket, + data: BinaryTypeList[DataBinaryType], + port: number, + address: string, + ): void | Promise; + drain?(socket: ConnectedSocket): void | Promise; + error?(socket: ConnectedSocket, error: Error): void | Promise; + } + + export interface SocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: SocketHandler; + } + + export interface ConnectSocketOptions { + hostname?: string; + port?: number; + binaryType?: DataBinaryType; + socket?: ConnectedSocketHandler; + connect: { + hostname: string; + port: number; + }; + } + + export interface BaseUDPSocket { + readonly hostname: string; + readonly port: number; + readonly address: SocketAddress; + readonly binaryType: BinaryType; + readonly closed: boolean; + ref(): void; + unref(): void; + close(): void; + } + + export interface ConnectedSocket extends BaseUDPSocket { + readonly remoteAddress: SocketAddress; + sendMany(packets: readonly Data[]): number; + send(data: Data): boolean; + reload(handler: ConnectedSocketHandler): void; + } + + export interface Socket extends BaseUDPSocket { + sendMany(packets: readonly (Data | string | number)[]): number; + send(data: Data, port: number, address: string): boolean; + reload(handler: SocketHandler): void; + } + } + + /** + * Create a UDP socket + * + * @param options The options to use when creating the server + * @param options.socket The socket handler to use + * @param options.hostname The hostname to listen on + * @param options.port The port to listen on + * @param options.binaryType The binary type to use for the socket + * @param options.connect The hostname and port to connect to + */ + export function udpSocket( + options: udp.SocketOptions, + ): Promise>; + export function udpSocket( + options: udp.ConnectSocketOptions, + ): Promise>; + + namespace SpawnOptions { + /** + * Option for stdout/stderr + */ + type Readable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number; + + /** + * Option for stdin + */ + type Writable = + | "pipe" + | "inherit" + | "ignore" + | null // equivalent to "ignore" + | undefined // to use default + | BunFile + | ArrayBufferView + | number + | ReadableStream + | Blob + | Response + | Request; + + interface OptionsObject< + In extends Writable = Writable, + Out extends Readable = Readable, + Err extends Readable = Readable, + > { + /** + * The current working directory of the process + * + * Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * The environment variables of the process + * + * Defaults to `process.env` as it was when the current Bun process launched. + * + * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. + */ + env?: Record; + + /** + * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. + * This overrides the `stdin`, `stdout`, and `stderr` properties. + * + * For stdin you may pass: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. + * - `number`: The process will read from the file descriptor + * + * For stdout and stdin you may pass: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default ["ignore", "pipe", "inherit"] for `spawn` + * ["ignore", "pipe", "pipe"] for `spawnSync` + */ + stdio?: [In, Out, Err]; + /** + * The file descriptor for the standard input. It may be: + * + * - `"ignore"`, `null`, `undefined`: The process will have no standard input + * - `"pipe"`: The process will have a new {@link FileSink} for standard input + * - `"inherit"`: The process will inherit the standard input of the current process + * - `ArrayBufferView`, `Blob`: The process will read from the buffer + * - `number`: The process will read from the file descriptor + * + * @default "ignore" + */ + stdin?: In; + /** + * The file descriptor for the standard output. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "pipe" + */ + stdout?: Out; + /** + * The file descriptor for the standard error. It may be: + * + * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error + * - `"ignore"`, `null`: The process will have no standard output/error + * - `"inherit"`: The process will inherit the standard output/error of the current process + * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. + * - `number`: The process will write to the file descriptor + * + * @default "inherit" for `spawn` + * "pipe" for `spawnSync` + */ + stderr?: Err; + + /** + * Callback that runs when the {@link Subprocess} exits + * + * This is called even if the process exits with a non-zero exit code. + * + * Warning: this may run before the `Bun.spawn` function returns. + * + * A simple alternative is `await subprocess.exited`. + * + * @example + * + * ```ts + * const subprocess = spawn({ + * cmd: ["echo", "hello"], + * onExit: (subprocess, code) => { + * console.log(`Process exited with code ${code}`); + * }, + * }); + * ``` + */ + onExit?( + subprocess: Subprocess, + exitCode: number | null, + signalCode: number | null, + /** + * If an error occurred in the call to waitpid2, this will be the error. + */ + error?: ErrorLike, + ): void | Promise; + + /** + * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for + * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized + * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + * + * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, + * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. + * + * Currently, this is only compatible with processes that are other `bun` instances. + */ + ipc?( + message: any, + /** + * The {@link Subprocess} that sent the message + */ + subprocess: Subprocess, + ): void; + + /** + * The serialization format to use for IPC messages. Defaults to `"advanced"`. + * + * To communicate with Node.js processes, use `"json"`. + * + * When `ipc` is not specified, this is ignored. + */ + serialization?: "json" | "advanced"; + + /** + * If true, the subprocess will have a hidden window. + */ + windowsHide?: boolean; + + /** + * If true, no quoting or escaping of arguments is done on Windows. + */ + windowsVerbatimArguments?: boolean; + + /** + * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. + * + * One use-case for this is for applications which wrap other applications or to simulate a symlink. + * + * @default cmds[0] + */ + argv0?: string; + + /** + * An {@link AbortSignal} that can be used to abort the subprocess. + * + * This is useful for aborting a subprocess when some other part of the + * program is aborted, such as a `fetch` response. + * + * Internally, this works by calling `subprocess.kill(1)`. + * + * @example + * ```ts + * const controller = new AbortController(); + * const { signal } = controller; + * const start = performance.now(); + * const subprocess = Bun.spawn({ + * cmd: ["sleep", "100"], + * signal, + * }); + * await Bun.sleep(1); + * controller.abort(); + * await subprocess.exited; + * const end = performance.now(); + * console.log(end - start); // 1ms instead of 101ms + * ``` + */ + signal?: AbortSignal; + } + + type OptionsToSubprocess = + Opts extends OptionsObject + ? Subprocess< + // "Writable extends In" means "if In === Writable", + // aka if true that means the user didn't specify anything + Writable extends In ? "ignore" : In, + Readable extends Out ? "pipe" : Out, + Readable extends Err ? "inherit" : Err + > + : Subprocess; + + type OptionsToSyncSubprocess = + Opts extends OptionsObject + ? SyncSubprocess + : SyncSubprocess; + + type ReadableIO = ReadableStream | number | undefined; + + type ReadableToIO = X extends "pipe" | undefined + ? ReadableStream + : X extends BunFile | ArrayBufferView | number + ? number + : undefined; + + type ReadableToSyncIO = X extends "pipe" | undefined ? Buffer : undefined; + + type WritableIO = FileSink | number | undefined; + + type WritableToIO = X extends "pipe" + ? FileSink + : X extends BunFile | ArrayBufferView | Blob | Request | Response | number + ? number + : undefined; + } + + interface ResourceUsage { + /** + * The number of voluntary and involuntary context switches that the process made. + */ + contextSwitches: { + /** + * Voluntary context switches (context switches that the process initiated). + */ + voluntary: number; + /** + * Involuntary context switches (context switches initiated by the system scheduler). + */ + involuntary: number; + }; + + /** + * The amount of CPU time used by the process, in microseconds. + */ + cpuTime: { + /** + * User CPU time used by the process, in microseconds. + */ + user: number; + /** + * System CPU time used by the process, in microseconds. + */ + system: number; + /** + * Total CPU time used by the process, in microseconds. + */ + total: number; + }; + /** + * The maximum amount of resident set size (in bytes) used by the process during its lifetime. + */ + maxRSS: number; + + /** + * IPC messages sent and received by the process. + */ + messages: { + /** + * The number of IPC messages sent. + */ + sent: number; + /** + * The number of IPC messages received. + */ + received: number; + }; + /** + * The number of IO operations done by the process. + */ + ops: { + /** + * The number of input operations via the file system. + */ + in: number; + /** + * The number of output operations via the file system. + */ + out: number; + }; + /** + * The amount of shared memory that the process used. + */ + shmSize: number; + /** + * The number of signals delivered to the process. + */ + signalCount: number; + /** + * The number of times the process was swapped out of main memory. + */ + swapCount: number; + } + + /** + * A process created by {@link Bun.spawn}. + * + * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSubprocess} (any, pipe, pipe) + * - {@link WritableSubprocess} (pipe, any, any) + * - {@link PipedSubprocess} (pipe, pipe, pipe) + * - {@link NullSubprocess} (ignore, ignore, ignore) + */ + interface Subprocess< + In extends SpawnOptions.Writable = SpawnOptions.Writable, + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > extends AsyncDisposable { + readonly stdin: SpawnOptions.WritableToIO; + readonly stdout: SpawnOptions.ReadableToIO; + readonly stderr: SpawnOptions.ReadableToIO; + + /** + * This returns the same value as {@link Subprocess.stdout} + * + * It exists for compatibility with {@link ReadableStream.pipeThrough} + */ + readonly readable: SpawnOptions.ReadableToIO; + + /** + * The process ID of the child process + * @example + * ```ts + * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); + * console.log(pid); // 1234 + * ``` + */ + readonly pid: number; + /** + * The exit code of the process + * + * The promise will resolve when the process exits + */ + readonly exited: Promise; + + /** + * Synchronously get the exit code of the process + * + * If the process hasn't exited yet, this will return `null` + */ + readonly exitCode: number | null; + + /** + * Synchronously get the signal code of the process + * + * If the process never sent a signal code, this will return `null` + * + * To receive signal code changes, use the `onExit` callback. + * + * If the signal code is unknown, it will return the original signal code + * number, but that case should essentially never happen. + */ + readonly signalCode: NodeJS.Signals | null; + + /** + * Has the process exited? + */ + readonly killed: boolean; + + /** + * Kill the process + * @param exitCode The exitCode to send to the process + */ + kill(exitCode?: number | NodeJS.Signals): void; + + /** + * This method will tell Bun to wait for this process to exit after you already + * called `unref()`. + * + * Before shutting down, Bun will wait for all subprocesses to exit by default + */ + ref(): void; + + /** + * Before shutting down, Bun will wait for all subprocesses to exit by default + * + * This method will tell Bun to not wait for this process to exit before shutting down. + */ + unref(): void; + + /** + * Send a message to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option, and is another instance of `bun`. + * + * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. + */ + send(message: any): void; + + /** + * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess + * was created with the `ipc` option. + */ + disconnect(): void; + + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + * + * Only available after the process has exited + * + * If the process hasn't exited yet, this will return `undefined` + */ + resourceUsage(): ResourceUsage | undefined; + } + + /** + * A process created by {@link Bun.spawnSync}. + * + * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: + * - {@link ReadableSyncSubprocess} (pipe, pipe) + * - {@link NullSyncSubprocess} (ignore, ignore) + */ + interface SyncSubprocess< + Out extends SpawnOptions.Readable = SpawnOptions.Readable, + Err extends SpawnOptions.Readable = SpawnOptions.Readable, + > { + stdout: SpawnOptions.ReadableToSyncIO; + stderr: SpawnOptions.ReadableToSyncIO; + exitCode: number; + success: boolean; + /** + * Get the resource usage information of the process (max RSS, CPU time, etc) + */ + resourceUsage: ResourceUsage; + + signalCode?: string; + } + + /** + * Spawn a new process + * + * ```js + * const subprocess = Bun.spawn({ + * cmd: ["echo", "hello"], + * stdout: "pipe", + * }); + * const text = await readableStreamToText(subprocess.stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmd: string[]; // to support dynamically constructed commands + }, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawn(["echo", "hello"]); + * const text = await readableStreamToText(stdout); + * console.log(text); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawn( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawn(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSubprocess; + + /** + * Spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync({ + * cmd: ["echo", "hello"], + * }); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + options: Opts & { + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); + * ``` + */ + cmd: string[]; + + onExit?: never; + }, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** + * Synchronously spawn a new process + * + * ```js + * const {stdout} = Bun.spawnSync(["echo", "hello"]); + * console.log(stdout.toString()); // "hello\n" + * ``` + * + * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) + */ + function spawnSync( + /** + * The command to run + * + * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. + * + * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. + * + * To check if the command exists before running it, use `Bun.which(bin)`. + * + * @example + * ```ts + * const subprocess = Bun.spawnSync(["echo", "hello"]); + * ``` + */ + cmds: string[], + options?: Opts, + ): SpawnOptions.OptionsToSyncSubprocess; + + /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ + type ReadableSubprocess = Subprocess; + /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ + type WritableSubprocess = Subprocess<"pipe", any, any>; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ + type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ + type NullSubprocess = Subprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ + type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; + /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ + type NullSyncSubprocess = SyncSubprocess< + "ignore" | "inherit" | null | undefined, + "ignore" | "inherit" | null | undefined + >; + + // Blocked on https://github.com/oven-sh/bun/issues/8329 + // /** + // * + // * Count the visible width of a string, as it would be displayed in a terminal. + // * + // * By default, strips ANSI escape codes before measuring the string. This is + // * because ANSI escape codes are not visible characters. If passed a non-string, + // * it will return 0. + // * + // * @param str The string to measure + // * @param options + // */ + // function stringWidth( + // str: string, + // options?: { + // /** + // * Whether to include ANSI escape codes in the width calculation + // * + // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. + // * @default false + // */ + // countAnsiEscapeCodes?: boolean; + // }, + // ): number; + + class FileSystemRouter { + /** + * Create a new {@link FileSystemRouter}. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: process.cwd() + "/pages", + * style: "nextjs", + * }); + * + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} + * ``` + * @param options The options to use when creating the router + * @param options.dir The root directory containing the files to route + * @param options.style The style of router to use (only "nextjs" supported + * for now) + */ + constructor(options: { + /** + * The root directory containing the files to route + * + * There is no default value for this option. + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: + */ + dir: string; + style: "nextjs"; + + /** The base path to use when routing */ + assetPrefix?: string; + origin?: string; + /** Limit the pages to those with particular file extensions. */ + fileExtensions?: string[]; + }); + + // todo: URL + match(input: string | Request | Response): MatchedRoute | null; + + readonly assetPrefix: string; + readonly origin: string; + readonly style: string; + readonly routes: Record; + + reload(): void; + } + + interface MatchedRoute { + /** + * A map of the parameters from the route + * + * @example + * ```ts + * const router = new FileSystemRouter({ + * dir: "/path/to/files", + * style: "nextjs", + * }); + * const {params} = router.match("/blog/2020/01/01/hello-world"); + * console.log(params.year); // "2020" + * console.log(params.month); // "01" + * console.log(params.day); // "01" + * console.log(params.slug); // "hello-world" + * ``` + */ + readonly params: Record; + readonly filePath: string; + readonly pathname: string; + readonly query: Record; + readonly name: string; + readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; + readonly src: string; + } + + /** + * The current version of Bun + * @example + * "0.2.0" + */ + const version: string; + + /** + * The current version of Bun with the shortened commit sha of the build + * @example "v1.1.30 (d09df1af)" + */ + const version_with_sha: string; + + /** + * The git sha at the time the currently-running version of Bun was compiled + * @example + * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" + */ + const revision: string; + + /** + * Find the index of a newline character in potentially ill-formed UTF-8 text. + * + * This is sort of like readline() except without the IO. + */ + function indexOfLine(buffer: ArrayBufferView | ArrayBufferLike, offset?: number): number; + + interface GlobScanOptions { + /** + * The root directory to start matching from. Defaults to `process.cwd()` + */ + cwd?: string; + + /** + * Allow patterns to match entries that begin with a period (`.`). + * + * @default false + */ + dot?: boolean; + + /** + * Return the absolute path for entries. + * + * @default false + */ + absolute?: boolean; + + /** + * Indicates whether to traverse descendants of symbolic link directories. + * + * @default false + */ + followSymlinks?: boolean; + + /** + * Throw an error when symbolic link is broken + * + * @default false + */ + throwErrorOnBrokenSymlink?: boolean; + + /** + * Return only files. + * + * @default true + */ + onlyFiles?: boolean; + } + + /** + * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). + * + * The supported pattern syntax for is: + * + * - `?` + * Matches any single character. + * - `*` + * Matches zero or more characters, except for path separators ('/' or '\'). + * - `**` + * Matches zero or more characters, including path separators. + * Must match a complete path segment, i.e. followed by a path separator or + * at the end of the pattern. + * - `[ab]` + * Matches one of the characters contained in the brackets. + * Character ranges (e.g. "[a-z]") are also supported. + * Use "[!ab]" or "[^ab]" to match any character *except* those contained + * in the brackets. + * - `{a,b}` + * Match one of the patterns contained in the braces. + * Any of the wildcards listed above can be used in the sub patterns. + * Braces may be nested up to 10 levels deep. + * - `!` + * Negates the result when at the start of the pattern. + * Multiple "!" characters negate the pattern multiple times. + * - `\` + * Used to escape any of the special characters above. + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + */ + export class Glob { + constructor(pattern: string); + + /** + * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for await (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scan(optionsOrCwd?: string | GlobScanOptions): AsyncIterableIterator; + + /** + * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. + * + * @throws {ENOTDIR} Given root cwd path must be a directory + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) + * ``` + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * for (const path of glob.scan()) { + * // do something + * } + * ``` + */ + scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; + + /** + * Match the glob against a string + * + * @example + * ```js + * const glob = new Glob("*.{ts,tsx}"); + * expect(glob.match('foo.ts')).toBeTrue(); + * ``` + */ + match(str: string): boolean; + } + + /** + * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. + * + * When the same timestamp is used multiple times, a monotonically increasing + * counter is appended to allow sorting. The final 8 bytes are + * cryptographically random. When the timestamp changes, the counter resets to + * a psuedo-random integer. + * + * @param encoding "hex" | "base64" | "base64url" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + * + * @example + * ```js + * import { randomUUIDv7 } from "bun"; + * const array = [ + * randomUUIDv7(), + * randomUUIDv7(), + * randomUUIDv7(), + * ] + * [ + * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", + * "0192ce07-8c4f-7d67-805f-0f71581b5622", + * "0192ce07-8c4f-7d68-8170-6816e4451a58" + * ] + * ``` + */ + function randomUUIDv7( + /** + * @default "hex" + */ + encoding?: "hex" | "base64" | "base64url", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): string; + + /** + * Generate a UUIDv7 as a Buffer + * + * @param encoding "buffer" + * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` + */ + function randomUUIDv7( + encoding: "buffer", + /** + * @default Date.now() + */ + timestamp?: number | Date, + ): Buffer; + + /** + * Types for `bun.lock` + */ + type BunLockFile = { + lockfileVersion: 0 | 1; + workspaces: { + [workspace: string]: BunLockFileWorkspacePackage; + }; + overrides?: Record; + patchedDependencies?: Record; + trustedDependencies?: string[]; + + /** + * ``` + * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } + * + * // first index is resolution for each type of package + * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] + * symlink -> [ "name@link:path", INFO ] + * folder -> [ "name@file:path", INFO ] + * workspace -> [ "name@workspace:path" ] // workspace is only path + * tarball -> [ "name@tarball", INFO ] + * root -> [ "name@root:", { bin, binDir } ] + * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] + * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] + * ``` + * */ + packages: { + [pkg: string]: BunLockFilePackageArray; + }; + }; + + type BunLockFileBasePackageInfo = { + dependencies?: Record; + devDependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; + optionalPeers?: string[]; + bin?: string | Record; + binDir?: string; + }; + + type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { + name?: string; + version?: string; + }; + + type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { + os?: string | string[]; + cpu?: string | string[]; + bundled?: true; + }; + + /** @see {@link BunLockFile.packages} for more info */ + type BunLockFilePackageArray = + /** npm */ + | [pkg: string, registry: string, info: BunLockFilePackageInfo, integrity: string] + /** symlink, folder, tarball */ + | [pkg: string, info: BunLockFilePackageInfo] + /** workspace */ + | [pkg: string] + /** git, github */ + | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] + /** root */ + | [pkg: string, info: Pick]; } diff --git a/packages/bun-types/new/bun.ns.d.ts b/packages/bun-types/new/bun.ns.d.ts index 629bcf1e4642f6..d55c3f5352c60a 100644 --- a/packages/bun-types/new/bun.ns.d.ts +++ b/packages/bun-types/new/bun.ns.d.ts @@ -1,7 +1,7 @@ import * as BunModule from "bun"; declare global { - export import Bun = BunModule; + export import Bun = BunModule; } export {}; diff --git a/packages/bun-types/new/devserver.d.ts b/packages/bun-types/new/devserver.d.ts index 81699996a7b9c9..e2fc9a9098fae4 100644 --- a/packages/bun-types/new/devserver.d.ts +++ b/packages/bun-types/new/devserver.d.ts @@ -1,136 +1,133 @@ export {}; declare global { - interface ImportMeta { - /** - * Hot module replacement APIs. This value is `undefined` in production and - * can be used in an `if` statement to check if HMR APIs are available - * - * ```ts - * if (import.meta.hot) { - * // HMR APIs are available - * } - * ``` - * - * However, this check is usually not needed as Bun will dead-code-eliminate - * calls to all of the HMR APIs in production builds. - * - * https://bun.sh/docs/bundler/hmr - */ - hot: { - /** - * `import.meta.hot.data` maintains state between module instances during - * hot replacement, enabling data transfer from previous to new versions. - * When `import.meta.hot.data` is written to, Bun will mark this module as - * capable of self-accepting (equivalent of calling `accept()`). - * - * @example - * ```ts - * const root = import.meta.hot.data.root ??= createRoot(elem); - * root.render(); // re-use an existing root - * ``` - * - * In production, `data` is inlined to be `{}`. This is handy because Bun - * knows it can minify `{}.prop ??= value` into `value` in production. - * - * - */ - data: any; + interface ImportMeta { + /** + * Hot module replacement APIs. This value is `undefined` in production and + * can be used in an `if` statement to check if HMR APIs are available + * + * ```ts + * if (import.meta.hot) { + * // HMR APIs are available + * } + * ``` + * + * However, this check is usually not needed as Bun will dead-code-eliminate + * calls to all of the HMR APIs in production builds. + * + * https://bun.sh/docs/bundler/hmr + */ + hot: { + /** + * `import.meta.hot.data` maintains state between module instances during + * hot replacement, enabling data transfer from previous to new versions. + * When `import.meta.hot.data` is written to, Bun will mark this module as + * capable of self-accepting (equivalent of calling `accept()`). + * + * @example + * ```ts + * const root = import.meta.hot.data.root ??= createRoot(elem); + * root.render(); // re-use an existing root + * ``` + * + * In production, `data` is inlined to be `{}`. This is handy because Bun + * knows it can minify `{}.prop ??= value` into `value` in production. + * + * + */ + data: any; - /** - * Indicate that this module can be replaced simply by re-evaluating the - * file. After a hot update, importers of this module will be - * automatically patched. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * import { getCount } from "./foo"; - * - * console.log("count is ", getCount()); - * - * import.meta.hot.accept(); - * ``` - */ - accept(): void; + /** + * Indicate that this module can be replaced simply by re-evaluating the + * file. After a hot update, importers of this module will be + * automatically patched. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + * + * @example + * ```ts + * import { getCount } from "./foo"; + * + * console.log("count is ", getCount()); + * + * import.meta.hot.accept(); + * ``` + */ + accept(): void; - /** - * Indicate that this module can be replaced by evaluating the new module, - * and then calling the callback with the new module. In this mode, the - * importers do not get patched. This is to match Vite, which is unable - * to patch their import statements. Prefer using `import.meta.hot.accept()` - * without an argument as it usually makes your code easier to understand. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * export const count = 0; - * - * import.meta.hot.accept((newModule) => { - * if (newModule) { - * // newModule is undefined when SyntaxError happened - * console.log('updated: count is now ', newModule.count) - * } - * }); - * ``` - * - * In production, calls to this are dead-code-eliminated. - */ - accept(cb: (newModule: any | undefined) => void): void; + /** + * Indicate that this module can be replaced by evaluating the new module, + * and then calling the callback with the new module. In this mode, the + * importers do not get patched. This is to match Vite, which is unable + * to patch their import statements. Prefer using `import.meta.hot.accept()` + * without an argument as it usually makes your code easier to understand. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + * + * @example + * ```ts + * export const count = 0; + * + * import.meta.hot.accept((newModule) => { + * if (newModule) { + * // newModule is undefined when SyntaxError happened + * console.log('updated: count is now ', newModule.count) + * } + * }); + * ``` + * + * In production, calls to this are dead-code-eliminated. + */ + accept(cb: (newModule: any | undefined) => void): void; - /** - * Indicate that a dependency's module can be accepted. When the dependency - * is updated, the callback will be called with the new module. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * import.meta.hot.accept('./foo', (newModule) => { - * if (newModule) { - * // newModule is undefined when SyntaxError happened - * console.log('updated: count is now ', newModule.count) - * } - * }); - * ``` - */ - accept(specifier: string, callback: (newModule: any) => void): void; + /** + * Indicate that a dependency's module can be accepted. When the dependency + * is updated, the callback will be called with the new module. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + * + * @example + * ```ts + * import.meta.hot.accept('./foo', (newModule) => { + * if (newModule) { + * // newModule is undefined when SyntaxError happened + * console.log('updated: count is now ', newModule.count) + * } + * }); + * ``` + */ + accept(specifier: string, callback: (newModule: any) => void): void; - /** - * Indicate that a dependency's module can be accepted. This variant - * accepts an array of dependencies, where the callback will receive - * the one updated module, and `undefined` for the rest. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - */ - accept( - specifiers: string[], - callback: (newModules: (any | undefined)[]) => void, - ): void; + /** + * Indicate that a dependency's module can be accepted. This variant + * accepts an array of dependencies, where the callback will receive + * the one updated module, and `undefined` for the rest. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + */ + accept(specifiers: string[], callback: (newModules: (any | undefined)[]) => void): void; - /** - * Attach an on-dispose callback. This is called: - * - Just before the module is replaced with another copy (before the next is loaded) - * - After the module is detached (removing all imports to this module) - * - * This callback is not called on route navigation or when the browser tab closes. - * - * Returning a promise will delay module replacement until the module is - * disposed. All dispose callbacks are called in parallel. - */ - dispose(cb: (data: any) => void | Promise): void; + /** + * Attach an on-dispose callback. This is called: + * - Just before the module is replaced with another copy (before the next is loaded) + * - After the module is detached (removing all imports to this module) + * + * This callback is not called on route navigation or when the browser tab closes. + * + * Returning a promise will delay module replacement until the module is + * disposed. All dispose callbacks are called in parallel. + */ + dispose(cb: (data: any) => void | Promise): void; - /** - * No-op - * @deprecated - */ - decline(): void; - }; - } + /** + * No-op + * @deprecated + */ + decline(): void; + }; + } } diff --git a/packages/bun-types/new/extensions.d.ts b/packages/bun-types/new/extensions.d.ts index f8c76296b6ecac..e70c5245ea4d23 100644 --- a/packages/bun-types/new/extensions.d.ts +++ b/packages/bun-types/new/extensions.d.ts @@ -1,4 +1,30 @@ declare module "*.svg" { - const content: `${string}.svg`; - export = content; + const content: `${string}.svg`; + export = content; +} + +declare module "*.txt" { + var text: string; + export = text; +} + +declare module "*.toml" { + var contents: any; + export = contents; +} + +declare module "*.jsonc" { + var contents: any; + export = contents; +} + +declare module "*/bun.lock" { + var contents: import("bun").BunLockFile; + export = contents; +} + +declare module "*.html" { + // In Bun v1.2, we might change this to Bun.HTMLBundle + var contents: any; + export = contents; } diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts index 0cbdb8895b314c..a5352a9e02c37e 100644 --- a/packages/bun-types/new/fetch.d.ts +++ b/packages/bun-types/new/fetch.d.ts @@ -1,10 +1,6 @@ type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; -type HeadersInit = - | Headers - | Record - | Array<[string, string]> - | IterableIterator<[string, string]>; +type HeadersInit = Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; // Comes from @types/node as they're declared globally interface RequestInit {} @@ -13,143 +9,138 @@ interface RequestInit {} interface ResponseInit {} declare module "bun" { - namespace __internal { - /** - * @internal - */ - type UndiciRequest = import("undici-types").Request; - - /** - * @internal - */ - type UndiciResponse = import("undici-types").Response; - - /** - * @internal - */ - type UndiciHeaders = import("undici-types").Headers; - } + namespace __internal { + /** + * @internal + */ + type UndiciRequest = import("undici-types").Request; + + /** + * @internal + */ + type UndiciResponse = import("undici-types").Response; + + /** + * @internal + */ + type UndiciHeaders = import("undici-types").Headers; + } } interface Headers extends Bun.__internal.UndiciHeaders { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; } declare var Headers: { - prototype: Headers; - new (init?: HeadersInit): Headers; + prototype: Headers; + new (init?: HeadersInit): Headers; }; interface Request extends Bun.__internal.UndiciRequest { - headers: Headers; + headers: Headers; } declare var Request: { - prototype: Request; - new (requestInfo: string, init?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, init?: RequestInit): Request; + prototype: Request; + new (requestInfo: string, init?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, init?: RequestInit): Request; }; interface Response extends Bun.__internal.UndiciResponse { - headers: Headers; + headers: Headers; } declare var Response: { - new ( - body?: BodyInit | null | undefined, - init?: ResponseInit | undefined, - ): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: ResponseInit | number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, status?: number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, options?: Bun.ResponseInit): Response; - - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; + new (body?: BodyInit | null | undefined, init?: ResponseInit | undefined): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, options?: ResponseInit | number): Response; + + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, status?: number): Response; + + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + // tslint:disable-next-line:unified-signatures + redirect(url: string, options?: Bun.ResponseInit): Response; + + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; }; interface BunFetchRequestInitTLS extends Bun.TLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable< - import("node:tls").ConnectionOptions["checkServerIdentity"] - >; + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable; } /** @@ -160,29 +151,29 @@ interface BunFetchRequestInitTLS extends Bun.TLSOptions { * if passed to `new Request()`. This is why it's a separate type. */ interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; - - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: Bun.S3Options; + /** + * Override the default TLS options + */ + tls?: BunFetchRequestInitTLS; + + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: Bun.S3Options; } /** @@ -193,10 +184,7 @@ interface BunFetchRequestInit extends RequestInit { * * @returns A promise that resolves to {@link Response} object. */ -declare function fetch( - request: Request, - init?: BunFetchRequestInit, -): Promise; +declare function fetch(request: Request, init?: BunFetchRequestInit): Promise; /** * Send a HTTP(s) request * @@ -205,10 +193,7 @@ declare function fetch( * * @returns A promise that resolves to {@link Response} object. */ -declare function fetch( - url: string | URL | Request, - init?: BunFetchRequestInit, -): Promise; +declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; /** * Send a HTTP(s) request @@ -218,19 +203,16 @@ declare function fetch( * * @returns A promise that resolves to {@link Response} object. */ -declare function fetch( - input: string | URL | Request, - init?: BunFetchRequestInit, -): Promise; +declare function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; declare namespace fetch { - export function preconnect( - url: string | URL, - options?: { - dns?: boolean; - tcp?: boolean; - http?: boolean; - https?: boolean; - }, - ): void; + export function preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; } diff --git a/packages/bun-types/new/ffi.d.ts b/packages/bun-types/new/ffi.d.ts index db21b4d03aa3d7..6a684678e209d3 100644 --- a/packages/bun-types/new/ffi.d.ts +++ b/packages/bun-types/new/ffi.d.ts @@ -15,1154 +15,1136 @@ * goes to Fabrice Bellard and TinyCC maintainers for making this possible. */ declare module "bun:ffi" { - enum FFIType { - char = 0, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int8_t = 1, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i8 = 1, + enum FFIType { + char = 0, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int8_t = 1, + /** + * 8-bit signed integer + * + * Must be a value between -127 and 127 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * signed char + * char // on x64 & aarch64 macOS + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i8 = 1, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint8_t = 2, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u8 = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint8_t = 2, + /** + * 8-bit unsigned integer + * + * Must be a value between 0 and 255 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * unsigned char + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u8 = 2, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int16_t = 3, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i16 = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + int16_t = 3, + /** + * 16-bit signed integer + * + * Must be a value between -32768 and 32767 + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * in16_t + * short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + i16 = 3, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint16_t = 4, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u16 = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + uint16_t = 4, + /** + * 16-bit unsigned integer + * + * Must be a value between 0 and 65535, inclusive. + * + * When passing to a FFI function (C ABI), type coercion is not performed. + * + * In C: + * ```c + * uint16_t + * unsigned short // on arm64 & x64 + * ``` + * + * In JavaScript: + * ```js + * var num = 0; + * ``` + */ + u16 = 4, - /** - * 32-bit signed integer - */ - int32_t = 5, + /** + * 32-bit signed integer + */ + int32_t = 5, - /** - * 32-bit signed integer - * - * Alias of {@link FFIType.int32_t} - */ - i32 = 5, - /** - * 32-bit signed integer - * - * The same as `int` in C - * - * ```c - * int - * ``` - */ - int = 5, + /** + * 32-bit signed integer + * + * Alias of {@link FFIType.int32_t} + */ + i32 = 5, + /** + * 32-bit signed integer + * + * The same as `int` in C + * + * ```c + * int + * ``` + */ + int = 5, - /** - * 32-bit unsigned integer - * - * The same as `unsigned int` in C (on x64 & arm64) - * - * C: - * ```c - * unsigned int - * ``` - * JavaScript: - * ```js - * ptr(new Uint32Array(1)) - * ``` - */ - uint32_t = 6, - /** - * 32-bit unsigned integer - * - * Alias of {@link FFIType.uint32_t} - */ - u32 = 6, + /** + * 32-bit unsigned integer + * + * The same as `unsigned int` in C (on x64 & arm64) + * + * C: + * ```c + * unsigned int + * ``` + * JavaScript: + * ```js + * ptr(new Uint32Array(1)) + * ``` + */ + uint32_t = 6, + /** + * 32-bit unsigned integer + * + * Alias of {@link FFIType.uint32_t} + */ + u32 = 6, - /** - * int64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - int64_t = 7, - /** - * i64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - i64 = 7, + /** + * int64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + int64_t = 7, + /** + * i64 is a 64-bit signed integer + * + * This is not implemented yet! + */ + i64 = 7, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - uint64_t = 8, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - u64 = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + uint64_t = 8, + /** + * 64-bit unsigned integer + * + * This is not implemented yet! + */ + u64 = 8, - /** - * Doubles are not supported yet! - */ - double = 9, - /** - * Doubles are not supported yet! - */ - f64 = 9, - /** - * Floats are not supported yet! - */ - float = 10, - /** - * Floats are not supported yet! - */ - f32 = 10, + /** + * Doubles are not supported yet! + */ + double = 9, + /** + * Doubles are not supported yet! + */ + f64 = 9, + /** + * Floats are not supported yet! + */ + float = 10, + /** + * Floats are not supported yet! + */ + f32 = 10, - /** - * Boolean value - * - * Must be `true` or `false`. `0` and `1` type coercion is not supported. - * - * In C, this corresponds to: - * ```c - * bool - * _Bool - * ``` - */ - bool = 11, + /** + * Boolean value + * + * Must be `true` or `false`. `0` and `1` type coercion is not supported. + * + * In C, this corresponds to: + * ```c + * bool + * _Bool + * ``` + */ + bool = 11, - /** - * Pointer value - * - * See {@link Bun.FFI.ptr} for more information - * - * In C: - * ```c - * void* - * ``` - * - * In JavaScript: - * ```js - * ptr(new Uint8Array(1)) - * ``` - */ - ptr = 12, - /** - * Pointer value - * - * alias of {@link FFIType.ptr} - */ - pointer = 12, + /** + * Pointer value + * + * See {@link Bun.FFI.ptr} for more information + * + * In C: + * ```c + * void* + * ``` + * + * In JavaScript: + * ```js + * ptr(new Uint8Array(1)) + * ``` + */ + ptr = 12, + /** + * Pointer value + * + * alias of {@link FFIType.ptr} + */ + pointer = 12, - /** - * void value - * - * void arguments are not supported - * - * void return type is the default return type - * - * In C: - * ```c - * void - * ``` - */ - void = 13, + /** + * void value + * + * void arguments are not supported + * + * void return type is the default return type + * + * In C: + * ```c + * void + * ``` + */ + void = 13, - /** - * When used as a `returns`, this will automatically become a {@link CString}. - * - * When used in `args` it is equivalent to {@link FFIType.pointer} - */ - cstring = 14, + /** + * When used as a `returns`, this will automatically become a {@link CString}. + * + * When used in `args` it is equivalent to {@link FFIType.pointer} + */ + cstring = 14, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `int64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - i64_fast = 15, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `int64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + i64_fast = 15, - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `uint64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - u64_fast = 16, - function = 17, + /** + * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance + * but means you might get a `BigInt` or you might get a `number`. + * + * In C, this always becomes `uint64_t` + * + * In JavaScript, this could be number or it could be BigInt, depending on what + * value is passed in. + */ + u64_fast = 16, + function = 17, - napi_env = 18, - napi_value = 19, - buffer = 20, - } + napi_env = 18, + napi_value = 19, + buffer = 20, + } - type Pointer = number & { __pointer__: null }; + type Pointer = number & { __pointer__: null }; - interface FFITypeToArgsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: number | bigint; - [FFIType.i64]: number | bigint; - [FFIType.uint64_t]: number | bigint; - [FFIType.u64]: number | bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.void]: undefined; - [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | JSCallback; // cannot be null - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeToReturnsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: bigint; - [FFIType.i64]: bigint; - [FFIType.uint64_t]: bigint; - [FFIType.u64]: bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: Pointer | null; - [FFIType.pointer]: Pointer | null; - [FFIType.void]: undefined; - [FFIType.cstring]: CString; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | null; - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeStringToType { - ["char"]: FFIType.char; - ["int8_t"]: FFIType.int8_t; - ["i8"]: FFIType.i8; - ["uint8_t"]: FFIType.uint8_t; - ["u8"]: FFIType.u8; - ["int16_t"]: FFIType.int16_t; - ["i16"]: FFIType.i16; - ["uint16_t"]: FFIType.uint16_t; - ["u16"]: FFIType.u16; - ["int32_t"]: FFIType.int32_t; - ["i32"]: FFIType.i32; - ["int"]: FFIType.int; - ["uint32_t"]: FFIType.uint32_t; - ["u32"]: FFIType.u32; - ["int64_t"]: FFIType.int64_t; - ["i64"]: FFIType.i64; - ["uint64_t"]: FFIType.uint64_t; - ["u64"]: FFIType.u64; - ["double"]: FFIType.double; - ["f64"]: FFIType.f64; - ["float"]: FFIType.float; - ["f32"]: FFIType.f32; - ["bool"]: FFIType.bool; - ["ptr"]: FFIType.ptr; - ["pointer"]: FFIType.pointer; - ["void"]: FFIType.void; - ["cstring"]: FFIType.cstring; - ["function"]: FFIType.pointer; // for now - ["usize"]: FFIType.uint64_t; // for now - ["callback"]: FFIType.pointer; // for now - ["napi_env"]: FFIType.napi_env; - ["napi_value"]: FFIType.napi_value; - ["buffer"]: FFIType.buffer; - } + interface FFITypeToArgsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: number | bigint; + [FFIType.i64]: number | bigint; + [FFIType.uint64_t]: number | bigint; + [FFIType.u64]: number | bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.void]: undefined; + [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | JSCallback; // cannot be null + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeToReturnsType { + [FFIType.char]: number; + [FFIType.int8_t]: number; + [FFIType.i8]: number; + [FFIType.uint8_t]: number; + [FFIType.u8]: number; + [FFIType.int16_t]: number; + [FFIType.i16]: number; + [FFIType.uint16_t]: number; + [FFIType.u16]: number; + [FFIType.int32_t]: number; + [FFIType.i32]: number; + [FFIType.int]: number; + [FFIType.uint32_t]: number; + [FFIType.u32]: number; + [FFIType.int64_t]: bigint; + [FFIType.i64]: bigint; + [FFIType.uint64_t]: bigint; + [FFIType.u64]: bigint; + [FFIType.double]: number; + [FFIType.f64]: number; + [FFIType.float]: number; + [FFIType.f32]: number; + [FFIType.bool]: boolean; + [FFIType.ptr]: Pointer | null; + [FFIType.pointer]: Pointer | null; + [FFIType.void]: undefined; + [FFIType.cstring]: CString; + [FFIType.i64_fast]: number | bigint; + [FFIType.u64_fast]: number | bigint; + [FFIType.function]: Pointer | null; + [FFIType.napi_env]: unknown; + [FFIType.napi_value]: unknown; + [FFIType.buffer]: NodeJS.TypedArray | DataView; + } + interface FFITypeStringToType { + ["char"]: FFIType.char; + ["int8_t"]: FFIType.int8_t; + ["i8"]: FFIType.i8; + ["uint8_t"]: FFIType.uint8_t; + ["u8"]: FFIType.u8; + ["int16_t"]: FFIType.int16_t; + ["i16"]: FFIType.i16; + ["uint16_t"]: FFIType.uint16_t; + ["u16"]: FFIType.u16; + ["int32_t"]: FFIType.int32_t; + ["i32"]: FFIType.i32; + ["int"]: FFIType.int; + ["uint32_t"]: FFIType.uint32_t; + ["u32"]: FFIType.u32; + ["int64_t"]: FFIType.int64_t; + ["i64"]: FFIType.i64; + ["uint64_t"]: FFIType.uint64_t; + ["u64"]: FFIType.u64; + ["double"]: FFIType.double; + ["f64"]: FFIType.f64; + ["float"]: FFIType.float; + ["f32"]: FFIType.f32; + ["bool"]: FFIType.bool; + ["ptr"]: FFIType.ptr; + ["pointer"]: FFIType.pointer; + ["void"]: FFIType.void; + ["cstring"]: FFIType.cstring; + ["function"]: FFIType.pointer; // for now + ["usize"]: FFIType.uint64_t; // for now + ["callback"]: FFIType.pointer; // for now + ["napi_env"]: FFIType.napi_env; + ["napi_value"]: FFIType.napi_value; + ["buffer"]: FFIType.buffer; + } - type FFITypeOrString = FFIType | keyof FFITypeStringToType; + type FFITypeOrString = FFIType | keyof FFITypeStringToType; - interface FFIFunction { - /** - * Arguments to a FFI function (C ABI) - * - * Defaults to an empty array, which means no arguments. - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, FFIType, suffix } from "bun:ffi" - * - * const lib = dlopen(`adder.${suffix}`, { - * add: { - * // FFIType can be used or you can pass string labels. - * args: [FFIType.i32, "i32"], - * returns: "i32", - * }, - * }) - * lib.symbols.add(1, 2) - * ``` - * In C: - * ```c - * int add(int a, int b) { - * return a + b; - * } - * ``` - */ - readonly args?: readonly FFITypeOrString[]; - /** - * Return type to a FFI function (C ABI) - * - * Defaults to {@link FFIType.void} - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, CString } from "bun:ffi" - * - * const lib = dlopen('z', { - * version: { - * returns: "ptr", - * } - * }); - * console.log(new CString(lib.symbols.version())); - * ``` - * In C: - * ```c - * char* version() - * { - * return "1.0.0"; - * } - * ``` - */ - readonly returns?: FFITypeOrString; + interface FFIFunction { + /** + * Arguments to a FFI function (C ABI) + * + * Defaults to an empty array, which means no arguments. + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, FFIType, suffix } from "bun:ffi" + * + * const lib = dlopen(`adder.${suffix}`, { + * add: { + * // FFIType can be used or you can pass string labels. + * args: [FFIType.i32, "i32"], + * returns: "i32", + * }, + * }) + * lib.symbols.add(1, 2) + * ``` + * In C: + * ```c + * int add(int a, int b) { + * return a + b; + * } + * ``` + */ + readonly args?: readonly FFITypeOrString[]; + /** + * Return type to a FFI function (C ABI) + * + * Defaults to {@link FFIType.void} + * + * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. + * + * @example + * From JavaScript: + * ```ts + * import { dlopen, CString } from "bun:ffi" + * + * const lib = dlopen('z', { + * version: { + * returns: "ptr", + * } + * }); + * console.log(new CString(lib.symbols.version())); + * ``` + * In C: + * ```c + * char* version() + * { + * return "1.0.0"; + * } + * ``` + */ + readonly returns?: FFITypeOrString; - /** - * Function pointer to the native function - * - * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. - * This pointer should not be null (0). - * - * This is useful if the library has already been loaded - * or if the module is also using Node-API. - */ - readonly ptr?: Pointer | bigint; + /** + * Function pointer to the native function + * + * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. + * This pointer should not be null (0). + * + * This is useful if the library has already been loaded + * or if the module is also using Node-API. + */ + readonly ptr?: Pointer | bigint; - /** - * Can C/FFI code call this function from a separate thread? - * - * Only supported with {@link JSCallback}. - * - * This does not make the function run in a separate thread. It is still up to the application/library - * to run their code in a separate thread. - * - * By default, {@link JSCallback} calls are not thread-safe. Turning this on - * incurs a small performance penalty for every function call. That small - * performance penalty needs to be less than the performance gain from - * running the function in a separate thread. - * - * @default false - */ - readonly threadsafe?: boolean; - } + /** + * Can C/FFI code call this function from a separate thread? + * + * Only supported with {@link JSCallback}. + * + * This does not make the function run in a separate thread. It is still up to the application/library + * to run their code in a separate thread. + * + * By default, {@link JSCallback} calls are not thread-safe. Turning this on + * incurs a small performance penalty for every function call. That small + * performance penalty needs to be less than the performance gain from + * running the function in a separate thread. + * + * @default false + */ + readonly threadsafe?: boolean; + } - type Symbols = Readonly>; + type Symbols = Readonly>; - interface Library { - symbols: ConvertFns; + interface Library { + symbols: ConvertFns; - /** - * `dlclose` the library, unloading the symbols and freeing allocated memory. - * - * Once called, the library is no longer usable. - * - * Calling a function from a library that has been closed is undefined behavior. - */ - close(): void; - } + /** + * `dlclose` the library, unloading the symbols and freeing allocated memory. + * + * Once called, the library is no longer usable. + * + * Calling a function from a library that has been closed is undefined behavior. + */ + close(): void; + } - type ToFFIType = T extends FFIType - ? T - : T extends string - ? FFITypeStringToType[T] - : never; + type ToFFIType = T extends FFIType ? T : T extends string ? FFITypeStringToType[T] : never; - const FFIFunctionCallableSymbol: unique symbol; - type ConvertFns = { - [K in keyof Fns]: { - ( - ...args: Fns[K]["args"] extends infer A extends - readonly FFITypeOrString[] - ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } - : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [unknown] extends [Fns[K]["args"]] - ? [] - : never - ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - ? undefined - : FFITypeToReturnsType[ToFFIType>]; - __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - }; + const FFIFunctionCallableSymbol: unique symbol; + type ConvertFns = { + [K in keyof Fns]: { + ( + ...args: Fns[K]["args"] extends infer A extends readonly FFITypeOrString[] + ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } + : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [unknown] extends [Fns[K]["args"]] + ? [] + : never + ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + ? undefined + : FFITypeToReturnsType[ToFFIType>]; + __ffi_function_callable: typeof FFIFunctionCallableSymbol; + }; + }; - /** - * Open a library using `"bun:ffi"` - * - * @param name The name of the library or file path. This will be passed to `dlopen()` - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import {dlopen} from 'bun:ffi'; - * - * const lib = dlopen("duckdb.dylib", { - * get_version: { - * returns: "cstring", - * args: [], - * }, - * }); - * lib.symbols.get_version(); - * // "1.0.0" - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function dlopen>( - name: string | import("bun").BunFile | URL, - symbols: Fns, - ): Library; + /** + * Open a library using `"bun:ffi"` + * + * @param name The name of the library or file path. This will be passed to `dlopen()` + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import {dlopen} from 'bun:ffi'; + * + * const lib = dlopen("duckdb.dylib", { + * get_version: { + * returns: "cstring", + * args: [], + * }, + * }); + * lib.symbols.get_version(); + * // "1.0.0" + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function dlopen>( + name: string | import("bun").BunFile | URL, + symbols: Fns, + ): Library; - /** - * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. - * - * @param options - * @returns Library - * - * @example - * ## Hello, World! - * - * JavaScript: - * ```js - * import { cc } from "bun:ffi"; - * import hello from "./hello.c" with {type: "file"}; - * const {symbols: {hello}} = cc({ - * source: hello, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * // "Hello, World!" - * console.log(hello()); - * ``` - * - * `./hello.c`: - * ```c - * #include - * const char* hello() { - * return "Hello, World!"; - * } - * ``` - */ - function cc>(options: { - /** - * File path to an ISO C11 source file to compile and link - */ - source: string | import("bun").BunFile | URL; + /** + * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. + * + * @param options + * @returns Library + * + * @example + * ## Hello, World! + * + * JavaScript: + * ```js + * import { cc } from "bun:ffi"; + * import hello from "./hello.c" with {type: "file"}; + * const {symbols: {hello}} = cc({ + * source: hello, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * // "Hello, World!" + * console.log(hello()); + * ``` + * + * `./hello.c`: + * ```c + * #include + * const char* hello() { + * return "Hello, World!"; + * } + * ``` + */ + function cc>(options: { + /** + * File path to an ISO C11 source file to compile and link + */ + source: string | import("bun").BunFile | URL; - /** - * Library names to link against - * - * Equivalent to `-l` option in gcc/clang. - */ - library?: string[] | string; + /** + * Library names to link against + * + * Equivalent to `-l` option in gcc/clang. + */ + library?: string[] | string; - /** - * Include directories to pass to the compiler - * - * Equivalent to `-I` option in gcc/clang. - */ - include?: string[] | string; + /** + * Include directories to pass to the compiler + * + * Equivalent to `-I` option in gcc/clang. + */ + include?: string[] | string; - /** - * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - */ - symbols: Fns; + /** + * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + */ + symbols: Fns; - /** - * Map of symbols to define where the key is the symbol name and the value is the symbol value - * - * Equivalent to `-D` option in gcc/clang. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * define: { - * "NDEBUG": "1", - * }, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - define?: Record; + /** + * Map of symbols to define where the key is the symbol name and the value is the symbol value + * + * Equivalent to `-D` option in gcc/clang. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * define: { + * "NDEBUG": "1", + * }, + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + define?: Record; - /** - * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. - * - * @default "-std=c11 -Wl,--export-all-symbols -g -O2" - * - * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * flags: ["-framework CoreFoundation", "-framework Security"], - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - flags?: string | string[]; - }): Library; + /** + * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. + * + * @default "-std=c11 -Wl,--export-all-symbols -g -O2" + * + * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. + * + * @example + * ```js + * import { cc } from "bun:ffi"; + * const {symbols: {hello}} = cc({ + * source: hello, + * flags: ["-framework CoreFoundation", "-framework Security"], + * symbols: { + * hello: { + * returns: "cstring", + * args: [], + * }, + * }, + * }); + * ``` + */ + flags?: string | string[]; + }): Library; - /** - * Turn a native library's function pointer into a JavaScript function - * - * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. - * - * @param fn {@link FFIFunction} declaration. `ptr` is required - * - * @example - * - * ```js - * import {CFunction} from 'bun:ffi'; - * - * const getVersion = new CFunction({ - * returns: "cstring", - * args: [], - * ptr: myNativeLibraryGetVersion, - * }); - * getVersion(); - * getVersion.close(); - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { - /** - * Free the memory allocated by the wrapping function - */ - close(): void; - }; + /** + * Turn a native library's function pointer into a JavaScript function + * + * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. + * + * @param fn {@link FFIFunction} declaration. `ptr` is required + * + * @example + * + * ```js + * import {CFunction} from 'bun:ffi'; + * + * const getVersion = new CFunction({ + * returns: "cstring", + * args: [], + * ptr: myNativeLibraryGetVersion, + * }); + * getVersion(); + * getVersion.close(); + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { + /** + * Free the memory allocated by the wrapping function + */ + close(): void; + }; - /** - * Link a map of symbols to JavaScript functions - * - * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. - * - * You could use this with Node-API to skip loading a second time. - * - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import { linkSymbols } from "bun:ffi"; - * - * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); - * - * const lib = linkSymbols({ - * // Unlike with dlopen(), the names here can be whatever you want - * getMajor: { - * returns: "cstring", - * args: [], - * - * // Since this doesn't use dlsym(), you have to provide a valid ptr - * // That ptr could be a number or a bigint - * // An invalid pointer will crash your program. - * ptr: majorPtr, - * }, - * getMinor: { - * returns: "cstring", - * args: [], - * ptr: minorPtr, - * }, - * getPatch: { - * returns: "cstring", - * args: [], - * ptr: patchPtr, - * }, - * }); - * - * const [major, minor, patch] = [ - * lib.symbols.getMajor(), - * lib.symbols.getMinor(), - * lib.symbols.getPatch(), - * ]; - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function linkSymbols>( - symbols: Fns, - ): Library; + /** + * Link a map of symbols to JavaScript functions + * + * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. + * + * You could use this with Node-API to skip loading a second time. + * + * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} + * + * @example + * + * ```js + * import { linkSymbols } from "bun:ffi"; + * + * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); + * + * const lib = linkSymbols({ + * // Unlike with dlopen(), the names here can be whatever you want + * getMajor: { + * returns: "cstring", + * args: [], + * + * // Since this doesn't use dlsym(), you have to provide a valid ptr + * // That ptr could be a number or a bigint + * // An invalid pointer will crash your program. + * ptr: majorPtr, + * }, + * getMinor: { + * returns: "cstring", + * args: [], + * ptr: minorPtr, + * }, + * getPatch: { + * returns: "cstring", + * args: [], + * ptr: patchPtr, + * }, + * }); + * + * const [major, minor, patch] = [ + * lib.symbols.getMajor(), + * lib.symbols.getMinor(), + * lib.symbols.getPatch(), + * ]; + * ``` + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks + * goes to Fabrice Bellard and TinyCC maintainers for making this possible. + */ + function linkSymbols>(symbols: Fns): Library; - /** - * Read a pointer as a {@link Buffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toBuffer( - ptr: Pointer, - byteOffset?: number, - byteLength?: number, - ): Buffer; + /** + * Read a pointer as a {@link Buffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): Buffer; - /** - * Read a pointer as an {@link ArrayBuffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toArrayBuffer( - ptr: Pointer, - byteOffset?: number, - byteLength?: number, - ): ArrayBuffer; + /** + * Read a pointer as an {@link ArrayBuffer} + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function toArrayBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): ArrayBuffer; - namespace read { - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f64(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function ptr(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function intptr(ptr: Pointer, byteOffset?: number): number; - } + namespace read { + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i8(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i16(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f32(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function u64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function i64(ptr: Pointer, byteOffset?: number): bigint; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function f64(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function ptr(ptr: Pointer, byteOffset?: number): number; + /** + * The read function behaves similarly to DataView, + * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. + * + * @param ptr The memory address to read + * @param byteOffset bytes to skip before reading + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + function intptr(ptr: Pointer, byteOffset?: number): number; + } - /** - * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} - * - * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. - * - * This is for use with FFI functions. For performance reasons, FFI will - * not automatically convert typed arrays to C pointers. - * - * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for - * @param {number} byteOffset optional offset into the view in bytes - * - * @example - * - * From JavaScript: - * ```js - * const array = new Uint8Array(10); - * const rawPtr = ptr(array); - * myFFIFunction(rawPtr); - * ``` - * To C: - * ```c - * void myFFIFunction(char* rawPtr) { - * // Do something with rawPtr - * } - * ``` - */ - function ptr( - view: NodeJS.TypedArray | ArrayBufferLike | DataView, - byteOffset?: number, - ): Pointer; + /** + * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} + * + * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. + * + * This is for use with FFI functions. For performance reasons, FFI will + * not automatically convert typed arrays to C pointers. + * + * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for + * @param {number} byteOffset optional offset into the view in bytes + * + * @example + * + * From JavaScript: + * ```js + * const array = new Uint8Array(10); + * const rawPtr = ptr(array); + * myFFIFunction(rawPtr); + * ``` + * To C: + * ```c + * void myFFIFunction(char* rawPtr) { + * // Do something with rawPtr + * } + * ``` + */ + function ptr(view: NodeJS.TypedArray | ArrayBufferLike | DataView, byteOffset?: number): Pointer; - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ - class CString extends String { - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @param ptr The pointer to the C string - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); + class CString extends String { + /** + * Get a string from a UTF-8 encoded C string + * If `byteLength` is not provided, the string is assumed to be null-terminated. + * + * @param ptr The pointer to the C string + * @param byteOffset bytes to skip before reading + * @param byteLength bytes to read + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * console.log(new CString(ptr)); + * ``` + * + * @example + * ```js + * var ptr = lib.symbols.getVersion(); + * // print the first 4 characters + * console.log(new CString(ptr, 0, 4)); + * ``` + * + * While there are some checks to catch invalid pointers, this is a difficult + * thing to do safely. Passing an invalid pointer can crash the program and + * reading beyond the bounds of the pointer will crash the program or cause + * undefined behavior. Use with care! + */ + constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); - /** - * The ptr to the C string - * - * This `CString` instance is a clone of the string, so it - * is safe to continue using this instance after the `ptr` has been - * freed. - */ - ptr: Pointer; - byteOffset?: number; - byteLength?: number; + /** + * The ptr to the C string + * + * This `CString` instance is a clone of the string, so it + * is safe to continue using this instance after the `ptr` has been + * freed. + */ + ptr: Pointer; + byteOffset?: number; + byteLength?: number; - /** - * Get the {@link ptr} as an `ArrayBuffer` - * - * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 - */ - get arrayBuffer(): ArrayBuffer; - } + /** + * Get the {@link ptr} as an `ArrayBuffer` + * + * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 + */ + get arrayBuffer(): ArrayBuffer; + } - /** - * Pass a JavaScript function to FFI (Foreign Function Interface) - */ - class JSCallback { - /** - * Enable a JavaScript callback function to be passed to C with bun:ffi - * - * @param callback The JavaScript function to be called - * @param definition The C function definition - */ - constructor(callback: (...args: any[]) => any, definition: FFIFunction); + /** + * Pass a JavaScript function to FFI (Foreign Function Interface) + */ + class JSCallback { + /** + * Enable a JavaScript callback function to be passed to C with bun:ffi + * + * @param callback The JavaScript function to be called + * @param definition The C function definition + */ + constructor(callback: (...args: any[]) => any, definition: FFIFunction); - /** - * The pointer to the C function - * - * Becomes `null` once {@link JSCallback.prototype.close} is called - */ - readonly ptr: Pointer | null; + /** + * The pointer to the C function + * + * Becomes `null` once {@link JSCallback.prototype.close} is called + */ + readonly ptr: Pointer | null; - /** - * Can the callback be called from a different thread? - */ - readonly threadsafe: boolean; + /** + * Can the callback be called from a different thread? + */ + readonly threadsafe: boolean; - /** - * Free the memory allocated for the callback - * - * If called multiple times, does nothing after the first call. - */ - close(): void; - } + /** + * Free the memory allocated for the callback + * + * If called multiple times, does nothing after the first call. + */ + close(): void; + } - /** - * View the generated C code for FFI bindings - * - * You probably won't need this unless there's a bug in the FFI bindings - * generator or you're just curious. - */ - function viewSource(symbols: Symbols, is_callback?: false): string[]; - function viewSource(callback: FFIFunction, is_callback: true): string; + /** + * View the generated C code for FFI bindings + * + * You probably won't need this unless there's a bug in the FFI bindings + * generator or you're just curious. + */ + function viewSource(symbols: Symbols, is_callback?: false): string[]; + function viewSource(callback: FFIFunction, is_callback: true): string; - /** - * Platform-specific file extension name for dynamic libraries - * - * "." is not included - * - * @example - * ```js - * "dylib" // macOS - * ``` - * - * @example - * ```js - * "so" // linux - * ``` - */ - const suffix: string; + /** + * Platform-specific file extension name for dynamic libraries + * + * "." is not included + * + * @example + * ```js + * "dylib" // macOS + * ``` + * + * @example + * ```js + * "so" // linux + * ``` + */ + const suffix: string; } diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 6b91aec9d7ab06..dc7ec942d43227 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -1,52 +1,40 @@ interface ReadableStream {} declare var ReadableStream: { - prototype: ReadableStream; - new ( - underlyingSource?: Bun.UnderlyingSource, - strategy?: QueuingStrategy, - ): ReadableStream; - new ( - underlyingSource?: Bun.DirectUnderlyingSource, - strategy?: QueuingStrategy, - ): ReadableStream; + prototype: ReadableStream; + new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; }; interface WritableStream {} declare var WritableStream: { - prototype: WritableStream; - new ( - underlyingSink?: Bun.UnderlyingSink, - strategy?: QueuingStrategy, - ): WritableStream; + prototype: WritableStream; + new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; }; declare module "bun" { - namespace __internal { - type NodeWorkerThreadsWorker = import("worker_threads").Worker; - } + namespace __internal { + type NodeWorkerThreadsWorker = import("worker_threads").Worker; + } } interface Worker extends Bun.__internal.NodeWorkerThreadsWorker {} declare var Worker: { - prototype: Worker; - new ( - scriptURL: string | URL, - options?: Bun.WorkerOptions | undefined, - ): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; + prototype: Worker; + new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; }; declare var WebSocket: typeof import("ws").WebSocket; interface Crypto {} declare var Crypto: { - prototype: Crypto; - new (): Crypto; + prototype: Crypto; + new (): Crypto; }; declare var crypto: Crypto; @@ -62,8 +50,8 @@ declare var crypto: Crypto; */ interface TextEncoder extends Bun.TextEncoder {} declare var TextEncoder: { - prototype: TextEncoder; - new (): TextEncoder; + prototype: TextEncoder; + new (): TextEncoder; }; /** @@ -76,8 +64,8 @@ declare var TextEncoder: { */ interface TextDecoder extends Bun.TextDecoder {} declare var TextDecoder: { - prototype: TextDecoder; - new (): TextDecoder; + prototype: TextDecoder; + new (): TextDecoder; }; type _Performance = import("perf_hooks").Performance; @@ -85,94 +73,90 @@ interface Performance extends _Performance {} declare var performance: Performance; interface Event { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly bubbles: boolean; + /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ + cancelBubble: () => void; + /** True if the event was created with the cancelable option */ + readonly cancelable: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly composed: boolean; + /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ + composedPath(): [EventTarget?]; + /** Alias for event.target. */ + readonly currentTarget: EventTarget | null; + /** Is true if cancelable is true and event.preventDefault() has been called. */ + readonly defaultPrevented: boolean; + /** This is not used in Node.js and is provided purely for completeness. */ + readonly eventPhase: 0 | 2; + /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ + readonly isTrusted: boolean; + /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ + preventDefault(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + returnValue: boolean; + /** Alias for event.target. */ + readonly srcElement: EventTarget | null; + /** Stops the invocation of event listeners after the current one completes. */ + stopImmediatePropagation(): void; + /** This is not used in Node.js and is provided purely for completeness. */ + stopPropagation(): void; + /** The `EventTarget` dispatching the event */ + readonly target: EventTarget | null; + /** The millisecond timestamp when the Event object was created. */ + readonly timeStamp: number; + /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ + readonly type: string; } declare var Event: { - prototype: Event; - new (type: string, eventInitDict?: Bun.EventInit): Event; + prototype: Event; + new (type: string, eventInitDict?: Bun.EventInit): Event; }; interface EventTarget { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; + /** + * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. + * + * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. + * + * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. + * Specifically, the `capture` option is used as part of the key when registering a `listener`. + * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. + */ + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ + dispatchEvent(event: Event): boolean; + /** Removes the event listener in target's event listener list with the same type, callback, and options. */ + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; } declare var EventTarget: { - prototype: EventTarget; - new (): EventTarget; + prototype: EventTarget; + new (): EventTarget; }; interface File extends Blob { - readonly lastModified: number; - readonly name: string; + readonly lastModified: number; + readonly name: string; } declare var File: { - prototype: File; - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new ( - parts: Bun.BlobPart[], - name: string, - options?: BlobPropertyBag & { lastModified?: Date | number }, - ): File; + prototype: File; + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; }; /** @@ -215,50 +199,50 @@ declare var File: { * ``` */ interface ShadowRealm { - /** - * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; + /** + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; } declare var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; + prototype: ShadowRealm; + new (): ShadowRealm; }; declare function queueMicrotask(callback: (...args: any[]) => void): void; @@ -269,12 +253,12 @@ declare function queueMicrotask(callback: (...args: any[]) => void): void; declare function reportError(error: any): void; interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; - [Symbol.toPrimitive](): number; + [Symbol.toPrimitive](): number; } /** @@ -296,129 +280,115 @@ declare function clearImmediate(id?: number | Timer): void; * Run a function immediately after main event loop is vacant * @param handler function to call */ -declare function setImmediate( - handler: Bun.TimerHandler, - ...arguments: any[] -): Timer; +declare function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; /** * Run a function every `interval` milliseconds * @param handler function to call * @param interval milliseconds to wait between calls */ -declare function setInterval( - handler: Bun.TimerHandler, - interval?: number, - ...arguments: any[] -): Timer; +declare function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; /** * Run a function after `timeout` (milliseconds) * @param handler function to call * @param timeout milliseconds to wait between calls */ -declare function setTimeout( - handler: Bun.TimerHandler, - timeout?: number, - ...arguments: any[] -): Timer; +declare function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; declare function addEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | AddEventListenerOptions, + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | AddEventListenerOptions, ): void; declare function addEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, ): void; declare function removeEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | Bun.EventListenerOptions, + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | Bun.EventListenerOptions, ): void; declare function removeEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | Bun.EventListenerOptions, + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | Bun.EventListenerOptions, ): void; /** * Events providing information related to errors in scripts or in files. */ interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; } declare var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; }; /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ interface CloseEvent extends Event { - /** Returns the WebSocket connection close code provided by the server. */ - readonly code: number; - /** Returns the WebSocket connection close reason provided by the server. */ - readonly reason: string; - /** Returns true if the connection closed cleanly; false otherwise. */ - readonly wasClean: boolean; + /** Returns the WebSocket connection close code provided by the server. */ + readonly code: number; + /** Returns the WebSocket connection close reason provided by the server. */ + readonly reason: string; + /** Returns true if the connection closed cleanly; false otherwise. */ + readonly wasClean: boolean; } declare var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; }; interface MessageEvent extends Bun.MessageEvent {} declare var MessageEvent: { - prototype: MessageEvent; - new ( - type: string, - eventInitDict?: Bun.MessageEventInit, - ): MessageEvent; + prototype: MessageEvent; + new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; }; interface CustomEvent extends Event { - /** Returns any custom data event was created with. Typically used for synthetic events. */ - readonly detail: T; + /** Returns any custom data event was created with. Typically used for synthetic events. */ + readonly detail: T; } declare var CustomEvent: { - prototype: CustomEvent; - new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; + prototype: CustomEvent; + new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; }; interface EventListener { - (evt: Event): void; + (evt: Event): void; } interface EventListenerObject { - handleEvent(object: Event): void; + handleEvent(object: Event): void; } interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; + readonly request: Request; + readonly url: string; - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; } interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; - // exit: Event; + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; + // exit: Event; } interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; + once?: boolean; + passive?: boolean; + signal?: AbortSignal; } /** @@ -437,333 +407,326 @@ interface AddEventListenerOptions extends Bun.EventListenerOptions { * Bun may inject additional imports into your code. This usually has a `bun:` prefix. */ declare var Loader: { - /** - * ESM module registry - * - * This lets you implement live reload in Bun. If you - * delete a module specifier from this map, the next time it's imported, it - * will be re-transpiled and loaded again. - * - * The keys are the module specifiers and the - * values are metadata about the module. - * - * The keys are an implementation detail for Bun that will change between - * versions. - * - * - Userland modules are an absolute file path - * - Virtual modules have a `bun:` prefix or `node:` prefix - * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill - * - If you have a `node_modules.bun` file, many modules will point to that file - * - * Virtual modules and JS polyfills are embedded in bun's binary. They don't - * point to anywhere in your local filesystem. - */ - registry: Map< - string, - { - key: string; - /** - * This refers to the state the ESM module is in - * - * TODO: make an enum for this number - */ - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array< - (typeof Loader)["registry"] extends Map ? V : any - >; - /** - * Your application will probably crash if you mess with this. - */ - module: { - dependenciesMap: (typeof Loader)["registry"]; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - /** - * For an already-evaluated module, return the dependencies as module specifiers - * - * This list is already sorted and uniqued. - * - * @example - * - * For this code: - * ```js - * // /foo.js - * import classNames from 'classnames'; - * import React from 'react'; - * import {createElement} from 'react'; - * ``` - * - * This would return: - * ```js - * Loader.dependencyKeysIfEvaluated("/foo.js") - * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] - * ``` - * - * @param specifier - module specifier as it appears in transpiled source code - */ - dependencyKeysIfEvaluated: (specifier: string) => string[]; - /** - * The function JavaScriptCore internally calls when you use an import statement. - * - * This may return a path to `node_modules.server.bun`, which will be confusing. - * - * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} - * instead. - * - * @param specifier - module specifier as it appears in transpiled source code - * @param referrer - module specifier that is resolving this specifier - */ - resolve: (specifier: string, referrer: string) => string; + /** + * ESM module registry + * + * This lets you implement live reload in Bun. If you + * delete a module specifier from this map, the next time it's imported, it + * will be re-transpiled and loaded again. + * + * The keys are the module specifiers and the + * values are metadata about the module. + * + * The keys are an implementation detail for Bun that will change between + * versions. + * + * - Userland modules are an absolute file path + * - Virtual modules have a `bun:` prefix or `node:` prefix + * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill + * - If you have a `node_modules.bun` file, many modules will point to that file + * + * Virtual modules and JS polyfills are embedded in bun's binary. They don't + * point to anywhere in your local filesystem. + */ + registry: Map< + string, + { + key: string; + /** + * This refers to the state the ESM module is in + * + * TODO: make an enum for this number + */ + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; + /** + * Your application will probably crash if you mess with this. + */ + module: { + dependenciesMap: (typeof Loader)["registry"]; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; + /** + * For an already-evaluated module, return the dependencies as module specifiers + * + * This list is already sorted and uniqued. + * + * @example + * + * For this code: + * ```js + * // /foo.js + * import classNames from 'classnames'; + * import React from 'react'; + * import {createElement} from 'react'; + * ``` + * + * This would return: + * ```js + * Loader.dependencyKeysIfEvaluated("/foo.js") + * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] + * ``` + * + * @param specifier - module specifier as it appears in transpiled source code + */ + dependencyKeysIfEvaluated: (specifier: string) => string[]; + /** + * The function JavaScriptCore internally calls when you use an import statement. + * + * This may return a path to `node_modules.server.bun`, which will be confusing. + * + * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} + * instead. + * + * @param specifier - module specifier as it appears in transpiled source code + * @param referrer - module specifier that is resolving this specifier + */ + resolve: (specifier: string, referrer: string) => string; }; interface QueuingStrategy { - highWaterMark?: number; - size?: QueuingStrategySize; + highWaterMark?: number; + size?: QueuingStrategySize; } interface QueuingStrategyInit { - /** - * Creates a new ByteLengthQueuingStrategy with the provided high water mark. - * - * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. - */ - highWaterMark: number; + /** + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. + */ + highWaterMark: number; } /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ interface ByteLengthQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - // changed from QueuingStrategySize - // to avoid conflict with lib.dom.d.ts - readonly size: QueuingStrategySize; + readonly highWaterMark: number; + // changed from QueuingStrategySize + // to avoid conflict with lib.dom.d.ts + readonly size: QueuingStrategySize; } declare var ByteLengthQueuingStrategy: { - prototype: ByteLengthQueuingStrategy; - new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; + prototype: ByteLengthQueuingStrategy; + new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; }; interface ReadableStreamDefaultController { - readonly desiredSize: number | null; - close(): void; - enqueue(chunk?: R): void; - error(e?: any): void; + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; } interface ReadableStreamDirectController { - close(error?: Error): void; - write( - data: Bun.BufferSource | ArrayBuffer | string, - ): number | Promise; - end(): number | Promise; - flush(): number | Promise; - start(): void; + close(error?: Error): void; + write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; + end(): number | Promise; + flush(): number | Promise; + start(): void; } declare var ReadableStreamDefaultController: { - prototype: ReadableStreamDefaultController; - new (): ReadableStreamDefaultController; + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; }; -interface ReadableStreamDefaultReader - extends ReadableStreamGenericReader { - read(): Promise>; - /** - * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. - * Will only return a promise if the data is not immediately available. - */ - readMany(): - | Promise> - | Bun.ReadableStreamDefaultReadManyResult; - releaseLock(): void; +interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { + read(): Promise>; + /** + * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. + * Will only return a promise if the data is not immediately available. + */ + readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; + releaseLock(): void; } declare var ReadableStreamDefaultReader: { - prototype: ReadableStreamDefaultReader; - new (stream: ReadableStream): ReadableStreamDefaultReader; + prototype: ReadableStreamDefaultReader; + new (stream: ReadableStream): ReadableStreamDefaultReader; }; interface ReadableStreamGenericReader { - readonly closed: Promise; - cancel(reason?: any): Promise; + readonly closed: Promise; + cancel(reason?: any): Promise; } interface ReadableStreamDefaultReadDoneResult { - done: true; - value?: undefined; + done: true; + value?: undefined; } interface ReadableStreamDefaultReadValueResult { - done: false; - value: T; + done: false; + value: T; } interface ReadableWritablePair { - readable: ReadableStream; - /** - * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - */ - writable: WritableStream; + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; } interface WritableStreamDefaultController { - error(e?: any): void; + error(e?: any): void; } declare var WritableStreamDefaultController: { - prototype: WritableStreamDefaultController; - new (): WritableStreamDefaultController; + prototype: WritableStreamDefaultController; + new (): WritableStreamDefaultController; }; /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ interface WritableStreamDefaultWriter { - readonly closed: Promise; - readonly desiredSize: number | null; - readonly ready: Promise; - abort(reason?: any): Promise; - close(): Promise; - releaseLock(): void; - write(chunk?: W): Promise; + readonly closed: Promise; + readonly desiredSize: number | null; + readonly ready: Promise; + abort(reason?: any): Promise; + close(): Promise; + releaseLock(): void; + write(chunk?: W): Promise; } declare var WritableStreamDefaultWriter: { - prototype: WritableStreamDefaultWriter; - new (stream: WritableStream): WritableStreamDefaultWriter; + prototype: WritableStreamDefaultWriter; + new (stream: WritableStream): WritableStreamDefaultWriter; }; interface TransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; + readonly readable: ReadableStream; + readonly writable: WritableStream; } declare var TransformStream: { - prototype: TransformStream; - new ( - transformer?: Transformer, - writableStrategy?: QueuingStrategy, - readableStrategy?: QueuingStrategy, - ): TransformStream; + prototype: TransformStream; + new ( + transformer?: Transformer, + writableStrategy?: QueuingStrategy, + readableStrategy?: QueuingStrategy, + ): TransformStream; }; interface TransformStreamDefaultController { - readonly desiredSize: number | null; - enqueue(chunk?: O): void; - error(reason?: any): void; - terminate(): void; + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; } declare var TransformStreamDefaultController: { - prototype: TransformStreamDefaultController; - new (): TransformStreamDefaultController; + prototype: TransformStreamDefaultController; + new (): TransformStreamDefaultController; }; interface StreamPipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - /** - * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - * - * Errors and closures of the source and destination streams propagate as follows: - * - * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. - * - * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. - * - * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. - * - * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. - * - * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. - */ - preventClose?: boolean; - signal?: AbortSignal; + preventAbort?: boolean; + preventCancel?: boolean; + /** + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + * + * Errors and closures of the source and destination streams propagate as follows: + * + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. + * + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. + * + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. + * + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. + */ + preventClose?: boolean; + signal?: AbortSignal; } /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ interface CountQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - readonly size: QueuingStrategySize; + readonly highWaterMark: number; + readonly size: QueuingStrategySize; } declare var CountQueuingStrategy: { - prototype: CountQueuingStrategy; - new (init: QueuingStrategyInit): CountQueuingStrategy; + prototype: CountQueuingStrategy; + new (init: QueuingStrategyInit): CountQueuingStrategy; }; interface QueuingStrategySize { - (chunk?: T): number; + (chunk?: T): number; } interface Transformer { - flush?: Bun.TransformerFlushCallback; - readableType?: undefined; - start?: Bun.TransformerStartCallback; - transform?: Bun.TransformerTransformCallback; - writableType?: undefined; + flush?: Bun.TransformerFlushCallback; + readableType?: undefined; + start?: Bun.TransformerStartCallback; + transform?: Bun.TransformerTransformCallback; + writableType?: undefined; } interface Dict { - [key: string]: T | undefined; + [key: string]: T | undefined; } interface ReadOnlyDict { - readonly [key: string]: T | undefined; + readonly [key: string]: T | undefined; } interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; } /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; } declare var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; + prototype: DOMException; + new (message?: string, name?: string): DOMException; }; declare function alert(message?: string): void; @@ -772,374 +735,370 @@ declare function prompt(message?: string, _default?: string): string | null; type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; declare var SubtleCrypto: { - prototype: _SubtleCrypto; - new (): _SubtleCrypto; + prototype: _SubtleCrypto; + new (): _SubtleCrypto; }; type _CryptoKey = import("crypto").webcrypto.CryptoKey; interface CryptoKey extends _CryptoKey {} declare var CryptoKey: { - prototype: CryptoKey; - new (): CryptoKey; + prototype: CryptoKey; + new (): CryptoKey; }; interface Position { - lineText: string; - file: string; - namespace: string; - line: number; - column: number; - length: number; - offset: number; + lineText: string; + file: string; + namespace: string; + line: number; + column: number; + length: number; + offset: number; } declare class ResolveMessage { - readonly name: "ResolveMessage"; - readonly position: Position | null; - readonly code: string; - readonly message: string; - readonly referrer: string; - readonly specifier: string; - readonly importKind: - | "entry_point" - | "stmt" - | "require" - | "import" - | "dynamic" - | "require_resolve" - | "at" - | "at_conditional" - | "url" - | "internal"; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - - toString(): string; + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; } declare class BuildMessage { - readonly name: "BuildMessage"; - readonly position: Position | null; - readonly message: string; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + readonly name: "BuildMessage"; + readonly position: Position | null; + readonly message: string; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; } // Declare "static" methods in Error interface ErrorConstructor { - /** Create .stack property on a target object */ - // eslint-disable-next-line @typescript-eslint/ban-types - captureStackTrace(targetObject: object, constructorOpt?: Function): void; - - /** - * Optional override for formatting stack traces - * - * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces - */ - prepareStackTrace?: - | ((err: Error, stackTraces: NodeJS.CallSite[]) => any) - | undefined; - - stackTraceLimit: number; + /** Create .stack property on a target object */ + + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; + + stackTraceLimit: number; } interface ArrayBufferConstructor { - new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; + new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; } interface ArrayBuffer { - /** - * Read-only. The length of the ArrayBuffer (in bytes). - */ - readonly byteLength: number; - /** - * Resize an ArrayBuffer in-place. - */ - resize(byteLength: number): ArrayBuffer; - - /** - * Returns a section of an ArrayBuffer. - */ - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; + /** + * Read-only. The length of the ArrayBuffer (in bytes). + */ + readonly byteLength: number; + /** + * Resize an ArrayBuffer in-place. + */ + resize(byteLength: number): ArrayBuffer; + + /** + * Returns a section of an ArrayBuffer. + */ + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; } interface SharedArrayBuffer { - /** - * Grow the SharedArrayBuffer in-place. - */ - grow(size: number): SharedArrayBuffer; + /** + * Grow the SharedArrayBuffer in-place. + */ + grow(size: number): SharedArrayBuffer; } interface ArrayConstructor { - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - ): Promise[]>; - - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. Results of the map function are also awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * await Array.fromAsync([1], (n) => n + 1); // [2] - * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. - * @param thisArg - The `this` to which `mapFn` is bound. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; + + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. Results of the map function are also awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * await Array.fromAsync([1], (n) => n + 1); // [2] + * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. + * @param thisArg - The `this` to which `mapFn` is bound. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; } interface ConsoleOptions { - stdout: import("stream").Writable; - stderr?: import("stream").Writable; - ignoreErrors?: boolean; - colorMode?: boolean | "auto"; - inspectOptions?: import("util").InspectOptions; - groupIndentation?: number; + stdout: import("stream").Writable; + stderr?: import("stream").Writable; + ignoreErrors?: boolean; + colorMode?: boolean | "auto"; + inspectOptions?: import("util").InspectOptions; + groupIndentation?: number; } interface Console { - /** - * Asynchronously read lines from standard input (fd 0) - * - * ```ts - * for await (const line of console) { - * console.log(line); - * } - * ``` - */ - [Symbol.asyncIterator](): AsyncIterableIterator; - - /** - * Write text or bytes to stdout - * - * Unlike {@link console.log}, this does no formatting and doesn't add a - * newline or spaces between arguments. You can pass it strings or bytes or - * any combination of the two. - * - * ```ts - * console.write("hello world!", "\n"); // "hello world\n" - * ``` - * - * @param data - The data to write - * @returns The number of bytes written - * - * This function is not available in the browser. - */ - write(...data: Array): number; - - /** - * Clear the console - */ - clear(): void; - - assert(condition?: boolean, ...data: any[]): void; - - /** - * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) - * @param label label counter - */ - count(label?: string): void; - countReset(label?: string): void; - debug(...data: any[]): void; - dir(item?: any, options?: any): void; - dirxml(...data: any[]): void; - /** - * Log to stderr in your terminal - * - * Appears in red - * - * @param data something to display - */ - error(...data: any[]): void; - /** Does nothing currently */ - group(...data: any[]): void; - /** Does nothing currently */ - groupCollapsed(...data: any[]): void; - /** Does nothing currently */ - groupEnd(): void; - info(...data: any[]): void; - log(...data: any[]): void; - /** - * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just - * logging the argument if it can't be parsed as tabular. - * - * ```js - * // These can't be parsed as tabular data - * console.table(Symbol()); - * // Symbol() - * - * console.table(undefined); - * // undefined - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ b โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * ``` - * @param properties Alternate properties for constructing the table. - */ - table(tabularData?: any, properties?: string[]): void; - /** - * Begin a timer to log with {@link console.timeEnd} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - time(label?: string): void; - /** - * End a timer to log with {@link console.time} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - timeEnd(label?: string): void; - timeLog(label?: string, ...data: any[]): void; - timeStamp(label?: string): void; - trace(...data: any[]): void; - warn(...data: any[]): void; - - /** - * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. - */ - // Console: { - // new (options: ConsoleOptions): Console; - // new ( - // stdout: import("stream").Writable, - // stderr?: import("stream").Writable, - // ignoreErrors?: boolean, - // ): Console; - // }; + /** + * Asynchronously read lines from standard input (fd 0) + * + * ```ts + * for await (const line of console) { + * console.log(line); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterableIterator; + + /** + * Write text or bytes to stdout + * + * Unlike {@link console.log}, this does no formatting and doesn't add a + * newline or spaces between arguments. You can pass it strings or bytes or + * any combination of the two. + * + * ```ts + * console.write("hello world!", "\n"); // "hello world\n" + * ``` + * + * @param data - The data to write + * @returns The number of bytes written + * + * This function is not available in the browser. + */ + write(...data: Array): number; + + /** + * Clear the console + */ + clear(): void; + + assert(condition?: boolean, ...data: any[]): void; + + /** + * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) + * @param label label counter + */ + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: any): void; + dirxml(...data: any[]): void; + /** + * Log to stderr in your terminal + * + * Appears in red + * + * @param data something to display + */ + error(...data: any[]): void; + /** Does nothing currently */ + group(...data: any[]): void; + /** Does nothing currently */ + groupCollapsed(...data: any[]): void; + /** Does nothing currently */ + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + /** + * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just + * logging the argument if it can't be parsed as tabular. + * + * ```js + * // These can't be parsed as tabular data + * console.table(Symbol()); + * // Symbol() + * + * console.table(undefined); + * // undefined + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ b โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * ``` + * @param properties Alternate properties for constructing the table. + */ + table(tabularData?: any, properties?: string[]): void; + /** + * Begin a timer to log with {@link console.timeEnd} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + time(label?: string): void; + /** + * End a timer to log with {@link console.time} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + timeStamp(label?: string): void; + trace(...data: any[]): void; + warn(...data: any[]): void; + + /** + * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. + */ + // Console: { + // new (options: ConsoleOptions): Console; + // new ( + // stdout: import("stream").Writable, + // stderr?: import("stream").Writable, + // ignoreErrors?: boolean, + // ): Console; + // }; } declare var console: Console; interface ImportMeta { - /** - * `file://` url string for the current module. - * - * @example - * ```ts - * console.log(import.meta.url); - * "file:///Users/me/projects/my-app/src/my-app.ts" - * ``` - */ - url: string; - /** - * Absolute path to the source file - */ - readonly path: string; - /** - * Absolute path to the directory containing the source file. - * - * Does not have a trailing slash - */ - readonly dir: string; - /** - * Filename of the source file - */ - readonly file: string; - /** - * The environment variables of the process - * - * ```ts - * import.meta.env === process.env - * ``` - */ - readonly env: NodeJS.ProcessEnv; - - /** - * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead - * - * Resolve a module ID the same as if you imported it - * - * The `parent` argument is optional, and defaults to the current module's path. - */ - resolveSync(moduleId: string, parent?: string): string; - - /** - * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all - * calls to `require` with `import.meta.require` when transpiling ES Modules - * for the runtime. - * - * Warning: **This API is not stable** and may change or be removed in the - * future. Use at your own risk. - */ - require: NodeJS.Require; - - /** - * Did the current file start the process? - * - * @example - * ```ts - * if (import.meta.main) { - * console.log("I started the process!"); - * } - * ``` - * - * @example - * ```ts - * console.log( - * import.meta.main === (import.meta.path === Bun.main) - * ) - * ``` - */ - readonly main: boolean; - - /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ - dirname: string; - - /** Alias of `import.meta.path`. Exists for Node.js compatibility */ - filename: string; + /** + * `file://` url string for the current module. + * + * @example + * ```ts + * console.log(import.meta.url); + * "file:///Users/me/projects/my-app/src/my-app.ts" + * ``` + */ + url: string; + /** + * Absolute path to the source file + */ + readonly path: string; + /** + * Absolute path to the directory containing the source file. + * + * Does not have a trailing slash + */ + readonly dir: string; + /** + * Filename of the source file + */ + readonly file: string; + /** + * The environment variables of the process + * + * ```ts + * import.meta.env === process.env + * ``` + */ + readonly env: NodeJS.ProcessEnv; + + /** + * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead + * + * Resolve a module ID the same as if you imported it + * + * The `parent` argument is optional, and defaults to the current module's path. + */ + resolveSync(moduleId: string, parent?: string): string; + + /** + * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all + * calls to `require` with `import.meta.require` when transpiling ES Modules + * for the runtime. + * + * Warning: **This API is not stable** and may change or be removed in the + * future. Use at your own risk. + */ + require: NodeJS.Require; + + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; + + /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ + dirname: string; + + /** Alias of `import.meta.path`. Exists for Node.js compatibility */ + filename: string; } /** @@ -1153,7 +1112,7 @@ declare var require: NodeJS.Require; declare var exports: any; interface NodeModule { - exports: any; + exports: any; } declare var module: NodeModule; @@ -1163,10 +1122,7 @@ declare var module: NodeModule; * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) */ -declare function structuredClone( - value: T, - options?: Bun.StructuredSerializeOptions, -): T; +declare function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; /** * Post a message to the parent thread. @@ -1176,81 +1132,81 @@ declare function structuredClone( declare function postMessage(message: any, transfer?: Bun.Transferable[]): void; interface EventSourceInit { - withCredentials?: boolean; + withCredentials?: boolean; } interface PromiseConstructor { - /** - * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called - * separately. - * - * This is useful when you want to return a Promise and have code outside the Promise - * resolve or reject it. - * - * ## Example - * ```ts - * const { promise, resolve, reject } = Promise.withResolvers(); - * - * setTimeout(() => { - * resolve("Hello world!"); - * }, 1000); - * - * await promise; // "Hello world!" - * ``` - * - * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). - */ - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; + /** + * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called + * separately. + * + * This is useful when you want to return a Promise and have code outside the Promise + * resolve or reject it. + * + * ## Example + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); + * + * setTimeout(() => { + * resolve("Hello world!"); + * }, 1000); + * + * await promise; // "Hello world!" + * ``` + * + * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). + */ + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; } interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; } declare var navigator: Navigator; interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; } interface Blob { - /** - * Read the data from the blob as a JSON object. - * - * This first decodes the data from UTF-8, then parses it as JSON. - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - json(): Promise; - - /** - * Read the data from the blob as a {@link FormData} object. - * - * This first decodes the data from UTF-8, then parses it as a - * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. - * - * The `type` property of the blob is used to determine the format of the - * body. - * - * This is a non-standard addition to the `Blob` API, to make it conform more - * closely to the `BodyMixin` API. - */ - formData(): Promise; - - arrayBuffer(): Promise; - - /** - * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` - */ - bytes(): Promise; + /** + * Read the data from the blob as a JSON object. + * + * This first decodes the data from UTF-8, then parses it as JSON. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + json(): Promise; + + /** + * Read the data from the blob as a {@link FormData} object. + * + * This first decodes the data from UTF-8, then parses it as a + * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. + * + * The `type` property of the blob is used to determine the format of the + * body. + * + * This is a non-standard addition to the `Blob` API, to make it conform more + * closely to the `BodyMixin` API. + */ + formData(): Promise; + + arrayBuffer(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + */ + bytes(): Promise; } /** @@ -1260,16 +1216,16 @@ interface Blob { * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) */ declare var Blob: { - prototype: Blob; - new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; + prototype: Blob; + new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; }; interface URL {} declare var URL: { - prototype: URL; - new (url: string | URL, base?: string | URL): URL; - canParse(url: string): boolean; - createObjectURL(object: any): string; - revokeObjectURL(url: string): void; - parse(url: string): URL; + prototype: URL; + new (url: string | URL, base?: string | URL): URL; + canParse(url: string): boolean; + createObjectURL(object: any): string; + revokeObjectURL(url: string): void; + parse(url: string): URL; }; diff --git a/packages/bun-types/new/html-rewriter.d.ts b/packages/bun-types/new/html-rewriter.d.ts index 6bec7fea979ab2..4b2b2954cff397 100644 --- a/packages/bun-types/new/html-rewriter.d.ts +++ b/packages/bun-types/new/html-rewriter.d.ts @@ -1,129 +1,129 @@ declare namespace HTMLRewriterTypes { - interface HTMLRewriterElementContentHandlers { - element?(element: Element): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - } + interface HTMLRewriterElementContentHandlers { + element?(element: Element): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + } - interface HTMLRewriterDocumentContentHandlers { - doctype?(doctype: Doctype): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - end?(end: DocumentEnd): void | Promise; - } + interface HTMLRewriterDocumentContentHandlers { + doctype?(doctype: Doctype): void | Promise; + comments?(comment: Comment): void | Promise; + text?(text: Text): void | Promise; + end?(end: DocumentEnd): void | Promise; + } - interface Text { - /** The text content */ - readonly text: string; - /** Whether this chunk is the last piece of text in a text node */ - readonly lastInTextNode: boolean; - /** Whether this chunk was removed */ - readonly removed: boolean; - /** Insert content before this chunk */ - before(content: Content, options?: ContentOptions): Text; - /** Insert content after this chunk */ - after(content: Content, options?: ContentOptions): Text; - /** Replace this chunk with new content */ - replace(content: Content, options?: ContentOptions): Text; - /** Remove this chunk */ - remove(): Text; - } + interface Text { + /** The text content */ + readonly text: string; + /** Whether this chunk is the last piece of text in a text node */ + readonly lastInTextNode: boolean; + /** Whether this chunk was removed */ + readonly removed: boolean; + /** Insert content before this chunk */ + before(content: Content, options?: ContentOptions): Text; + /** Insert content after this chunk */ + after(content: Content, options?: ContentOptions): Text; + /** Replace this chunk with new content */ + replace(content: Content, options?: ContentOptions): Text; + /** Remove this chunk */ + remove(): Text; + } - interface Doctype { - /** The doctype name (e.g. "html" for ) */ - readonly name: string | null; - /** The doctype public identifier */ - readonly publicId: string | null; - /** The doctype system identifier */ - readonly systemId: string | null; - /** Whether this doctype was removed */ - readonly removed: boolean; - /** Remove this doctype */ - remove(): Doctype; - } + interface Doctype { + /** The doctype name (e.g. "html" for ) */ + readonly name: string | null; + /** The doctype public identifier */ + readonly publicId: string | null; + /** The doctype system identifier */ + readonly systemId: string | null; + /** Whether this doctype was removed */ + readonly removed: boolean; + /** Remove this doctype */ + remove(): Doctype; + } - interface DocumentEnd { - /** Append content at the end of the document */ - append(content: Content, options?: ContentOptions): DocumentEnd; - } + interface DocumentEnd { + /** Append content at the end of the document */ + append(content: Content, options?: ContentOptions): DocumentEnd; + } - interface ContentOptions { - /** Whether to parse the content as HTML */ - html?: boolean; - } + interface ContentOptions { + /** Whether to parse the content as HTML */ + html?: boolean; + } - type Content = string; + type Content = string; - interface Comment { - /** The comment text */ - text: string; - /** Whether this comment was removed */ - readonly removed: boolean; - /** Insert content before this comment */ - before(content: Content, options?: ContentOptions): Comment; - /** Insert content after this comment */ - after(content: Content, options?: ContentOptions): Comment; - /** Replace this comment with new content */ - replace(content: Content, options?: ContentOptions): Comment; - /** Remove this comment */ - remove(): Comment; - } + interface Comment { + /** The comment text */ + text: string; + /** Whether this comment was removed */ + readonly removed: boolean; + /** Insert content before this comment */ + before(content: Content, options?: ContentOptions): Comment; + /** Insert content after this comment */ + after(content: Content, options?: ContentOptions): Comment; + /** Replace this comment with new content */ + replace(content: Content, options?: ContentOptions): Comment; + /** Remove this comment */ + remove(): Comment; + } - interface Element { - /** The tag name in lowercase (e.g. "div", "span") */ - tagName: string; - /** Iterator for the element's attributes */ - readonly attributes: IterableIterator<[string, string]>; - /** Whether this element was removed */ - readonly removed: boolean; - /** Whether the element is explicitly self-closing, e.g. */ - readonly selfClosing: boolean; - /** - * Whether the element can have inner content. Returns `true` unless - * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) - * - or it's self-closing in a foreign context (eg. in SVG, MathML). - */ - readonly canHaveContent: boolean; - /** The element's namespace URI */ - readonly namespaceURI: string; - /** Get an attribute value by name */ - getAttribute(name: string): string | null; - /** Check if an attribute exists */ - hasAttribute(name: string): boolean; - /** Set an attribute value */ - setAttribute(name: string, value: string): Element; - /** Remove an attribute */ - removeAttribute(name: string): Element; - /** Insert content before this element */ - before(content: Content, options?: ContentOptions): Element; - /** Insert content after this element */ - after(content: Content, options?: ContentOptions): Element; - /** Insert content at the start of this element */ - prepend(content: Content, options?: ContentOptions): Element; - /** Insert content at the end of this element */ - append(content: Content, options?: ContentOptions): Element; - /** Replace this element with new content */ - replace(content: Content, options?: ContentOptions): Element; - /** Remove this element and its contents */ - remove(): Element; - /** Remove this element but keep its contents */ - removeAndKeepContent(): Element; - /** Set the inner content of this element */ - setInnerContent(content: Content, options?: ContentOptions): Element; - /** Add a handler for the end tag of this element */ - onEndTag(handler: (tag: EndTag) => void | Promise): void; - } + interface Element { + /** The tag name in lowercase (e.g. "div", "span") */ + tagName: string; + /** Iterator for the element's attributes */ + readonly attributes: IterableIterator<[string, string]>; + /** Whether this element was removed */ + readonly removed: boolean; + /** Whether the element is explicitly self-closing, e.g. */ + readonly selfClosing: boolean; + /** + * Whether the element can have inner content. Returns `true` unless + * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) + * - or it's self-closing in a foreign context (eg. in SVG, MathML). + */ + readonly canHaveContent: boolean; + /** The element's namespace URI */ + readonly namespaceURI: string; + /** Get an attribute value by name */ + getAttribute(name: string): string | null; + /** Check if an attribute exists */ + hasAttribute(name: string): boolean; + /** Set an attribute value */ + setAttribute(name: string, value: string): Element; + /** Remove an attribute */ + removeAttribute(name: string): Element; + /** Insert content before this element */ + before(content: Content, options?: ContentOptions): Element; + /** Insert content after this element */ + after(content: Content, options?: ContentOptions): Element; + /** Insert content at the start of this element */ + prepend(content: Content, options?: ContentOptions): Element; + /** Insert content at the end of this element */ + append(content: Content, options?: ContentOptions): Element; + /** Replace this element with new content */ + replace(content: Content, options?: ContentOptions): Element; + /** Remove this element and its contents */ + remove(): Element; + /** Remove this element but keep its contents */ + removeAndKeepContent(): Element; + /** Set the inner content of this element */ + setInnerContent(content: Content, options?: ContentOptions): Element; + /** Add a handler for the end tag of this element */ + onEndTag(handler: (tag: EndTag) => void | Promise): void; + } - interface EndTag { - /** The tag name in lowercase */ - name: string; - /** Insert content before this end tag */ - before(content: Content, options?: ContentOptions): EndTag; - /** Insert content after this end tag */ - after(content: Content, options?: ContentOptions): EndTag; - /** Remove this end tag */ - remove(): EndTag; - } + interface EndTag { + /** The tag name in lowercase */ + name: string; + /** Insert content before this end tag */ + before(content: Content, options?: ContentOptions): EndTag; + /** Insert content after this end tag */ + after(content: Content, options?: ContentOptions): EndTag; + /** Remove this end tag */ + remove(): EndTag; + } } /** @@ -149,41 +149,36 @@ declare namespace HTMLRewriterTypes { * ``` */ declare class HTMLRewriter { - constructor(); - /** - * Add handlers for elements matching a CSS selector - * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") - * @param handlers - Object containing handler functions for elements, comments, and text nodes - */ - on( - selector: string, - handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers, - ): HTMLRewriter; + constructor(); + /** + * Add handlers for elements matching a CSS selector + * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") + * @param handlers - Object containing handler functions for elements, comments, and text nodes + */ + on(selector: string, handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers): HTMLRewriter; - /** - * Add handlers for document-level events - * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end - */ - onDocument( - handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers, - ): HTMLRewriter; + /** + * Add handlers for document-level events + * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end + */ + onDocument(handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers): HTMLRewriter; - /** - * Transform HTML content - * @param input - The HTML to transform - * @returns A new {@link Response} with the transformed HTML - */ - transform(input: Response | Blob | Bun.BufferSource): Response; - /** - * Transform HTML content - * @param input - The HTML string to transform - * @returns A new {@link String} containing the transformed HTML - */ - transform(input: string): string; - /** - * Transform HTML content - * @param input - The HTML to transform as a {@link ArrayBuffer} - * @returns A new {@link ArrayBuffer} with the transformed HTML - */ - transform(input: ArrayBuffer): ArrayBuffer; + /** + * Transform HTML content + * @param input - The HTML to transform + * @returns A new {@link Response} with the transformed HTML + */ + transform(input: Response | Blob | Bun.BufferSource): Response; + /** + * Transform HTML content + * @param input - The HTML string to transform + * @returns A new {@link String} containing the transformed HTML + */ + transform(input: string): string; + /** + * Transform HTML content + * @param input - The HTML to transform as a {@link ArrayBuffer} + * @returns A new {@link ArrayBuffer} with the transformed HTML + */ + transform(input: ArrayBuffer): ArrayBuffer; } diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index 249ee82803cdd9..1a42a7e4802d84 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -16,6 +16,8 @@ /// /// /// +/// +/// /// diff --git a/packages/bun-types/new/jsc.d.ts b/packages/bun-types/new/jsc.d.ts index c5942da2813fb5..2a07534586516c 100644 --- a/packages/bun-types/new/jsc.d.ts +++ b/packages/bun-types/new/jsc.d.ts @@ -1,243 +1,229 @@ declare module "bun:jsc" { - /** - * This used to be called "describe" but it could be confused with the test runner. - */ - function jscDescribe(value: any): string; - function jscDescribeArray(args: any[]): string; - function gcAndSweep(): number; - function fullGC(): number; - function edenGC(): number; - function heapSize(): number; - function heapStats(): { - heapSize: number; - heapCapacity: number; - extraMemorySize: number; - objectCount: number; - protectedObjectCount: number; - globalObjectCount: number; - protectedGlobalObjectCount: number; - objectTypeCounts: Record; - protectedObjectTypeCounts: Record; - }; - function memoryUsage(): { - current: number; - peak: number; - currentCommit: number; - peakCommit: number; - pageFaults: number; - }; - function getRandomSeed(): number; - function setRandomSeed(value: number): void; - function isRope(input: string): boolean; - function callerSourceOrigin(): string; - function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; - function noOSRExitFuzzing( - func: (...args: any[]) => any, - ): (...args: any[]) => any; - function optimizeNextInvocation(func: (...args: any[]) => any): void; - function numberOfDFGCompiles(func: (...args: any[]) => any): number; - function releaseWeakRefs(): void; - function totalCompileTime(func: (...args: any[]) => any): number; - function reoptimizationRetryCount(func: (...args: any[]) => any): number; - function drainMicrotasks(): void; + /** + * This used to be called "describe" but it could be confused with the test runner. + */ + function jscDescribe(value: any): string; + function jscDescribeArray(args: any[]): string; + function gcAndSweep(): number; + function fullGC(): number; + function edenGC(): number; + function heapSize(): number; + function heapStats(): { + heapSize: number; + heapCapacity: number; + extraMemorySize: number; + objectCount: number; + protectedObjectCount: number; + globalObjectCount: number; + protectedGlobalObjectCount: number; + objectTypeCounts: Record; + protectedObjectTypeCounts: Record; + }; + function memoryUsage(): { + current: number; + peak: number; + currentCommit: number; + peakCommit: number; + pageFaults: number; + }; + function getRandomSeed(): number; + function setRandomSeed(value: number): void; + function isRope(input: string): boolean; + function callerSourceOrigin(): string; + function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; + function noOSRExitFuzzing(func: (...args: any[]) => any): (...args: any[]) => any; + function optimizeNextInvocation(func: (...args: any[]) => any): void; + function numberOfDFGCompiles(func: (...args: any[]) => any): number; + function releaseWeakRefs(): void; + function totalCompileTime(func: (...args: any[]) => any): number; + function reoptimizationRetryCount(func: (...args: any[]) => any): number; + function drainMicrotasks(): void; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A SharedArrayBuffer that can be sent to another Bun instance. - */ - function serialize( - value: any, - options?: { binaryType?: "arraybuffer" }, - ): SharedArrayBuffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A SharedArrayBuffer that can be sent to another Bun instance. + */ + function serialize(value: any, options?: { binaryType?: "arraybuffer" }): SharedArrayBuffer; - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A Buffer that can be sent to another Bun instance. - */ - function serialize( - value: any, - options?: { binaryType: "nodebuffer" }, - ): Buffer; + /** + * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. + * + * Internally, this uses the serialization format from WebKit/Safari. + * + * @param value A JavaScript value, usually an object or array, to be converted. + * @returns A Buffer that can be sent to another Bun instance. + */ + function serialize(value: any, options?: { binaryType: "nodebuffer" }): Buffer; - /** - * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. - * - * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. - */ - function deserialize( - value: ArrayBufferLike | NodeJS.TypedArray | Buffer, - ): any; + /** + * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. + * + * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. + */ + function deserialize(value: ArrayBufferLike | NodeJS.TypedArray | Buffer): any; - /** - * Set the timezone used by Intl, Date, etc. - * - * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" - * - * @returns The normalized time zone string - * - * You can also set process.env.TZ to the time zone you want to use. - * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` - */ - function setTimeZone(timeZone: string): string; + /** + * Set the timezone used by Intl, Date, etc. + * + * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" + * + * @returns The normalized time zone string + * + * You can also set process.env.TZ to the time zone you want to use. + * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` + */ + function setTimeZone(timeZone: string): string; - interface SamplingProfile { - /** - * A formatted summary of the top functions - * - * Example output: - * ```js - * - * Sampling rate: 100.000000 microseconds. Total samples: 6858 - * Top functions as - * 2948 '#:8' - * 393 'visit#:8' - * 263 'push#:8' - * 164 'scan_ref_scoped#:8' - * 164 'walk#:8' - * 144 'pop#:8' - * 107 'extract_candidates#:8' - * 94 'get#:8' - * 82 'Function#:4294967295' - * 79 'set#:8' - * 67 'forEach#:5' - * 58 'collapse#:8' - * ``` - */ - functions: string; - /** - * A formatted summary of the top bytecodes - * - * Example output: - * ```js - * Tier breakdown: - * ----------------------------------- - * LLInt: 106 (1.545640%) - * Baseline: 2355 (34.339458%) - * DFG: 3290 (47.973170%) - * FTL: 833 (12.146398%) - * js builtin: 132 (1.924759%) - * Wasm: 0 (0.000000%) - * Host: 111 (1.618548%) - * RegExp: 15 (0.218723%) - * C/C++: 0 (0.000000%) - * Unknown Executable: 148 (2.158064%) - * - * Hottest bytecodes as - * 273 'visit#:DFG:bc#63' - * 121 'walk#:DFG:bc#7' - * 119 '#:Baseline:bc#1' - * 82 'Function#:None:' - * 66 '#:DFG:bc#11' - * 65 '#:DFG:bc#33' - * 58 '#:Baseline:bc#7' - * 53 '#:Baseline:bc#23' - * 50 'forEach#:DFG:bc#83' - * 49 'pop#:FTL:bc#65' - * 47 '#:DFG:bc#99' - * 45 '#:DFG:bc#16' - * 44 '#:DFG:bc#7' - * 44 '#:Baseline:bc#30' - * 44 'push#:FTL:bc#214' - * 41 '#:DFG:bc#50' - * 39 'get#:DFG:bc#27' - * 39 '#:Baseline:bc#0' - * 36 '#:DFG:bc#27' - * 36 'Dictionary#:DFG:bc#41' - * 36 'visit#:DFG:bc#81' - * 36 'get#:FTL:bc#11' - * 32 'push#:FTL:bc#49' - * 31 '#:DFG:bc#76' - * 31 '#:DFG:bc#10' - * 31 '#:DFG:bc#73' - * 29 'set#:DFG:bc#28' - * 28 'in_boolean_context#:DFG:bc#104' - * 28 '#:Baseline:' - * 28 'regExpSplitFast#:None:' - * 26 'visit#:DFG:bc#95' - * 26 'pop#:FTL:bc#120' - * 25 '#:DFG:bc#23' - * 25 'push#:FTL:bc#152' - * 24 'push#:FTL:bc#262' - * 24 '#:FTL:bc#10' - * 23 'is_identifier_char#:DFG:bc#22' - * 23 'visit#:DFG:bc#22' - * 22 '#:FTL:bc#27' - * 22 'indexOf#:None:' - * ``` - */ - bytecodes: string; + interface SamplingProfile { + /** + * A formatted summary of the top functions + * + * Example output: + * ```js + * + * Sampling rate: 100.000000 microseconds. Total samples: 6858 + * Top functions as + * 2948 '#:8' + * 393 'visit#:8' + * 263 'push#:8' + * 164 'scan_ref_scoped#:8' + * 164 'walk#:8' + * 144 'pop#:8' + * 107 'extract_candidates#:8' + * 94 'get#:8' + * 82 'Function#:4294967295' + * 79 'set#:8' + * 67 'forEach#:5' + * 58 'collapse#:8' + * ``` + */ + functions: string; + /** + * A formatted summary of the top bytecodes + * + * Example output: + * ```js + * Tier breakdown: + * ----------------------------------- + * LLInt: 106 (1.545640%) + * Baseline: 2355 (34.339458%) + * DFG: 3290 (47.973170%) + * FTL: 833 (12.146398%) + * js builtin: 132 (1.924759%) + * Wasm: 0 (0.000000%) + * Host: 111 (1.618548%) + * RegExp: 15 (0.218723%) + * C/C++: 0 (0.000000%) + * Unknown Executable: 148 (2.158064%) + * + * Hottest bytecodes as + * 273 'visit#:DFG:bc#63' + * 121 'walk#:DFG:bc#7' + * 119 '#:Baseline:bc#1' + * 82 'Function#:None:' + * 66 '#:DFG:bc#11' + * 65 '#:DFG:bc#33' + * 58 '#:Baseline:bc#7' + * 53 '#:Baseline:bc#23' + * 50 'forEach#:DFG:bc#83' + * 49 'pop#:FTL:bc#65' + * 47 '#:DFG:bc#99' + * 45 '#:DFG:bc#16' + * 44 '#:DFG:bc#7' + * 44 '#:Baseline:bc#30' + * 44 'push#:FTL:bc#214' + * 41 '#:DFG:bc#50' + * 39 'get#:DFG:bc#27' + * 39 '#:Baseline:bc#0' + * 36 '#:DFG:bc#27' + * 36 'Dictionary#:DFG:bc#41' + * 36 'visit#:DFG:bc#81' + * 36 'get#:FTL:bc#11' + * 32 'push#:FTL:bc#49' + * 31 '#:DFG:bc#76' + * 31 '#:DFG:bc#10' + * 31 '#:DFG:bc#73' + * 29 'set#:DFG:bc#28' + * 28 'in_boolean_context#:DFG:bc#104' + * 28 '#:Baseline:' + * 28 'regExpSplitFast#:None:' + * 26 'visit#:DFG:bc#95' + * 26 'pop#:FTL:bc#120' + * 25 '#:DFG:bc#23' + * 25 'push#:FTL:bc#152' + * 24 'push#:FTL:bc#262' + * 24 '#:FTL:bc#10' + * 23 'is_identifier_char#:DFG:bc#22' + * 23 'visit#:DFG:bc#22' + * 22 '#:FTL:bc#27' + * 22 'indexOf#:None:' + * ``` + */ + bytecodes: string; - /** - * Stack traces of the top functions - */ - stackTraces: string[]; - } + /** + * Stack traces of the top functions + */ + stackTraces: string[]; + } - /** - * Run JavaScriptCore's sampling profiler for a particular function - * - * This is pretty low-level. - * - * Things to know: - * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation - * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile - * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile - * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile - */ - function profile any>( - callback: T, - sampleInterval?: number, - ...args: Parameters - ): ReturnType extends Promise - ? Promise - : SamplingProfile; + /** + * Run JavaScriptCore's sampling profiler for a particular function + * + * This is pretty low-level. + * + * Things to know: + * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation + * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile + * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile + * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile + */ + function profile any>( + callback: T, + sampleInterval?: number, + ...args: Parameters + ): ReturnType extends Promise ? Promise : SamplingProfile; - /** - * This returns objects which native code has explicitly protected from being - * garbage collected - * - * By calling this function you create another reference to the object, which - * will further prevent it from being garbage collected - * - * This function is mostly a debugging tool for bun itself. - * - * Warning: not all objects returned are supposed to be observable from JavaScript - */ - function getProtectedObjects(): any[]; + /** + * This returns objects which native code has explicitly protected from being + * garbage collected + * + * By calling this function you create another reference to the object, which + * will further prevent it from being garbage collected + * + * This function is mostly a debugging tool for bun itself. + * + * Warning: not all objects returned are supposed to be observable from JavaScript + */ + function getProtectedObjects(): any[]; - /** - * Start a remote debugging socket server on the given port. - * - * This exposes JavaScriptCore's built-in debugging server. - * - * This is untested. May not be supported yet on macOS - */ - function startRemoteDebugger(host?: string, port?: number): void; + /** + * Start a remote debugging socket server on the given port. + * + * This exposes JavaScriptCore's built-in debugging server. + * + * This is untested. May not be supported yet on macOS + */ + function startRemoteDebugger(host?: string, port?: number): void; - /** - * Run JavaScriptCore's sampling profiler - */ - function startSamplingProfiler(optionalDirectory?: string): void; + /** + * Run JavaScriptCore's sampling profiler + */ + function startSamplingProfiler(optionalDirectory?: string): void; - /** - * Non-recursively estimate the memory usage of an object, excluding the memory usage of - * properties or other objects it references. For more accurate per-object - * memory usage, use {@link Bun.generateHeapSnapshot}. - * - * This is a best-effort estimate. It may not be 100% accurate. When it's - * wrong, it may mean the memory is non-contiguous (such as a large array). - * - * Passing a primitive type that isn't heap allocated returns 0. - */ - function estimateShallowMemoryUsageOf( - value: object | CallableFunction | bigint | symbol | string, - ): number; + /** + * Non-recursively estimate the memory usage of an object, excluding the memory usage of + * properties or other objects it references. For more accurate per-object + * memory usage, use {@link Bun.generateHeapSnapshot}. + * + * This is a best-effort estimate. It may not be 100% accurate. When it's + * wrong, it may mean the memory is non-contiguous (such as a large array). + * + * Passing a primitive type that isn't heap allocated returns 0. + */ + function estimateShallowMemoryUsageOf(value: object | CallableFunction | bigint | symbol | string): number; } diff --git a/packages/bun-types/new/overrides.d.ts b/packages/bun-types/new/overrides.d.ts index 152db35bd28d20..03ad7b0bf2cff4 100644 --- a/packages/bun-types/new/overrides.d.ts +++ b/packages/bun-types/new/overrides.d.ts @@ -1,17 +1,79 @@ -export {}; // `declare global` requires the ambient file to be a module +export {}; declare global { - namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - - /** Whether you are using Bun */ - isBun: true; - /** The current git sha of Bun **/ - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - } + namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; + + /** + * Whether you are using Bun + */ + isBun: true; + + /** + * The current git sha of Bun + */ + revision: string; + + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + + interface ProcessVersions extends Dict { + bun: string; + } + } +} + +declare module "fs/promises" { + function exists(path: Bun.PathLike): Promise; +} + +declare module "tls" { + interface BunConnectionOptions extends Omit { + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: string | Buffer | NodeJS.TypedArray | Bun.BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: + | string + | Buffer + | NodeJS.TypedArray + | Bun.BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: + | string + | Buffer + | Bun.BunFile + | NodeJS.TypedArray + | Array + | undefined; + } + + function connect(options: BunConnectionOptions, secureConnectListener?: () => void): TLSSocket; } diff --git a/packages/bun-types/new/s3.d.ts b/packages/bun-types/new/s3.d.ts index 92274b3f5f608f..b1e5f08ed8a930 100644 --- a/packages/bun-types/new/s3.d.ts +++ b/packages/bun-types/new/s3.d.ts @@ -1,753 +1,744 @@ declare module "bun" { - /** - * Configuration options for S3 operations - */ - interface S3Options extends BlobPropertyBag { - /** - * The Access Control List (ACL) policy for the file. - * Controls who can access the file and what permissions they have. - * - * @example - * // Setting public read access - * const file = s3("public-file.txt", { - * acl: "public-read", - * bucket: "my-bucket" - * }); - * - * @example - * // Using with presigned URLs - * const url = file.presign({ - * acl: "public-read", - * expiresIn: 3600 - * }); - */ - acl?: - | "private" - | "public-read" - | "public-read-write" - | "aws-exec-read" - | "authenticated-read" - | "bucket-owner-read" - | "bucket-owner-full-control" - | "log-delivery-write"; - - /** - * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. - * - * @example - * // Using explicit bucket - * const file = s3("my-file.txt", { bucket: "my-bucket" }); - * - * @example - * // Using environment variables - * // With S3_BUCKET=my-bucket in .env - * const file = s3("my-file.txt"); - */ - bucket?: string; - - /** - * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. - * - * @example - * const file = s3("my-file.txt", { - * bucket: "my-bucket", - * region: "us-west-2" - * }); - */ - region?: string; - - /** - * The access key ID for authentication. - * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. - */ - accessKeyId?: string; - - /** - * The secret access key for authentication. - * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. - */ - secretAccessKey?: string; - - /** - * Optional session token for temporary credentials. - * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. - * - * @example - * // Using temporary credentials - * const file = s3("my-file.txt", { - * accessKeyId: tempAccessKey, - * secretAccessKey: tempSecretKey, - * sessionToken: tempSessionToken - * }); - */ - sessionToken?: string; - - /** - * The S3-compatible service endpoint URL. - * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. - * - * @example - * // AWS S3 - * const file = s3("my-file.txt", { - * endpoint: "https://s3.us-east-1.amazonaws.com" - * }); - * - * @example - * // Cloudflare R2 - * const file = s3("my-file.txt", { - * endpoint: "https://.r2.cloudflarestorage.com" - * }); - * - * @example - * // DigitalOcean Spaces - * const file = s3("my-file.txt", { - * endpoint: "https://.digitaloceanspaces.com" - * }); - * - * @example - * // MinIO (local development) - * const file = s3("my-file.txt", { - * endpoint: "http://localhost:9000" - * }); - */ - endpoint?: string; - - /** - * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` - * - * @example - * // Using virtual hosted style - * const file = s3("my-file.txt", { - * virtualHostedStyle: true, - * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" - * }); - */ - virtualHostedStyle?: boolean; - - /** - * The size of each part in multipart uploads (in bytes). - * - Minimum: 5 MiB - * - Maximum: 5120 MiB - * - Default: 5 MiB - * - * @example - * // Configuring multipart uploads - * const file = s3("large-file.dat", { - * partSize: 10 * 1024 * 1024, // 10 MiB parts - * queueSize: 4 // Upload 4 parts in parallel - * }); - * - * const writer = file.writer(); - * // ... write large file in chunks - */ - partSize?: number; - - /** - * Number of parts to upload in parallel for multipart uploads. - * - Default: 5 - * - Maximum: 255 - * - * Increasing this value can improve upload speeds for large files - * but will use more memory. - */ - queueSize?: number; - - /** - * Number of retry attempts for failed uploads. - * - Default: 3 - * - Maximum: 255 - * - * @example - * // Setting retry attempts - * const file = s3("my-file.txt", { - * retry: 5 // Retry failed uploads up to 5 times - * }); - */ - retry?: number; - - /** - * The Content-Type of the file. - * Automatically set based on file extension when possible. - * - * @example - * // Setting explicit content type - * const file = s3("data.bin", { - * type: "application/octet-stream" - * }); - */ - type?: string; - - /** - * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. - * - * @example - * // Setting explicit Storage class - * const file = s3("my-file.json", { - * storageClass: "STANDARD_IA" - * }); - */ - storageClass?: - | "STANDARD" - | "DEEP_ARCHIVE" - | "EXPRESS_ONEZONE" - | "GLACIER" - | "GLACIER_IR" - | "INTELLIGENT_TIERING" - | "ONEZONE_IA" - | "OUTPOSTS" - | "REDUCED_REDUNDANCY" - | "SNOW" - | "STANDARD_IA"; - - /** - * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. - */ - highWaterMark?: number; - } - - /** - * Options for generating presigned URLs - */ - interface S3FilePresignOptions extends S3Options { - /** - * Number of seconds until the presigned URL expires. - * - Default: 86400 (1 day) - * - * @example - * // Short-lived URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Long-lived public URL - * const url = file.presign({ - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - expiresIn?: number; - - /** - * The HTTP method allowed for the presigned URL. - * - * @example - * // GET URL for downloads - * const downloadUrl = file.presign({ - * method: "GET", - * expiresIn: 3600 - * }); - * - * @example - * // PUT URL for uploads - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "application/json" - * }); - */ - method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; - } - - interface S3Stats { - size: number; - lastModified: Date; - etag: string; - type: string; - } - - /** - * Represents a file in an S3-compatible storage service. - * Extends the Blob interface for compatibility with web APIs. - */ - interface S3File extends Blob { - /** - * The size of the file in bytes. - * This is a Promise because it requires a network request to determine the size. - * - * @example - * // Getting file size - * const size = await file.size; - * console.log(`File size: ${size} bytes`); - * - * @example - * // Check if file is larger than 1MB - * if (await file.size > 1024 * 1024) { - * console.log("Large file detected"); - * } - */ - /** - * TODO: figure out how to get the typescript types to not error for this property. - */ - // size: Promise; - - /** - * Creates a new S3File representing a slice of the original file. - * Uses HTTP Range headers for efficient partial downloads. - * - * @param begin - Starting byte offset - * @param end - Ending byte offset (exclusive) - * @param contentType - Optional MIME type for the slice - * @returns A new S3File representing the specified range - * - * @example - * // Reading file header - * const header = file.slice(0, 1024); - * const headerText = await header.text(); - * - * @example - * // Reading with content type - * const jsonSlice = file.slice(1024, 2048, "application/json"); - * const data = await jsonSlice.json(); - * - * @example - * // Reading from offset to end - * const remainder = file.slice(1024); - * const content = await remainder.text(); - */ - slice(begin?: number, end?: number, contentType?: string): S3File; - slice(begin?: number, contentType?: string): S3File; - slice(contentType?: string): S3File; - - /** - * Creates a writable stream for uploading data. - * Suitable for large files as it uses multipart upload. - * - * @param options - Configuration for the upload - * @returns A NetworkSink for writing data - * - * @example - * // Basic streaming write - * const writer = file.writer({ - * type: "application/json" - * }); - * writer.write('{"hello": '); - * writer.write('"world"}'); - * await writer.end(); - * - * @example - * // Optimized large file upload - * const writer = file.writer({ - * partSize: 10 * 1024 * 1024, // 10MB parts - * queueSize: 4, // Upload 4 parts in parallel - * retry: 3 // Retry failed parts - * }); - * - * // Write large chunks of data efficiently - * for (const chunk of largeDataChunks) { - * writer.write(chunk); - * } - * await writer.end(); - * - * @example - * // Error handling - * const writer = file.writer(); - * try { - * writer.write(data); - * await writer.end(); - * } catch (err) { - * console.error('Upload failed:', err); - * // Writer will automatically abort multipart upload on error - * } - */ - writer(options?: S3Options): NetworkSink; - - /** - * Gets a readable stream of the file's content. - * Useful for processing large files without loading them entirely into memory. - * - * @returns A ReadableStream for the file content - * - * @example - * // Basic streaming read - * const stream = file.stream(); - * for await (const chunk of stream) { - * console.log('Received chunk:', chunk); - * } - * - * @example - * // Piping to response - * const stream = file.stream(); - * return new Response(stream, { - * headers: { 'Content-Type': file.type } - * }); - * - * @example - * // Processing large files - * const stream = file.stream(); - * const textDecoder = new TextDecoder(); - * for await (const chunk of stream) { - * const text = textDecoder.decode(chunk); - * // Process text chunk by chunk - * } - */ - readonly readable: ReadableStream; - stream(): ReadableStream; - - /** - * The name or path of the file in the bucket. - * - * @example - * const file = s3("folder/image.jpg"); - * console.log(file.name); // "folder/image.jpg" - */ - readonly name?: string; - - /** - * The bucket name containing the file. - * - * @example - * const file = s3("s3://my-bucket/file.txt"); - * console.log(file.bucket); // "my-bucket" - */ - readonly bucket?: string; - - /** - * Checks if the file exists in S3. - * Uses HTTP HEAD request to efficiently check existence without downloading. - * - * @returns Promise resolving to true if file exists, false otherwise - * - * @example - * // Basic existence check - * if (await file.exists()) { - * console.log("File exists in S3"); - * } - * - * @example - * // With error handling - * try { - * const exists = await file.exists(); - * if (!exists) { - * console.log("File not found"); - * } - * } catch (err) { - * console.error("Error checking file:", err); - * } - */ - exists(): Promise; - - /** - * Uploads data to S3. - * Supports various input types and automatically handles large files. - * - * @param data - The data to upload - * @param options - Upload configuration options - * @returns Promise resolving to number of bytes written - * - * @example - * // Writing string data - * await file.write("Hello World", { - * type: "text/plain" - * }); - * - * @example - * // Writing JSON - * const data = { hello: "world" }; - * await file.write(JSON.stringify(data), { - * type: "application/json" - * }); - * - * @example - * // Writing from Response - * const response = await fetch("https://example.com/data"); - * await file.write(response); - * - * @example - * // Writing with ACL - * await file.write(data, { - * acl: "public-read", - * type: "application/octet-stream" - * }); - */ - write( - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob, - options?: S3Options, - ): Promise; - - /** - * Generates a presigned URL for the file. - * Allows temporary access to the file without exposing credentials. - * - * @param options - Configuration for the presigned URL - * @returns Presigned URL string - * - * @example - * // Basic download URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Upload URL with specific content type - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * @example - * // URL with custom permissions - * const url = file.presign({ - * method: "GET", - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(options?: S3FilePresignOptions): string; - - /** - * Deletes the file from S3. - * - * @returns Promise that resolves when deletion is complete - * - * @example - * // Basic deletion - * await file.delete(); - * - * @example - * // With error handling - * try { - * await file.delete(); - * console.log("File deleted successfully"); - * } catch (err) { - * console.error("Failed to delete file:", err); - * } - */ - delete(): Promise; - - /** - * Alias for delete() method. - * Provided for compatibility with Node.js fs API naming. - * - * @example - * await file.unlink(); - */ - unlink: S3File["delete"]; - - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @returns Promise resolving to S3Stat - */ - stat(): Promise; - } - - /** - * A configured S3 bucket instance for managing files. - * The instance is callable to create S3File instances and provides methods - * for common operations. - * - * @example - * // Basic bucket setup - * const bucket = new S3Client({ - * bucket: "my-bucket", - * accessKeyId: "key", - * secretAccessKey: "secret" - * }); - * - * // Get file instance - * const file = bucket("image.jpg"); - * - * // Common operations - * await bucket.write("data.json", JSON.stringify({hello: "world"})); - * const url = bucket.presign("file.pdf"); - * await bucket.unlink("old.txt"); - */ - class S3Client { - prototype: S3Client; - /** - * Create a new instance of an S3 bucket so that credentials can be managed - * from a single instance instead of being passed to every method. - * - * @param options The default options to use for the S3 client. Can be - * overriden by passing options to the methods. - * - * ## Keep S3 credentials in a single instance - * - * @example - * const bucket = new Bun.S3Client({ - * accessKeyId: "your-access-key", - * secretAccessKey: "your-secret-key", - * bucket: "my-bucket", - * endpoint: "https://s3.us-east-1.amazonaws.com", - * sessionToken: "your-session-token", - * }); - * - * // S3Client is callable, so you can do this: - * const file = bucket.file("my-file.txt"); - * - * // or this: - * await file.write("Hello Bun!"); - * await file.text(); - * - * // To delete the file: - * await bucket.delete("my-file.txt"); - * - * // To write a file without returning the instance: - * await bucket.write("my-file.txt", "Hello Bun!"); - * - */ - constructor(options?: S3Options); - - /** - * Creates an S3File instance for the given path. - * - * @example - * const file = bucket.file("image.jpg"); - * await file.write(imageData); - * const configFile = bucket("config.json", { - * type: "application/json", - * acl: "private" - * }); - */ - file(path: string, options?: S3Options): S3File; - - /** - * Writes data directly to a path in the bucket. - * Supports strings, buffers, streams, and web API types. - * - * @example - * // Write string - * await bucket.write("hello.txt", "Hello World"); - * - * // Write JSON with type - * await bucket.write( - * "data.json", - * JSON.stringify({hello: "world"}), - * {type: "application/json"} - * ); - * - * // Write from fetch - * const res = await fetch("https://example.com/data"); - * await bucket.write("data.bin", res); - * - * // Write with ACL - * await bucket.write("public.html", html, { - * acl: "public-read", - * type: "text/html" - * }); - */ - write( - path: string, - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob - | File, - options?: S3Options, - ): Promise; - - /** - * Generate a presigned URL for temporary access to a file. - * Useful for generating upload/download URLs without exposing credentials. - * - * @example - * // Download URL - * const downloadUrl = bucket.presign("file.pdf", { - * expiresIn: 3600 // 1 hour - * }); - * - * // Upload URL - * const uploadUrl = bucket.presign("uploads/image.jpg", { - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); - * - * // Long-lived public URL - * const publicUrl = bucket.presign("public/doc.pdf", { - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - presign(path: string, options?: S3FilePresignOptions): string; - - /** - * Delete a file from the bucket. - * - * @example - * // Simple delete - * await bucket.unlink("old-file.txt"); - * - * // With error handling - * try { - * await bucket.unlink("file.dat"); - * console.log("File deleted"); - * } catch (err) { - * console.error("Delete failed:", err); - * } - */ - unlink(path: string, options?: S3Options): Promise; - delete: S3Client["unlink"]; - - /** - * Get the size of a file in bytes. - * Uses HEAD request to efficiently get size. - * - * @example - * // Get size - * const bytes = await bucket.size("video.mp4"); - * console.log(`Size: ${bytes} bytes`); - * - * // Check if file is large - * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { - * console.log("File is larger than 100MB"); - * } - */ - size(path: string, options?: S3Options): Promise; - - /** - * Check if a file exists in the bucket. - * Uses HEAD request to check existence. - * - * @example - * // Check existence - * if (await bucket.exists("config.json")) { - * const file = bucket("config.json"); - * const config = await file.json(); - * } - * - * // With error handling - * try { - * if (!await bucket.exists("required.txt")) { - * throw new Error("Required file missing"); - * } - * } catch (err) { - * console.error("Check failed:", err); - * } - */ - exists(path: string, options?: S3Options): Promise; - /** - * Get the stat of a file in an S3-compatible storage service. - * - * @param path The path to the file. - * @param options The options to use for the S3 client. - */ - stat(path: string, options?: S3Options): Promise; - } - - /** - * A default instance of S3Client - * - * Pulls credentials from environment variables. Use `new Bun.S3Client()` if you need to explicitly set credentials. - */ - var s3: S3Client; + /** + * Configuration options for S3 operations + */ + interface S3Options extends BlobPropertyBag { + /** + * The Access Control List (ACL) policy for the file. + * Controls who can access the file and what permissions they have. + * + * @example + * // Setting public read access + * const file = s3("public-file.txt", { + * acl: "public-read", + * bucket: "my-bucket" + * }); + * + * @example + * // Using with presigned URLs + * const url = file.presign({ + * acl: "public-read", + * expiresIn: 3600 + * }); + */ + acl?: + | "private" + | "public-read" + | "public-read-write" + | "aws-exec-read" + | "authenticated-read" + | "bucket-owner-read" + | "bucket-owner-full-control" + | "log-delivery-write"; + + /** + * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. + * + * @example + * // Using explicit bucket + * const file = s3("my-file.txt", { bucket: "my-bucket" }); + * + * @example + * // Using environment variables + * // With S3_BUCKET=my-bucket in .env + * const file = s3("my-file.txt"); + */ + bucket?: string; + + /** + * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. + * + * @example + * const file = s3("my-file.txt", { + * bucket: "my-bucket", + * region: "us-west-2" + * }); + */ + region?: string; + + /** + * The access key ID for authentication. + * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. + */ + accessKeyId?: string; + + /** + * The secret access key for authentication. + * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. + */ + secretAccessKey?: string; + + /** + * Optional session token for temporary credentials. + * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. + * + * @example + * // Using temporary credentials + * const file = s3("my-file.txt", { + * accessKeyId: tempAccessKey, + * secretAccessKey: tempSecretKey, + * sessionToken: tempSessionToken + * }); + */ + sessionToken?: string; + + /** + * The S3-compatible service endpoint URL. + * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. + * + * @example + * // AWS S3 + * const file = s3("my-file.txt", { + * endpoint: "https://s3.us-east-1.amazonaws.com" + * }); + * + * @example + * // Cloudflare R2 + * const file = s3("my-file.txt", { + * endpoint: "https://.r2.cloudflarestorage.com" + * }); + * + * @example + * // DigitalOcean Spaces + * const file = s3("my-file.txt", { + * endpoint: "https://.digitaloceanspaces.com" + * }); + * + * @example + * // MinIO (local development) + * const file = s3("my-file.txt", { + * endpoint: "http://localhost:9000" + * }); + */ + endpoint?: string; + + /** + * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` + * + * @example + * // Using virtual hosted style + * const file = s3("my-file.txt", { + * virtualHostedStyle: true, + * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" + * }); + */ + virtualHostedStyle?: boolean; + + /** + * The size of each part in multipart uploads (in bytes). + * - Minimum: 5 MiB + * - Maximum: 5120 MiB + * - Default: 5 MiB + * + * @example + * // Configuring multipart uploads + * const file = s3("large-file.dat", { + * partSize: 10 * 1024 * 1024, // 10 MiB parts + * queueSize: 4 // Upload 4 parts in parallel + * }); + * + * const writer = file.writer(); + * // ... write large file in chunks + */ + partSize?: number; + + /** + * Number of parts to upload in parallel for multipart uploads. + * - Default: 5 + * - Maximum: 255 + * + * Increasing this value can improve upload speeds for large files + * but will use more memory. + */ + queueSize?: number; + + /** + * Number of retry attempts for failed uploads. + * - Default: 3 + * - Maximum: 255 + * + * @example + * // Setting retry attempts + * const file = s3("my-file.txt", { + * retry: 5 // Retry failed uploads up to 5 times + * }); + */ + retry?: number; + + /** + * The Content-Type of the file. + * Automatically set based on file extension when possible. + * + * @example + * // Setting explicit content type + * const file = s3("data.bin", { + * type: "application/octet-stream" + * }); + */ + type?: string; + + /** + * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. + * + * @example + * // Setting explicit Storage class + * const file = s3("my-file.json", { + * storageClass: "STANDARD_IA" + * }); + */ + storageClass?: + | "STANDARD" + | "DEEP_ARCHIVE" + | "EXPRESS_ONEZONE" + | "GLACIER" + | "GLACIER_IR" + | "INTELLIGENT_TIERING" + | "ONEZONE_IA" + | "OUTPOSTS" + | "REDUCED_REDUNDANCY" + | "SNOW" + | "STANDARD_IA"; + + /** + * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. + */ + highWaterMark?: number; + } + + /** + * Options for generating presigned URLs + */ + interface S3FilePresignOptions extends S3Options { + /** + * Number of seconds until the presigned URL expires. + * - Default: 86400 (1 day) + * + * @example + * // Short-lived URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Long-lived public URL + * const url = file.presign({ + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + expiresIn?: number; + + /** + * The HTTP method allowed for the presigned URL. + * + * @example + * // GET URL for downloads + * const downloadUrl = file.presign({ + * method: "GET", + * expiresIn: 3600 + * }); + * + * @example + * // PUT URL for uploads + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "application/json" + * }); + */ + method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; + } + + interface S3Stats { + size: number; + lastModified: Date; + etag: string; + type: string; + } + + /** + * Represents a file in an S3-compatible storage service. + * Extends the Blob interface for compatibility with web APIs. + */ + interface S3File extends Blob { + /** + * The size of the file in bytes. + * This is a Promise because it requires a network request to determine the size. + * + * @example + * // Getting file size + * const size = await file.size; + * console.log(`File size: ${size} bytes`); + * + * @example + * // Check if file is larger than 1MB + * if (await file.size > 1024 * 1024) { + * console.log("Large file detected"); + * } + */ + /** + * TODO: figure out how to get the typescript types to not error for this property. + */ + // size: Promise; + + /** + * Creates a new S3File representing a slice of the original file. + * Uses HTTP Range headers for efficient partial downloads. + * + * @param begin - Starting byte offset + * @param end - Ending byte offset (exclusive) + * @param contentType - Optional MIME type for the slice + * @returns A new S3File representing the specified range + * + * @example + * // Reading file header + * const header = file.slice(0, 1024); + * const headerText = await header.text(); + * + * @example + * // Reading with content type + * const jsonSlice = file.slice(1024, 2048, "application/json"); + * const data = await jsonSlice.json(); + * + * @example + * // Reading from offset to end + * const remainder = file.slice(1024); + * const content = await remainder.text(); + */ + slice(begin?: number, end?: number, contentType?: string): S3File; + slice(begin?: number, contentType?: string): S3File; + slice(contentType?: string): S3File; + + /** + * Creates a writable stream for uploading data. + * Suitable for large files as it uses multipart upload. + * + * @param options - Configuration for the upload + * @returns A NetworkSink for writing data + * + * @example + * // Basic streaming write + * const writer = file.writer({ + * type: "application/json" + * }); + * writer.write('{"hello": '); + * writer.write('"world"}'); + * await writer.end(); + * + * @example + * // Optimized large file upload + * const writer = file.writer({ + * partSize: 10 * 1024 * 1024, // 10MB parts + * queueSize: 4, // Upload 4 parts in parallel + * retry: 3 // Retry failed parts + * }); + * + * // Write large chunks of data efficiently + * for (const chunk of largeDataChunks) { + * writer.write(chunk); + * } + * await writer.end(); + * + * @example + * // Error handling + * const writer = file.writer(); + * try { + * writer.write(data); + * await writer.end(); + * } catch (err) { + * console.error('Upload failed:', err); + * // Writer will automatically abort multipart upload on error + * } + */ + writer(options?: S3Options): NetworkSink; + + /** + * Gets a readable stream of the file's content. + * Useful for processing large files without loading them entirely into memory. + * + * @returns A ReadableStream for the file content + * + * @example + * // Basic streaming read + * const stream = file.stream(); + * for await (const chunk of stream) { + * console.log('Received chunk:', chunk); + * } + * + * @example + * // Piping to response + * const stream = file.stream(); + * return new Response(stream, { + * headers: { 'Content-Type': file.type } + * }); + * + * @example + * // Processing large files + * const stream = file.stream(); + * const textDecoder = new TextDecoder(); + * for await (const chunk of stream) { + * const text = textDecoder.decode(chunk); + * // Process text chunk by chunk + * } + */ + readonly readable: ReadableStream; + stream(): ReadableStream; + + /** + * The name or path of the file in the bucket. + * + * @example + * const file = s3("folder/image.jpg"); + * console.log(file.name); // "folder/image.jpg" + */ + readonly name?: string; + + /** + * The bucket name containing the file. + * + * @example + * const file = s3("s3://my-bucket/file.txt"); + * console.log(file.bucket); // "my-bucket" + */ + readonly bucket?: string; + + /** + * Checks if the file exists in S3. + * Uses HTTP HEAD request to efficiently check existence without downloading. + * + * @returns Promise resolving to true if file exists, false otherwise + * + * @example + * // Basic existence check + * if (await file.exists()) { + * console.log("File exists in S3"); + * } + * + * @example + * // With error handling + * try { + * const exists = await file.exists(); + * if (!exists) { + * console.log("File not found"); + * } + * } catch (err) { + * console.error("Error checking file:", err); + * } + */ + exists(): Promise; + + /** + * Uploads data to S3. + * Supports various input types and automatically handles large files. + * + * @param data - The data to upload + * @param options - Upload configuration options + * @returns Promise resolving to number of bytes written + * + * @example + * // Writing string data + * await file.write("Hello World", { + * type: "text/plain" + * }); + * + * @example + * // Writing JSON + * const data = { hello: "world" }; + * await file.write(JSON.stringify(data), { + * type: "application/json" + * }); + * + * @example + * // Writing from Response + * const response = await fetch("https://example.com/data"); + * await file.write(response); + * + * @example + * // Writing with ACL + * await file.write(data, { + * acl: "public-read", + * type: "application/octet-stream" + * }); + */ + write( + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | Request | Response | BunFile | S3File | Blob, + options?: S3Options, + ): Promise; + + /** + * Generates a presigned URL for the file. + * Allows temporary access to the file without exposing credentials. + * + * @param options - Configuration for the presigned URL + * @returns Presigned URL string + * + * @example + * // Basic download URL + * const url = file.presign({ + * expiresIn: 3600 // 1 hour + * }); + * + * @example + * // Upload URL with specific content type + * const uploadUrl = file.presign({ + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * @example + * // URL with custom permissions + * const url = file.presign({ + * method: "GET", + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(options?: S3FilePresignOptions): string; + + /** + * Deletes the file from S3. + * + * @returns Promise that resolves when deletion is complete + * + * @example + * // Basic deletion + * await file.delete(); + * + * @example + * // With error handling + * try { + * await file.delete(); + * console.log("File deleted successfully"); + * } catch (err) { + * console.error("Failed to delete file:", err); + * } + */ + delete(): Promise; + + /** + * Alias for delete() method. + * Provided for compatibility with Node.js fs API naming. + * + * @example + * await file.unlink(); + */ + unlink: S3File["delete"]; + + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @returns Promise resolving to S3Stat + */ + stat(): Promise; + } + + /** + * A configured S3 bucket instance for managing files. + * The instance is callable to create S3File instances and provides methods + * for common operations. + * + * @example + * // Basic bucket setup + * const bucket = new S3Client({ + * bucket: "my-bucket", + * accessKeyId: "key", + * secretAccessKey: "secret" + * }); + * + * // Get file instance + * const file = bucket("image.jpg"); + * + * // Common operations + * await bucket.write("data.json", JSON.stringify({hello: "world"})); + * const url = bucket.presign("file.pdf"); + * await bucket.unlink("old.txt"); + */ + class S3Client { + prototype: S3Client; + /** + * Create a new instance of an S3 bucket so that credentials can be managed + * from a single instance instead of being passed to every method. + * + * @param options The default options to use for the S3 client. Can be + * overriden by passing options to the methods. + * + * ## Keep S3 credentials in a single instance + * + * @example + * const bucket = new Bun.S3Client({ + * accessKeyId: "your-access-key", + * secretAccessKey: "your-secret-key", + * bucket: "my-bucket", + * endpoint: "https://s3.us-east-1.amazonaws.com", + * sessionToken: "your-session-token", + * }); + * + * // S3Client is callable, so you can do this: + * const file = bucket.file("my-file.txt"); + * + * // or this: + * await file.write("Hello Bun!"); + * await file.text(); + * + * // To delete the file: + * await bucket.delete("my-file.txt"); + * + * // To write a file without returning the instance: + * await bucket.write("my-file.txt", "Hello Bun!"); + * + */ + constructor(options?: S3Options); + + /** + * Creates an S3File instance for the given path. + * + * @example + * const file = bucket.file("image.jpg"); + * await file.write(imageData); + * const configFile = bucket("config.json", { + * type: "application/json", + * acl: "private" + * }); + */ + file(path: string, options?: S3Options): S3File; + + /** + * Writes data directly to a path in the bucket. + * Supports strings, buffers, streams, and web API types. + * + * @example + * // Write string + * await bucket.write("hello.txt", "Hello World"); + * + * // Write JSON with type + * await bucket.write( + * "data.json", + * JSON.stringify({hello: "world"}), + * {type: "application/json"} + * ); + * + * // Write from fetch + * const res = await fetch("https://example.com/data"); + * await bucket.write("data.bin", res); + * + * // Write with ACL + * await bucket.write("public.html", html, { + * acl: "public-read", + * type: "text/html" + * }); + */ + write( + path: string, + data: + | string + | ArrayBufferView + | ArrayBuffer + | SharedArrayBuffer + | Request + | Response + | BunFile + | S3File + | Blob + | File, + options?: S3Options, + ): Promise; + + /** + * Generate a presigned URL for temporary access to a file. + * Useful for generating upload/download URLs without exposing credentials. + * + * @example + * // Download URL + * const downloadUrl = bucket.presign("file.pdf", { + * expiresIn: 3600 // 1 hour + * }); + * + * // Upload URL + * const uploadUrl = bucket.presign("uploads/image.jpg", { + * method: "PUT", + * expiresIn: 3600, + * type: "image/jpeg", + * acl: "public-read" + * }); + * + * // Long-lived public URL + * const publicUrl = bucket.presign("public/doc.pdf", { + * expiresIn: 7 * 24 * 60 * 60, // 7 days + * acl: "public-read" + * }); + */ + presign(path: string, options?: S3FilePresignOptions): string; + + /** + * Delete a file from the bucket. + * + * @example + * // Simple delete + * await bucket.unlink("old-file.txt"); + * + * // With error handling + * try { + * await bucket.unlink("file.dat"); + * console.log("File deleted"); + * } catch (err) { + * console.error("Delete failed:", err); + * } + */ + unlink(path: string, options?: S3Options): Promise; + delete: S3Client["unlink"]; + + /** + * Get the size of a file in bytes. + * Uses HEAD request to efficiently get size. + * + * @example + * // Get size + * const bytes = await bucket.size("video.mp4"); + * console.log(`Size: ${bytes} bytes`); + * + * // Check if file is large + * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { + * console.log("File is larger than 100MB"); + * } + */ + size(path: string, options?: S3Options): Promise; + + /** + * Check if a file exists in the bucket. + * Uses HEAD request to check existence. + * + * @example + * // Check existence + * if (await bucket.exists("config.json")) { + * const file = bucket("config.json"); + * const config = await file.json(); + * } + * + * // With error handling + * try { + * if (!await bucket.exists("required.txt")) { + * throw new Error("Required file missing"); + * } + * } catch (err) { + * console.error("Check failed:", err); + * } + */ + exists(path: string, options?: S3Options): Promise; + /** + * Get the stat of a file in an S3-compatible storage service. + * + * @param path The path to the file. + * @param options The options to use for the S3 client. + */ + stat(path: string, options?: S3Options): Promise; + } + + /** + * A default instance of S3Client + * + * Pulls credentials from environment variables. Use `new Bun.S3Client()` if you need to explicitly set credentials. + */ + var s3: S3Client; } diff --git a/packages/bun-types/new/sink.d.ts b/packages/bun-types/new/sink.d.ts index d4557529193c5c..e0ace23621c53e 100644 --- a/packages/bun-types/new/sink.d.ts +++ b/packages/bun-types/new/sink.d.ts @@ -1,86 +1,82 @@ declare module "bun" { - /** - * 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; - /** - * Close the file descriptor. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; + /** + * 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; + /** + * Close the file descriptor. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; - start(options?: { - /** - * Preallocate an internal buffer of this size - * This can significantly improve performance when the chunk size is small - */ - highWaterMark?: number; - }): void; + 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. + * + * 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; - } + /** + * 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 NetworkSink extends FileSink { - /** - * Write a chunk of data to the network. - * - * If the network is not writable yet, the data is buffered. - */ - write( - chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - ): number; - /** - * Flush the internal buffer, committing the data to the network. - */ - flush(): number | Promise; - /** - * Finish the upload. This also flushes the internal buffer. - */ - end(error?: Error): number | Promise; + interface NetworkSink extends FileSink { + /** + * Write a chunk of data to the network. + * + * If the network is not writable yet, the data is buffered. + */ + write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number; + /** + * Flush the internal buffer, committing the data to the network. + */ + flush(): number | Promise; + /** + * Finish the upload. This also flushes the internal buffer. + */ + end(error?: Error): number | Promise; - /** - * Get the stat of the file. - */ - stat(): Promise; - } + /** + * Get the stat of the file. + */ + stat(): Promise; + } } diff --git a/packages/bun-types/new/sqlite.d.ts b/packages/bun-types/new/sqlite.d.ts index 303469772cb98c..dd370d3f46bcc2 100644 --- a/packages/bun-types/new/sqlite.d.ts +++ b/packages/bun-types/new/sqlite.d.ts @@ -24,1143 +24,1118 @@ * | `null` | `NULL` | */ declare module "bun:sqlite" { - export class Database implements Disposable { - /** - * Open or create a SQLite3 database - * - * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. - * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. - * - * @example - * - * ```ts - * const db = new Database("mydb.sqlite"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open an in-memory database - * - * ```ts - * const db = new Database(":memory:"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open read-only - * - * ```ts - * const db = new Database("mydb.sqlite", {readonly: true}); - * ``` - */ - constructor( - filename?: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; + export class Database implements Disposable { + /** + * Open or create a SQLite3 database + * + * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. + * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. + * + * @example + * + * ```ts + * const db = new Database("mydb.sqlite"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open an in-memory database + * + * ```ts + * const db = new Database(":memory:"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open read-only + * + * ```ts + * const db = new Database("mydb.sqlite", {readonly: true}); + * ``` + */ + constructor( + filename?: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; - /** - * When set to `true`, integers are returned as `bigint` types. - * - * When set to `false`, integers are returned as `number` types and truncated to 52 bits. - * - * @default false - * @since v1.1.14 - */ - safeIntegers?: boolean; + /** + * When set to `true`, integers are returned as `bigint` types. + * + * When set to `false`, integers are returned as `number` types and truncated to 52 bits. + * + * @default false + * @since v1.1.14 + */ + safeIntegers?: boolean; - /** - * When set to `false` or `undefined`: - * - Queries missing bound parameters will NOT throw an error - * - Bound named parameters in JavaScript need to exactly match the SQL query. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: false }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); - * ``` - * - * When set to `true`: - * - Queries missing bound parameters will throw an error - * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: true }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); - * ``` - * @since v1.1.14 - */ - strict?: boolean; - }, - ); + /** + * When set to `false` or `undefined`: + * - Queries missing bound parameters will NOT throw an error + * - Bound named parameters in JavaScript need to exactly match the SQL query. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: false }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); + * ``` + * + * When set to `true`: + * - Queries missing bound parameters will throw an error + * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: true }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); + * ``` + * @since v1.1.14 + */ + strict?: boolean; + }, + ); - /** - * This is an alias of `new Database()` - * - * See {@link Database} - */ - static open( - filename: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; - }, - ): Database; + /** + * This is an alias of `new Database()` + * + * See {@link Database} + */ + static open( + filename: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; + }, + ): Database; - /** - * Execute a SQL query **without returning any results**. - * - * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * ``` - * - * Useful for queries like: - * - `CREATE TABLE` - * - `INSERT INTO` - * - `UPDATE` - * - `DELETE FROM` - * - `DROP TABLE` - * - `PRAGMA` - * - `ATTACH DATABASE` - * - `DETACH DATABASE` - * - `REINDEX` - * - `VACUUM` - * - `EXPLAIN ANALYZE` - * - `CREATE INDEX` - * - `CREATE TRIGGER` - * - `CREATE VIEW` - * - `CREATE VIRTUAL TABLE` - * - `CREATE TEMPORARY TABLE` - * - * @param sql The SQL query to run - * - * @param bindings Optional bindings for the query - * - * @returns `Database` instance - * - * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. - * - * * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run( - sqlQuery: string, - ...bindings: ParamsType[] - ): Changes; - /** + /** + * Execute a SQL query **without returning any results**. + * + * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * ``` + * + * Useful for queries like: + * - `CREATE TABLE` + * - `INSERT INTO` + * - `UPDATE` + * - `DELETE FROM` + * - `DROP TABLE` + * - `PRAGMA` + * - `ATTACH DATABASE` + * - `DETACH DATABASE` + * - `REINDEX` + * - `VACUUM` + * - `EXPLAIN ANALYZE` + * - `CREATE INDEX` + * - `CREATE TRIGGER` + * - `CREATE VIEW` + * - `CREATE VIRTUAL TABLE` + * - `CREATE TEMPORARY TABLE` + * + * @param sql The SQL query to run + * + * @param bindings Optional bindings for the query + * + * @returns `Database` instance + * + * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. + * + * * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(sqlQuery: string, ...bindings: ParamsType[]): Changes; + /** This is an alias of {@link Database.prototype.run} */ - exec( - sqlQuery: string, - ...bindings: ParamsType[] - ): Changes; + exec(sqlQuery: string, ...bindings: ParamsType[]): Changes; - /** - * Compile a SQL query and return a {@link Statement} object. This is the - * same as {@link prepare} except that it caches the compiled query. - * - * This **does not execute** the query, but instead prepares it for later - * execution and caches the compiled query if possible. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * - * // run the query again - * stmt.all(); - * ``` - * - * @param sql The SQL query to compile - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - query( - sqlQuery: string, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. This is the + * same as {@link prepare} except that it caches the compiled query. + * + * This **does not execute** the query, but instead prepares it for later + * execution and caches the compiled query if possible. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * + * // run the query again + * stmt.all(); + * ``` + * + * @param sql The SQL query to compile + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + query( + sqlQuery: string, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Compile a SQL query and return a {@link Statement} object. - * - * This does not cache the compiled query and does not execute the query. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * ``` - * - * @param sql The SQL query to compile - * @param params Optional bindings for the query - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - prepare< - ReturnType, - ParamsType extends SQLQueryBindings | SQLQueryBindings[], - >( - sqlQuery: string, - params?: ParamsType, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. + * + * This does not cache the compiled query and does not execute the query. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * ``` + * + * @param sql The SQL query to compile + * @param params Optional bindings for the query + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + prepare( + sqlQuery: string, + params?: ParamsType, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Is the database in a transaction? - * - * @returns `true` if the database is in a transaction, `false` otherwise - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * db.run("BEGIN"); - * db.run("INSERT INTO foo VALUES (?)", ["qux"]); - * console.log(db.inTransaction()); - * ``` - */ - get inTransaction(): boolean; + /** + * Is the database in a transaction? + * + * @returns `true` if the database is in a transaction, `false` otherwise + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * db.run("BEGIN"); + * db.run("INSERT INTO foo VALUES (?)", ["qux"]); + * console.log(db.inTransaction()); + * ``` + */ + get inTransaction(): boolean; - /** - * Close the database connection. - * - * It is safe to call this method multiple times. If the database is already - * closed, this is a no-op. Running queries after the database has been - * closed will throw an error. - * - * @example - * ```ts - * db.close(); - * ``` - * This is called automatically when the database instance is garbage collected. - * - * Internally, this calls `sqlite3_close_v2`. - */ - close( - /** - * If `true`, then the database will throw an error if it is in use - * @default false - * - * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. - * - * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). - * - * Bun will automatically call close by default when the database instance is garbage collected. - * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. - */ - throwOnError?: boolean, - ): void; + /** + * Close the database connection. + * + * It is safe to call this method multiple times. If the database is already + * closed, this is a no-op. Running queries after the database has been + * closed will throw an error. + * + * @example + * ```ts + * db.close(); + * ``` + * This is called automatically when the database instance is garbage collected. + * + * Internally, this calls `sqlite3_close_v2`. + */ + close( + /** + * If `true`, then the database will throw an error if it is in use + * @default false + * + * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. + * + * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). + * + * Bun will automatically call close by default when the database instance is garbage collected. + * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. + */ + throwOnError?: boolean, + ): void; - /** - * The filename passed when `new Database()` was called - * @example - * ```ts - * const db = new Database("mydb.sqlite"); - * console.log(db.filename); - * // => "mydb.sqlite" - * ``` - */ - readonly filename: string; + /** + * The filename passed when `new Database()` was called + * @example + * ```ts + * const db = new Database("mydb.sqlite"); + * console.log(db.filename); + * // => "mydb.sqlite" + * ``` + */ + readonly filename: string; - /** - * The underlying `sqlite3` database handle - * - * In native code, this is not a file descriptor, but an index into an array of database handles - */ - readonly handle: number; + /** + * The underlying `sqlite3` database handle + * + * In native code, this is not a file descriptor, but an index into an array of database handles + */ + readonly handle: number; - /** - * Load a SQLite3 extension - * - * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} - * - * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. - * - * @param extension name/path of the extension to load - * @param entryPoint optional entry point of the extension - */ - loadExtension(extension: string, entryPoint?: string): void; + /** + * Load a SQLite3 extension + * + * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} + * + * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. + * + * @param extension name/path of the extension to load + * @param entryPoint optional entry point of the extension + */ + loadExtension(extension: string, entryPoint?: string): void; - /** - * Change the dynamic library path to SQLite - * - * @note macOS-only - * - * This only works before SQLite is loaded, so - * that's before you call `new Database()`. - * - * It can only be run once because this will load - * the SQLite library into the process. - * - * @param path The path to the SQLite library - */ - static setCustomSQLite(path: string): boolean; + /** + * Change the dynamic library path to SQLite + * + * @note macOS-only + * + * This only works before SQLite is loaded, so + * that's before you call `new Database()`. + * + * It can only be run once because this will load + * the SQLite library into the process. + * + * @param path The path to the SQLite library + */ + static setCustomSQLite(path: string): boolean; - [Symbol.dispose](): void; + [Symbol.dispose](): void; - /** - * Creates a function that always runs inside a transaction. When the - * function is invoked, it will begin a new transaction. When the function - * returns, the transaction will be committed. If an exception is thrown, - * the transaction will be rolled back (and the exception will propagate as - * usual). - * - * @param insideTransaction The callback which runs inside a transaction - * - * @example - * ```ts - * // setup - * import { Database } from "bun:sqlite"; - * const db = Database.open(":memory:"); - * db.exec( - * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" - * ); - * - * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); - * const insertMany = db.transaction((cats) => { - * for (const cat of cats) insert.run(cat); - * }); - * - * insertMany([ - * { $name: "Joey", $age: 2 }, - * { $name: "Sally", $age: 4 }, - * { $name: "Junior", $age: 1 }, - * ]); - * ``` - */ - transaction(insideTransaction: (...args: any) => void): CallableFunction & { - /** - * uses "BEGIN DEFERRED" - */ - deferred: (...args: any) => void; - /** - * uses "BEGIN IMMEDIATE" - */ - immediate: (...args: any) => void; - /** - * uses "BEGIN EXCLUSIVE" - */ - exclusive: (...args: any) => void; - }; + /** + * Creates a function that always runs inside a transaction. When the + * function is invoked, it will begin a new transaction. When the function + * returns, the transaction will be committed. If an exception is thrown, + * the transaction will be rolled back (and the exception will propagate as + * usual). + * + * @param insideTransaction The callback which runs inside a transaction + * + * @example + * ```ts + * // setup + * import { Database } from "bun:sqlite"; + * const db = Database.open(":memory:"); + * db.exec( + * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" + * ); + * + * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); + * const insertMany = db.transaction((cats) => { + * for (const cat of cats) insert.run(cat); + * }); + * + * insertMany([ + * { $name: "Joey", $age: 2 }, + * { $name: "Sally", $age: 4 }, + * { $name: "Junior", $age: 1 }, + * ]); + * ``` + */ + transaction(insideTransaction: (...args: any) => void): CallableFunction & { + /** + * uses "BEGIN DEFERRED" + */ + deferred: (...args: any) => void; + /** + * uses "BEGIN IMMEDIATE" + */ + immediate: (...args: any) => void; + /** + * uses "BEGIN EXCLUSIVE" + */ + exclusive: (...args: any) => void; + }; - /** - * Save the database to an in-memory {@link Buffer} object. - * - * Internally, this calls `sqlite3_serialize`. - * - * @param name Name to save the database as @default "main" - * @returns Buffer containing the serialized database - */ - serialize(name?: string): Buffer; + /** + * Save the database to an in-memory {@link Buffer} object. + * + * Internally, this calls `sqlite3_serialize`. + * + * @param name Name to save the database as @default "main" + * @returns Buffer containing the serialized database + */ + serialize(name?: string): Buffer; - /** - * Load a serialized SQLite3 database - * - * Internally, this calls `sqlite3_deserialize`. - * - * @param serialized Data to load - * @returns `Database` instance - * - * @example - * ```ts - * test("supports serialize/deserialize", () => { - * const db = Database.open(":memory:"); - * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); - * db.exec('INSERT INTO test (name) VALUES ("Hello")'); - * db.exec('INSERT INTO test (name) VALUES ("World")'); - * - * const input = db.serialize(); - * const db2 = new Database(input); - * - * const stmt = db2.prepare("SELECT * FROM test"); - * expect(JSON.stringify(stmt.get())).toBe( - * JSON.stringify({ - * id: 1, - * name: "Hello", - * }), - * ); - * - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * ]), - * ); - * db2.exec("insert into test (name) values ('foo')"); - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * { - * id: 3, - * name: "foo", - * }, - * ]), - * ); - * - * const db3 = Database.deserialize(input, true); - * try { - * db3.exec("insert into test (name) values ('foo')"); - * throw new Error("Expected error"); - * } catch (e) { - * expect(e.message).toBe("attempt to write a readonly database"); - * } - * }); - * ``` - */ - static deserialize( - serialized: NodeJS.TypedArray | ArrayBufferLike, - isReadOnly?: boolean, - ): Database; + /** + * Load a serialized SQLite3 database + * + * Internally, this calls `sqlite3_deserialize`. + * + * @param serialized Data to load + * @returns `Database` instance + * + * @example + * ```ts + * test("supports serialize/deserialize", () => { + * const db = Database.open(":memory:"); + * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); + * db.exec('INSERT INTO test (name) VALUES ("Hello")'); + * db.exec('INSERT INTO test (name) VALUES ("World")'); + * + * const input = db.serialize(); + * const db2 = new Database(input); + * + * const stmt = db2.prepare("SELECT * FROM test"); + * expect(JSON.stringify(stmt.get())).toBe( + * JSON.stringify({ + * id: 1, + * name: "Hello", + * }), + * ); + * + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * ]), + * ); + * db2.exec("insert into test (name) values ('foo')"); + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * { + * id: 3, + * name: "foo", + * }, + * ]), + * ); + * + * const db3 = Database.deserialize(input, true); + * try { + * db3.exec("insert into test (name) values ('foo')"); + * throw new Error("Expected error"); + * } catch (e) { + * expect(e.message).toBe("attempt to write a readonly database"); + * } + * }); + * ``` + */ + static deserialize(serialized: NodeJS.TypedArray | ArrayBufferLike, isReadOnly?: boolean): Database; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(op: number, arg?: ArrayBufferView | number): number; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl( - zDbName: string, - op: number, - arg?: ArrayBufferView | number, - ): number; - } + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(op: number, arg?: ArrayBufferView | number): number; + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(zDbName: string, op: number, arg?: ArrayBufferView | number): number; + } - /** - * A prepared statement. - * - * This is returned by {@link Database.prepare} and {@link Database.query}. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.all("baz"); - * // => [{bar: "baz"}] - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.get("baz"); - * // => {bar: "baz"} - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.run("baz"); - * // => undefined - * ``` - */ - export class Statement< - ReturnType = unknown, - ParamsType extends SQLQueryBindings[] = any[], - > implements Disposable - { - /** - * Creates a new prepared statement from native code. - * - * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. - */ - constructor(nativeHandle: any); + /** + * A prepared statement. + * + * This is returned by {@link Database.prepare} and {@link Database.query}. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.all("baz"); + * // => [{bar: "baz"}] + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.get("baz"); + * // => {bar: "baz"} + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.run("baz"); + * // => undefined + * ``` + */ + export class Statement implements Disposable { + /** + * Creates a new prepared statement from native code. + * + * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. + */ + constructor(nativeHandle: any); - /** - * Execute the prepared statement and return all results as objects. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.all("baz"); - * // => [{bar: "baz"}] - * - * stmt.all(); - * // => [] - * - * stmt.all("foo"); - * // => [{bar: "foo"}] - * ``` - */ - all(...params: ParamsType): ReturnType[]; + /** + * Execute the prepared statement and return all results as objects. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.all("baz"); + * // => [{bar: "baz"}] + * + * stmt.all(); + * // => [] + * + * stmt.all("foo"); + * // => [{bar: "foo"}] + * ``` + */ + all(...params: ParamsType): ReturnType[]; - /** - * Execute the prepared statement and return **the first** result. - * - * If no result is returned, this returns `null`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.get("baz"); - * // => {bar: "baz"} - * - * stmt.get(); - * // => null - * - * stmt.get("foo"); - * // => {bar: "foo"} - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - get(...params: ParamsType): ReturnType | null; + /** + * Execute the prepared statement and return **the first** result. + * + * If no result is returned, this returns `null`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.get("baz"); + * // => {bar: "baz"} + * + * stmt.get(); + * // => null + * + * stmt.get("foo"); + * // => {bar: "foo"} + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + get(...params: ParamsType): ReturnType | null; - /** - * Execute the prepared statement and return an - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - */ - iterate(...params: ParamsType): IterableIterator; - [Symbol.iterator](): IterableIterator; + /** + * Execute the prepared statement and return an + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + */ + iterate(...params: ParamsType): IterableIterator; + [Symbol.iterator](): IterableIterator; - /** - * Execute the prepared statement. This returns `undefined`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("UPDATE foo SET bar = ?"); - * stmt.run("baz"); - * // => undefined - * - * stmt.run(); - * // => undefined - * - * stmt.run("foo"); - * // => undefined - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(...params: ParamsType): Changes; + /** + * Execute the prepared statement. This returns `undefined`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("UPDATE foo SET bar = ?"); + * stmt.run("baz"); + * // => undefined + * + * stmt.run(); + * // => undefined + * + * stmt.run("foo"); + * // => undefined + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(...params: ParamsType): Changes; - /** - * Execute the prepared statement and return the results as an array of arrays. - * - * In Bun v0.6.7 and earlier, this method returned `null` if there were no - * results instead of `[]`. This was changed in v0.6.8 to align - * more with what people expect. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.values("baz"); - * // => [['baz']] - * - * stmt.values(); - * // => [['baz']] - * - * stmt.values("foo"); - * // => [['foo']] - * - * stmt.values("not-found"); - * // => [] - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | ---------------|-------------| - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - values( - ...params: ParamsType - ): Array>; + /** + * Execute the prepared statement and return the results as an array of arrays. + * + * In Bun v0.6.7 and earlier, this method returned `null` if there were no + * results instead of `[]`. This was changed in v0.6.8 to align + * more with what people expect. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.values("baz"); + * // => [['baz']] + * + * stmt.values(); + * // => [['baz']] + * + * stmt.values("foo"); + * // => [['foo']] + * + * stmt.values("not-found"); + * // => [] + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | ---------------|-------------| + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + values(...params: ParamsType): Array>; - /** - * The names of the columns returned by the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); - * - * console.log(stmt.columnNames); - * // => ["bar"] - * ``` - */ - readonly columnNames: string[]; + /** + * The names of the columns returned by the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); + * + * console.log(stmt.columnNames); + * // => ["bar"] + * ``` + */ + readonly columnNames: string[]; - /** - * The number of parameters expected in the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * console.log(stmt.paramsCount); - * // => 1 - * ``` - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); - * console.log(stmt.paramsCount); - * // => 2 - * ``` - */ - readonly paramsCount: number; + /** + * The number of parameters expected in the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * console.log(stmt.paramsCount); + * // => 1 + * ``` + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); + * console.log(stmt.paramsCount); + * // => 2 + * ``` + */ + readonly paramsCount: number; - /** - * Finalize the prepared statement, freeing the resources used by the - * statement and preventing it from being executed again. - * - * This is called automatically when the prepared statement is garbage collected. - * - * It is safe to call this multiple times. Calling this on a finalized - * statement has no effect. - * - * Internally, this calls `sqlite3_finalize`. - */ - finalize(): void; + /** + * Finalize the prepared statement, freeing the resources used by the + * statement and preventing it from being executed again. + * + * This is called automatically when the prepared statement is garbage collected. + * + * It is safe to call this multiple times. Calling this on a finalized + * statement has no effect. + * + * Internally, this calls `sqlite3_finalize`. + */ + finalize(): void; - /** - * Calls {@link finalize} if it wasn't already called. - */ - [Symbol.dispose](): void; + /** + * Calls {@link finalize} if it wasn't already called. + */ + [Symbol.dispose](): void; - /** - * Return the expanded SQL string for the prepared statement. - * - * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); - * console.log(stmt.toString()); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * console.log(stmt); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * ``` - */ - toString(): string; + /** + * Return the expanded SQL string for the prepared statement. + * + * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); + * console.log(stmt.toString()); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * console.log(stmt); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * ``` + */ + toString(): string; - /** - * - * Make {@link get} and {@link all} return an instance of the provided - * `Class` instead of the default `Object`. - * - * @param Class A class to use - * @returns The same statement instance, modified to return an instance of `Class` - * - * This lets you attach methods, getters, and setters to the returned - * objects. - * - * For performance reasons, constructors for classes are not called, which means - * initializers will not be called and private fields will not be - * accessible. - * - * @example - * - * ## Custom class - * ```ts - * class User { - * rawBirthdate: string; - * get birthdate() { - * return new Date(this.rawBirthdate); - * } - * } - * - * const db = new Database(":memory:"); - * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); - * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); - * const query = db.query("SELECT * FROM users"); - * query.as(User); - * const user = query.get(); - * console.log(user.birthdate); - * // => Date(1995, 12, 19) - * ``` - */ - as(Class: new (...args: any[]) => T): Statement; + /** + * + * Make {@link get} and {@link all} return an instance of the provided + * `Class` instead of the default `Object`. + * + * @param Class A class to use + * @returns The same statement instance, modified to return an instance of `Class` + * + * This lets you attach methods, getters, and setters to the returned + * objects. + * + * For performance reasons, constructors for classes are not called, which means + * initializers will not be called and private fields will not be + * accessible. + * + * @example + * + * ## Custom class + * ```ts + * class User { + * rawBirthdate: string; + * get birthdate() { + * return new Date(this.rawBirthdate); + * } + * } + * + * const db = new Database(":memory:"); + * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); + * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); + * const query = db.query("SELECT * FROM users"); + * query.as(User); + * const user = query.get(); + * console.log(user.birthdate); + * // => Date(1995, 12, 19) + * ``` + */ + as(Class: new (...args: any[]) => T): Statement; - /** - * Native object representing the underlying `sqlite3_stmt` - * - * This is left untyped because the ABI of the native bindings may change at any time. - */ - readonly native: any; - } + /** + * Native object representing the underlying `sqlite3_stmt` + * + * This is left untyped because the ABI of the native bindings may change at any time. + */ + readonly native: any; + } - /** - * Constants from `sqlite3.h` - * - * This list isn't exhaustive, but some of the ones which are relevant - */ - export const constants: { - /** - * Open the database as read-only (no write operations, no create). - * @constant 0x00000001 - */ - SQLITE_OPEN_READONLY: number; - /** - * Open the database for reading and writing - * @constant 0x00000002 - */ - SQLITE_OPEN_READWRITE: number; - /** - * Allow creating a new database - * @constant 0x00000004 - */ - SQLITE_OPEN_CREATE: number; - /** - * @constant 0x00000008 - */ - SQLITE_OPEN_DELETEONCLOSE: number; - /** - * @constant 0x00000010 - */ - SQLITE_OPEN_EXCLUSIVE: number; - /** - * @constant 0x00000020 - */ - SQLITE_OPEN_AUTOPROXY: number; - /** - * @constant 0x00000040 - */ - SQLITE_OPEN_URI: number; - /** - * @constant 0x00000080 - */ - SQLITE_OPEN_MEMORY: number; - /** - * @constant 0x00000100 - */ - SQLITE_OPEN_MAIN_DB: number; - /** - * @constant 0x00000200 - */ - SQLITE_OPEN_TEMP_DB: number; - /** - * @constant 0x00000400 - */ - SQLITE_OPEN_TRANSIENT_DB: number; - /** - * @constant 0x00000800 - */ - SQLITE_OPEN_MAIN_JOURNAL: number; - /** - * @constant 0x00001000 - */ - SQLITE_OPEN_TEMP_JOURNAL: number; - /** - * @constant 0x00002000 - */ - SQLITE_OPEN_SUBJOURNAL: number; - /** - * @constant 0x00004000 - */ - SQLITE_OPEN_SUPER_JOURNAL: number; - /** - * @constant 0x00008000 - */ - SQLITE_OPEN_NOMUTEX: number; - /** - * @constant 0x00010000 - */ - SQLITE_OPEN_FULLMUTEX: number; - /** - * @constant 0x00020000 - */ - SQLITE_OPEN_SHAREDCACHE: number; - /** - * @constant 0x00040000 - */ - SQLITE_OPEN_PRIVATECACHE: number; - /** - * @constant 0x00080000 - */ - SQLITE_OPEN_WAL: number; - /** - * @constant 0x01000000 - */ - SQLITE_OPEN_NOFOLLOW: number; - /** - * @constant 0x02000000 - */ - SQLITE_OPEN_EXRESCODE: number; - /** - * @constant 0x01 - */ - SQLITE_PREPARE_PERSISTENT: number; - /** - * @constant 0x02 - */ - SQLITE_PREPARE_NORMALIZE: number; - /** - * @constant 0x04 - */ - SQLITE_PREPARE_NO_VTAB: number; + /** + * Constants from `sqlite3.h` + * + * This list isn't exhaustive, but some of the ones which are relevant + */ + export const constants: { + /** + * Open the database as read-only (no write operations, no create). + * @constant 0x00000001 + */ + SQLITE_OPEN_READONLY: number; + /** + * Open the database for reading and writing + * @constant 0x00000002 + */ + SQLITE_OPEN_READWRITE: number; + /** + * Allow creating a new database + * @constant 0x00000004 + */ + SQLITE_OPEN_CREATE: number; + /** + * @constant 0x00000008 + */ + SQLITE_OPEN_DELETEONCLOSE: number; + /** + * @constant 0x00000010 + */ + SQLITE_OPEN_EXCLUSIVE: number; + /** + * @constant 0x00000020 + */ + SQLITE_OPEN_AUTOPROXY: number; + /** + * @constant 0x00000040 + */ + SQLITE_OPEN_URI: number; + /** + * @constant 0x00000080 + */ + SQLITE_OPEN_MEMORY: number; + /** + * @constant 0x00000100 + */ + SQLITE_OPEN_MAIN_DB: number; + /** + * @constant 0x00000200 + */ + SQLITE_OPEN_TEMP_DB: number; + /** + * @constant 0x00000400 + */ + SQLITE_OPEN_TRANSIENT_DB: number; + /** + * @constant 0x00000800 + */ + SQLITE_OPEN_MAIN_JOURNAL: number; + /** + * @constant 0x00001000 + */ + SQLITE_OPEN_TEMP_JOURNAL: number; + /** + * @constant 0x00002000 + */ + SQLITE_OPEN_SUBJOURNAL: number; + /** + * @constant 0x00004000 + */ + SQLITE_OPEN_SUPER_JOURNAL: number; + /** + * @constant 0x00008000 + */ + SQLITE_OPEN_NOMUTEX: number; + /** + * @constant 0x00010000 + */ + SQLITE_OPEN_FULLMUTEX: number; + /** + * @constant 0x00020000 + */ + SQLITE_OPEN_SHAREDCACHE: number; + /** + * @constant 0x00040000 + */ + SQLITE_OPEN_PRIVATECACHE: number; + /** + * @constant 0x00080000 + */ + SQLITE_OPEN_WAL: number; + /** + * @constant 0x01000000 + */ + SQLITE_OPEN_NOFOLLOW: number; + /** + * @constant 0x02000000 + */ + SQLITE_OPEN_EXRESCODE: number; + /** + * @constant 0x01 + */ + SQLITE_PREPARE_PERSISTENT: number; + /** + * @constant 0x02 + */ + SQLITE_PREPARE_NORMALIZE: number; + /** + * @constant 0x04 + */ + SQLITE_PREPARE_NO_VTAB: number; - /** - * @constant 1 - */ - SQLITE_FCNTL_LOCKSTATE: number; - /** - * @constant 2 - */ - SQLITE_FCNTL_GET_LOCKPROXYFILE: number; - /** - * @constant 3 - */ - SQLITE_FCNTL_SET_LOCKPROXYFILE: number; - /** - * @constant 4 - */ - SQLITE_FCNTL_LAST_ERRNO: number; - /** - * @constant 5 - */ - SQLITE_FCNTL_SIZE_HINT: number; - /** - * @constant 6 - */ - SQLITE_FCNTL_CHUNK_SIZE: number; - /** - * @constant 7 - */ - SQLITE_FCNTL_FILE_POINTER: number; - /** - * @constant 8 - */ - SQLITE_FCNTL_SYNC_OMITTED: number; - /** - * @constant 9 - */ - SQLITE_FCNTL_WIN32_AV_RETRY: number; - /** - * @constant 10 - * - * Control whether or not the WAL is persisted - * Some versions of macOS configure WAL to be persistent by default. - * - * You can change this with code like the below: - * ```ts - * import { Database } from "bun:sqlite"; - * - * const db = Database.open("mydb.sqlite"); - * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); - * // enable WAL - * db.exec("PRAGMA journal_mode = WAL"); - * // .. do some work - * db.close(); - * ``` - * - */ - SQLITE_FCNTL_PERSIST_WAL: number; - /** - * @constant 11 - */ - SQLITE_FCNTL_OVERWRITE: number; - /** - * @constant 12 - */ - SQLITE_FCNTL_VFSNAME: number; - /** - * @constant 13 - */ - SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; - /** - * @constant 14 - */ - SQLITE_FCNTL_PRAGMA: number; - /** - * @constant 15 - */ - SQLITE_FCNTL_BUSYHANDLER: number; - /** - * @constant 16 - */ - SQLITE_FCNTL_TEMPFILENAME: number; - /** - * @constant 18 - */ - SQLITE_FCNTL_MMAP_SIZE: number; - /** - * @constant 19 - */ - SQLITE_FCNTL_TRACE: number; - /** - * @constant 20 - */ - SQLITE_FCNTL_HAS_MOVED: number; - /** - * @constant 21 - */ - SQLITE_FCNTL_SYNC: number; - /** - * @constant 22 - */ - SQLITE_FCNTL_COMMIT_PHASETWO: number; - /** - * @constant 23 - */ - SQLITE_FCNTL_WIN32_SET_HANDLE: number; - /** - * @constant 24 - */ - SQLITE_FCNTL_WAL_BLOCK: number; - /** - * @constant 25 - */ - SQLITE_FCNTL_ZIPVFS: number; - /** - * @constant 26 - */ - SQLITE_FCNTL_RBU: number; - /** - * @constant 27 - */ - SQLITE_FCNTL_VFS_POINTER: number; - /** - * @constant 28 - */ - SQLITE_FCNTL_JOURNAL_POINTER: number; - /** - * @constant 29 - */ - SQLITE_FCNTL_WIN32_GET_HANDLE: number; - /** - * @constant 30 - */ - SQLITE_FCNTL_PDB: number; - /** - * @constant 31 - */ - SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; - /** - * @constant 32 - */ - SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; - /** - * @constant 33 - */ - SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; - /** - * @constant 34 - */ - SQLITE_FCNTL_LOCK_TIMEOUT: number; - /** - * @constant 35 - */ - SQLITE_FCNTL_DATA_VERSION: number; - /** - * @constant 36 - */ - SQLITE_FCNTL_SIZE_LIMIT: number; - /** - * @constant 37 - */ - SQLITE_FCNTL_CKPT_DONE: number; - /** - * @constant 38 - */ - SQLITE_FCNTL_RESERVE_BYTES: number; - /** - * @constant 39 - */ - SQLITE_FCNTL_CKPT_START: number; - /** - * @constant 40 - */ - SQLITE_FCNTL_EXTERNAL_READER: number; - /** - * @constant 41 - */ - SQLITE_FCNTL_CKSM_FILE: number; - /** - * @constant 42 - */ - SQLITE_FCNTL_RESET_CACHE: number; - }; + /** + * @constant 1 + */ + SQLITE_FCNTL_LOCKSTATE: number; + /** + * @constant 2 + */ + SQLITE_FCNTL_GET_LOCKPROXYFILE: number; + /** + * @constant 3 + */ + SQLITE_FCNTL_SET_LOCKPROXYFILE: number; + /** + * @constant 4 + */ + SQLITE_FCNTL_LAST_ERRNO: number; + /** + * @constant 5 + */ + SQLITE_FCNTL_SIZE_HINT: number; + /** + * @constant 6 + */ + SQLITE_FCNTL_CHUNK_SIZE: number; + /** + * @constant 7 + */ + SQLITE_FCNTL_FILE_POINTER: number; + /** + * @constant 8 + */ + SQLITE_FCNTL_SYNC_OMITTED: number; + /** + * @constant 9 + */ + SQLITE_FCNTL_WIN32_AV_RETRY: number; + /** + * @constant 10 + * + * Control whether or not the WAL is persisted + * Some versions of macOS configure WAL to be persistent by default. + * + * You can change this with code like the below: + * ```ts + * import { Database } from "bun:sqlite"; + * + * const db = Database.open("mydb.sqlite"); + * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); + * // enable WAL + * db.exec("PRAGMA journal_mode = WAL"); + * // .. do some work + * db.close(); + * ``` + * + */ + SQLITE_FCNTL_PERSIST_WAL: number; + /** + * @constant 11 + */ + SQLITE_FCNTL_OVERWRITE: number; + /** + * @constant 12 + */ + SQLITE_FCNTL_VFSNAME: number; + /** + * @constant 13 + */ + SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; + /** + * @constant 14 + */ + SQLITE_FCNTL_PRAGMA: number; + /** + * @constant 15 + */ + SQLITE_FCNTL_BUSYHANDLER: number; + /** + * @constant 16 + */ + SQLITE_FCNTL_TEMPFILENAME: number; + /** + * @constant 18 + */ + SQLITE_FCNTL_MMAP_SIZE: number; + /** + * @constant 19 + */ + SQLITE_FCNTL_TRACE: number; + /** + * @constant 20 + */ + SQLITE_FCNTL_HAS_MOVED: number; + /** + * @constant 21 + */ + SQLITE_FCNTL_SYNC: number; + /** + * @constant 22 + */ + SQLITE_FCNTL_COMMIT_PHASETWO: number; + /** + * @constant 23 + */ + SQLITE_FCNTL_WIN32_SET_HANDLE: number; + /** + * @constant 24 + */ + SQLITE_FCNTL_WAL_BLOCK: number; + /** + * @constant 25 + */ + SQLITE_FCNTL_ZIPVFS: number; + /** + * @constant 26 + */ + SQLITE_FCNTL_RBU: number; + /** + * @constant 27 + */ + SQLITE_FCNTL_VFS_POINTER: number; + /** + * @constant 28 + */ + SQLITE_FCNTL_JOURNAL_POINTER: number; + /** + * @constant 29 + */ + SQLITE_FCNTL_WIN32_GET_HANDLE: number; + /** + * @constant 30 + */ + SQLITE_FCNTL_PDB: number; + /** + * @constant 31 + */ + SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; + /** + * @constant 32 + */ + SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; + /** + * @constant 33 + */ + SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; + /** + * @constant 34 + */ + SQLITE_FCNTL_LOCK_TIMEOUT: number; + /** + * @constant 35 + */ + SQLITE_FCNTL_DATA_VERSION: number; + /** + * @constant 36 + */ + SQLITE_FCNTL_SIZE_LIMIT: number; + /** + * @constant 37 + */ + SQLITE_FCNTL_CKPT_DONE: number; + /** + * @constant 38 + */ + SQLITE_FCNTL_RESERVE_BYTES: number; + /** + * @constant 39 + */ + SQLITE_FCNTL_CKPT_START: number; + /** + * @constant 40 + */ + SQLITE_FCNTL_EXTERNAL_READER: number; + /** + * @constant 41 + */ + SQLITE_FCNTL_CKSM_FILE: number; + /** + * @constant 42 + */ + SQLITE_FCNTL_RESET_CACHE: number; + }; - /** - * The native module implementing the sqlite3 C bindings - * - * It is lazily-initialized, so this will return `undefined` until the first - * call to new Database(). - * - * The native module makes no gurantees about ABI stability, so it is left - * untyped - * - * If you need to use it directly for some reason, please let us know because - * that probably points to a deficiency in this API. - */ - export var native: any; + /** + * The native module implementing the sqlite3 C bindings + * + * It is lazily-initialized, so this will return `undefined` until the first + * call to new Database(). + * + * The native module makes no gurantees about ABI stability, so it is left + * untyped + * + * If you need to use it directly for some reason, please let us know because + * that probably points to a deficiency in this API. + */ + export var native: any; - export type SQLQueryBindings = - | string - | bigint - | NodeJS.TypedArray - | number - | boolean - | null - | Record< - string, - string | bigint | NodeJS.TypedArray | number | boolean | null - >; + export type SQLQueryBindings = + | string + | bigint + | NodeJS.TypedArray + | number + | boolean + | null + | Record; - export default Database; + export default Database; - /** - * Errors from SQLite have a name `SQLiteError`. - * - */ - export class SQLiteError extends Error { - readonly name: "SQLiteError"; + /** + * Errors from SQLite have a name `SQLiteError`. + * + */ + export class SQLiteError extends Error { + readonly name: "SQLiteError"; - /** - * The SQLite3 extended error code - * - * This corresponds to `sqlite3_extended_errcode`. - * - * @since v1.0.21 - */ - errno: number; + /** + * The SQLite3 extended error code + * + * This corresponds to `sqlite3_extended_errcode`. + * + * @since v1.0.21 + */ + errno: number; - /** - * The name of the SQLite3 error code - * - * @example - * "SQLITE_CONSTRAINT_UNIQUE" - * - * @since v1.0.21 - */ - code?: string; + /** + * The name of the SQLite3 error code + * + * @example + * "SQLITE_CONSTRAINT_UNIQUE" + * + * @since v1.0.21 + */ + code?: string; - /** - * The UTF-8 byte offset of the sqlite3 query that failed, if known - * - * This corresponds to `sqlite3_error_offset`. - * - * @since v1.0.21 - */ - readonly byteOffset: number; - } + /** + * The UTF-8 byte offset of the sqlite3 query that failed, if known + * + * This corresponds to `sqlite3_error_offset`. + * + * @since v1.0.21 + */ + readonly byteOffset: number; + } - /** - * An object representing the changes made to the database since the last `run` or `exec` call. - * - * @since Bun v1.1.14 - */ - export interface Changes { - /** - * The number of rows changed by the last `run` or `exec` call. - */ - changes: number; + /** + * An object representing the changes made to the database since the last `run` or `exec` call. + * + * @since Bun v1.1.14 + */ + export interface Changes { + /** + * The number of rows changed by the last `run` or `exec` call. + */ + changes: number; - /** - * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. - */ - lastInsertRowid: number | bigint; - } + /** + * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. + */ + lastInsertRowid: number | bigint; + } } diff --git a/packages/bun-types/new/test.d.ts b/packages/bun-types/new/test.d.ts index e2d4a01871c381..acd28c72153ef7 100644 --- a/packages/bun-types/new/test.d.ts +++ b/packages/bun-types/new/test.d.ts @@ -14,1060 +14,1001 @@ * ``` */ declare module "bun:test" { - /** - * -- Mocks -- - */ - export type Mock any> = JestMock.Mock; - - export const mock: { - any>(Function?: T): Mock; - - /** - * Replace the module `id` with the return value of `factory`. - * - * This is useful for mocking modules. - * - * @param id module ID to mock - * @param factory a function returning an object that will be used as the exports of the mocked module - * - * @example - * ## Example - * ```ts - * import { mock } from "bun:test"; - * - * mock.module("fs/promises", () => { - * return { - * readFile: () => Promise.resolve("hello world"), - * }; - * }); - * - * import { readFile } from "fs/promises"; - * - * console.log(await readFile("hello.txt", "utf8")); // hello world - * ``` - * - * ## More notes - * - * If the module is already loaded, exports are overwritten with the return - * value of `factory`. If the export didn't exist before, it will not be - * added to existing import statements. This is due to how ESM works. - */ - module(id: string, factory: () => any): void | Promise; - /** - * Restore the previous value of mocks. - */ - restore(): void; - }; - - /** - * Control the system time used by: - * - `Date.now()` - * - `new Date()` - * - `Intl.DateTimeFormat().format()` - * - * In the future, we may add support for more functions, but we haven't done that yet. - * - * @param now The time to set the system time to. If not provided, the system time will be reset. - * @returns `this` - * @since v0.6.13 - * - * ## Set Date to a specific time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); - * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z - * ``` - * ## Reset Date to the current time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(); - * ``` - */ - export function setSystemTime(now?: Date | number): ThisType; - - interface Jest { - restoreAllMocks(): void; - clearAllMocks(): void; - fn any>(func?: T): Mock; - setSystemTime(now?: number | Date): void; - setTimeout(milliseconds: number): void; - } - export const jest: Jest; - export namespace jest { - /** - * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. - */ - type Mock any = (...args: any[]) => any> = - JestMock.Mock; - /** - * Wraps a class, function or object type with Jest mock type definitions. - */ - // type Mocked = JestMock.Mocked; - /** - * Wraps a class type with Jest mock type definitions. - */ - // type MockedClass = JestMock.MockedClass; - /** - * Wraps a function type with Jest mock type definitions. - */ - // type MockedFunction any> = JestMock.MockedFunction; - /** - * Wraps an object type with Jest mock type definitions. - */ - // type MockedObject = JestMock.MockedObject; - /** - * Constructs the type of a replaced property. - */ - type Replaced = JestMock.Replaced; - /** - * Constructs the type of a spied class or function. - */ - type Spied any)> = - JestMock.Spied; - /** - * Constructs the type of a spied class. - */ - type SpiedClass = JestMock.SpiedClass; - /** - * Constructs the type of a spied function. - */ - type SpiedFunction any> = - JestMock.SpiedFunction; - /** - * Constructs the type of a spied getter. - */ - type SpiedGetter = JestMock.SpiedGetter; - /** - * Constructs the type of a spied setter. - */ - type SpiedSetter = JestMock.SpiedSetter; - } - - export function spyOn( - obj: T, - methodOrPropertyValue: K, - ): Mock any ? T[K] : never>; - - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export interface Describe { - (label: string, fn: () => void): void; - /** - * Skips all other tests, except this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - only(label: string, fn: () => void): void; - /** - * Skips this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - skip(label: string, fn: () => void): void; - /** - * Marks this group of tests as to be written or to be fixed. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - todo(label: string, fn?: () => void): void; - /** - * Runs this group of tests, only if `condition` is true. - * - * This is the opposite of `describe.skipIf()`. - * - * @param condition if these tests should run - */ - if(condition: boolean): (label: string, fn: () => void) => void; - /** - * Skips this group of tests, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - skipIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Marks this group of tests as to be written or to be fixed, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - todoIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): ( - label: string, - fn: (...args: [...T]) => void | Promise, - options?: number | TestOptions, - ) => void; - each( - table: readonly T[], - ): ( - label: string, - fn: (...args: Readonly) => void | Promise, - options?: number | TestOptions, - ) => void; - each( - table: T[], - ): ( - label: string, - fn: (...args: T[]) => void | Promise, - options?: number | TestOptions, - ) => void; - } - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export const describe: Describe; - /** - * Runs a function, once, before all the tests. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, tests will not run in this file. - * - * @example - * let database; - * beforeAll(async () => { - * database = await connect("localhost"); - * }); - * - * @param fn the function to run - */ - export function beforeAll( - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Runs a function before each test. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, the test will not run. - * - * @param fn the function to run - */ - export function beforeEach( - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Runs a function, once, after all the tests. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @example - * let database; - * afterAll(async () => { - * if (database) { - * await database.close(); - * } - * }); - * - * @param fn the function to run - */ - export function afterAll( - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Runs a function after each test. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @param fn the function to run - */ - export function afterEach( - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will - * override this value. The default timeout is 5000ms (5 seconds). - * - * @param milliseconds the number of milliseconds for the default timeout - */ - export function setDefaultTimeout(milliseconds: number): void; - export interface TestOptions { - /** - * Sets the timeout for the test in milliseconds. - * - * If the test does not complete within this time, the test will fail with: - * ```ts - * 'Timeout: test {name} timed out after 5000ms' - * ``` - * - * @default 5000 // 5 seconds - */ - timeout?: number; - /** - * Sets the number of times to retry the test if it fails. - * - * @default 0 - */ - retry?: number; - /** - * Sets the number of times to repeat the test, regardless of whether it passed or failed. - * - * @default 0 - */ - repeats?: number; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * test("can set a timeout", async () => { - * await Bun.sleep(100); - * }, 50); // or { timeout: 50 } - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - export interface Test { - ( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - /** - * - If a `number`, sets the timeout for the test in milliseconds. - * - If an `object`, sets the options for the test. - * - `timeout` sets the timeout for the test in milliseconds. - * - `retry` sets the number of times to retry the test if it fails. - * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. - */ - options?: number | TestOptions, - ): void; - /** - * Skips all other tests, except this test when run with the `--only` option. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - only( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Skips this test. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - skip( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as to be written or to be fixed. - * - * These tests will not be executed unless the `--todo` flag is passed. With the flag, - * if the test passes, the test will be marked as `fail` in the results; you will have to - * remove the `.todo` or check that your test - * is implemented correctly. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - todo( - label: string, - fn?: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as failing. - * - * Use `test.failing` when you are writing a test and expecting it to fail. - * These tests will behave the other way normal tests do. If failing test - * will throw any errors then it will pass. If it does not throw it will - * fail. - * - * `test.failing` is very similar to {@link test.todo} except that it always - * runs, regardless of the `--todo` flag. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - failing( - label: string, - fn?: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - ): void; - /** - * Runs this test, if `condition` is true. - * - * This is the opposite of `test.skipIf()`. - * - * @param condition if the test should run - */ - if( - condition: boolean, - ): ( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Skips this test, if `condition` is true. - * - * @param condition if the test should be skipped - */ - skipIf( - condition: boolean, - ): ( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Marks this test as to be written or to be fixed, if `condition` is true. - * - * @param condition if the test should be marked TODO - */ - todoIf( - condition: boolean, - ): ( - label: string, - fn: - | (() => void | Promise) - | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): ( - label: string, - fn: (...args: [...T]) => void | Promise, - options?: number | TestOptions, - ) => void; - each( - table: readonly T[], - ): ( - label: string, - fn: (...args: Readonly) => void | Promise, - options?: number | TestOptions, - ) => void; - each( - table: T[], - ): ( - label: string, - fn: (...args: T[]) => void | Promise, - options?: number | TestOptions, - ) => void; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * @param label the label for the test - * @param fn the test function - */ - export const test: Test; - export { test as it }; - - /** - * Asserts that a value matches some criteria. - * - * @link https://jestjs.io/docs/expect#reference - * @example - * expect(1 + 1).toBe(2); - * expect([1,2,3]).toContain(2); - * expect(null).toBeNull(); - * - * @param actual The actual (received) value - */ - export const expect: Expect; - - type ExpectNot = Omit & - AsymmetricMatchersBuiltinNegated; - - export interface Expect extends AsymmetricMatchers { - // the `expect()` callable signature - /** - * @param actual the actual value - * @param customFailMessage an optional custom message to display if the test fails. - * */ - - (actual?: T, customFailMessage?: string): Matchers; - - /** - * Access to negated asymmetric matchers. - * - * @example - * expect("abc").toEqual(expect.stringContaining("abc")); // will pass - * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail - */ - not: ExpectNot; - - /** - * Create an asymmetric matcher for a promise resolved value. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass - * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail - * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail - */ - resolvesTo: AsymmetricMatchers; - - /** - * Create an asymmetric matcher for a promise rejected value. - * - * @example - * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass - * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail - * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail - */ - rejectsTo: AsymmetricMatchers; - - /** - * Register new custom matchers. - * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. - * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` - * - * @example - * expect.extend({ - * toBeWithinRange(actual, min, max) { - * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') - * throw new Error('Invalid usage'); - * const pass = actual >= min && actual <= max; - * return { - * pass: pass, - * message: () => `expected ${this.utils.printReceived(actual)} ` + - * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, - * }; - * }, - * }); - * - * test('some test', () => { - * expect(50).toBeWithinRange(0, 100); // will pass - * expect(50).toBeWithinRange(100, 200); // will fail - * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass - * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass - * }); - */ - extend(matchers: ExpectExtendMatchers): void; - - /** - * Throw an error if this function is called. - * - * @param msg Optional message to display if the test fails - * @returns never - * - * @example - * ## Example - * - * ```ts - * import { expect, test } from "bun:test"; - * - * test("!!abc!! is not a module", () => { - * try { - * require("!!abc!!"); - * expect.unreachable(); - * } catch(e) { - * expect(e.name).not.toBe("UnreachableError"); - * } - * }); - * ``` - */ - unreachable(msg?: string | Error): never; - - /** - * Ensures that an assertion is made - */ - hasAssertions(): void; - - /** - * Ensures that a specific number of assertions are made - */ - assertions(neededAssertions: number): void; - } - - /** - * You can extend this interface with declaration merging, in order to add type support for custom matchers. - * @template T Type of the actual value - * - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface Matchers extends MatchersBuiltin {} - - /** - * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} - - export interface AsymmetricMatchersBuiltin { - /** - * Matches anything that was created with the given constructor. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * @example - * - * function randocall(fn) { - * return fn(Math.floor(Math.random() * 6 + 1)); - * } - * - * test('randocall calls its callback with a number', () => { - * const mock = jest.fn(); - * randocall(mock); - * expect(mock).toBeCalledWith(expect.any(Number)); - * }); - */ - any( - constructor: ((...args: any[]) => any) | { new (...args: any[]): any }, - ): AsymmetricMatcher; - /** - * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead - * of a literal value. For example, if you want to check that a mock function is called with a - * non-null argument: - * - * @example - * - * test('map calls its argument with a non-null argument', () => { - * const mock = jest.fn(); - * [1].map(x => mock(x)); - * expect(mock).toBeCalledWith(expect.anything()); - * }); - */ - anything(): AsymmetricMatcher; - /** - * Matches any array made up entirely of elements in the provided array. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - /** - * Matches any object that recursively matches the provided keys. - * This is often handy in conjunction with other asymmetric matchers. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - /** - * Matches any received string that contains the exact expected string - */ - stringContaining(str: string | String): AsymmetricMatcher; - /** - * Matches any string that contains the exact provided string - */ - stringMatching(regex: string | String | RegExp): AsymmetricMatcher; - /** - * Useful when comparing floating point numbers in object properties or array item. - * If you need to compare a number, use `.toBeCloseTo` instead. - * - * The optional `numDigits` argument limits the number of digits to check after the decimal point. - * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - interface AsymmetricMatchersBuiltinNegated { - /** - * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail - * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - */ - resolvesTo: ExpectNot; - - /** - * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. - * - * @example - * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail - * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - */ - rejectsTo: ExpectNot; - - /** - * `expect.not.arrayContaining(array)` matches a received array which - * does not contain all of the elements in the expected array. That is, - * the expected array is not a subset of the received array. It is the - * inverse of `expect.arrayContaining`. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - - /** - * `expect.not.objectContaining(object)` matches any received object - * that does not recursively match the expected properties. That is, the - * expected object is not a subset of the received object. Therefore, - * it matches a received object which contains properties that are not - * in the expected object. It is the inverse of `expect.objectContaining`. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - - /** - * `expect.not.stringContaining(string)` matches the received string - * that does not contain the exact expected string. It is the inverse of - * `expect.stringContaining`. - */ - stringContaining(str: string | String): AsymmetricMatcher; - - /** - * `expect.not.stringMatching(string | regexp)` matches the received - * string that does not match the expected regexp. It is the inverse of - * `expect.stringMatching`. - */ - stringMatching(str: string | String | RegExp): AsymmetricMatcher; - - /** - * `expect.not.closeTo` matches a number not close to the provided value. - * Useful when comparing floating point numbers in object properties or array item. - * It is the inverse of `expect.closeTo`. - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - export interface MatchersBuiltin { - /** - * Negates the result of a subsequent assertion. - * If you know how to test something, `.not` lets you test its opposite. - * - * @example - * expect(1).not.toBe(0); - * expect(null).not.toBeNull(); - * - * @example - * expect(42).toEqual(42); // will pass - * expect(42).not.toEqual(42); // will fail - */ - not: Matchers; - - /** - * Expects the value to be a promise that resolves. - * - * @example - * expect(Promise.resolve(1)).resolves.toBe(1); - */ - resolves: Matchers>; - - /** - * Expects the value to be a promise that rejects. - * - * @example - * expect(Promise.reject("error")).rejects.toBe("error"); - */ - rejects: Matchers; - - /** - * Assertion which passes. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass - * @example - * expect().pass(); - * expect().pass("message is optional"); - * expect().not.pass(); - * expect().not.pass("hi"); - * - * @param message the message to display if the test fails (optional) - */ - pass: (message?: string) => void; - /** - * Assertion which fails. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail - * @example - * expect().fail(); - * expect().fail("message is optional"); - * expect().not.fail(); - * expect().not.fail("hi"); - */ - fail: (message?: string) => void; - /** - * Asserts that a value equals what is expected. - * - * - For non-primitive values, like objects and arrays, - * use `toEqual()` instead. - * - For floating-point numbers, use `toBeCloseTo()` instead. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([123]).toBe([123]); // fail, use toEqual() - * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() - * - * @param expected the expected value - */ - toBe(expected: T): void; - /** - * Asserts that a number is odd. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd - * @example - * expect(1).toBeOdd(); - * expect(2).not.toBeOdd(); - */ - toBeOdd(): void; - /** - * Asserts that a number is even. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven - * @example - * expect(2).toBeEven(); - * expect(1).not.toBeEven(); - */ - toBeEven(): void; - /** - * Asserts that value is close to the expected by floating point precision. - * - * For example, the following fails because arithmetic on decimal (base 10) - * values often have rounding errors in limited precision binary (base 2) representation. - * - * @example - * expect(0.2 + 0.1).toBe(0.3); // fails - * - * Use `toBeCloseTo` to compare floating point numbers for approximate equality. - * - * @example - * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes - * - * @param expected the expected value - * @param numDigits the number of digits to check after the decimal point. Default is `2` - */ - toBeCloseTo(expected: number, numDigits?: number): void; - /** - * Asserts that a value is deeply equal to what is expected. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([456]).toEqual([456]); - * expect({ value: 1 }).toEqual({ value: 1 }); - * - * @param expected the expected value - */ - toEqual(expected: T): void; - /** - * Asserts that a value is deeply and strictly equal to - * what is expected. - * - * There are two key differences from `toEqual()`: - * 1. It checks that the class is the same. - * 2. It checks that `undefined` values match as well. - * - * @example - * class Dog { - * type = "dog"; - * } - * const actual = new Dog(); - * expect(actual).toStrictEqual(new Dog()); - * expect(actual).toStrictEqual({ type: "dog" }); // fail - * - * @example - * const actual = { value: 1, name: undefined }; - * expect(actual).toEqual({ value: 1 }); - * expect(actual).toStrictEqual({ value: 1 }); // fail - * - * @param expected the expected value - */ - toStrictEqual(expected: T): void; - /** - * Asserts that the value is deep equal to an element in the expected array. - * - * The value must be an array or iterable, which includes strings. - * - * @example - * expect(1).toBeOneOf([1,2,3]); - * expect("foo").toBeOneOf(["foo", "bar"]); - * expect(true).toBeOneOf(new Set([true])); - * - * @param expected the expected value - */ - toBeOneOf(expected: Array | Iterable): void; - /** - * Asserts that a value contains what is expected. - * - * The value must be an array or iterable, which - * includes strings. - * - * @example - * expect([1, 2, 3]).toContain(1); - * expect(new Set([true])).toContain(true); - * expect("hello").toContain("o"); - * - * @param expected the expected value - */ - toContain(expected: unknown): void; - /** - * Asserts that an `object` contains a key. - * - * The value must be an object - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); - * - * @param expected the expected value - */ - toContainKey(expected: unknown): void; - /** - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); - * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); - * - * @param expected the expected value - */ - toContainAllKeys(expected: unknown): void; - /** - * Asserts that an `object` contains at least one of the provided keys. - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); - * - * @param expected the expected value - */ - toContainAnyKeys(expected: unknown): void; - - /** + /** + * -- Mocks -- + */ + export type Mock any> = JestMock.Mock; + + export const mock: { + any>(Function?: T): Mock; + + /** + * Replace the module `id` with the return value of `factory`. + * + * This is useful for mocking modules. + * + * @param id module ID to mock + * @param factory a function returning an object that will be used as the exports of the mocked module + * + * @example + * ## Example + * ```ts + * import { mock } from "bun:test"; + * + * mock.module("fs/promises", () => { + * return { + * readFile: () => Promise.resolve("hello world"), + * }; + * }); + * + * import { readFile } from "fs/promises"; + * + * console.log(await readFile("hello.txt", "utf8")); // hello world + * ``` + * + * ## More notes + * + * If the module is already loaded, exports are overwritten with the return + * value of `factory`. If the export didn't exist before, it will not be + * added to existing import statements. This is due to how ESM works. + */ + module(id: string, factory: () => any): void | Promise; + /** + * Restore the previous value of mocks. + */ + restore(): void; + }; + + /** + * Control the system time used by: + * - `Date.now()` + * - `new Date()` + * - `Intl.DateTimeFormat().format()` + * + * In the future, we may add support for more functions, but we haven't done that yet. + * + * @param now The time to set the system time to. If not provided, the system time will be reset. + * @returns `this` + * @since v0.6.13 + * + * ## Set Date to a specific time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); + * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z + * ``` + * ## Reset Date to the current time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(); + * ``` + */ + export function setSystemTime(now?: Date | number): ThisType; + + interface Jest { + restoreAllMocks(): void; + clearAllMocks(): void; + fn any>(func?: T): Mock; + setSystemTime(now?: number | Date): void; + setTimeout(milliseconds: number): void; + } + export const jest: Jest; + export namespace jest { + /** + * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. + */ + type Mock any = (...args: any[]) => any> = JestMock.Mock; + /** + * Wraps a class, function or object type with Jest mock type definitions. + */ + // type Mocked = JestMock.Mocked; + /** + * Wraps a class type with Jest mock type definitions. + */ + // type MockedClass = JestMock.MockedClass; + /** + * Wraps a function type with Jest mock type definitions. + */ + // type MockedFunction any> = JestMock.MockedFunction; + /** + * Wraps an object type with Jest mock type definitions. + */ + // type MockedObject = JestMock.MockedObject; + /** + * Constructs the type of a replaced property. + */ + type Replaced = JestMock.Replaced; + /** + * Constructs the type of a spied class or function. + */ + type Spied any)> = JestMock.Spied; + /** + * Constructs the type of a spied class. + */ + type SpiedClass = JestMock.SpiedClass; + /** + * Constructs the type of a spied function. + */ + type SpiedFunction any> = JestMock.SpiedFunction; + /** + * Constructs the type of a spied getter. + */ + type SpiedGetter = JestMock.SpiedGetter; + /** + * Constructs the type of a spied setter. + */ + type SpiedSetter = JestMock.SpiedSetter; + } + + export function spyOn( + obj: T, + methodOrPropertyValue: K, + ): Mock any ? T[K] : never>; + + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + + interface FunctionLike { + readonly name: string; + } + export interface Describe { + (fn: () => void): void; + + (label: number | string | Function | FunctionLike, fn: () => void): void; + /** + * Skips all other tests, except this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + only(label: string, fn: () => void): void; + /** + * Skips this group of tests. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + skip(label: string, fn: () => void): void; + /** + * Marks this group of tests as to be written or to be fixed. + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + todo(label: string, fn?: () => void): void; + /** + * Runs this group of tests, only if `condition` is true. + * + * This is the opposite of `describe.skipIf()`. + * + * @param condition if these tests should run + */ + if(condition: boolean): (label: string, fn: () => void) => void; + /** + * Skips this group of tests, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + skipIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Marks this group of tests as to be written or to be fixed, if `condition` is true. + * + * @param condition if these tests should be skipped + */ + todoIf(condition: boolean): (label: string, fn: () => void) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; + each( + table: readonly T[], + ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; + each( + table: T[], + ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; + } + /** + * Describes a group of related tests. + * + * @example + * function sum(a, b) { + * return a + b; + * } + * describe("sum()", () => { + * test("can sum two values", () => { + * expect(sum(1, 1)).toBe(2); + * }); + * }); + * + * @param label the label for the tests + * @param fn the function that defines the tests + */ + export const describe: Describe; + /** + * Runs a function, once, before all the tests. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, tests will not run in this file. + * + * @example + * let database; + * beforeAll(async () => { + * database = await connect("localhost"); + * }); + * + * @param fn the function to run + */ + export function beforeAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Runs a function before each test. + * + * This is useful for running set up tasks, like initializing + * a global variable or connecting to a database. + * + * If this function throws, the test will not run. + * + * @param fn the function to run + */ + export function beforeEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Runs a function, once, after all the tests. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @example + * let database; + * afterAll(async () => { + * if (database) { + * await database.close(); + * } + * }); + * + * @param fn the function to run + */ + export function afterAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Runs a function after each test. + * + * This is useful for running clean up tasks, like closing + * a socket or deleting temporary files. + * + * @param fn the function to run + */ + export function afterEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will + * override this value. The default timeout is 5000ms (5 seconds). + * + * @param milliseconds the number of milliseconds for the default timeout + */ + export function setDefaultTimeout(milliseconds: number): void; + export interface TestOptions { + /** + * Sets the timeout for the test in milliseconds. + * + * If the test does not complete within this time, the test will fail with: + * ```ts + * 'Timeout: test {name} timed out after 5000ms' + * ``` + * + * @default 5000 // 5 seconds + */ + timeout?: number; + /** + * Sets the number of times to retry the test if it fails. + * + * @default 0 + */ + retry?: number; + /** + * Sets the number of times to repeat the test, regardless of whether it passed or failed. + * + * @default 0 + */ + repeats?: number; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * test("can set a timeout", async () => { + * await Bun.sleep(100); + * }, 50); // or { timeout: 50 } + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + export interface Test { + ( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + /** + * - If a `number`, sets the timeout for the test in milliseconds. + * - If an `object`, sets the options for the test. + * - `timeout` sets the timeout for the test in milliseconds. + * - `retry` sets the number of times to retry the test if it fails. + * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. + */ + options?: number | TestOptions, + ): void; + /** + * Skips all other tests, except this test when run with the `--only` option. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + only( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Skips this test. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + skip( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as to be written or to be fixed. + * + * These tests will not be executed unless the `--todo` flag is passed. With the flag, + * if the test passes, the test will be marked as `fail` in the results; you will have to + * remove the `.todo` or check that your test + * is implemented correctly. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + todo( + label: string, + fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ): void; + /** + * Marks this test as failing. + * + * Use `test.failing` when you are writing a test and expecting it to fail. + * These tests will behave the other way normal tests do. If failing test + * will throw any errors then it will pass. If it does not throw it will + * fail. + * + * `test.failing` is very similar to {@link test.todo} except that it always + * runs, regardless of the `--todo` flag. + * + * @param label the label for the test + * @param fn the test function + * @param options the test timeout or options + */ + failing(label: string, fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; + /** + * Runs this test, if `condition` is true. + * + * This is the opposite of `test.skipIf()`. + * + * @param condition if the test should run + */ + if( + condition: boolean, + ): ( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Skips this test, if `condition` is true. + * + * @param condition if the test should be skipped + */ + skipIf( + condition: boolean, + ): ( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Marks this test as to be written or to be fixed, if `condition` is true. + * + * @param condition if the test should be marked TODO + */ + todoIf( + condition: boolean, + ): ( + label: string, + fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), + options?: number | TestOptions, + ) => void; + /** + * Returns a function that runs for each item in `table`. + * + * @param table Array of Arrays with the arguments that are passed into the test fn for each row. + */ + each>( + table: readonly T[], + ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; + each( + table: readonly T[], + ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; + each( + table: T[], + ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; + } + /** + * Runs a test. + * + * @example + * test("can check if using Bun", () => { + * expect(Bun).toBeDefined(); + * }); + * + * test("can make a fetch() request", async () => { + * const response = await fetch("https://example.com/"); + * expect(response.ok).toBe(true); + * }); + * + * @param label the label for the test + * @param fn the test function + */ + export const test: Test; + export { test as it }; + + /** + * Asserts that a value matches some criteria. + * + * @link https://jestjs.io/docs/expect#reference + * @example + * expect(1 + 1).toBe(2); + * expect([1,2,3]).toContain(2); + * expect(null).toBeNull(); + * + * @param actual The actual (received) value + */ + export const expect: Expect; + + type ExpectNot = Omit & AsymmetricMatchersBuiltinNegated; + + export interface Expect extends AsymmetricMatchers { + // the `expect()` callable signature + /** + * @param actual the actual value + * @param customFailMessage an optional custom message to display if the test fails. + * */ + + (actual?: T, customFailMessage?: string): Matchers; + + /** + * Access to negated asymmetric matchers. + * + * @example + * expect("abc").toEqual(expect.stringContaining("abc")); // will pass + * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail + */ + not: ExpectNot; + + /** + * Create an asymmetric matcher for a promise resolved value. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass + * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail + * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail + */ + resolvesTo: AsymmetricMatchers; + + /** + * Create an asymmetric matcher for a promise rejected value. + * + * @example + * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass + * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail + * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail + */ + rejectsTo: AsymmetricMatchers; + + /** + * Register new custom matchers. + * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. + * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` + * + * @example + * expect.extend({ + * toBeWithinRange(actual, min, max) { + * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') + * throw new Error('Invalid usage'); + * const pass = actual >= min && actual <= max; + * return { + * pass: pass, + * message: () => `expected ${this.utils.printReceived(actual)} ` + + * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, + * }; + * }, + * }); + * + * test('some test', () => { + * expect(50).toBeWithinRange(0, 100); // will pass + * expect(50).toBeWithinRange(100, 200); // will fail + * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass + * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass + * }); + */ + extend(matchers: ExpectExtendMatchers): void; + + /** + * Throw an error if this function is called. + * + * @param msg Optional message to display if the test fails + * @returns never + * + * @example + * ## Example + * + * ```ts + * import { expect, test } from "bun:test"; + * + * test("!!abc!! is not a module", () => { + * try { + * require("!!abc!!"); + * expect.unreachable(); + * } catch(e) { + * expect(e.name).not.toBe("UnreachableError"); + * } + * }); + * ``` + */ + unreachable(msg?: string | Error): never; + + /** + * Ensures that an assertion is made + */ + hasAssertions(): void; + + /** + * Ensures that a specific number of assertions are made + */ + assertions(neededAssertions: number): void; + } + + /** + * You can extend this interface with declaration merging, in order to add type support for custom matchers. + * @template T Type of the actual value + * + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface Matchers extends MatchersBuiltin {} + + /** + * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. + * @example + * // my_modules.d.ts + * interface MyCustomMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * declare module "bun:test" { + * interface Matchers extends MyCustomMatchers {} + * interface AsymmetricMatchers extends MyCustomMatchers {} + * } + * + * @example + * // my_modules.d.ts (alternatively) + * declare module "bun:test" { + * interface Matchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * interface AsymmetricMatchers { + * toBeWithinRange(floor: number, ceiling: number): any; + * } + * } + */ + export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} + + export interface AsymmetricMatchersBuiltin { + /** + * Matches anything that was created with the given constructor. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * @example + * + * function randocall(fn) { + * return fn(Math.floor(Math.random() * 6 + 1)); + * } + * + * test('randocall calls its callback with a number', () => { + * const mock = jest.fn(); + * randocall(mock); + * expect(mock).toBeCalledWith(expect.any(Number)); + * }); + */ + any(constructor: ((...args: any[]) => any) | { new (...args: any[]): any }): AsymmetricMatcher; + /** + * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead + * of a literal value. For example, if you want to check that a mock function is called with a + * non-null argument: + * + * @example + * + * test('map calls its argument with a non-null argument', () => { + * const mock = jest.fn(); + * [1].map(x => mock(x)); + * expect(mock).toBeCalledWith(expect.anything()); + * }); + */ + anything(): AsymmetricMatcher; + /** + * Matches any array made up entirely of elements in the provided array. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + /** + * Matches any object that recursively matches the provided keys. + * This is often handy in conjunction with other asymmetric matchers. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + /** + * Matches any received string that contains the exact expected string + */ + stringContaining(str: string | String): AsymmetricMatcher; + /** + * Matches any string that contains the exact provided string + */ + stringMatching(regex: string | String | RegExp): AsymmetricMatcher; + /** + * Useful when comparing floating point numbers in object properties or array item. + * If you need to compare a number, use `.toBeCloseTo` instead. + * + * The optional `numDigits` argument limits the number of digits to check after the decimal point. + * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + interface AsymmetricMatchersBuiltinNegated { + /** + * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. + * + * @example + * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail + * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass + */ + resolvesTo: ExpectNot; + + /** + * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. + * + * @example + * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail + * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass + */ + rejectsTo: ExpectNot; + + /** + * `expect.not.arrayContaining(array)` matches a received array which + * does not contain all of the elements in the expected array. That is, + * the expected array is not a subset of the received array. It is the + * inverse of `expect.arrayContaining`. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: readonly E[]): AsymmetricMatcher; + + /** + * `expect.not.objectContaining(object)` matches any received object + * that does not recursively match the expected properties. That is, the + * expected object is not a subset of the received object. Therefore, + * it matches a received object which contains properties that are not + * in the expected object. It is the inverse of `expect.objectContaining`. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: object): AsymmetricMatcher; + + /** + * `expect.not.stringContaining(string)` matches the received string + * that does not contain the exact expected string. It is the inverse of + * `expect.stringContaining`. + */ + stringContaining(str: string | String): AsymmetricMatcher; + + /** + * `expect.not.stringMatching(string | regexp)` matches the received + * string that does not match the expected regexp. It is the inverse of + * `expect.stringMatching`. + */ + stringMatching(str: string | String | RegExp): AsymmetricMatcher; + + /** + * `expect.not.closeTo` matches a number not close to the provided value. + * Useful when comparing floating point numbers in object properties or array item. + * It is the inverse of `expect.closeTo`. + */ + closeTo(num: number, numDigits?: number): AsymmetricMatcher; + } + + export interface MatchersBuiltin { + /** + * Negates the result of a subsequent assertion. + * If you know how to test something, `.not` lets you test its opposite. + * + * @example + * expect(1).not.toBe(0); + * expect(null).not.toBeNull(); + * + * @example + * expect(42).toEqual(42); // will pass + * expect(42).not.toEqual(42); // will fail + */ + not: Matchers; + + /** + * Expects the value to be a promise that resolves. + * + * @example + * expect(Promise.resolve(1)).resolves.toBe(1); + */ + resolves: Matchers>; + + /** + * Expects the value to be a promise that rejects. + * + * @example + * expect(Promise.reject("error")).rejects.toBe("error"); + */ + rejects: Matchers; + + /** + * Assertion which passes. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass + * @example + * expect().pass(); + * expect().pass("message is optional"); + * expect().not.pass(); + * expect().not.pass("hi"); + * + * @param message the message to display if the test fails (optional) + */ + pass: (message?: string) => void; + /** + * Assertion which fails. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail + * @example + * expect().fail(); + * expect().fail("message is optional"); + * expect().not.fail(); + * expect().not.fail("hi"); + */ + fail: (message?: string) => void; + /** + * Asserts that a value equals what is expected. + * + * - For non-primitive values, like objects and arrays, + * use `toEqual()` instead. + * - For floating-point numbers, use `toBeCloseTo()` instead. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([123]).toBe([123]); // fail, use toEqual() + * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() + * + * @param expected the expected value + */ + toBe(expected: T): void; + /** + * Asserts that a number is odd. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd + * @example + * expect(1).toBeOdd(); + * expect(2).not.toBeOdd(); + */ + toBeOdd(): void; + /** + * Asserts that a number is even. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven + * @example + * expect(2).toBeEven(); + * expect(1).not.toBeEven(); + */ + toBeEven(): void; + /** + * Asserts that value is close to the expected by floating point precision. + * + * For example, the following fails because arithmetic on decimal (base 10) + * values often have rounding errors in limited precision binary (base 2) representation. + * + * @example + * expect(0.2 + 0.1).toBe(0.3); // fails + * + * Use `toBeCloseTo` to compare floating point numbers for approximate equality. + * + * @example + * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes + * + * @param expected the expected value + * @param numDigits the number of digits to check after the decimal point. Default is `2` + */ + toBeCloseTo(expected: number, numDigits?: number): void; + /** + * Asserts that a value is deeply equal to what is expected. + * + * @example + * expect(100 + 23).toBe(123); + * expect("d" + "og").toBe("dog"); + * expect([456]).toEqual([456]); + * expect({ value: 1 }).toEqual({ value: 1 }); + * + * @param expected the expected value + */ + toEqual(expected: T): void; + /** + * Asserts that a value is deeply and strictly equal to + * what is expected. + * + * There are two key differences from `toEqual()`: + * 1. It checks that the class is the same. + * 2. It checks that `undefined` values match as well. + * + * @example + * class Dog { + * type = "dog"; + * } + * const actual = new Dog(); + * expect(actual).toStrictEqual(new Dog()); + * expect(actual).toStrictEqual({ type: "dog" }); // fail + * + * @example + * const actual = { value: 1, name: undefined }; + * expect(actual).toEqual({ value: 1 }); + * expect(actual).toStrictEqual({ value: 1 }); // fail + * + * @param expected the expected value + */ + toStrictEqual(expected: T): void; + /** + * Asserts that the value is deep equal to an element in the expected array. + * + * The value must be an array or iterable, which includes strings. + * + * @example + * expect(1).toBeOneOf([1,2,3]); + * expect("foo").toBeOneOf(["foo", "bar"]); + * expect(true).toBeOneOf(new Set([true])); + * + * @param expected the expected value + */ + toBeOneOf(expected: Array | Iterable): void; + /** + * Asserts that a value contains what is expected. + * + * The value must be an array or iterable, which + * includes strings. + * + * @example + * expect([1, 2, 3]).toContain(1); + * expect(new Set([true])).toContain(true); + * expect("hello").toContain("o"); + * + * @param expected the expected value + */ + toContain(expected: unknown): void; + /** + * Asserts that an `object` contains a key. + * + * The value must be an object + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); + * + * @param expected the expected value + */ + toContainKey(expected: unknown): void; + /** + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); + * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); + * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); + * + * @param expected the expected value + */ + toContainAllKeys(expected: unknown): void; + /** + * Asserts that an `object` contains at least one of the provided keys. + * Asserts that an `object` contains all the provided keys. + * + * The value must be an object + * + * @example + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); + * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); + * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); + * + * @param expected the expected value + */ + toContainAnyKeys(expected: unknown): void; + + /** * Asserts that an `object` contain the provided value. * * The value must be an object @@ -1094,1189 +1035,1148 @@ declare module "bun:test" { * * @param expected the expected value */ - toContainValue(expected: unknown): void; - - /** - * Asserts that an `object` contain the provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainValues(['foo']); - * expect(o).toContainValues(['baz', 'bar']); - * expect(o).not.toContainValues(['qux', 'foo']); - * @param expected the expected value - */ - toContainValues(expected: unknown): void; - - /** - * Asserts that an `object` contain all the provided values. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAllValues(['foo', 'bar', 'baz']); - * expect(o).toContainAllValues(['baz', 'bar', 'foo']); - * expect(o).not.toContainAllValues(['bar', 'foo']); - * @param expected the expected value - */ - toContainAllValues(expected: unknown): void; - - /** - * Asserts that an `object` contain any provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAnyValues(['qux', 'foo']); - * expect(o).toContainAnyValues(['qux', 'bar']); - * expect(o).toContainAnyValues(['qux', 'baz']); - * expect(o).not.toContainAnyValues(['qux']); - * @param expected the expected value - */ - toContainAnyValues(expected: unknown): void; - - /** - * Asserts that an `object` contains all the provided keys. - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); - * - * @param expected the expected value - */ - toContainKeys(expected: unknown): void; - /** - * Asserts that a value contains and equals what is expected. - * - * This matcher will perform a deep equality check for members - * of arrays, rather than checking for object identity. - * - * @example - * expect([{ a: 1 }]).toContainEqual({ a: 1 }); - * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); - * - * @param expected the expected value - */ - toContainEqual(expected: unknown): void; - /** - * Asserts that a value has a `.length` property - * that is equal to the expected length. - * - * @example - * expect([]).toHaveLength(0); - * expect("hello").toHaveLength(4); - * - * @param length the expected length - */ - toHaveLength(length: number): void; - /** - * Asserts that a value has a property with the - * expected name, and value if provided. - * - * @example - * expect(new Set()).toHaveProperty("size"); - * expect(new Uint8Array()).toHaveProperty("byteLength", 0); - * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); - * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); - * - * @param keyPath the expected property name or path, or an index - * @param value the expected property value, if provided - */ - toHaveProperty( - keyPath: string | number | Array, - value?: unknown, - ): void; - /** - * Asserts that a value is "truthy". - * - * To assert that a value equals `true`, use `toBe(true)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeTruthy(): void; - /** - * Asserts that a value is "falsy". - * - * To assert that a value equals `false`, use `toBe(false)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeFalsy(): void; - /** - * Asserts that a value is defined. (e.g. is not `undefined`) - * - * @example - * expect(true).toBeDefined(); - * expect(undefined).toBeDefined(); // fail - */ - toBeDefined(): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that a value is `undefined`. - * - * @example - * expect(undefined).toBeUndefined(); - * expect(null).toBeUndefined(); // fail - */ - toBeUndefined(): void; - /** - * Asserts that a value is `null`. - * - * @example - * expect(null).toBeNull(); - * expect(undefined).toBeNull(); // fail - */ - toBeNull(): void; - /** - * Asserts that a value is `NaN`. - * - * Same as using `Number.isNaN()`. - * - * @example - * expect(NaN).toBeNaN(); - * expect(Infinity).toBeNaN(); // fail - * expect("notanumber").toBeNaN(); // fail - */ - toBeNaN(): void; - /** - * Asserts that a value is a `number` and is greater than the expected value. - * - * @example - * expect(1).toBeGreaterThan(0); - * expect(3.14).toBeGreaterThan(3); - * expect(9).toBeGreaterThan(9); // fail - * - * @param expected the expected number - */ - toBeGreaterThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is greater than or equal to the expected value. - * - * @example - * expect(1).toBeGreaterThanOrEqual(0); - * expect(3.14).toBeGreaterThanOrEqual(3); - * expect(9).toBeGreaterThanOrEqual(9); - * - * @param expected the expected number - */ - toBeGreaterThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than the expected value. - * - * @example - * expect(-1).toBeLessThan(0); - * expect(3).toBeLessThan(3.14); - * expect(9).toBeLessThan(9); // fail - * - * @param expected the expected number - */ - toBeLessThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than or equal to the expected value. - * - * @example - * expect(-1).toBeLessThanOrEqual(0); - * expect(3).toBeLessThanOrEqual(3.14); - * expect(9).toBeLessThanOrEqual(9); - * - * @param expected the expected number - */ - toBeLessThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrow("Oops!"); - * expect(fail).toThrow(/oops/i); - * expect(fail).toThrow(Error); - * expect(fail).toThrow(); - * - * @param expected the expected error, error message, or error pattern - */ - toThrow(expected?: unknown): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowError("Oops!"); - * expect(fail).toThrowError(/oops/i); - * expect(fail).toThrowError(Error); - * expect(fail).toThrowError(); - * - * @param expected the expected error, error message, or error pattern - * @alias toThrow - */ - toThrowError(expected?: unknown): void; - /** - * Asserts that a value matches a regular expression or includes a substring. - * - * @example - * expect("dog").toMatch(/dog/); - * expect("dog").toMatch("og"); - * - * @param expected the expected substring or pattern. - */ - toMatch(expected: string | RegExp): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot('hint message'); - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(hint?: string): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot(); - * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); - * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(propertyMatchers?: object, hint?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect("Hello").toMatchInlineSnapshot(); - * expect("Hello").toMatchInlineSnapshot(`"Hello"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(value?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` - * { - * "v": Any, - * } - * `); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingSnapshot(); - * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingSnapshot(hint?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingInlineSnapshot(); - * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingInlineSnapshot(value?: string): void; - /** - * Asserts that an object matches a subset of properties. - * - * @example - * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); - * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); - * - * @param subset Subset of properties to match with. - */ - toMatchObject(subset: object): void; - /** - * Asserts that a value is empty. - * - * @example - * expect("").toBeEmpty(); - * expect([]).toBeEmpty(); - * expect({}).toBeEmpty(); - * expect(new Set()).toBeEmpty(); - */ - toBeEmpty(): void; - /** - * Asserts that a value is an empty `object`. - * - * @example - * expect({}).toBeEmptyObject(); - * expect({ a: 'hello' }).not.toBeEmptyObject(); - */ - toBeEmptyObject(): void; - /** - * Asserts that a value is `null` or `undefined`. - * - * @example - * expect(null).toBeNil(); - * expect(undefined).toBeNil(); - */ - toBeNil(): void; - /** - * Asserts that a value is a `array`. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray - * @example - * expect([1]).toBeArray(); - * expect(new Array(1)).toBeArray(); - * expect({}).not.toBeArray(); - */ - toBeArray(): void; - /** - * Asserts that a value is a `array` of a certain length. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize - * @example - * expect([]).toBeArrayOfSize(0); - * expect([1]).toBeArrayOfSize(1); - * expect(new Array(1)).toBeArrayOfSize(1); - * expect({}).not.toBeArrayOfSize(0); - */ - toBeArrayOfSize(size: number): void; - /** - * Asserts that a value is a `boolean`. - * - * @example - * expect(true).toBeBoolean(); - * expect(false).toBeBoolean(); - * expect(null).not.toBeBoolean(); - * expect(0).not.toBeBoolean(); - */ - toBeBoolean(): void; - /** - * Asserts that a value is `true`. - * - * @example - * expect(true).toBeTrue(); - * expect(false).not.toBeTrue(); - * expect(1).not.toBeTrue(); - */ - toBeTrue(): void; - /** - * Asserts that a value matches a specific type. - * - * @link https://vitest.dev/api/expect.html#tobetypeof - * @example - * expect(1).toBeTypeOf("number"); - * expect("hello").toBeTypeOf("string"); - * expect([]).not.toBeTypeOf("boolean"); - */ - toBeTypeOf( - type: - | "bigint" - | "boolean" - | "function" - | "number" - | "object" - | "string" - | "symbol" - | "undefined", - ): void; - /** - * Asserts that a value is `false`. - * - * @example - * expect(false).toBeFalse(); - * expect(true).not.toBeFalse(); - * expect(0).not.toBeFalse(); - */ - toBeFalse(): void; - /** - * Asserts that a value is a `number`. - * - * @example - * expect(1).toBeNumber(); - * expect(3.14).toBeNumber(); - * expect(NaN).toBeNumber(); - * expect(BigInt(1)).not.toBeNumber(); - */ - toBeNumber(): void; - /** - * Asserts that a value is a `number`, and is an integer. - * - * @example - * expect(1).toBeInteger(); - * expect(3.14).not.toBeInteger(); - * expect(NaN).not.toBeInteger(); - */ - toBeInteger(): void; - /** - * Asserts that a value is an `object`. - * - * @example - * expect({}).toBeObject(); - * expect("notAnObject").not.toBeObject(); - * expect(NaN).not.toBeObject(); - */ - toBeObject(): void; - /** - * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. - * - * @example - * expect(1).toBeFinite(); - * expect(3.14).toBeFinite(); - * expect(NaN).not.toBeFinite(); - * expect(Infinity).not.toBeFinite(); - */ - toBeFinite(): void; - /** - * Asserts that a value is a positive `number`. - * - * @example - * expect(1).toBePositive(); - * expect(-3.14).not.toBePositive(); - * expect(NaN).not.toBePositive(); - */ - toBePositive(): void; - /** - * Asserts that a value is a negative `number`. - * - * @example - * expect(-3.14).toBeNegative(); - * expect(1).not.toBeNegative(); - * expect(NaN).not.toBeNegative(); - */ - toBeNegative(): void; - /** - * Asserts that a value is a number between a start and end value. - * - * @param start the start number (inclusive) - * @param end the end number (exclusive) - */ - toBeWithin(start: number, end: number): void; - /** - * Asserts that a value is equal to the expected string, ignoring any whitespace. - * - * @example - * expect(" foo ").toEqualIgnoringWhitespace("foo"); - * expect("bar").toEqualIgnoringWhitespace(" bar "); - * - * @param expected the expected string - */ - toEqualIgnoringWhitespace(expected: string): void; - /** - * Asserts that a value is a `symbol`. - * - * @example - * expect(Symbol("foo")).toBeSymbol(); - * expect("foo").not.toBeSymbol(); - */ - toBeSymbol(): void; - /** - * Asserts that a value is a `function`. - * - * @example - * expect(() => {}).toBeFunction(); - */ - toBeFunction(): void; - /** - * Asserts that a value is a `Date` object. - * - * To check if a date is valid, use `toBeValidDate()` instead. - * - * @example - * expect(new Date()).toBeDate(); - * expect(new Date(null)).toBeDate(); - * expect("2020-03-01").not.toBeDate(); - */ - toBeDate(): void; - /** - * Asserts that a value is a valid `Date` object. - * - * @example - * expect(new Date()).toBeValidDate(); - * expect(new Date(null)).not.toBeValidDate(); - * expect("2020-03-01").not.toBeValidDate(); - */ - toBeValidDate(): void; - /** - * Asserts that a value is a `string`. - * - * @example - * expect("foo").toBeString(); - * expect(new String("bar")).toBeString(); - * expect(123).not.toBeString(); - */ - toBeString(): void; - /** - * Asserts that a value includes a `string`. - * - * For non-string values, use `toContain()` instead. - * - * @param expected the expected substring - */ - toInclude(expected: string): void; - /** - * Asserts that a value includes a `string` {times} times. - * @param expected the expected substring - * @param times the number of times the substring should occur - */ - toIncludeRepeated(expected: string, times: number): void; - /** - * Checks whether a value satisfies a custom condition. - * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. - * @example - * expect(1).toSatisfy((val) => val > 0); - * expect("foo").toSatisfy((val) => val === "foo"); - * expect("bar").not.toSatisfy((val) => val === "bun"); - * @link https://vitest.dev/api/expect.html#tosatisfy - * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy - */ - toSatisfy(predicate: (value: T) => boolean): void; - /** - * Asserts that a value starts with a `string`. - * - * @param expected the string to start with - */ - toStartWith(expected: string): void; - /** - * Asserts that a value ends with a `string`. - * - * @param expected the string to end with - */ - toEndWith(expected: string): void; - /** - * Ensures that a mock function has returned successfully at least once. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturned(): void; - - /** - * Ensures that a mock function has returned successfully at `times` times. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturnedTimes(times: number): void; - - /** - * Ensures that a mock function is called. - */ - toHaveBeenCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - * @alias toHaveBeenCalled - */ - toBeCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - */ - toHaveBeenCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledTimes - */ - toBeCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - */ - toHaveBeenCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledWith - */ - toBeCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the last call. - */ - toHaveBeenLastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - lastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - */ - toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - nthCalledWith(n: number, ...expected: unknown[]): void; - } - - /** - * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. - */ - // Defined as an alias of `any` so that it does not trigger any type mismatch - export type AsymmetricMatcher = any; - - export interface MatcherResult { - pass: boolean; - message?: string | (() => string); - } - - export type CustomMatcher = ( - this: MatcherContext, - expected: E, - ...matcherArguments: P - ) => MatcherResult | Promise; - - /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ - export type CustomMatchersDetected = Omit< - Matchers, - keyof MatchersBuiltin - > & - Omit; - - /** - * If the types has been defined through declaration merging, enforce it. - * Otherwise enforce the generic custom matcher signature. - */ - export type ExpectExtendMatchers = { - [k in keyof M]: k extends keyof CustomMatchersDetected - ? CustomMatcher> - : CustomMatcher; - }; - - /** Custom equality tester */ - export type Tester = ( - this: TesterContext, - a: any, - b: any, - customTesters: Tester[], - ) => boolean | undefined; - - export type EqualsFunction = ( - a: unknown, - b: unknown, - //customTesters?: Array, - //strictCheck?: boolean, - ) => boolean; - - export interface TesterContext { - equals: EqualsFunction; - } - - interface MatcherState { - //assertionCalls: number; - //currentConcurrentTestName?: () => string | undefined; - //currentTestName?: string; - //error?: Error; - //expand: boolean; - //expectedAssertionsNumber: number | null; - //expectedAssertionsNumberError?: Error; - //isExpectingAssertions: boolean; - //isExpectingAssertionsError?: Error; - isNot: boolean; - //numPassingAsserts: number; - promise: string; - //suppressedErrors: Array; - //testPath?: string; - } - - type MatcherHintColor = (arg: string) => string; // subset of Chalk type - - interface MatcherUtils { - //customTesters: Array; - //dontThrow(): void; // (internally used by jest snapshot) - equals: EqualsFunction; - utils: Readonly<{ - stringify(value: unknown): string; - printReceived(value: unknown): string; - printExpected(value: unknown): string; - matcherHint( - matcherName: string, - received?: unknown, - expected?: unknown, - options?: { - isNot?: boolean; - promise?: string; - isDirectExpectCall?: boolean; // (internal) - comment?: string; - expectedColor?: MatcherHintColor; - receivedColor?: MatcherHintColor; - secondArgument?: string; - secondArgumentColor?: MatcherHintColor; - }, - ): string; - //iterableEquality: Tester; - //subsetEquality: Tester; - // ... - }>; - } - - type MatcherContext = MatcherUtils & MatcherState; + toContainValue(expected: unknown): void; + + /** + * Asserts that an `object` contain the provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainValues(['foo']); + * expect(o).toContainValues(['baz', 'bar']); + * expect(o).not.toContainValues(['qux', 'foo']); + * @param expected the expected value + */ + toContainValues(expected: unknown): void; + + /** + * Asserts that an `object` contain all the provided values. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAllValues(['foo', 'bar', 'baz']); + * expect(o).toContainAllValues(['baz', 'bar', 'foo']); + * expect(o).not.toContainAllValues(['bar', 'foo']); + * @param expected the expected value + */ + toContainAllValues(expected: unknown): void; + + /** + * Asserts that an `object` contain any provided value. + * + * The value must be an object + * + * @example + * const o = { a: 'foo', b: 'bar', c: 'baz' }; + * expect(o).toContainAnyValues(['qux', 'foo']); + * expect(o).toContainAnyValues(['qux', 'bar']); + * expect(o).toContainAnyValues(['qux', 'baz']); + * expect(o).not.toContainAnyValues(['qux']); + * @param expected the expected value + */ + toContainAnyValues(expected: unknown): void; + + /** + * Asserts that an `object` contains all the provided keys. + * + * @example + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); + * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); + * + * @param expected the expected value + */ + toContainKeys(expected: unknown): void; + /** + * Asserts that a value contains and equals what is expected. + * + * This matcher will perform a deep equality check for members + * of arrays, rather than checking for object identity. + * + * @example + * expect([{ a: 1 }]).toContainEqual({ a: 1 }); + * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); + * + * @param expected the expected value + */ + toContainEqual(expected: unknown): void; + /** + * Asserts that a value has a `.length` property + * that is equal to the expected length. + * + * @example + * expect([]).toHaveLength(0); + * expect("hello").toHaveLength(4); + * + * @param length the expected length + */ + toHaveLength(length: number): void; + /** + * Asserts that a value has a property with the + * expected name, and value if provided. + * + * @example + * expect(new Set()).toHaveProperty("size"); + * expect(new Uint8Array()).toHaveProperty("byteLength", 0); + * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); + * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); + * + * @param keyPath the expected property name or path, or an index + * @param value the expected property value, if provided + */ + toHaveProperty(keyPath: string | number | Array, value?: unknown): void; + /** + * Asserts that a value is "truthy". + * + * To assert that a value equals `true`, use `toBe(true)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeTruthy(): void; + /** + * Asserts that a value is "falsy". + * + * To assert that a value equals `false`, use `toBe(false)` instead. + * + * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy + * @example + * expect(true).toBeTruthy(); + * expect(1).toBeTruthy(); + * expect({}).toBeTruthy(); + */ + toBeFalsy(): void; + /** + * Asserts that a value is defined. (e.g. is not `undefined`) + * + * @example + * expect(true).toBeDefined(); + * expect(undefined).toBeDefined(); // fail + */ + toBeDefined(): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that the expected value is an instance of value + * + * @example + * expect([]).toBeInstanceOf(Array); + * expect(null).toBeInstanceOf(Array); // fail + */ + toBeInstanceOf(value: unknown): void; + /** + * Asserts that a value is `undefined`. + * + * @example + * expect(undefined).toBeUndefined(); + * expect(null).toBeUndefined(); // fail + */ + toBeUndefined(): void; + /** + * Asserts that a value is `null`. + * + * @example + * expect(null).toBeNull(); + * expect(undefined).toBeNull(); // fail + */ + toBeNull(): void; + /** + * Asserts that a value is `NaN`. + * + * Same as using `Number.isNaN()`. + * + * @example + * expect(NaN).toBeNaN(); + * expect(Infinity).toBeNaN(); // fail + * expect("notanumber").toBeNaN(); // fail + */ + toBeNaN(): void; + /** + * Asserts that a value is a `number` and is greater than the expected value. + * + * @example + * expect(1).toBeGreaterThan(0); + * expect(3.14).toBeGreaterThan(3); + * expect(9).toBeGreaterThan(9); // fail + * + * @param expected the expected number + */ + toBeGreaterThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is greater than or equal to the expected value. + * + * @example + * expect(1).toBeGreaterThanOrEqual(0); + * expect(3.14).toBeGreaterThanOrEqual(3); + * expect(9).toBeGreaterThanOrEqual(9); + * + * @param expected the expected number + */ + toBeGreaterThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than the expected value. + * + * @example + * expect(-1).toBeLessThan(0); + * expect(3).toBeLessThan(3.14); + * expect(9).toBeLessThan(9); // fail + * + * @param expected the expected number + */ + toBeLessThan(expected: number | bigint): void; + /** + * Asserts that a value is a `number` and is less than or equal to the expected value. + * + * @example + * expect(-1).toBeLessThanOrEqual(0); + * expect(3).toBeLessThanOrEqual(3.14); + * expect(9).toBeLessThanOrEqual(9); + * + * @param expected the expected number + */ + toBeLessThanOrEqual(expected: number | bigint): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrow("Oops!"); + * expect(fail).toThrow(/oops/i); + * expect(fail).toThrow(Error); + * expect(fail).toThrow(); + * + * @param expected the expected error, error message, or error pattern + */ + toThrow(expected?: unknown): void; + /** + * Asserts that a function throws an error. + * + * - If expected is a `string` or `RegExp`, it will check the `message` property. + * - If expected is an `Error` object, it will check the `name` and `message` properties. + * - If expected is an `Error` constructor, it will check the class of the `Error`. + * - If expected is not provided, it will check if anything has thrown. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowError("Oops!"); + * expect(fail).toThrowError(/oops/i); + * expect(fail).toThrowError(Error); + * expect(fail).toThrowError(); + * + * @param expected the expected error, error message, or error pattern + * @alias toThrow + */ + toThrowError(expected?: unknown): void; + /** + * Asserts that a value matches a regular expression or includes a substring. + * + * @example + * expect("dog").toMatch(/dog/); + * expect("dog").toMatch("og"); + * + * @param expected the expected substring or pattern. + */ + toMatch(expected: string | RegExp): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot('hint message'); + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(hint?: string): void; + /** + * Asserts that a value matches the most recent snapshot. + * + * @example + * expect([1, 2, 3]).toMatchSnapshot(); + * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); + * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param hint Hint used to identify the snapshot in the snapshot file. + */ + toMatchSnapshot(propertyMatchers?: object, hint?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect("Hello").toMatchInlineSnapshot(); + * expect("Hello").toMatchInlineSnapshot(`"Hello"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(value?: string): void; + /** + * Asserts that a value matches the most recent inline snapshot. + * + * @example + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); + * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` + * { + * "v": Any, + * } + * `); + * + * @param propertyMatchers Object containing properties to match against the value. + * @param value The latest automatically-updated snapshot value. + */ + toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingSnapshot(); + * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingSnapshot(hint?: string): void; + /** + * Asserts that a function throws an error matching the most recent snapshot. + * + * @example + * function fail() { + * throw new Error("Oops!"); + * } + * expect(fail).toThrowErrorMatchingInlineSnapshot(); + * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); + * + * @param value The latest automatically-updated snapshot value. + */ + toThrowErrorMatchingInlineSnapshot(value?: string): void; + /** + * Asserts that an object matches a subset of properties. + * + * @example + * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); + * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); + * + * @param subset Subset of properties to match with. + */ + toMatchObject(subset: object): void; + /** + * Asserts that a value is empty. + * + * @example + * expect("").toBeEmpty(); + * expect([]).toBeEmpty(); + * expect({}).toBeEmpty(); + * expect(new Set()).toBeEmpty(); + */ + toBeEmpty(): void; + /** + * Asserts that a value is an empty `object`. + * + * @example + * expect({}).toBeEmptyObject(); + * expect({ a: 'hello' }).not.toBeEmptyObject(); + */ + toBeEmptyObject(): void; + /** + * Asserts that a value is `null` or `undefined`. + * + * @example + * expect(null).toBeNil(); + * expect(undefined).toBeNil(); + */ + toBeNil(): void; + /** + * Asserts that a value is a `array`. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray + * @example + * expect([1]).toBeArray(); + * expect(new Array(1)).toBeArray(); + * expect({}).not.toBeArray(); + */ + toBeArray(): void; + /** + * Asserts that a value is a `array` of a certain length. + * + * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize + * @example + * expect([]).toBeArrayOfSize(0); + * expect([1]).toBeArrayOfSize(1); + * expect(new Array(1)).toBeArrayOfSize(1); + * expect({}).not.toBeArrayOfSize(0); + */ + toBeArrayOfSize(size: number): void; + /** + * Asserts that a value is a `boolean`. + * + * @example + * expect(true).toBeBoolean(); + * expect(false).toBeBoolean(); + * expect(null).not.toBeBoolean(); + * expect(0).not.toBeBoolean(); + */ + toBeBoolean(): void; + /** + * Asserts that a value is `true`. + * + * @example + * expect(true).toBeTrue(); + * expect(false).not.toBeTrue(); + * expect(1).not.toBeTrue(); + */ + toBeTrue(): void; + /** + * Asserts that a value matches a specific type. + * + * @link https://vitest.dev/api/expect.html#tobetypeof + * @example + * expect(1).toBeTypeOf("number"); + * expect("hello").toBeTypeOf("string"); + * expect([]).not.toBeTypeOf("boolean"); + */ + toBeTypeOf(type: "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"): void; + /** + * Asserts that a value is `false`. + * + * @example + * expect(false).toBeFalse(); + * expect(true).not.toBeFalse(); + * expect(0).not.toBeFalse(); + */ + toBeFalse(): void; + /** + * Asserts that a value is a `number`. + * + * @example + * expect(1).toBeNumber(); + * expect(3.14).toBeNumber(); + * expect(NaN).toBeNumber(); + * expect(BigInt(1)).not.toBeNumber(); + */ + toBeNumber(): void; + /** + * Asserts that a value is a `number`, and is an integer. + * + * @example + * expect(1).toBeInteger(); + * expect(3.14).not.toBeInteger(); + * expect(NaN).not.toBeInteger(); + */ + toBeInteger(): void; + /** + * Asserts that a value is an `object`. + * + * @example + * expect({}).toBeObject(); + * expect("notAnObject").not.toBeObject(); + * expect(NaN).not.toBeObject(); + */ + toBeObject(): void; + /** + * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. + * + * @example + * expect(1).toBeFinite(); + * expect(3.14).toBeFinite(); + * expect(NaN).not.toBeFinite(); + * expect(Infinity).not.toBeFinite(); + */ + toBeFinite(): void; + /** + * Asserts that a value is a positive `number`. + * + * @example + * expect(1).toBePositive(); + * expect(-3.14).not.toBePositive(); + * expect(NaN).not.toBePositive(); + */ + toBePositive(): void; + /** + * Asserts that a value is a negative `number`. + * + * @example + * expect(-3.14).toBeNegative(); + * expect(1).not.toBeNegative(); + * expect(NaN).not.toBeNegative(); + */ + toBeNegative(): void; + /** + * Asserts that a value is a number between a start and end value. + * + * @param start the start number (inclusive) + * @param end the end number (exclusive) + */ + toBeWithin(start: number, end: number): void; + /** + * Asserts that a value is equal to the expected string, ignoring any whitespace. + * + * @example + * expect(" foo ").toEqualIgnoringWhitespace("foo"); + * expect("bar").toEqualIgnoringWhitespace(" bar "); + * + * @param expected the expected string + */ + toEqualIgnoringWhitespace(expected: string): void; + /** + * Asserts that a value is a `symbol`. + * + * @example + * expect(Symbol("foo")).toBeSymbol(); + * expect("foo").not.toBeSymbol(); + */ + toBeSymbol(): void; + /** + * Asserts that a value is a `function`. + * + * @example + * expect(() => {}).toBeFunction(); + */ + toBeFunction(): void; + /** + * Asserts that a value is a `Date` object. + * + * To check if a date is valid, use `toBeValidDate()` instead. + * + * @example + * expect(new Date()).toBeDate(); + * expect(new Date(null)).toBeDate(); + * expect("2020-03-01").not.toBeDate(); + */ + toBeDate(): void; + /** + * Asserts that a value is a valid `Date` object. + * + * @example + * expect(new Date()).toBeValidDate(); + * expect(new Date(null)).not.toBeValidDate(); + * expect("2020-03-01").not.toBeValidDate(); + */ + toBeValidDate(): void; + /** + * Asserts that a value is a `string`. + * + * @example + * expect("foo").toBeString(); + * expect(new String("bar")).toBeString(); + * expect(123).not.toBeString(); + */ + toBeString(): void; + /** + * Asserts that a value includes a `string`. + * + * For non-string values, use `toContain()` instead. + * + * @param expected the expected substring + */ + toInclude(expected: string): void; + /** + * Asserts that a value includes a `string` {times} times. + * @param expected the expected substring + * @param times the number of times the substring should occur + */ + toIncludeRepeated(expected: string, times: number): void; + /** + * Checks whether a value satisfies a custom condition. + * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. + * @example + * expect(1).toSatisfy((val) => val > 0); + * expect("foo").toSatisfy((val) => val === "foo"); + * expect("bar").not.toSatisfy((val) => val === "bun"); + * @link https://vitest.dev/api/expect.html#tosatisfy + * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy + */ + toSatisfy(predicate: (value: T) => boolean): void; + /** + * Asserts that a value starts with a `string`. + * + * @param expected the string to start with + */ + toStartWith(expected: string): void; + /** + * Asserts that a value ends with a `string`. + * + * @param expected the string to end with + */ + toEndWith(expected: string): void; + /** + * Ensures that a mock function has returned successfully at least once. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturned(): void; + + /** + * Ensures that a mock function has returned successfully at `times` times. + * + * A promise that is unfulfilled will be considered a failure. If the + * function threw an error, it will be considered a failure. + */ + toHaveReturnedTimes(times: number): void; + + /** + * Ensures that a mock function is called. + */ + toHaveBeenCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + * @alias toHaveBeenCalled + */ + toBeCalled(): void; + /** + * Ensures that a mock function is called an exact number of times. + */ + toHaveBeenCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledTimes + */ + toBeCalledTimes(expected: number): void; + /** + * Ensure that a mock function is called with specific arguments. + */ + toHaveBeenCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments. + * @alias toHaveBeenCalledWith + */ + toBeCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the last call. + */ + toHaveBeenLastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + lastCalledWith(...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + */ + toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; + /** + * Ensure that a mock function is called with specific arguments for the nth call. + * @alias toHaveBeenCalledWith + */ + nthCalledWith(n: number, ...expected: unknown[]): void; + } + + /** + * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. + */ + // Defined as an alias of `any` so that it does not trigger any type mismatch + export type AsymmetricMatcher = any; + + export interface MatcherResult { + pass: boolean; + message?: string | (() => string); + } + + export type CustomMatcher = ( + this: MatcherContext, + expected: E, + ...matcherArguments: P + ) => MatcherResult | Promise; + + /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ + export type CustomMatchersDetected = Omit, keyof MatchersBuiltin> & + Omit; + + /** + * If the types has been defined through declaration merging, enforce it. + * Otherwise enforce the generic custom matcher signature. + */ + export type ExpectExtendMatchers = { + [k in keyof M]: k extends keyof CustomMatchersDetected + ? CustomMatcher> + : CustomMatcher; + }; + + /** Custom equality tester */ + export type Tester = (this: TesterContext, a: any, b: any, customTesters: Tester[]) => boolean | undefined; + + export type EqualsFunction = ( + a: unknown, + b: unknown, + //customTesters?: Array, + //strictCheck?: boolean, + ) => boolean; + + export interface TesterContext { + equals: EqualsFunction; + } + + interface MatcherState { + //assertionCalls: number; + //currentConcurrentTestName?: () => string | undefined; + //currentTestName?: string; + //error?: Error; + //expand: boolean; + //expectedAssertionsNumber: number | null; + //expectedAssertionsNumberError?: Error; + //isExpectingAssertions: boolean; + //isExpectingAssertionsError?: Error; + isNot: boolean; + //numPassingAsserts: number; + promise: string; + //suppressedErrors: Array; + //testPath?: string; + } + + type MatcherHintColor = (arg: string) => string; // subset of Chalk type + + interface MatcherUtils { + //customTesters: Array; + //dontThrow(): void; // (internally used by jest snapshot) + equals: EqualsFunction; + utils: Readonly<{ + stringify(value: unknown): string; + printReceived(value: unknown): string; + printExpected(value: unknown): string; + matcherHint( + matcherName: string, + received?: unknown, + expected?: unknown, + options?: { + isNot?: boolean; + promise?: string; + isDirectExpectCall?: boolean; // (internal) + comment?: string; + expectedColor?: MatcherHintColor; + receivedColor?: MatcherHintColor; + secondArgument?: string; + secondArgumentColor?: MatcherHintColor; + }, + ): string; + //iterableEquality: Tester; + //subsetEquality: Tester; + // ... + }>; + } + + type MatcherContext = MatcherUtils & MatcherState; } declare module "test" { - export type * from "bun:test"; + export type * from "bun:test"; } declare namespace JestMock { - /** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - export interface ClassLike { - new (...args: any): any; - } - - export type ConstructorLikeKeys = keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - }; - - // export const fn: ( - // implementation?: T | undefined, - // ) => Mock; - - export type FunctionLike = (...args: any) => any; - - export type MethodLikeKeys = keyof { - [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; - }; - - export interface Mock any> - extends MockInstance { - (...args: Parameters): ReturnType; - } - - /** - * All what the internal typings need is to be sure that we have any-function. - * `FunctionLike` type ensures that and helps to constrain the type as well. - * The default of `UnknownFunction` makes sure that `any`s do not leak to the - * user side. For instance, calling `fn()` without implementation will return - * a mock of `(...args: Array) => unknown` type. If implementation - * is provided, its typings are inferred correctly. - */ - // export interface Mock - // extends Function, - // MockInstance { - // new (...args: Parameters): ReturnType; - // (...args: Parameters): ReturnType; - // } - - // export type Mocked = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunction - // : T extends object - // ? MockedObject - // : T; - - // export const mocked: { - // ( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // ( - // source: T_1, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // }; - - // export type MockedClass = MockInstance< - // (...args: ConstructorParameters) => Mocked> - // > & - // MockedObject; - - // export type MockedFunction = MockInstance & - // MockedObject; - - // type MockedFunctionShallow = MockInstance & T; - - // export type MockedObject = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunction - // : T[K] extends object - // ? MockedObject - // : T[K]; - // } & T; - - // type MockedObjectShallow = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunctionShallow - // : T[K]; - // } & T; - - // export type MockedShallow = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunctionShallow - // : T extends object - // ? MockedObjectShallow - // : T; - - // export type MockFunctionMetadata< - // T = unknown, - // MetadataType = MockMetadataType, - // > = MockMetadata; - - // export type MockFunctionMetadataType = MockMetadataType; - - type MockFunctionResult = - | MockFunctionResultIncomplete - | MockFunctionResultReturn - | MockFunctionResultThrow; - - interface MockFunctionResultIncomplete { - type: "incomplete"; - /** - * Result of a single call to a mock function that has not yet completed. - * This occurs if you test the result from within the mock function itself, - * or from within a function that was called by the mock. - */ - value: undefined; - } - - interface MockFunctionResultReturn { - type: "return"; - /** - * Result of a single call to a mock function that returned. - */ - value: ReturnType; - } - - interface MockFunctionResultThrow { - type: "throw"; - /** - * Result of a single call to a mock function that threw. - */ - value: unknown; - } - - interface MockFunctionState { - /** - * List of the call arguments of all calls that have been made to the mock. - */ - calls: Array>; - /** - * List of all the object instances that have been instantiated from the mock. - */ - instances: Array>; - /** - * List of all the function contexts that have been applied to calls to the mock. - */ - contexts: Array>; - /** - * List of the call order indexes of the mock. Jest is indexing the order of - * invocations of all mocks in a test file. The index is starting with `1`. - */ - invocationCallOrder: number[]; - /** - * List of the call arguments of the last call that was made to the mock. - * If the function was not called, it will return `undefined`. - */ - lastCall?: Parameters; - /** - * List of the results of all calls that have been made to the mock. - */ - results: Array>; - } - - export interface MockInstance { - _isMockFunction: true; - _protoImpl: Function; - getMockImplementation(): T | undefined; - getMockName(): string; - mock: MockFunctionState; - mockClear(): this; - mockReset(): this; - mockRestore(): void; - mockImplementation(fn: T): this; - mockImplementationOnce(fn: T): this; - withImplementation(fn: T, callback: () => Promise): Promise; - withImplementation(fn: T, callback: () => void): void; - mockName(name: string): this; - mockReturnThis(): this; - mockReturnValue(value: ReturnType): this; - mockReturnValueOnce(value: ReturnType): this; - mockResolvedValue(value: ResolveType): this; - mockResolvedValueOnce(value: ResolveType): this; - mockRejectedValue(value: RejectType): this; - mockRejectedValueOnce(value: RejectType): this; - } - - // export type MockMetadata = { - // ref?: number; - // members?: Record>; - // mockImpl?: T; - // name?: string; - // refID?: number; - // type?: MetadataType; - // value?: T; - // length?: number; - // }; - - // export type MockMetadataType = - // | "object" - // | "array" - // | "regexp" - // | "function" - // | "constant" - // | "collection" - // | "null" - // | "undefined"; - - // export class ModuleMocker { - // private readonly _environmentGlobal; - // private _mockState; - // private _mockConfigRegistry; - // private _spyState; - // private _invocationCallCounter; - // /** - // * @see README.md - // * @param global Global object of the test environment, used to create - // * mocks - // */ - // constructor(global: typeof globalThis); - // private _getSlots; - // private _ensureMockConfig; - // private _ensureMockState; - // private _defaultMockConfig; - // private _defaultMockState; - // private _makeComponent; - // private _createMockFunction; - // private _generateMock; - // /** - // * Check whether the given property of an object has been already replaced. - // */ - // private _findReplacedProperty; - // /** - // * @see README.md - // * @param metadata Metadata for the mock in the schema returned by the - // * getMetadata method of this module. - // */ - // generateFromMetadata(metadata: MockMetadata): Mocked; - // /** - // * @see README.md - // * @param component The component for which to retrieve metadata. - // */ - // getMetadata( - // component: T, - // _refs?: Map, - // ): MockMetadata | null; - // isMockFunction( - // fn: MockInstance, - // ): fn is MockInstance; - // isMockFunction

, R>( - // fn: (...args: P) => R, - // ): fn is Mock<(...args: P) => R>; - // isMockFunction(fn: unknown): fn is Mock; - // fn(implementation?: T): Mock; - // private _attachMockImplementation; - // spyOn< - // T extends object, - // K extends PropertyLikeKeys, - // A extends "get" | "set", - // >( - // object: T, - // methodKey: K, - // accessType: A, - // ): A extends "get" - // ? SpiedGetter - // : A extends "set" - // ? SpiedSetter - // : never; - // spyOn< - // T extends object, - // K extends ConstructorLikeKeys | MethodLikeKeys, - // V extends Required[K], - // >( - // object: T, - // methodKey: K, - // ): V extends ClassLike | FunctionLike ? Spied : never; - // private _spyOnProperty; - // replaceProperty< - // T extends object, - // K extends PropertyLikeKeys, - // V extends T[K], - // >(object: T, propertyKey: K, value: V): Replaced; - // clearAllMocks(): void; - // resetAllMocks(): void; - // restoreAllMocks(): void; - // private _typeOf; - // mocked( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // mocked( - // source: T, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // } - - export type PropertyLikeKeys = Exclude< - keyof T, - ConstructorLikeKeys | MethodLikeKeys - >; - - export type RejectType = - ReturnType extends PromiseLike ? unknown : never; - - export interface Replaced { - /** - * Restore property to its original value known at the time of mocking. - */ - restore(): void; - /** - * Change the value of the property. - */ - replaceValue(value: T): this; - } - - export function replaceProperty< - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike - ? K_1 - : never]: T[K_1]; - } - >, - V extends T[K_2], - >(object: T, propertyKey: K_2, value: V): Replaced; - - export type ResolveType = - ReturnType extends PromiseLike ? U : never; - - export type Spied = T extends ClassLike - ? SpiedClass - : T extends FunctionLike - ? SpiedFunction - : never; - - export type SpiedClass = MockInstance< - (...args: ConstructorParameters) => InstanceType - >; - - export type SpiedFunction = - MockInstance<(...args: Parameters) => ReturnType>; - - export type SpiedGetter = MockInstance<() => T>; - - export type SpiedSetter = MockInstance<(arg: T) => void>; - - export interface SpyInstance - extends MockInstance {} - - export const spyOn: { - < - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike - ? K - : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike - ? K_1 - : never]: T[K_1]; - } - >, - V extends Required[K_2], - A extends "set" | "get", - >( - object: T, - methodKey: K_2, - accessType: A, - ): A extends "get" - ? SpiedGetter - : A extends "set" - ? SpiedSetter - : never; - < - T_1 extends object, - K_5 extends - | keyof { - [K_3 in keyof T_1 as Required[K_3] extends ClassLike - ? K_3 - : never]: T_1[K_3]; - } - | keyof { - [K_4 in keyof T_1 as Required[K_4] extends FunctionLike - ? K_4 - : never]: T_1[K_4]; - }, - V_1 extends Required[K_5], - >( - object: T_1, - methodKey: K_5, - ): V_1 extends ClassLike | FunctionLike ? Spied : never; - }; - - export interface UnknownClass { - new (...args: unknown[]): unknown; - } - - export type UnknownFunction = (...args: unknown[]) => unknown; + /** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + export interface ClassLike { + new (...args: any): any; + } + + export type ConstructorLikeKeys = keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + }; + + // export const fn: ( + // implementation?: T | undefined, + // ) => Mock; + + export type FunctionLike = (...args: any) => any; + + export type MethodLikeKeys = keyof { + [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; + }; + + export interface Mock any> extends MockInstance { + (...args: Parameters): ReturnType; + } + + /** + * All what the internal typings need is to be sure that we have any-function. + * `FunctionLike` type ensures that and helps to constrain the type as well. + * The default of `UnknownFunction` makes sure that `any`s do not leak to the + * user side. For instance, calling `fn()` without implementation will return + * a mock of `(...args: Array) => unknown` type. If implementation + * is provided, its typings are inferred correctly. + */ + // export interface Mock + // extends Function, + // MockInstance { + // new (...args: Parameters): ReturnType; + // (...args: Parameters): ReturnType; + // } + + // export type Mocked = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunction + // : T extends object + // ? MockedObject + // : T; + + // export const mocked: { + // ( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // ( + // source: T_1, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // }; + + // export type MockedClass = MockInstance< + // (...args: ConstructorParameters) => Mocked> + // > & + // MockedObject; + + // export type MockedFunction = MockInstance & + // MockedObject; + + // type MockedFunctionShallow = MockInstance & T; + + // export type MockedObject = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunction + // : T[K] extends object + // ? MockedObject + // : T[K]; + // } & T; + + // type MockedObjectShallow = { + // [K in keyof T]: T[K] extends ClassLike + // ? MockedClass + // : T[K] extends FunctionLike + // ? MockedFunctionShallow + // : T[K]; + // } & T; + + // export type MockedShallow = T extends ClassLike + // ? MockedClass + // : T extends FunctionLike + // ? MockedFunctionShallow + // : T extends object + // ? MockedObjectShallow + // : T; + + // export type MockFunctionMetadata< + // T = unknown, + // MetadataType = MockMetadataType, + // > = MockMetadata; + + // export type MockFunctionMetadataType = MockMetadataType; + + type MockFunctionResult = + | MockFunctionResultIncomplete + | MockFunctionResultReturn + | MockFunctionResultThrow; + + interface MockFunctionResultIncomplete { + type: "incomplete"; + /** + * Result of a single call to a mock function that has not yet completed. + * This occurs if you test the result from within the mock function itself, + * or from within a function that was called by the mock. + */ + value: undefined; + } + + interface MockFunctionResultReturn { + type: "return"; + /** + * Result of a single call to a mock function that returned. + */ + value: ReturnType; + } + + interface MockFunctionResultThrow { + type: "throw"; + /** + * Result of a single call to a mock function that threw. + */ + value: unknown; + } + + interface MockFunctionState { + /** + * List of the call arguments of all calls that have been made to the mock. + */ + calls: Array>; + /** + * List of all the object instances that have been instantiated from the mock. + */ + instances: Array>; + /** + * List of all the function contexts that have been applied to calls to the mock. + */ + contexts: Array>; + /** + * List of the call order indexes of the mock. Jest is indexing the order of + * invocations of all mocks in a test file. The index is starting with `1`. + */ + invocationCallOrder: number[]; + /** + * List of the call arguments of the last call that was made to the mock. + * If the function was not called, it will return `undefined`. + */ + lastCall?: Parameters; + /** + * List of the results of all calls that have been made to the mock. + */ + results: Array>; + } + + export interface MockInstance { + _isMockFunction: true; + _protoImpl: Function; + getMockImplementation(): T | undefined; + getMockName(): string; + mock: MockFunctionState; + mockClear(): this; + mockReset(): this; + mockRestore(): void; + mockImplementation(fn: T): this; + mockImplementationOnce(fn: T): this; + withImplementation(fn: T, callback: () => Promise): Promise; + withImplementation(fn: T, callback: () => void): void; + mockName(name: string): this; + mockReturnThis(): this; + mockReturnValue(value: ReturnType): this; + mockReturnValueOnce(value: ReturnType): this; + mockResolvedValue(value: ResolveType): this; + mockResolvedValueOnce(value: ResolveType): this; + mockRejectedValue(value: RejectType): this; + mockRejectedValueOnce(value: RejectType): this; + } + + // export type MockMetadata = { + // ref?: number; + // members?: Record>; + // mockImpl?: T; + // name?: string; + // refID?: number; + // type?: MetadataType; + // value?: T; + // length?: number; + // }; + + // export type MockMetadataType = + // | "object" + // | "array" + // | "regexp" + // | "function" + // | "constant" + // | "collection" + // | "null" + // | "undefined"; + + // export class ModuleMocker { + // private readonly _environmentGlobal; + // private _mockState; + // private _mockConfigRegistry; + // private _spyState; + // private _invocationCallCounter; + // /** + // * @see README.md + // * @param global Global object of the test environment, used to create + // * mocks + // */ + // constructor(global: typeof globalThis); + // private _getSlots; + // private _ensureMockConfig; + // private _ensureMockState; + // private _defaultMockConfig; + // private _defaultMockState; + // private _makeComponent; + // private _createMockFunction; + // private _generateMock; + // /** + // * Check whether the given property of an object has been already replaced. + // */ + // private _findReplacedProperty; + // /** + // * @see README.md + // * @param metadata Metadata for the mock in the schema returned by the + // * getMetadata method of this module. + // */ + // generateFromMetadata(metadata: MockMetadata): Mocked; + // /** + // * @see README.md + // * @param component The component for which to retrieve metadata. + // */ + // getMetadata( + // component: T, + // _refs?: Map, + // ): MockMetadata | null; + // isMockFunction( + // fn: MockInstance, + // ): fn is MockInstance; + // isMockFunction

, R>( + // fn: (...args: P) => R, + // ): fn is Mock<(...args: P) => R>; + // isMockFunction(fn: unknown): fn is Mock; + // fn(implementation?: T): Mock; + // private _attachMockImplementation; + // spyOn< + // T extends object, + // K extends PropertyLikeKeys, + // A extends "get" | "set", + // >( + // object: T, + // methodKey: K, + // accessType: A, + // ): A extends "get" + // ? SpiedGetter + // : A extends "set" + // ? SpiedSetter + // : never; + // spyOn< + // T extends object, + // K extends ConstructorLikeKeys | MethodLikeKeys, + // V extends Required[K], + // >( + // object: T, + // methodKey: K, + // ): V extends ClassLike | FunctionLike ? Spied : never; + // private _spyOnProperty; + // replaceProperty< + // T extends object, + // K extends PropertyLikeKeys, + // V extends T[K], + // >(object: T, propertyKey: K, value: V): Replaced; + // clearAllMocks(): void; + // resetAllMocks(): void; + // restoreAllMocks(): void; + // private _typeOf; + // mocked( + // source: T, + // options?: { + // shallow: false; + // }, + // ): Mocked; + // mocked( + // source: T, + // options: { + // shallow: true; + // }, + // ): MockedShallow; + // } + + export type PropertyLikeKeys = Exclude | MethodLikeKeys>; + + export type RejectType = ReturnType extends PromiseLike ? unknown : never; + + export interface Replaced { + /** + * Restore property to its original value known at the time of mocking. + */ + restore(): void; + /** + * Change the value of the property. + */ + replaceValue(value: T): this; + } + + export function replaceProperty< + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; + } + >, + V extends T[K_2], + >(object: T, propertyKey: K_2, value: V): Replaced; + + export type ResolveType = ReturnType extends PromiseLike ? U : never; + + export type Spied = T extends ClassLike + ? SpiedClass + : T extends FunctionLike + ? SpiedFunction + : never; + + export type SpiedClass = MockInstance< + (...args: ConstructorParameters) => InstanceType + >; + + export type SpiedFunction = MockInstance< + (...args: Parameters) => ReturnType + >; + + export type SpiedGetter = MockInstance<() => T>; + + export type SpiedSetter = MockInstance<(arg: T) => void>; + + export interface SpyInstance extends MockInstance {} + + export const spyOn: { + < + T extends object, + K_2 extends Exclude< + keyof T, + | keyof { + [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; + } + | keyof { + [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; + } + >, + V extends Required[K_2], + A extends "set" | "get", + >( + object: T, + methodKey: K_2, + accessType: A, + ): A extends "get" ? SpiedGetter : A extends "set" ? SpiedSetter : never; + < + T_1 extends object, + K_5 extends + | keyof { + [K_3 in keyof T_1 as Required[K_3] extends ClassLike ? K_3 : never]: T_1[K_3]; + } + | keyof { + [K_4 in keyof T_1 as Required[K_4] extends FunctionLike ? K_4 : never]: T_1[K_4]; + }, + V_1 extends Required[K_5], + >( + object: T_1, + methodKey: K_5, + ): V_1 extends ClassLike | FunctionLike ? Spied : never; + }; + + export interface UnknownClass { + new (...args: unknown[]): unknown; + } + + export type UnknownFunction = (...args: unknown[]) => unknown; } diff --git a/packages/bun-types/new/wasm.d.ts b/packages/bun-types/new/wasm.d.ts new file mode 100644 index 00000000000000..aeec8d4aceaaa5 --- /dev/null +++ b/packages/bun-types/new/wasm.d.ts @@ -0,0 +1,188 @@ +declare module "bun" { + namespace WebAssembly { + type ImportExportKind = "function" | "global" | "memory" | "table"; + type TableKind = "anyfunc" | "externref"; + type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table; + type Exports = Record; + type ImportValue = ExportValue | number; + type Imports = Record; + type ModuleImports = Record; + + interface ValueTypeMap { + anyfunc: Function; + externref: any; + f32: number; + f64: number; + i32: number; + i64: bigint; + v128: never; + } + + type ValueType = keyof ValueTypeMap; + + interface GlobalDescriptor { + mutable?: boolean; + value: T; + } + + interface Global { + // { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ + value: ValueTypeMap[T]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ + valueOf(): ValueTypeMap[T]; + } + + interface CompileError extends Error {} + + interface LinkError extends Error {} + + interface RuntimeError extends Error {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ + interface Instance { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ + readonly exports: Exports; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ + interface Memory { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ + readonly buffer: ArrayBuffer; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ + grow(delta: number): number; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ + interface Module {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ + interface Table { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ + readonly length: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ + get(index: number): any; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ + grow(delta: number, value?: any): number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ + set(index: number, value?: any): void; + } + + interface MemoryDescriptor { + initial: number; + maximum?: number; + shared?: boolean; + } + + interface ModuleExportDescriptor { + kind: ImportExportKind; + name: string; + } + + interface ModuleImportDescriptor { + kind: ImportExportKind; + module: string; + name: string; + } + + interface TableDescriptor { + element: TableKind; + initial: number; + maximum?: number; + } + + interface WebAssemblyInstantiatedSource { + instance: Instance; + module: Module; + } + } +} + +declare namespace WebAssembly { + interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} + interface GlobalDescriptor + extends Bun.WebAssembly.GlobalDescriptor {} + interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} + interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} + interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} + interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} + interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} + + interface LinkError extends Bun.WebAssembly.LinkError {} + var LinkError: { + prototype: LinkError; + new (message?: string): LinkError; + (message?: string): LinkError; + }; + + interface CompileError extends Bun.WebAssembly.CompileError {} + var CompileError: { + prototype: CompileError; + new (message?: string): CompileError; + (message?: string): CompileError; + }; + + interface RuntimeError extends Bun.WebAssembly.RuntimeError {} + var RuntimeError: { + prototype: RuntimeError; + new (message?: string): RuntimeError; + (message?: string): RuntimeError; + }; + + interface Global extends Bun.WebAssembly.Global {} + var Global: { + prototype: Global; + new ( + descriptor: GlobalDescriptor, + v?: ValueTypeMap[T], + ): Global; + }; + + interface Instance extends Bun.WebAssembly.Instance {} + var Instance: { + prototype: Instance; + new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; + }; + + interface Memory extends Bun.WebAssembly.Memory {} + var Memory: { + prototype: Memory; + new (descriptor: MemoryDescriptor): Memory; + }; + + interface Module extends Bun.WebAssembly.Module {} + var Module: { + prototype: Module; + new (bytes: Bun.BufferSource): Module; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ + customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ + exports(moduleObject: Module): ModuleExportDescriptor[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + + interface Table extends Bun.WebAssembly.Table {} + var Table: { + prototype: Table; + new (descriptor: TableDescriptor, value?: any): Table; + }; + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ + function compile(bytes: Bun.BufferSource): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ + function compileStreaming(source: Response | PromiseLike): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ + function instantiate( + bytes: Bun.BufferSource, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ + function instantiateStreaming( + source: Response | PromiseLike, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ + function validate(bytes: Bun.BufferSource): boolean; +} diff --git a/packages/bun-types/overrides.d.ts b/packages/bun-types/overrides.d.ts index e679e20ae30824..2c9563224342e2 100644 --- a/packages/bun-types/overrides.d.ts +++ b/packages/bun-types/overrides.d.ts @@ -3,72 +3,62 @@ export {}; import type { BunFile, Env, PathLike } from "bun"; declare global { - namespace NodeJS { - interface ProcessVersions extends Dict { - bun: string; - } - interface ProcessEnv extends Env {} - } + namespace NodeJS { + interface ProcessVersions extends Dict { + bun: string; + } + interface ProcessEnv extends Env {} + } } declare module "fs/promises" { - function exists(path: PathLike): Promise; + function exists(path: PathLike): Promise; } declare module "tls" { - interface BunConnectionOptions - extends Omit { - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: - | string - | Buffer - | NodeJS.TypedArray - | BunFile - | Array - | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: - | string - | Buffer - | NodeJS.TypedArray - | BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: - | string - | Buffer - | BunFile - | NodeJS.TypedArray - | Array - | undefined; - } + interface BunConnectionOptions extends Omit { + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: string | Buffer | NodeJS.TypedArray | BunFile | Array | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: + | string + | Buffer + | NodeJS.TypedArray + | BunFile + | Array + | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: [, + * passphrase: ]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: + | string + | Buffer + | BunFile + | NodeJS.TypedArray + | Array + | undefined; + } - function connect( - options: BunConnectionOptions, - secureConnectListener?: () => void, - ): TLSSocket; + function connect(options: BunConnectionOptions, secureConnectListener?: () => void): TLSSocket; } diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index f07e563727bd7e..4078ec8835e103 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -1,39 +1,32 @@ { - "name": "bun-types", - "license": "MIT", - "types": "./new/index.d.ts", - "description": "Type definitions and documentation for Bun, an incredibly fast JavaScript runtime", - "repository": { - "type": "git", - "url": "https://github.com/oven-sh/bun", - "directory": "packages/bun-types" - }, - "files": [ - "new/**/*.d.ts", - "docs/**/*.md", - "docs/*.md" - ], - "homepage": "https://bun.sh", - "dependencies": { - "@types/node": "*", - "@types/ws": "~8.5.10" - }, - "devDependencies": { - "@biomejs/biome": "^1.5.3", - "@definitelytyped/dtslint": "^0.0.199", - "@definitelytyped/eslint-plugin": "^0.0.197", - "typescript": "^5.0.2" - }, - "scripts": { - "prebuild": "echo $(pwd)", - "copy-docs": "rm -rf docs && cp -rL ../../docs/ ./docs && find ./docs -type f -name '*.md' -exec sed -i 's/\\$BUN_LATEST_VERSION/'\"${BUN_VERSION#bun-v}\"'/g' {} +", - "build": "bun run copy-docs && bun scripts/build.ts && bun run fmt", - "test": "tsc", - "fmt": "echo $(which biome) && biome format --write ." - }, - "keywords": [ - "bun", - "bun.js", - "types" - ] + "version": "1.2.5", + "name": "bun-types", + "license": "MIT", + "types": "./new/index.d.ts", + "description": "Type definitions and documentation for Bun, an incredibly fast JavaScript runtime", + "repository": { + "type": "git", + "url": "https://github.com/oven-sh/bun", + "directory": "packages/bun-types" + }, + "files": ["new/**/*.d.ts", "docs/**/*.md", "docs/*.md"], + "homepage": "https://bun.sh", + "dependencies": { + "@types/node": "*", + "@types/ws": "~8.5.10" + }, + "devDependencies": { + "@biomejs/biome": "^1.5.3", + "@definitelytyped/dtslint": "^0.0.199", + "@definitelytyped/eslint-plugin": "^0.0.197", + "typescript": "^5.0.2" + }, + "scripts": { + "prebuild": "echo $(pwd)", + "copy-docs": "rm -rf docs && cp -rL ../../docs/ ./docs && find ./docs -type f -name '*.md' -exec sed -i 's/\\$BUN_LATEST_VERSION/'\"${BUN_VERSION#bun-v}\"'/g' {} +", + "build": "bun run copy-docs && bun scripts/build.ts && bun run fmt", + "test": "tsc", + "fmt": "echo $(which biome) && biome format --write ." + }, + "keywords": ["bun", "bun.js", "types"] } diff --git a/packages/bun-types/sqlite.d.ts b/packages/bun-types/sqlite.d.ts index 303469772cb98c..dd370d3f46bcc2 100644 --- a/packages/bun-types/sqlite.d.ts +++ b/packages/bun-types/sqlite.d.ts @@ -24,1143 +24,1118 @@ * | `null` | `NULL` | */ declare module "bun:sqlite" { - export class Database implements Disposable { - /** - * Open or create a SQLite3 database - * - * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. - * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. - * - * @example - * - * ```ts - * const db = new Database("mydb.sqlite"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open an in-memory database - * - * ```ts - * const db = new Database(":memory:"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open read-only - * - * ```ts - * const db = new Database("mydb.sqlite", {readonly: true}); - * ``` - */ - constructor( - filename?: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; + export class Database implements Disposable { + /** + * Open or create a SQLite3 database + * + * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. + * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. + * + * @example + * + * ```ts + * const db = new Database("mydb.sqlite"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open an in-memory database + * + * ```ts + * const db = new Database(":memory:"); + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); + * console.log(db.query("SELECT * FROM foo").all()); + * ``` + * + * @example + * + * Open read-only + * + * ```ts + * const db = new Database("mydb.sqlite", {readonly: true}); + * ``` + */ + constructor( + filename?: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; - /** - * When set to `true`, integers are returned as `bigint` types. - * - * When set to `false`, integers are returned as `number` types and truncated to 52 bits. - * - * @default false - * @since v1.1.14 - */ - safeIntegers?: boolean; + /** + * When set to `true`, integers are returned as `bigint` types. + * + * When set to `false`, integers are returned as `number` types and truncated to 52 bits. + * + * @default false + * @since v1.1.14 + */ + safeIntegers?: boolean; - /** - * When set to `false` or `undefined`: - * - Queries missing bound parameters will NOT throw an error - * - Bound named parameters in JavaScript need to exactly match the SQL query. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: false }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); - * ``` - * - * When set to `true`: - * - Queries missing bound parameters will throw an error - * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: true }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); - * ``` - * @since v1.1.14 - */ - strict?: boolean; - }, - ); + /** + * When set to `false` or `undefined`: + * - Queries missing bound parameters will NOT throw an error + * - Bound named parameters in JavaScript need to exactly match the SQL query. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: false }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); + * ``` + * + * When set to `true`: + * - Queries missing bound parameters will throw an error + * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. + * + * @example + * ```ts + * const db = new Database(":memory:", { strict: true }); + * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); + * ``` + * @since v1.1.14 + */ + strict?: boolean; + }, + ); - /** - * This is an alias of `new Database()` - * - * See {@link Database} - */ - static open( - filename: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; - }, - ): Database; + /** + * This is an alias of `new Database()` + * + * See {@link Database} + */ + static open( + filename: string, + options?: + | number + | { + /** + * Open the database as read-only (no write operations, no create). + * + * Equivalent to {@link constants.SQLITE_OPEN_READONLY} + */ + readonly?: boolean; + /** + * Allow creating a new database + * + * Equivalent to {@link constants.SQLITE_OPEN_CREATE} + */ + create?: boolean; + /** + * Open the database as read-write + * + * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} + */ + readwrite?: boolean; + }, + ): Database; - /** - * Execute a SQL query **without returning any results**. - * - * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * ``` - * - * Useful for queries like: - * - `CREATE TABLE` - * - `INSERT INTO` - * - `UPDATE` - * - `DELETE FROM` - * - `DROP TABLE` - * - `PRAGMA` - * - `ATTACH DATABASE` - * - `DETACH DATABASE` - * - `REINDEX` - * - `VACUUM` - * - `EXPLAIN ANALYZE` - * - `CREATE INDEX` - * - `CREATE TRIGGER` - * - `CREATE VIEW` - * - `CREATE VIRTUAL TABLE` - * - `CREATE TEMPORARY TABLE` - * - * @param sql The SQL query to run - * - * @param bindings Optional bindings for the query - * - * @returns `Database` instance - * - * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. - * - * * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run( - sqlQuery: string, - ...bindings: ParamsType[] - ): Changes; - /** + /** + * Execute a SQL query **without returning any results**. + * + * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * ``` + * + * Useful for queries like: + * - `CREATE TABLE` + * - `INSERT INTO` + * - `UPDATE` + * - `DELETE FROM` + * - `DROP TABLE` + * - `PRAGMA` + * - `ATTACH DATABASE` + * - `DETACH DATABASE` + * - `REINDEX` + * - `VACUUM` + * - `EXPLAIN ANALYZE` + * - `CREATE INDEX` + * - `CREATE TRIGGER` + * - `CREATE VIEW` + * - `CREATE VIRTUAL TABLE` + * - `CREATE TEMPORARY TABLE` + * + * @param sql The SQL query to run + * + * @param bindings Optional bindings for the query + * + * @returns `Database` instance + * + * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. + * + * * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(sqlQuery: string, ...bindings: ParamsType[]): Changes; + /** This is an alias of {@link Database.prototype.run} */ - exec( - sqlQuery: string, - ...bindings: ParamsType[] - ): Changes; + exec(sqlQuery: string, ...bindings: ParamsType[]): Changes; - /** - * Compile a SQL query and return a {@link Statement} object. This is the - * same as {@link prepare} except that it caches the compiled query. - * - * This **does not execute** the query, but instead prepares it for later - * execution and caches the compiled query if possible. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * - * // run the query again - * stmt.all(); - * ``` - * - * @param sql The SQL query to compile - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - query( - sqlQuery: string, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. This is the + * same as {@link prepare} except that it caches the compiled query. + * + * This **does not execute** the query, but instead prepares it for later + * execution and caches the compiled query if possible. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * + * // run the query again + * stmt.all(); + * ``` + * + * @param sql The SQL query to compile + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + query( + sqlQuery: string, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Compile a SQL query and return a {@link Statement} object. - * - * This does not cache the compiled query and does not execute the query. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * ``` - * - * @param sql The SQL query to compile - * @param params Optional bindings for the query - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - prepare< - ReturnType, - ParamsType extends SQLQueryBindings | SQLQueryBindings[], - >( - sqlQuery: string, - params?: ParamsType, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; + /** + * Compile a SQL query and return a {@link Statement} object. + * + * This does not cache the compiled query and does not execute the query. + * + * @example + * ```ts + * // compile the query + * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); + * // run the query + * stmt.all("baz"); + * ``` + * + * @param sql The SQL query to compile + * @param params Optional bindings for the query + * + * @returns `Statment` instance + * + * Under the hood, this calls `sqlite3_prepare_v3`. + */ + prepare( + sqlQuery: string, + params?: ParamsType, + ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + Statement; - /** - * Is the database in a transaction? - * - * @returns `true` if the database is in a transaction, `false` otherwise - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * db.run("BEGIN"); - * db.run("INSERT INTO foo VALUES (?)", ["qux"]); - * console.log(db.inTransaction()); - * ``` - */ - get inTransaction(): boolean; + /** + * Is the database in a transaction? + * + * @returns `true` if the database is in a transaction, `false` otherwise + * + * @example + * ```ts + * db.run("CREATE TABLE foo (bar TEXT)"); + * db.run("INSERT INTO foo VALUES (?)", ["baz"]); + * db.run("BEGIN"); + * db.run("INSERT INTO foo VALUES (?)", ["qux"]); + * console.log(db.inTransaction()); + * ``` + */ + get inTransaction(): boolean; - /** - * Close the database connection. - * - * It is safe to call this method multiple times. If the database is already - * closed, this is a no-op. Running queries after the database has been - * closed will throw an error. - * - * @example - * ```ts - * db.close(); - * ``` - * This is called automatically when the database instance is garbage collected. - * - * Internally, this calls `sqlite3_close_v2`. - */ - close( - /** - * If `true`, then the database will throw an error if it is in use - * @default false - * - * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. - * - * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). - * - * Bun will automatically call close by default when the database instance is garbage collected. - * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. - */ - throwOnError?: boolean, - ): void; + /** + * Close the database connection. + * + * It is safe to call this method multiple times. If the database is already + * closed, this is a no-op. Running queries after the database has been + * closed will throw an error. + * + * @example + * ```ts + * db.close(); + * ``` + * This is called automatically when the database instance is garbage collected. + * + * Internally, this calls `sqlite3_close_v2`. + */ + close( + /** + * If `true`, then the database will throw an error if it is in use + * @default false + * + * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. + * + * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). + * + * Bun will automatically call close by default when the database instance is garbage collected. + * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. + */ + throwOnError?: boolean, + ): void; - /** - * The filename passed when `new Database()` was called - * @example - * ```ts - * const db = new Database("mydb.sqlite"); - * console.log(db.filename); - * // => "mydb.sqlite" - * ``` - */ - readonly filename: string; + /** + * The filename passed when `new Database()` was called + * @example + * ```ts + * const db = new Database("mydb.sqlite"); + * console.log(db.filename); + * // => "mydb.sqlite" + * ``` + */ + readonly filename: string; - /** - * The underlying `sqlite3` database handle - * - * In native code, this is not a file descriptor, but an index into an array of database handles - */ - readonly handle: number; + /** + * The underlying `sqlite3` database handle + * + * In native code, this is not a file descriptor, but an index into an array of database handles + */ + readonly handle: number; - /** - * Load a SQLite3 extension - * - * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} - * - * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. - * - * @param extension name/path of the extension to load - * @param entryPoint optional entry point of the extension - */ - loadExtension(extension: string, entryPoint?: string): void; + /** + * Load a SQLite3 extension + * + * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} + * + * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. + * + * @param extension name/path of the extension to load + * @param entryPoint optional entry point of the extension + */ + loadExtension(extension: string, entryPoint?: string): void; - /** - * Change the dynamic library path to SQLite - * - * @note macOS-only - * - * This only works before SQLite is loaded, so - * that's before you call `new Database()`. - * - * It can only be run once because this will load - * the SQLite library into the process. - * - * @param path The path to the SQLite library - */ - static setCustomSQLite(path: string): boolean; + /** + * Change the dynamic library path to SQLite + * + * @note macOS-only + * + * This only works before SQLite is loaded, so + * that's before you call `new Database()`. + * + * It can only be run once because this will load + * the SQLite library into the process. + * + * @param path The path to the SQLite library + */ + static setCustomSQLite(path: string): boolean; - [Symbol.dispose](): void; + [Symbol.dispose](): void; - /** - * Creates a function that always runs inside a transaction. When the - * function is invoked, it will begin a new transaction. When the function - * returns, the transaction will be committed. If an exception is thrown, - * the transaction will be rolled back (and the exception will propagate as - * usual). - * - * @param insideTransaction The callback which runs inside a transaction - * - * @example - * ```ts - * // setup - * import { Database } from "bun:sqlite"; - * const db = Database.open(":memory:"); - * db.exec( - * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" - * ); - * - * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); - * const insertMany = db.transaction((cats) => { - * for (const cat of cats) insert.run(cat); - * }); - * - * insertMany([ - * { $name: "Joey", $age: 2 }, - * { $name: "Sally", $age: 4 }, - * { $name: "Junior", $age: 1 }, - * ]); - * ``` - */ - transaction(insideTransaction: (...args: any) => void): CallableFunction & { - /** - * uses "BEGIN DEFERRED" - */ - deferred: (...args: any) => void; - /** - * uses "BEGIN IMMEDIATE" - */ - immediate: (...args: any) => void; - /** - * uses "BEGIN EXCLUSIVE" - */ - exclusive: (...args: any) => void; - }; + /** + * Creates a function that always runs inside a transaction. When the + * function is invoked, it will begin a new transaction. When the function + * returns, the transaction will be committed. If an exception is thrown, + * the transaction will be rolled back (and the exception will propagate as + * usual). + * + * @param insideTransaction The callback which runs inside a transaction + * + * @example + * ```ts + * // setup + * import { Database } from "bun:sqlite"; + * const db = Database.open(":memory:"); + * db.exec( + * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" + * ); + * + * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); + * const insertMany = db.transaction((cats) => { + * for (const cat of cats) insert.run(cat); + * }); + * + * insertMany([ + * { $name: "Joey", $age: 2 }, + * { $name: "Sally", $age: 4 }, + * { $name: "Junior", $age: 1 }, + * ]); + * ``` + */ + transaction(insideTransaction: (...args: any) => void): CallableFunction & { + /** + * uses "BEGIN DEFERRED" + */ + deferred: (...args: any) => void; + /** + * uses "BEGIN IMMEDIATE" + */ + immediate: (...args: any) => void; + /** + * uses "BEGIN EXCLUSIVE" + */ + exclusive: (...args: any) => void; + }; - /** - * Save the database to an in-memory {@link Buffer} object. - * - * Internally, this calls `sqlite3_serialize`. - * - * @param name Name to save the database as @default "main" - * @returns Buffer containing the serialized database - */ - serialize(name?: string): Buffer; + /** + * Save the database to an in-memory {@link Buffer} object. + * + * Internally, this calls `sqlite3_serialize`. + * + * @param name Name to save the database as @default "main" + * @returns Buffer containing the serialized database + */ + serialize(name?: string): Buffer; - /** - * Load a serialized SQLite3 database - * - * Internally, this calls `sqlite3_deserialize`. - * - * @param serialized Data to load - * @returns `Database` instance - * - * @example - * ```ts - * test("supports serialize/deserialize", () => { - * const db = Database.open(":memory:"); - * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); - * db.exec('INSERT INTO test (name) VALUES ("Hello")'); - * db.exec('INSERT INTO test (name) VALUES ("World")'); - * - * const input = db.serialize(); - * const db2 = new Database(input); - * - * const stmt = db2.prepare("SELECT * FROM test"); - * expect(JSON.stringify(stmt.get())).toBe( - * JSON.stringify({ - * id: 1, - * name: "Hello", - * }), - * ); - * - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * ]), - * ); - * db2.exec("insert into test (name) values ('foo')"); - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * { - * id: 3, - * name: "foo", - * }, - * ]), - * ); - * - * const db3 = Database.deserialize(input, true); - * try { - * db3.exec("insert into test (name) values ('foo')"); - * throw new Error("Expected error"); - * } catch (e) { - * expect(e.message).toBe("attempt to write a readonly database"); - * } - * }); - * ``` - */ - static deserialize( - serialized: NodeJS.TypedArray | ArrayBufferLike, - isReadOnly?: boolean, - ): Database; + /** + * Load a serialized SQLite3 database + * + * Internally, this calls `sqlite3_deserialize`. + * + * @param serialized Data to load + * @returns `Database` instance + * + * @example + * ```ts + * test("supports serialize/deserialize", () => { + * const db = Database.open(":memory:"); + * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); + * db.exec('INSERT INTO test (name) VALUES ("Hello")'); + * db.exec('INSERT INTO test (name) VALUES ("World")'); + * + * const input = db.serialize(); + * const db2 = new Database(input); + * + * const stmt = db2.prepare("SELECT * FROM test"); + * expect(JSON.stringify(stmt.get())).toBe( + * JSON.stringify({ + * id: 1, + * name: "Hello", + * }), + * ); + * + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * ]), + * ); + * db2.exec("insert into test (name) values ('foo')"); + * expect(JSON.stringify(stmt.all())).toBe( + * JSON.stringify([ + * { + * id: 1, + * name: "Hello", + * }, + * { + * id: 2, + * name: "World", + * }, + * { + * id: 3, + * name: "foo", + * }, + * ]), + * ); + * + * const db3 = Database.deserialize(input, true); + * try { + * db3.exec("insert into test (name) values ('foo')"); + * throw new Error("Expected error"); + * } catch (e) { + * expect(e.message).toBe("attempt to write a readonly database"); + * } + * }); + * ``` + */ + static deserialize(serialized: NodeJS.TypedArray | ArrayBufferLike, isReadOnly?: boolean): Database; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(op: number, arg?: ArrayBufferView | number): number; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl( - zDbName: string, - op: number, - arg?: ArrayBufferView | number, - ): number; - } + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(op: number, arg?: ArrayBufferView | number): number; + /** + * See `sqlite3_file_control` for more information. + * @link https://www.sqlite.org/c3ref/file_control.html + */ + fileControl(zDbName: string, op: number, arg?: ArrayBufferView | number): number; + } - /** - * A prepared statement. - * - * This is returned by {@link Database.prepare} and {@link Database.query}. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.all("baz"); - * // => [{bar: "baz"}] - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.get("baz"); - * // => {bar: "baz"} - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.run("baz"); - * // => undefined - * ``` - */ - export class Statement< - ReturnType = unknown, - ParamsType extends SQLQueryBindings[] = any[], - > implements Disposable - { - /** - * Creates a new prepared statement from native code. - * - * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. - */ - constructor(nativeHandle: any); + /** + * A prepared statement. + * + * This is returned by {@link Database.prepare} and {@link Database.query}. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.all("baz"); + * // => [{bar: "baz"}] + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.get("baz"); + * // => {bar: "baz"} + * ``` + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * stmt.run("baz"); + * // => undefined + * ``` + */ + export class Statement implements Disposable { + /** + * Creates a new prepared statement from native code. + * + * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. + */ + constructor(nativeHandle: any); - /** - * Execute the prepared statement and return all results as objects. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.all("baz"); - * // => [{bar: "baz"}] - * - * stmt.all(); - * // => [] - * - * stmt.all("foo"); - * // => [{bar: "foo"}] - * ``` - */ - all(...params: ParamsType): ReturnType[]; + /** + * Execute the prepared statement and return all results as objects. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.all("baz"); + * // => [{bar: "baz"}] + * + * stmt.all(); + * // => [] + * + * stmt.all("foo"); + * // => [{bar: "foo"}] + * ``` + */ + all(...params: ParamsType): ReturnType[]; - /** - * Execute the prepared statement and return **the first** result. - * - * If no result is returned, this returns `null`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.get("baz"); - * // => {bar: "baz"} - * - * stmt.get(); - * // => null - * - * stmt.get("foo"); - * // => {bar: "foo"} - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - get(...params: ParamsType): ReturnType | null; + /** + * Execute the prepared statement and return **the first** result. + * + * If no result is returned, this returns `null`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.get("baz"); + * // => {bar: "baz"} + * + * stmt.get(); + * // => null + * + * stmt.get("foo"); + * // => {bar: "foo"} + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + get(...params: ParamsType): ReturnType | null; - /** - * Execute the prepared statement and return an - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - */ - iterate(...params: ParamsType): IterableIterator; - [Symbol.iterator](): IterableIterator; + /** + * Execute the prepared statement and return an + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + */ + iterate(...params: ParamsType): IterableIterator; + [Symbol.iterator](): IterableIterator; - /** - * Execute the prepared statement. This returns `undefined`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("UPDATE foo SET bar = ?"); - * stmt.run("baz"); - * // => undefined - * - * stmt.run(); - * // => undefined - * - * stmt.run("foo"); - * // => undefined - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(...params: ParamsType): Changes; + /** + * Execute the prepared statement. This returns `undefined`. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("UPDATE foo SET bar = ?"); + * stmt.run("baz"); + * // => undefined + * + * stmt.run(); + * // => undefined + * + * stmt.run("foo"); + * // => undefined + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | -------------- | ----------- | + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + run(...params: ParamsType): Changes; - /** - * Execute the prepared statement and return the results as an array of arrays. - * - * In Bun v0.6.7 and earlier, this method returned `null` if there were no - * results instead of `[]`. This was changed in v0.6.8 to align - * more with what people expect. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.values("baz"); - * // => [['baz']] - * - * stmt.values(); - * // => [['baz']] - * - * stmt.values("foo"); - * // => [['foo']] - * - * stmt.values("not-found"); - * // => [] - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | ---------------|-------------| - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - values( - ...params: ParamsType - ): Array>; + /** + * Execute the prepared statement and return the results as an array of arrays. + * + * In Bun v0.6.7 and earlier, this method returned `null` if there were no + * results instead of `[]`. This was changed in v0.6.8 to align + * more with what people expect. + * + * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * + * stmt.values("baz"); + * // => [['baz']] + * + * stmt.values(); + * // => [['baz']] + * + * stmt.values("foo"); + * // => [['foo']] + * + * stmt.values("not-found"); + * // => [] + * ``` + * + * The following types can be used when binding parameters: + * + * | JavaScript type | SQLite type | + * | ---------------|-------------| + * | `string` | `TEXT` | + * | `number` | `INTEGER` or `DECIMAL` | + * | `boolean` | `INTEGER` (1 or 0) | + * | `Uint8Array` | `BLOB` | + * | `Buffer` | `BLOB` | + * | `bigint` | `INTEGER` | + * | `null` | `NULL` | + */ + values(...params: ParamsType): Array>; - /** - * The names of the columns returned by the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); - * - * console.log(stmt.columnNames); - * // => ["bar"] - * ``` - */ - readonly columnNames: string[]; + /** + * The names of the columns returned by the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); + * + * console.log(stmt.columnNames); + * // => ["bar"] + * ``` + */ + readonly columnNames: string[]; - /** - * The number of parameters expected in the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * console.log(stmt.paramsCount); - * // => 1 - * ``` - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); - * console.log(stmt.paramsCount); - * // => 2 - * ``` - */ - readonly paramsCount: number; + /** + * The number of parameters expected in the prepared statement. + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); + * console.log(stmt.paramsCount); + * // => 1 + * ``` + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); + * console.log(stmt.paramsCount); + * // => 2 + * ``` + */ + readonly paramsCount: number; - /** - * Finalize the prepared statement, freeing the resources used by the - * statement and preventing it from being executed again. - * - * This is called automatically when the prepared statement is garbage collected. - * - * It is safe to call this multiple times. Calling this on a finalized - * statement has no effect. - * - * Internally, this calls `sqlite3_finalize`. - */ - finalize(): void; + /** + * Finalize the prepared statement, freeing the resources used by the + * statement and preventing it from being executed again. + * + * This is called automatically when the prepared statement is garbage collected. + * + * It is safe to call this multiple times. Calling this on a finalized + * statement has no effect. + * + * Internally, this calls `sqlite3_finalize`. + */ + finalize(): void; - /** - * Calls {@link finalize} if it wasn't already called. - */ - [Symbol.dispose](): void; + /** + * Calls {@link finalize} if it wasn't already called. + */ + [Symbol.dispose](): void; - /** - * Return the expanded SQL string for the prepared statement. - * - * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); - * console.log(stmt.toString()); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * console.log(stmt); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * ``` - */ - toString(): string; + /** + * Return the expanded SQL string for the prepared statement. + * + * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. + * + * @example + * ```ts + * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); + * console.log(stmt.toString()); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * console.log(stmt); + * // => "SELECT * FROM foo WHERE bar = 'baz'" + * ``` + */ + toString(): string; - /** - * - * Make {@link get} and {@link all} return an instance of the provided - * `Class` instead of the default `Object`. - * - * @param Class A class to use - * @returns The same statement instance, modified to return an instance of `Class` - * - * This lets you attach methods, getters, and setters to the returned - * objects. - * - * For performance reasons, constructors for classes are not called, which means - * initializers will not be called and private fields will not be - * accessible. - * - * @example - * - * ## Custom class - * ```ts - * class User { - * rawBirthdate: string; - * get birthdate() { - * return new Date(this.rawBirthdate); - * } - * } - * - * const db = new Database(":memory:"); - * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); - * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); - * const query = db.query("SELECT * FROM users"); - * query.as(User); - * const user = query.get(); - * console.log(user.birthdate); - * // => Date(1995, 12, 19) - * ``` - */ - as(Class: new (...args: any[]) => T): Statement; + /** + * + * Make {@link get} and {@link all} return an instance of the provided + * `Class` instead of the default `Object`. + * + * @param Class A class to use + * @returns The same statement instance, modified to return an instance of `Class` + * + * This lets you attach methods, getters, and setters to the returned + * objects. + * + * For performance reasons, constructors for classes are not called, which means + * initializers will not be called and private fields will not be + * accessible. + * + * @example + * + * ## Custom class + * ```ts + * class User { + * rawBirthdate: string; + * get birthdate() { + * return new Date(this.rawBirthdate); + * } + * } + * + * const db = new Database(":memory:"); + * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); + * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); + * const query = db.query("SELECT * FROM users"); + * query.as(User); + * const user = query.get(); + * console.log(user.birthdate); + * // => Date(1995, 12, 19) + * ``` + */ + as(Class: new (...args: any[]) => T): Statement; - /** - * Native object representing the underlying `sqlite3_stmt` - * - * This is left untyped because the ABI of the native bindings may change at any time. - */ - readonly native: any; - } + /** + * Native object representing the underlying `sqlite3_stmt` + * + * This is left untyped because the ABI of the native bindings may change at any time. + */ + readonly native: any; + } - /** - * Constants from `sqlite3.h` - * - * This list isn't exhaustive, but some of the ones which are relevant - */ - export const constants: { - /** - * Open the database as read-only (no write operations, no create). - * @constant 0x00000001 - */ - SQLITE_OPEN_READONLY: number; - /** - * Open the database for reading and writing - * @constant 0x00000002 - */ - SQLITE_OPEN_READWRITE: number; - /** - * Allow creating a new database - * @constant 0x00000004 - */ - SQLITE_OPEN_CREATE: number; - /** - * @constant 0x00000008 - */ - SQLITE_OPEN_DELETEONCLOSE: number; - /** - * @constant 0x00000010 - */ - SQLITE_OPEN_EXCLUSIVE: number; - /** - * @constant 0x00000020 - */ - SQLITE_OPEN_AUTOPROXY: number; - /** - * @constant 0x00000040 - */ - SQLITE_OPEN_URI: number; - /** - * @constant 0x00000080 - */ - SQLITE_OPEN_MEMORY: number; - /** - * @constant 0x00000100 - */ - SQLITE_OPEN_MAIN_DB: number; - /** - * @constant 0x00000200 - */ - SQLITE_OPEN_TEMP_DB: number; - /** - * @constant 0x00000400 - */ - SQLITE_OPEN_TRANSIENT_DB: number; - /** - * @constant 0x00000800 - */ - SQLITE_OPEN_MAIN_JOURNAL: number; - /** - * @constant 0x00001000 - */ - SQLITE_OPEN_TEMP_JOURNAL: number; - /** - * @constant 0x00002000 - */ - SQLITE_OPEN_SUBJOURNAL: number; - /** - * @constant 0x00004000 - */ - SQLITE_OPEN_SUPER_JOURNAL: number; - /** - * @constant 0x00008000 - */ - SQLITE_OPEN_NOMUTEX: number; - /** - * @constant 0x00010000 - */ - SQLITE_OPEN_FULLMUTEX: number; - /** - * @constant 0x00020000 - */ - SQLITE_OPEN_SHAREDCACHE: number; - /** - * @constant 0x00040000 - */ - SQLITE_OPEN_PRIVATECACHE: number; - /** - * @constant 0x00080000 - */ - SQLITE_OPEN_WAL: number; - /** - * @constant 0x01000000 - */ - SQLITE_OPEN_NOFOLLOW: number; - /** - * @constant 0x02000000 - */ - SQLITE_OPEN_EXRESCODE: number; - /** - * @constant 0x01 - */ - SQLITE_PREPARE_PERSISTENT: number; - /** - * @constant 0x02 - */ - SQLITE_PREPARE_NORMALIZE: number; - /** - * @constant 0x04 - */ - SQLITE_PREPARE_NO_VTAB: number; + /** + * Constants from `sqlite3.h` + * + * This list isn't exhaustive, but some of the ones which are relevant + */ + export const constants: { + /** + * Open the database as read-only (no write operations, no create). + * @constant 0x00000001 + */ + SQLITE_OPEN_READONLY: number; + /** + * Open the database for reading and writing + * @constant 0x00000002 + */ + SQLITE_OPEN_READWRITE: number; + /** + * Allow creating a new database + * @constant 0x00000004 + */ + SQLITE_OPEN_CREATE: number; + /** + * @constant 0x00000008 + */ + SQLITE_OPEN_DELETEONCLOSE: number; + /** + * @constant 0x00000010 + */ + SQLITE_OPEN_EXCLUSIVE: number; + /** + * @constant 0x00000020 + */ + SQLITE_OPEN_AUTOPROXY: number; + /** + * @constant 0x00000040 + */ + SQLITE_OPEN_URI: number; + /** + * @constant 0x00000080 + */ + SQLITE_OPEN_MEMORY: number; + /** + * @constant 0x00000100 + */ + SQLITE_OPEN_MAIN_DB: number; + /** + * @constant 0x00000200 + */ + SQLITE_OPEN_TEMP_DB: number; + /** + * @constant 0x00000400 + */ + SQLITE_OPEN_TRANSIENT_DB: number; + /** + * @constant 0x00000800 + */ + SQLITE_OPEN_MAIN_JOURNAL: number; + /** + * @constant 0x00001000 + */ + SQLITE_OPEN_TEMP_JOURNAL: number; + /** + * @constant 0x00002000 + */ + SQLITE_OPEN_SUBJOURNAL: number; + /** + * @constant 0x00004000 + */ + SQLITE_OPEN_SUPER_JOURNAL: number; + /** + * @constant 0x00008000 + */ + SQLITE_OPEN_NOMUTEX: number; + /** + * @constant 0x00010000 + */ + SQLITE_OPEN_FULLMUTEX: number; + /** + * @constant 0x00020000 + */ + SQLITE_OPEN_SHAREDCACHE: number; + /** + * @constant 0x00040000 + */ + SQLITE_OPEN_PRIVATECACHE: number; + /** + * @constant 0x00080000 + */ + SQLITE_OPEN_WAL: number; + /** + * @constant 0x01000000 + */ + SQLITE_OPEN_NOFOLLOW: number; + /** + * @constant 0x02000000 + */ + SQLITE_OPEN_EXRESCODE: number; + /** + * @constant 0x01 + */ + SQLITE_PREPARE_PERSISTENT: number; + /** + * @constant 0x02 + */ + SQLITE_PREPARE_NORMALIZE: number; + /** + * @constant 0x04 + */ + SQLITE_PREPARE_NO_VTAB: number; - /** - * @constant 1 - */ - SQLITE_FCNTL_LOCKSTATE: number; - /** - * @constant 2 - */ - SQLITE_FCNTL_GET_LOCKPROXYFILE: number; - /** - * @constant 3 - */ - SQLITE_FCNTL_SET_LOCKPROXYFILE: number; - /** - * @constant 4 - */ - SQLITE_FCNTL_LAST_ERRNO: number; - /** - * @constant 5 - */ - SQLITE_FCNTL_SIZE_HINT: number; - /** - * @constant 6 - */ - SQLITE_FCNTL_CHUNK_SIZE: number; - /** - * @constant 7 - */ - SQLITE_FCNTL_FILE_POINTER: number; - /** - * @constant 8 - */ - SQLITE_FCNTL_SYNC_OMITTED: number; - /** - * @constant 9 - */ - SQLITE_FCNTL_WIN32_AV_RETRY: number; - /** - * @constant 10 - * - * Control whether or not the WAL is persisted - * Some versions of macOS configure WAL to be persistent by default. - * - * You can change this with code like the below: - * ```ts - * import { Database } from "bun:sqlite"; - * - * const db = Database.open("mydb.sqlite"); - * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); - * // enable WAL - * db.exec("PRAGMA journal_mode = WAL"); - * // .. do some work - * db.close(); - * ``` - * - */ - SQLITE_FCNTL_PERSIST_WAL: number; - /** - * @constant 11 - */ - SQLITE_FCNTL_OVERWRITE: number; - /** - * @constant 12 - */ - SQLITE_FCNTL_VFSNAME: number; - /** - * @constant 13 - */ - SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; - /** - * @constant 14 - */ - SQLITE_FCNTL_PRAGMA: number; - /** - * @constant 15 - */ - SQLITE_FCNTL_BUSYHANDLER: number; - /** - * @constant 16 - */ - SQLITE_FCNTL_TEMPFILENAME: number; - /** - * @constant 18 - */ - SQLITE_FCNTL_MMAP_SIZE: number; - /** - * @constant 19 - */ - SQLITE_FCNTL_TRACE: number; - /** - * @constant 20 - */ - SQLITE_FCNTL_HAS_MOVED: number; - /** - * @constant 21 - */ - SQLITE_FCNTL_SYNC: number; - /** - * @constant 22 - */ - SQLITE_FCNTL_COMMIT_PHASETWO: number; - /** - * @constant 23 - */ - SQLITE_FCNTL_WIN32_SET_HANDLE: number; - /** - * @constant 24 - */ - SQLITE_FCNTL_WAL_BLOCK: number; - /** - * @constant 25 - */ - SQLITE_FCNTL_ZIPVFS: number; - /** - * @constant 26 - */ - SQLITE_FCNTL_RBU: number; - /** - * @constant 27 - */ - SQLITE_FCNTL_VFS_POINTER: number; - /** - * @constant 28 - */ - SQLITE_FCNTL_JOURNAL_POINTER: number; - /** - * @constant 29 - */ - SQLITE_FCNTL_WIN32_GET_HANDLE: number; - /** - * @constant 30 - */ - SQLITE_FCNTL_PDB: number; - /** - * @constant 31 - */ - SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; - /** - * @constant 32 - */ - SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; - /** - * @constant 33 - */ - SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; - /** - * @constant 34 - */ - SQLITE_FCNTL_LOCK_TIMEOUT: number; - /** - * @constant 35 - */ - SQLITE_FCNTL_DATA_VERSION: number; - /** - * @constant 36 - */ - SQLITE_FCNTL_SIZE_LIMIT: number; - /** - * @constant 37 - */ - SQLITE_FCNTL_CKPT_DONE: number; - /** - * @constant 38 - */ - SQLITE_FCNTL_RESERVE_BYTES: number; - /** - * @constant 39 - */ - SQLITE_FCNTL_CKPT_START: number; - /** - * @constant 40 - */ - SQLITE_FCNTL_EXTERNAL_READER: number; - /** - * @constant 41 - */ - SQLITE_FCNTL_CKSM_FILE: number; - /** - * @constant 42 - */ - SQLITE_FCNTL_RESET_CACHE: number; - }; + /** + * @constant 1 + */ + SQLITE_FCNTL_LOCKSTATE: number; + /** + * @constant 2 + */ + SQLITE_FCNTL_GET_LOCKPROXYFILE: number; + /** + * @constant 3 + */ + SQLITE_FCNTL_SET_LOCKPROXYFILE: number; + /** + * @constant 4 + */ + SQLITE_FCNTL_LAST_ERRNO: number; + /** + * @constant 5 + */ + SQLITE_FCNTL_SIZE_HINT: number; + /** + * @constant 6 + */ + SQLITE_FCNTL_CHUNK_SIZE: number; + /** + * @constant 7 + */ + SQLITE_FCNTL_FILE_POINTER: number; + /** + * @constant 8 + */ + SQLITE_FCNTL_SYNC_OMITTED: number; + /** + * @constant 9 + */ + SQLITE_FCNTL_WIN32_AV_RETRY: number; + /** + * @constant 10 + * + * Control whether or not the WAL is persisted + * Some versions of macOS configure WAL to be persistent by default. + * + * You can change this with code like the below: + * ```ts + * import { Database } from "bun:sqlite"; + * + * const db = Database.open("mydb.sqlite"); + * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); + * // enable WAL + * db.exec("PRAGMA journal_mode = WAL"); + * // .. do some work + * db.close(); + * ``` + * + */ + SQLITE_FCNTL_PERSIST_WAL: number; + /** + * @constant 11 + */ + SQLITE_FCNTL_OVERWRITE: number; + /** + * @constant 12 + */ + SQLITE_FCNTL_VFSNAME: number; + /** + * @constant 13 + */ + SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; + /** + * @constant 14 + */ + SQLITE_FCNTL_PRAGMA: number; + /** + * @constant 15 + */ + SQLITE_FCNTL_BUSYHANDLER: number; + /** + * @constant 16 + */ + SQLITE_FCNTL_TEMPFILENAME: number; + /** + * @constant 18 + */ + SQLITE_FCNTL_MMAP_SIZE: number; + /** + * @constant 19 + */ + SQLITE_FCNTL_TRACE: number; + /** + * @constant 20 + */ + SQLITE_FCNTL_HAS_MOVED: number; + /** + * @constant 21 + */ + SQLITE_FCNTL_SYNC: number; + /** + * @constant 22 + */ + SQLITE_FCNTL_COMMIT_PHASETWO: number; + /** + * @constant 23 + */ + SQLITE_FCNTL_WIN32_SET_HANDLE: number; + /** + * @constant 24 + */ + SQLITE_FCNTL_WAL_BLOCK: number; + /** + * @constant 25 + */ + SQLITE_FCNTL_ZIPVFS: number; + /** + * @constant 26 + */ + SQLITE_FCNTL_RBU: number; + /** + * @constant 27 + */ + SQLITE_FCNTL_VFS_POINTER: number; + /** + * @constant 28 + */ + SQLITE_FCNTL_JOURNAL_POINTER: number; + /** + * @constant 29 + */ + SQLITE_FCNTL_WIN32_GET_HANDLE: number; + /** + * @constant 30 + */ + SQLITE_FCNTL_PDB: number; + /** + * @constant 31 + */ + SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; + /** + * @constant 32 + */ + SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; + /** + * @constant 33 + */ + SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; + /** + * @constant 34 + */ + SQLITE_FCNTL_LOCK_TIMEOUT: number; + /** + * @constant 35 + */ + SQLITE_FCNTL_DATA_VERSION: number; + /** + * @constant 36 + */ + SQLITE_FCNTL_SIZE_LIMIT: number; + /** + * @constant 37 + */ + SQLITE_FCNTL_CKPT_DONE: number; + /** + * @constant 38 + */ + SQLITE_FCNTL_RESERVE_BYTES: number; + /** + * @constant 39 + */ + SQLITE_FCNTL_CKPT_START: number; + /** + * @constant 40 + */ + SQLITE_FCNTL_EXTERNAL_READER: number; + /** + * @constant 41 + */ + SQLITE_FCNTL_CKSM_FILE: number; + /** + * @constant 42 + */ + SQLITE_FCNTL_RESET_CACHE: number; + }; - /** - * The native module implementing the sqlite3 C bindings - * - * It is lazily-initialized, so this will return `undefined` until the first - * call to new Database(). - * - * The native module makes no gurantees about ABI stability, so it is left - * untyped - * - * If you need to use it directly for some reason, please let us know because - * that probably points to a deficiency in this API. - */ - export var native: any; + /** + * The native module implementing the sqlite3 C bindings + * + * It is lazily-initialized, so this will return `undefined` until the first + * call to new Database(). + * + * The native module makes no gurantees about ABI stability, so it is left + * untyped + * + * If you need to use it directly for some reason, please let us know because + * that probably points to a deficiency in this API. + */ + export var native: any; - export type SQLQueryBindings = - | string - | bigint - | NodeJS.TypedArray - | number - | boolean - | null - | Record< - string, - string | bigint | NodeJS.TypedArray | number | boolean | null - >; + export type SQLQueryBindings = + | string + | bigint + | NodeJS.TypedArray + | number + | boolean + | null + | Record; - export default Database; + export default Database; - /** - * Errors from SQLite have a name `SQLiteError`. - * - */ - export class SQLiteError extends Error { - readonly name: "SQLiteError"; + /** + * Errors from SQLite have a name `SQLiteError`. + * + */ + export class SQLiteError extends Error { + readonly name: "SQLiteError"; - /** - * The SQLite3 extended error code - * - * This corresponds to `sqlite3_extended_errcode`. - * - * @since v1.0.21 - */ - errno: number; + /** + * The SQLite3 extended error code + * + * This corresponds to `sqlite3_extended_errcode`. + * + * @since v1.0.21 + */ + errno: number; - /** - * The name of the SQLite3 error code - * - * @example - * "SQLITE_CONSTRAINT_UNIQUE" - * - * @since v1.0.21 - */ - code?: string; + /** + * The name of the SQLite3 error code + * + * @example + * "SQLITE_CONSTRAINT_UNIQUE" + * + * @since v1.0.21 + */ + code?: string; - /** - * The UTF-8 byte offset of the sqlite3 query that failed, if known - * - * This corresponds to `sqlite3_error_offset`. - * - * @since v1.0.21 - */ - readonly byteOffset: number; - } + /** + * The UTF-8 byte offset of the sqlite3 query that failed, if known + * + * This corresponds to `sqlite3_error_offset`. + * + * @since v1.0.21 + */ + readonly byteOffset: number; + } - /** - * An object representing the changes made to the database since the last `run` or `exec` call. - * - * @since Bun v1.1.14 - */ - export interface Changes { - /** - * The number of rows changed by the last `run` or `exec` call. - */ - changes: number; + /** + * An object representing the changes made to the database since the last `run` or `exec` call. + * + * @since Bun v1.1.14 + */ + export interface Changes { + /** + * The number of rows changed by the last `run` or `exec` call. + */ + changes: number; - /** - * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. - */ - lastInsertRowid: number | bigint; - } + /** + * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. + */ + lastInsertRowid: number | bigint; + } } diff --git a/packages/bun-types/test/array-buffer.test.ts b/packages/bun-types/test/array-buffer.test.ts index 9fd63d35108368..a3253138e308c2 100644 --- a/packages/bun-types/test/array-buffer.test.ts +++ b/packages/bun-types/test/array-buffer.test.ts @@ -1,5 +1,5 @@ const buffer = new ArrayBuffer(1024, { - maxByteLength: 2048, + maxByteLength: 2048, }); console.log(buffer.byteLength); // 1024 diff --git a/packages/bun-types/test/array.test.ts b/packages/bun-types/test/array.test.ts index d9fce478c69188..af57108192d40d 100644 --- a/packages/bun-types/test/array.test.ts +++ b/packages/bun-types/test/array.test.ts @@ -1,18 +1,16 @@ import { expectType } from "./utilities.test"; async function* listReleases() { - for (let page = 1; ; page++) { - const response = await fetch( - `https://api.github.com/repos/oven-sh/bun/releases?page=${page}`, - ); - const releases = (await response.json()) as Array<{ data: string }>; - if (!releases.length) { - break; - } - for (const release of releases) { - yield release; - } - } + for (let page = 1; ; page++) { + const response = await fetch(`https://api.github.com/repos/oven-sh/bun/releases?page=${page}`); + const releases = (await response.json()) as Array<{ data: string }>; + if (!releases.length) { + break; + } + for (const release of releases) { + yield release; + } + } } await Array.fromAsync(listReleases()); @@ -20,12 +18,12 @@ await Array.fromAsync(listReleases()); // Tests from issue #8484 // https://github.com/oven-sh/bun/issues/8484 async function* naturals() { - for (let i = 0; i < 10; i++) { - yield i; - } + for (let i = 0; i < 10; i++) { + yield i; + } } -const test1 = await Array.fromAsync(naturals(), (n) => Promise.resolve(`${n}`)); +const test1 = await Array.fromAsync(naturals(), n => Promise.resolve(`${n}`)); expectType(test1); const test2 = await Array.fromAsync([Promise.resolve(1), Promise.resolve(2)]); diff --git a/packages/bun-types/test/broadcast.test.ts b/packages/bun-types/test/broadcast.test.ts index 1458e0c0615365..1d853f7fec23dc 100644 --- a/packages/bun-types/test/broadcast.test.ts +++ b/packages/bun-types/test/broadcast.test.ts @@ -1,9 +1,9 @@ const channel = new BroadcastChannel("my-channel"); const message = { hello: "world" }; -channel.onmessage = (event) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - console.log((event as any).data); // { hello: "world" } +channel.onmessage = event => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + console.log((event as any).data); // { hello: "world" } }; channel.postMessage(message); diff --git a/packages/bun-types/test/bun.test.ts b/packages/bun-types/test/bun.test.ts index b3cfb1bfeed41b..ae642ff6f1e53c 100644 --- a/packages/bun-types/test/bun.test.ts +++ b/packages/bun-types/test/bun.test.ts @@ -1,51 +1,51 @@ import { BunFile, BunPlugin, FileBlob } from "bun"; import * as tsd from "./utilities.test"; { - const _plugin: BunPlugin = { - name: "asdf", - setup() {}, - }; - _plugin; + const _plugin: BunPlugin = { + name: "asdf", + setup() {}, + }; + _plugin; } { - // tslint:disable-next-line:no-void-expression - const arg = Bun.plugin({ - name: "arg", - setup() {}, - }); + // tslint:disable-next-line:no-void-expression + const arg = Bun.plugin({ + name: "arg", + setup() {}, + }); - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - tsd.expectType(arg); + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + tsd.expectType(arg); } { - // tslint:disable-next-line:no-void-expression - const arg = Bun.plugin({ - name: "arg", - async setup() {}, - }); + // tslint:disable-next-line:no-void-expression + const arg = Bun.plugin({ + name: "arg", + async setup() {}, + }); - tsd.expectType>(arg); + tsd.expectType>(arg); } { - const f = Bun.file("asdf"); - tsd.expectType(f); - tsd.expectType(f); + const f = Bun.file("asdf"); + tsd.expectType(f); + tsd.expectType(f); } { - Bun.spawn(["anything"], { - env: process.env, - }); - Bun.spawn(["anything"], { - env: { ...process.env }, - }); - Bun.spawn(["anything"], { - env: { ...process.env, dummy: "" }, - }); + Bun.spawn(["anything"], { + env: process.env, + }); + Bun.spawn(["anything"], { + env: { ...process.env }, + }); + Bun.spawn(["anything"], { + env: { ...process.env, dummy: "" }, + }); } { - Bun.TOML.parse("asdf = asdf"); + Bun.TOML.parse("asdf = asdf"); } DOMException; diff --git a/packages/bun-types/test/console.test.ts b/packages/bun-types/test/console.test.ts index b00be4b0c7e101..779bbab1984711 100644 --- a/packages/bun-types/test/console.test.ts +++ b/packages/bun-types/test/console.test.ts @@ -5,19 +5,19 @@ c1.log(); c2.log(); async () => { - // tslint:disable-next-line:await-promise - for await (const line of c1) { - console.log("Received:", line); - } + // tslint:disable-next-line:await-promise + for await (const line of c1) { + console.log("Received:", line); + } - // tslint:disable-next-line:await-promise - for await (const line of c2) { - console.log("Received:", line); - } - // tslint:disable-next-line:await-promise - for await (const line of console) { - console.log("Received:", line); - } + // tslint:disable-next-line:await-promise + for await (const line of c2) { + console.log("Received:", line); + } + // tslint:disable-next-line:await-promise + for await (const line of console) { + console.log("Received:", line); + } - return null; + return null; }; diff --git a/packages/bun-types/test/diag.test.ts b/packages/bun-types/test/diag.test.ts index df3aef7e3c6e82..35f41ce050664d 100644 --- a/packages/bun-types/test/diag.test.ts +++ b/packages/bun-types/test/diag.test.ts @@ -5,7 +5,7 @@ const channel = diagnostics_channel.channel("my-channel"); // Subscribe to the channel channel.subscribe((message, name) => { - console.log("Received message:", message); + console.log("Received message:", message); }); // Publish a message to the channel diff --git a/packages/bun-types/test/dom.test.ts b/packages/bun-types/test/dom.test.ts index 804f5cead79e61..c3d8a4383640e5 100644 --- a/packages/bun-types/test/dom.test.ts +++ b/packages/bun-types/test/dom.test.ts @@ -3,23 +3,23 @@ import { INSPECT_MAX_BYTES } from "buffer"; INSPECT_MAX_BYTES; { - new Blob([]); + new Blob([]); } { - new MessagePort(); + new MessagePort(); } { - new MessageChannel(); + new MessageChannel(); } { - new BroadcastChannel("zxgdfg"); + new BroadcastChannel("zxgdfg"); } { - new Response("asdf"); + new Response("asdf"); } { - Response.json({ asdf: "asdf" }).ok; - const r = Response.json({ hello: "world" }); - r.body; + Response.json({ asdf: "asdf" }).ok; + const r = Response.json({ hello: "world" }); + r.body; } diff --git a/packages/bun-types/test/env.test.ts b/packages/bun-types/test/env.test.ts index aa26b9f002ee84..f9b1d53be648b4 100644 --- a/packages/bun-types/test/env.test.ts +++ b/packages/bun-types/test/env.test.ts @@ -1,19 +1,19 @@ import { expectType } from "./utilities.test"; declare module "bun" { - interface Env { - FOO: "FOO"; - } + interface Env { + FOO: "FOO"; + } } expectType<"FOO">(process.env.FOO); declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace NodeJS { - interface ProcessEnv { - BAR: "BAR"; - } - } + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace NodeJS { + interface ProcessEnv { + BAR: "BAR"; + } + } } expectType<"BAR">(process.env.BAR); diff --git a/packages/bun-types/test/events.test.ts b/packages/bun-types/test/events.test.ts index b3404096aa7185..d774a4b619d0dd 100644 --- a/packages/bun-types/test/events.test.ts +++ b/packages/bun-types/test/events.test.ts @@ -13,8 +13,8 @@ import { expectType } from "./utilities.test"; const e2 = new EventEmitter(); e2.on("qwer", (_: any) => { - _; + _; }); -e2.on("asdf", (arg) => { - expectType(arg); +e2.on("asdf", arg => { + expectType(arg); }); diff --git a/packages/bun-types/test/ffi.test.ts b/packages/bun-types/test/ffi.test.ts index c7a74e0cdb5ff4..277c45b5ec57a6 100644 --- a/packages/bun-types/test/ffi.test.ts +++ b/packages/bun-types/test/ffi.test.ts @@ -1,12 +1,4 @@ -import { - CString, - dlopen, - FFIType, - JSCallback, - Pointer, - read, - suffix, -} from "bun:ffi"; +import { CString, dlopen, FFIType, JSCallback, Pointer, read, suffix } from "bun:ffi"; import * as tsd from "./utilities.test"; // `suffix` is either "dylib", "so", or "dll" depending on the platform @@ -14,60 +6,60 @@ import * as tsd from "./utilities.test"; const path = `libsqlite3.${suffix}`; const lib = dlopen( - path, // a library name or file path - { - sqlite3_libversion: { - // no arguments, returns a string - args: [], - returns: FFIType.cstring, - }, - add: { - args: [FFIType.i32, FFIType.i32], - returns: FFIType.i32, - }, - ptr_type: { - args: [FFIType.pointer], - returns: FFIType.pointer, - }, - fn_type: { - args: [FFIType.function], - returns: FFIType.function, - }, - allArgs: { - args: [ - FFIType.char, // string - FFIType.int8_t, - FFIType.i8, - FFIType.uint8_t, - FFIType.u8, - FFIType.int16_t, - FFIType.i16, - FFIType.uint16_t, - FFIType.u16, - FFIType.int32_t, - FFIType.i32, - FFIType.int, - FFIType.uint32_t, - FFIType.u32, - FFIType.int64_t, - FFIType.i64, - FFIType.uint64_t, - FFIType.u64, - FFIType.double, - FFIType.f64, - FFIType.float, - FFIType.f32, - FFIType.bool, - FFIType.ptr, - FFIType.pointer, - FFIType.void, - FFIType.cstring, - FFIType.i64_fast, - FFIType.u64_fast, - ], - returns: FFIType.void, - }, - }, + path, // a library name or file path + { + sqlite3_libversion: { + // no arguments, returns a string + args: [], + returns: FFIType.cstring, + }, + add: { + args: [FFIType.i32, FFIType.i32], + returns: FFIType.i32, + }, + ptr_type: { + args: [FFIType.pointer], + returns: FFIType.pointer, + }, + fn_type: { + args: [FFIType.function], + returns: FFIType.function, + }, + allArgs: { + args: [ + FFIType.char, // string + FFIType.int8_t, + FFIType.i8, + FFIType.uint8_t, + FFIType.u8, + FFIType.int16_t, + FFIType.i16, + FFIType.uint16_t, + FFIType.u16, + FFIType.int32_t, + FFIType.i32, + FFIType.int, + FFIType.uint32_t, + FFIType.u32, + FFIType.int64_t, + FFIType.i64, + FFIType.uint64_t, + FFIType.u64, + FFIType.double, + FFIType.f64, + FFIType.float, + FFIType.f32, + FFIType.bool, + FFIType.ptr, + FFIType.pointer, + FFIType.void, + FFIType.cstring, + FFIType.i64_fast, + FFIType.u64_fast, + ], + returns: FFIType.void, + }, + }, ); declare const ptr: Pointer; @@ -77,46 +69,44 @@ tsd.expectType(lib.symbols.add(1, 2)); tsd.expectType(lib.symbols.ptr_type(ptr)); -tsd.expectType( - lib.symbols.fn_type(new JSCallback(() => {}, {})), -); +tsd.expectType(lib.symbols.fn_type(new JSCallback(() => {}, {}))); function _arg( - ...params: [ - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - boolean, - Pointer, - Pointer, - // tslint:disable-next-line: void-return - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - void, - CString, - number | bigint, - number | bigint, - ] + ...params: [ + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + boolean, + Pointer, + Pointer, + // tslint:disable-next-line: void-return + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + void, + CString, + number | bigint, + number | bigint, + ] ) { - console.log("asdf"); + console.log("asdf"); } _arg; @@ -153,20 +143,20 @@ tsd.expectTypeEquals(true); // tslint:disable-next-line:no-object-literal-type-assertion const as_const_test = { - sqlite3_libversion: { - args: [], - returns: FFIType.cstring, - }, - multi_args: { - args: [FFIType.i32, FFIType.f32], - returns: FFIType.void, - }, - no_returns: { - args: [FFIType.i32], - }, - no_args: { - returns: FFIType.i32, - }, + sqlite3_libversion: { + args: [], + returns: FFIType.cstring, + }, + multi_args: { + args: [FFIType.i32, FFIType.f32], + returns: FFIType.void, + }, + no_returns: { + args: [FFIType.i32], + }, + no_args: { + returns: FFIType.i32, + }, } as const; const lib2 = dlopen(path, as_const_test); @@ -175,10 +165,7 @@ tsd.expectType(lib2.symbols.sqlite3_libversion()); // tslint:disable-next-line:no-void-expression // eslint-disable-next-line @typescript-eslint/no-invalid-void-type tsd.expectType(lib2.symbols.multi_args(1, 2)); -tsd.expectTypeEquals< - ReturnType<(typeof lib2)["symbols"]["no_returns"]>, - undefined ->(true); +tsd.expectTypeEquals, undefined>(true); tsd.expectTypeEquals, []>(true); tsd.expectType(read.u8(ptr)); diff --git a/packages/bun-types/test/fs.test.ts b/packages/bun-types/test/fs.test.ts index 5fe2e4c920835c..863c528d1ba72b 100644 --- a/packages/bun-types/test/fs.test.ts +++ b/packages/bun-types/test/fs.test.ts @@ -11,10 +11,10 @@ tsd.expectType>(fs.promises.exists("/etc/passwd")); // file path watch(".", (eventType, filename) => { - console.log(`event type = ${eventType}`); - if (filename) { - console.log(`filename = ${filename}`); - } + console.log(`event type = ${eventType}`); + if (filename) { + console.log(`filename = ${filename}`); + } }); await Bun.file("sdf").exists(); diff --git a/packages/bun-types/test/fsrouter.test.ts b/packages/bun-types/test/fsrouter.test.ts index 2e26f90bb0e066..1a1b9975560bff 100644 --- a/packages/bun-types/test/fsrouter.test.ts +++ b/packages/bun-types/test/fsrouter.test.ts @@ -2,8 +2,8 @@ import { FileSystemRouter } from "bun"; import { expectType } from "./utilities.test"; const router = new FileSystemRouter({ - dir: "/pages", - style: "nextjs", + dir: "/pages", + style: "nextjs", }); const match = router.match("/"); diff --git a/packages/bun-types/test/globals.test.ts b/packages/bun-types/test/globals.test.ts index 3644f515ba4c0d..d2fb69e4c9eb89 100644 --- a/packages/bun-types/test/globals.test.ts +++ b/packages/bun-types/test/globals.test.ts @@ -26,16 +26,14 @@ expectType(new Bun.SHA512_256().update("test").digest("hex")); expectType(Bun.deflateSync(new Uint8Array(128))); expectType(Bun.gzipSync(new Uint8Array(128))); expectType( - Bun.deflateSync(new Uint8Array(128), { - level: -1, - memLevel: 8, - strategy: 0, - windowBits: 15, - }), -); -expectType( - Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 }), + Bun.deflateSync(new Uint8Array(128), { + level: -1, + memLevel: 8, + strategy: 0, + windowBits: 15, + }), ); +expectType(Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 })); expectType(Bun.inflateSync(new Uint8Array(64))); // Pretend this is DEFLATE compressed data expectType(Bun.gunzipSync(new Uint8Array(64))); // Pretend this is GZIP compressed data expectAssignable({ windowBits: -11 }); @@ -47,9 +45,7 @@ expectType(Bun.pathToFileURL("/foo/bar.txt")); expectType(Bun.fileURLToPath(new URL("file:///foo/bar.txt"))); // Testing ../fs.d.ts -expectType( - fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString(), -); +expectType(fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString()); expectType(fs.existsSync("./index.d.ts")); // tslint:disable-next-line:no-void-expression // eslint-disable-next-line @typescript-eslint/no-invalid-void-type @@ -62,9 +58,7 @@ expectType(fs.appendFileSync("./index.d.ts", "test")); expectType(fs.mkdirSync("./index.d.ts")); // Testing ^promises.d.ts -expectType( - (await fsPromises.readFile("./index.d.ts", { encoding: "utf-8" })).toString(), -); +expectType((await fsPromises.readFile("./index.d.ts", { encoding: "utf-8" })).toString()); expectType>(fsPromises.access("./index.d.ts")); expectType>(fsPromises.appendFile("./index.d.ts", "test")); expectType>(fsPromises.mkdir("./index.d.ts")); @@ -142,7 +136,7 @@ function stuff(arg: ReadableStreamDefaultReader): any; function stuff(arg: ReadableStreamDefaultController): any; function stuff(arg: WritableStreamDefaultWriter): any; function stuff(arg: any) { - return "asfd"; + return "asfd"; } stuff("asdf" as any as Blob); @@ -163,145 +157,145 @@ const readableStream = new ReadableStream(); const writableStream = new WritableStream(); { - const a = new ByteLengthQueuingStrategy({ highWaterMark: 0 }); - a.highWaterMark; + const a = new ByteLengthQueuingStrategy({ highWaterMark: 0 }); + a.highWaterMark; } { - const a = new ReadableStreamDefaultController(); - a.close(); + const a = new ReadableStreamDefaultController(); + a.close(); } { - const a = new ReadableStreamDefaultReader(readableStream); - await a.cancel(); + const a = new ReadableStreamDefaultReader(readableStream); + await a.cancel(); } { - const a = new WritableStreamDefaultController(); - a.error(); + const a = new WritableStreamDefaultController(); + a.error(); } { - const a = new WritableStreamDefaultWriter(writableStream); - await a.close(); + const a = new WritableStreamDefaultWriter(writableStream); + await a.close(); } { - const a = new TransformStream(); - a.readable; + const a = new TransformStream(); + a.readable; } { - const a = new TransformStreamDefaultController(); - a.enqueue("asdf"); + const a = new TransformStreamDefaultController(); + a.enqueue("asdf"); } { - const a = new CountQueuingStrategy({ highWaterMark: 0 }); - a.highWaterMark; + const a = new CountQueuingStrategy({ highWaterMark: 0 }); + a.highWaterMark; } { - const a = new DOMException(); - a.DATA_CLONE_ERR; + const a = new DOMException(); + a.DATA_CLONE_ERR; } { - const a = new SubtleCrypto(); - await a.decrypt("asdf", new CryptoKey(), new Uint8Array()); + const a = new SubtleCrypto(); + await a.decrypt("asdf", new CryptoKey(), new Uint8Array()); } { - const a = new CryptoKey(); - a.algorithm; + const a = new CryptoKey(); + a.algorithm; } { - const a = new BuildError(); - a.level; + const a = new BuildError(); + a.level; } { - const a = new ResolveError(); - a.level; + const a = new ResolveError(); + a.level; } { - const a = new AbortController(); - a; + const a = new AbortController(); + a; } { - const a = new AbortSignal(); - a.aborted; + const a = new AbortSignal(); + a.aborted; } { - const a = new Request("asdf"); - await a.json(); - a.cache; + const a = new Request("asdf"); + await a.json(); + a.cache; } { - const a = new Response(); - await a.text(); - a.ok; + const a = new Response(); + await a.text(); + a.ok; } { - const a = new FormData(); - a.delete("asdf"); + const a = new FormData(); + a.delete("asdf"); } { - const a = new Headers(); - a.append("asdf", "asdf"); + const a = new Headers(); + a.append("asdf", "asdf"); } { - const a = new EventTarget(); - a.dispatchEvent(new Event("asdf")); + const a = new EventTarget(); + a.dispatchEvent(new Event("asdf")); } { - const a = new Event("asdf"); - a.bubbles; - a.composedPath()[0]; + const a = new Event("asdf"); + a.bubbles; + a.composedPath()[0]; } { - const a = new Blob(); - a.size; + const a = new Blob(); + a.size; } { - const a = new File(["asdf"], "stuff.txt "); - a.name; + const a = new File(["asdf"], "stuff.txt "); + a.name; } { - performance.now(); + performance.now(); } { - const a = new URL("asdf"); - a.host; - a.href; + const a = new URL("asdf"); + a.host; + a.href; } { - const a = new URLSearchParams(); - a; + const a = new URLSearchParams(); + a; } { - const a = new TextDecoder(); - a.decode(new Uint8Array()); + const a = new TextDecoder(); + a.decode(new Uint8Array()); } { - const a = new TextEncoder(); - a.encode("asdf"); + const a = new TextEncoder(); + a.encode("asdf"); } { - const a = new BroadcastChannel("stuff"); - a.close(); + const a = new BroadcastChannel("stuff"); + a.close(); } { - const a = new MessageChannel(); - a.port1; + const a = new MessageChannel(); + a.port1; } { - const a = new MessagePort(); - a.close(); + const a = new MessagePort(); + a.close(); } { - var a!: RequestInit; - a.mode; - a.credentials; + var a!: RequestInit; + a.mode; + a.credentials; } { - var b!: ResponseInit; - b.status; + var b!: ResponseInit; + b.status; } { - const ws = new WebSocket("ws://www.host.com/path"); - ws.send("asdf"); + const ws = new WebSocket("ws://www.host.com/path"); + ws.send("asdf"); } atob("asf"); diff --git a/packages/bun-types/test/http.test.ts b/packages/bun-types/test/http.test.ts index 49ee1e02c1b9f0..c78ab80c233ce8 100644 --- a/packages/bun-types/test/http.test.ts +++ b/packages/bun-types/test/http.test.ts @@ -29,7 +29,7 @@ export {}; // URLSearchParams should be iterable const sp = new URLSearchParams("q=foo&bar=baz"); for (const q of sp) { - console.log(q); + console.log(q); } fetch; diff --git a/packages/bun-types/test/jsc.test.ts b/packages/bun-types/test/jsc.test.ts index 181c5d84179a69..c1a531f1153af3 100644 --- a/packages/bun-types/test/jsc.test.ts +++ b/packages/bun-types/test/jsc.test.ts @@ -6,5 +6,5 @@ const buffer = serialize(obj); const clone = deserialize(buffer); if (deepEquals(obj, clone)) { - console.log("They are equal!"); + console.log("They are equal!"); } diff --git a/packages/bun-types/test/mocks.test.ts b/packages/bun-types/test/mocks.test.ts index 87eb74dcea59db..8c891743356fcc 100644 --- a/packages/bun-types/test/mocks.test.ts +++ b/packages/bun-types/test/mocks.test.ts @@ -2,7 +2,7 @@ import { jest, mock } from "bun:test"; import { expectType } from "./utilities.test"; const mock1 = mock((arg: string) => { - return arg.length; + return arg.length; }); const arg1 = mock1("1"); diff --git a/packages/bun-types/test/net.test.ts b/packages/bun-types/test/net.test.ts index 2756dd4d1dd7d4..76ad4b01516fe9 100644 --- a/packages/bun-types/test/net.test.ts +++ b/packages/bun-types/test/net.test.ts @@ -1,11 +1,11 @@ import * as net from "node:net"; const socket = net.connect({ - port: 80, - host: "localhost", + port: 80, + host: "localhost", }); socket.connect({ - port: 80, - host: "localhost", + port: 80, + host: "localhost", }); diff --git a/packages/bun-types/test/process.test.ts b/packages/bun-types/test/process.test.ts index 04c8d17b249856..6ea7cf043d902c 100644 --- a/packages/bun-types/test/process.test.ts +++ b/packages/bun-types/test/process.test.ts @@ -2,15 +2,15 @@ process.memoryUsage(); process.cpuUsage().system; process.cpuUsage().user; process.on("SIGINT", () => { - console.log("Interrupt from keyboard"); + console.log("Interrupt from keyboard"); }); -process.on("beforeExit", (code) => { - console.log("Event loop is empty and no work is left to schedule.", code); +process.on("beforeExit", code => { + console.log("Event loop is empty and no work is left to schedule.", code); }); -process.on("exit", (code) => { - console.log("Exiting with code:", code); +process.on("exit", code => { + console.log("Exiting with code:", code); }); process.kill(123, "SIGTERM"); @@ -21,7 +21,7 @@ process.getgroups!(); process.getuid!(); process.once("SIGINT", () => { - console.log("Interrupt from keyboard"); + console.log("Interrupt from keyboard"); }); // commented methods are not yet implemented diff --git a/packages/bun-types/test/readline.test.ts b/packages/bun-types/test/readline.test.ts index 7b4be00a01a201..967d9b06d5db79 100644 --- a/packages/bun-types/test/readline.test.ts +++ b/packages/bun-types/test/readline.test.ts @@ -1,10 +1,10 @@ import * as readline from "node:readline/promises"; const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: true, + input: process.stdin, + output: process.stdout, + terminal: true, }); -await rl.question("What is your age?\n").then((answer) => { - console.log("Your age is: " + answer); +await rl.question("What is your age?\n").then(answer => { + console.log("Your age is: " + answer); }); diff --git a/packages/bun-types/test/serve.test.ts b/packages/bun-types/test/serve.test.ts index 60903bf71fc7fc..1ddd23a0c6dff3 100644 --- a/packages/bun-types/test/serve.test.ts +++ b/packages/bun-types/test/serve.test.ts @@ -1,160 +1,160 @@ Bun.serve({ - fetch(req) { - console.log(req.url); // => http://localhost:3000/ - return new Response("Hello World"); - }, + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, }); Bun.serve({ - fetch(req) { - console.log(req.url); // => http://localhost:3000/ - return new Response("Hello World"); - }, - keyFile: "ca.pem", - certFile: "cert.pem", + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, + keyFile: "ca.pem", + certFile: "cert.pem", }); Bun.serve({ - websocket: { - message(ws, message) { - ws.send(message); - }, - }, - - fetch(req, server) { - // Upgrade to a ServerWebSocket if we can - // This automatically checks for the `Sec-WebSocket-Key` header - // meaning you don't have to check headers, you can just call `upgrade()` - if (server.upgrade(req)) { - // When upgrading, we return undefined since we don't want to send a Response - return; - } - - return new Response("Regular HTTP response"); - }, + websocket: { + message(ws, message) { + ws.send(message); + }, + }, + + fetch(req, server) { + // Upgrade to a ServerWebSocket if we can + // This automatically checks for the `Sec-WebSocket-Key` header + // meaning you don't have to check headers, you can just call `upgrade()` + if (server.upgrade(req)) { + // When upgrading, we return undefined since we don't want to send a Response + return; + } + + return new Response("Regular HTTP response"); + }, }); Bun.serve<{ - name: string; + name: string; }>({ - fetch(req, server) { - const url = new URL(req.url); - if (url.pathname === "/chat") { - if ( - server.upgrade(req, { - data: { - name: new URL(req.url).searchParams.get("name") || "Friend", - }, - headers: { - "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), - }, - }) - ) { - return; - } - } - - return new Response("Expected a websocket connection", { status: 400 }); - }, - - websocket: { - open(ws) { - console.log("WebSocket opened"); - ws.subscribe("the-group-chat"); - }, - - message(ws, message) { - ws.publish("the-group-chat", `${ws.data.name}: ${message.toString()}`); - }, - - close(ws, code, reason) { - ws.publish("the-group-chat", `${ws.data.name} left the chat`); - }, - - drain(ws) { - console.log("Please send me data. I am ready to receive it."); - }, - - perMessageDeflate: true, - }, + fetch(req, server) { + const url = new URL(req.url); + if (url.pathname === "/chat") { + if ( + server.upgrade(req, { + data: { + name: new URL(req.url).searchParams.get("name") || "Friend", + }, + headers: { + "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), + }, + }) + ) { + return; + } + } + + return new Response("Expected a websocket connection", { status: 400 }); + }, + + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("the-group-chat"); + }, + + message(ws, message) { + ws.publish("the-group-chat", `${ws.data.name}: ${message.toString()}`); + }, + + close(ws, code, reason) { + ws.publish("the-group-chat", `${ws.data.name} left the chat`); + }, + + drain(ws) { + console.log("Please send me data. I am ready to receive it."); + }, + + perMessageDeflate: true, + }, }); Bun.serve({ - fetch(req) { - throw new Error("woops!"); - }, - error(error) { - return new Response(`

${error.message}\n${error.stack}
`, { - headers: { - "Content-Type": "text/html", - }, - }); - }, + fetch(req) { + throw new Error("woops!"); + }, + error(error) { + return new Response(`
${error.message}\n${error.stack}
`, { + headers: { + "Content-Type": "text/html", + }, + }); + }, }); export {}; Bun.serve({ - port: 1234, - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, + port: 1234, + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch() { - return new Response(); - }, + unix: "/tmp/bun.sock", + fetch() { + return new Response(); + }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, + unix: "/tmp/bun.sock", + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch() { - return new Response(); - }, - tls: {}, + unix: "/tmp/bun.sock", + fetch() { + return new Response(); + }, + tls: {}, }); Bun.serve({ - unix: "/tmp/bun.sock", - fetch(req, server) { - server.upgrade(req); - if (Math.random() > 0.5) return undefined; - return new Response(); - }, - websocket: { message() {} }, - tls: {}, + unix: "/tmp/bun.sock", + fetch(req, server) { + server.upgrade(req); + if (Math.random() > 0.5) return undefined; + return new Response(); + }, + websocket: { message() {} }, + tls: {}, }); Bun.serve({ - fetch(req, server) { - server.upgrade(req); - }, - websocket: { - open(ws) { - console.log("WebSocket opened"); - ws.subscribe("test-channel"); - }, - - message(ws, message) { - ws.publish("test-channel", `${message.toString()}`); - }, - perMessageDeflate: true, - }, + fetch(req, server) { + server.upgrade(req); + }, + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("test-channel"); + }, + + message(ws, message) { + ws.publish("test-channel", `${message.toString()}`); + }, + perMessageDeflate: true, + }, }); // Bun.serve({ // unix: "/tmp/bun.sock", diff --git a/packages/bun-types/test/spawn.test.ts b/packages/bun-types/test/spawn.test.ts index 9dbfef61bf9264..a6c8fddff15b5d 100644 --- a/packages/bun-types/test/spawn.test.ts +++ b/packages/bun-types/test/spawn.test.ts @@ -1,176 +1,145 @@ -import { - FileSink, - NullSubprocess, - PipedSubprocess, - ReadableSubprocess, - SyncSubprocess, - WritableSubprocess, -} from "bun"; +import { FileSink, NullSubprocess, PipedSubprocess, ReadableSubprocess, SyncSubprocess, WritableSubprocess } from "bun"; import * as tsd from "./utilities.test"; Bun.spawn(["echo", "hello"]); function depromise(_promise: Promise): T { - return "asdf" as any as T; + return "asdf" as any as T; } { - const proc = Bun.spawn(["echo", "hello"], { - cwd: "./path/to/subdir", // specify a working direcory - env: { ...process.env, FOO: "bar" }, // specify environment variables - onExit(proc, exitCode, signalCode, error) { - // exit handler - }, - }); - - proc.pid; // process ID of subprocess - - tsd.expectType>(proc.stdout); - tsd.expectType(proc.stderr); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + cwd: "./path/to/subdir", // specify a working direcory + env: { ...process.env, FOO: "bar" }, // specify environment variables + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + proc.pid; // process ID of subprocess + + tsd.expectType>(proc.stdout); + tsd.expectType(proc.stderr); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["cat"], { - stdin: depromise( - fetch( - "https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js", - ), - ), - }); - - const text = depromise(new Response(proc.stdout).text()); - console.log(text); // "const input = "hello world".repeat(400); ..." + const proc = Bun.spawn(["cat"], { + stdin: depromise(fetch("https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js")), + }); + + const text = depromise(new Response(proc.stdout).text()); + console.log(text); // "const input = "hello world".repeat(400); ..." } { - const proc = Bun.spawn(["cat"], { - stdin: "pipe", // return a FileSink for writing - }); - - // enqueue string data - proc.stdin.write("hello"); - - // enqueue binary data - const enc = new TextEncoder(); - proc.stdin.write(enc.encode(" world!")); - enc.encodeInto(" world!", {} as any as Uint8Array); - // Bun-specific overloads - // these fail when lib.dom.d.ts is present - enc.encodeInto(" world!", new Uint32Array(124)); - enc.encodeInto(" world!", {} as any as DataView); - - // send buffered data - await proc.stdin.flush(); - - // close the input stream - await proc.stdin.end(); + const proc = Bun.spawn(["cat"], { + stdin: "pipe", // return a FileSink for writing + }); + + // enqueue string data + proc.stdin.write("hello"); + + // enqueue binary data + const enc = new TextEncoder(); + proc.stdin.write(enc.encode(" world!")); + enc.encodeInto(" world!", {} as any as Uint8Array); + // Bun-specific overloads + // these fail when lib.dom.d.ts is present + enc.encodeInto(" world!", new Uint32Array(124)); + enc.encodeInto(" world!", {} as any as DataView); + + // send buffered data + await proc.stdin.flush(); + + // close the input stream + await proc.stdin.end(); } { - const proc = Bun.spawn(["echo", "hello"]); - const text = depromise(new Response(proc.stdout).text()); - console.log(text); // => "hello" + const proc = Bun.spawn(["echo", "hello"]); + const text = depromise(new Response(proc.stdout).text()); + console.log(text); // => "hello" } { - const proc = Bun.spawn(["echo", "hello"], { - onExit(proc, exitCode, signalCode, error) { - // exit handler - }, - }); - - await proc.exited; // resolves when process exit - proc.killed; // boolean โ€” was the process killed? - proc.exitCode; // null | number - proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... - proc.kill(); - proc.killed; // true - - proc.kill(); // specify an exit code - proc.unref(); + const proc = Bun.spawn(["echo", "hello"], { + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + await proc.exited; // resolves when process exit + proc.killed; // boolean โ€” was the process killed? + proc.exitCode; // null | number + proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... + proc.kill(); + proc.killed; // true + + proc.kill(); // specify an exit code + proc.unref(); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["pipe", "pipe", "pipe"], - }); - tsd.expectType(proc.stdin); - tsd.expectType>(proc.stdout); - tsd.expectType>(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["pipe", "pipe", "pipe"], + }); + tsd.expectType(proc.stdin); + tsd.expectType>(proc.stdout); + tsd.expectType>(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["inherit", "inherit", "inherit"], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["inherit", "inherit", "inherit"], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: ["ignore", "ignore", "ignore"], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: ["ignore", "ignore", "ignore"], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [null, null, null], - }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [null, null, null], + }); + tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout); + tsd.expectType(proc.stderr); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Request("1"), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Request("1"), null, null], + }); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Response("1"), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Response("1"), null, null], + }); + tsd.expectType(proc.stdin); } { - const proc = Bun.spawn(["echo", "hello"], { - stdio: [new Uint8Array([]), null, null], - }); - tsd.expectType(proc.stdin); + const proc = Bun.spawn(["echo", "hello"], { + stdio: [new Uint8Array([]), null, null], + }); + tsd.expectType(proc.stdin); } -tsd.expectAssignable( - Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), -); -tsd.expectNotAssignable( - Bun.spawn([], { stdio: ["inherit", "inherit", "inherit"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), -); -tsd.expectNotAssignable( - Bun.spawn([], { stdio: ["pipe", "ignore", "pipe"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["pipe", "ignore", "inherit"] }), -); -tsd.expectNotAssignable( - Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: ["ignore", "inherit", "ignore"] }), -); -tsd.expectAssignable( - Bun.spawn([], { stdio: [null, null, null] }), -); +tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); +tsd.expectNotAssignable(Bun.spawn([], { stdio: ["inherit", "inherit", "inherit"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); +tsd.expectNotAssignable(Bun.spawn([], { stdio: ["pipe", "ignore", "pipe"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "pipe", "pipe"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["pipe", "ignore", "inherit"] })); +tsd.expectNotAssignable(Bun.spawn([], { stdio: ["ignore", "pipe", "pipe"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: ["ignore", "inherit", "ignore"] })); +tsd.expectAssignable(Bun.spawn([], { stdio: [null, null, null] })); tsd.expectNotAssignable(Bun.spawn([], {})); tsd.expectNotAssignable(Bun.spawn([], {})); diff --git a/packages/bun-types/test/sqlite.test.ts b/packages/bun-types/test/sqlite.test.ts index 7cb261f571f397..32cd98057e3d7a 100644 --- a/packages/bun-types/test/sqlite.test.ts +++ b/packages/bun-types/test/sqlite.test.ts @@ -3,14 +3,14 @@ import { expectType } from "./utilities.test"; const db = new Database(":memory:"); const query1 = db.query< - { name: string; dob: number }, // return type first - { $id: string } + { name: string; dob: number }, // return type first + { $id: string } >("select name, dob from users where id = $id"); query1.all({ $id: "asdf" }); // => {name: string; dob:string}[] const query2 = db.query< - { name: string; dob: number }, - [string, number] // pass tuple for positional params + { name: string; dob: number }, + [string, number] // pass tuple for positional params >("select ?1 as name, ?2 as dob"); const allResults = query2.all("Shaq", 50); // => {name: string; dob:string}[] const getResults = query2.get("Shaq", 50); // => {name: string; dob:string}[] @@ -25,9 +25,9 @@ expectType<{ name: string; dob: number } | null>(getResults); expectType(runResults); const query3 = db.prepare< - { name: string; dob: number }, // return type first - // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [{ $id: string }] + { name: string; dob: number }, // return type first + // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type + [{ $id: string }] >("select name, dob from users where id = $id"); const allResults3 = query3.all({ $id: "asdf" }); expectType>(allResults3); diff --git a/packages/bun-types/test/streams.test.ts b/packages/bun-types/test/streams.test.ts index 3a303a618b8bc9..50c6fdeb65dd6f 100644 --- a/packages/bun-types/test/streams.test.ts +++ b/packages/bun-types/test/streams.test.ts @@ -1,23 +1,23 @@ new ReadableStream({ - start(controller) { - controller.enqueue("hello"); - controller.enqueue("world"); - controller.close(); - }, + start(controller) { + controller.enqueue("hello"); + controller.enqueue("world"); + controller.close(); + }, }); // this will have type errors when lib.dom.d.ts is present // afaik this isn't fixable new ReadableStream({ - type: "direct", - pull(controller) { - // eslint-disable-next-line - controller.write("hello"); - // eslint-disable-next-line - controller.write("world"); - controller.close(); - }, - cancel() { - // called if stream.cancel() is called - }, + type: "direct", + pull(controller) { + // eslint-disable-next-line + controller.write("hello"); + // eslint-disable-next-line + controller.write("world"); + controller.close(); + }, + cancel() { + // called if stream.cancel() is called + }, }); diff --git a/packages/bun-types/test/tcp.test.ts b/packages/bun-types/test/tcp.test.ts index f9f1038f2fbb43..fe1b66a64880c5 100644 --- a/packages/bun-types/test/tcp.test.ts +++ b/packages/bun-types/test/tcp.test.ts @@ -1,134 +1,134 @@ import * as Bun from "bun"; await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLocaleLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLocaleLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); await Bun.connect({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, - tls: { - certFile: "asdf", - keyFile: "adsf", - }, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, + tls: { + certFile: "asdf", + keyFile: "adsf", + }, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - hostname: "adsf", - port: 324, - tls: { - cert: "asdf", - key: Bun.file("adsf"), - ca: Buffer.from("asdf"), - }, + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + hostname: "adsf", + port: 324, + tls: { + cert: "asdf", + key: Bun.file("adsf"), + ca: Buffer.from("asdf"), + }, }); Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); const listener = Bun.listen({ - data: { arg: "asdf" }, - socket: { - data(socket) { - socket.data.arg.toLowerCase(); - }, - open() { - console.log("asdf"); - }, - }, - unix: "asdf", + data: { arg: "asdf" }, + socket: { + data(socket) { + socket.data.arg.toLowerCase(); + }, + open() { + console.log("asdf"); + }, + }, + unix: "asdf", }); listener.data.arg = "asdf"; @@ -140,8 +140,8 @@ listener.data.arg = 234; // }); listener.reload({ - socket: { - open() {}, - // ...listener. - }, + socket: { + open() {}, + // ...listener. + }, }); diff --git a/packages/bun-types/test/test.test.ts b/packages/bun-types/test/test.test.ts index 6f7d1a4951dab3..31a580aba2cfd5 100644 --- a/packages/bun-types/test/test.test.ts +++ b/packages/bun-types/test/test.test.ts @@ -1,13 +1,4 @@ -import { - afterAll, - afterEach, - beforeAll, - beforeEach, - describe, - expect, - spyOn, - test, -} from "bun:test"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { expectType } from "./utilities.test"; const spy = spyOn(console, "log"); @@ -16,119 +7,119 @@ expectType(spy.mock.calls); const hooks = [beforeAll, beforeEach, afterAll, afterEach]; for (const hook of hooks) { - hook(() => { - // ... - }); - // eslint-disable-next-line - hook(async () => { - // ... - return; - }); - hook((done: (err?: unknown) => void) => { - done(); - done(new Error()); - done("Error"); - }); + hook(() => { + // ... + }); + // eslint-disable-next-line + hook(async () => { + // ... + return; + }); + hook((done: (err?: unknown) => void) => { + done(); + done(new Error()); + done("Error"); + }); } describe("bun:test", () => { - describe("expect()", () => { - test("toThrow()", () => { - function fail() { - throw new Error("Bad"); - } - expect(fail).toThrow(); - expect(fail).toThrow("Bad"); - expect(fail).toThrow(/bad/i); - expect(fail).toThrow(Error); - expect(fail).toThrow(new Error("Bad")); - }); - }); - test("expect()", () => { - expect(1).toBe(1); - expect(1).not.toBe(2); - // @ts-expect-error - expect({ a: 1 }).toEqual({ a: 1, b: undefined }); - expect({ a: 1 }).toStrictEqual({ a: 1 }); - expect(new Set()).toHaveProperty("size"); - expect(new Uint8Array()).toHaveProperty("byteLength", 0); - expect([]).toHaveLength(0); - expect(["bun"]).toContain("bun"); - expect(true).toBeTruthy(); - expect(false).toBeFalsy(); - expect(Math.PI).toBeGreaterThan(3.14); - expect(Math.PI).toBeGreaterThan(3n); - expect(Math.PI).toBeGreaterThanOrEqual(3.14); - expect(Math.PI).toBeGreaterThanOrEqual(3n); - expect(NaN).toBeNaN(); - expect(null).toBeNull(); - expect(undefined).toBeUndefined(); - expect(undefined).not.toBeDefined(); - }); + describe("expect()", () => { + test("toThrow()", () => { + function fail() { + throw new Error("Bad"); + } + expect(fail).toThrow(); + expect(fail).toThrow("Bad"); + expect(fail).toThrow(/bad/i); + expect(fail).toThrow(Error); + expect(fail).toThrow(new Error("Bad")); + }); + }); + test("expect()", () => { + expect(1).toBe(1); + expect(1).not.toBe(2); + // @ts-expect-error + expect({ a: 1 }).toEqual({ a: 1, b: undefined }); + expect({ a: 1 }).toStrictEqual({ a: 1 }); + expect(new Set()).toHaveProperty("size"); + expect(new Uint8Array()).toHaveProperty("byteLength", 0); + expect([]).toHaveLength(0); + expect(["bun"]).toContain("bun"); + expect(true).toBeTruthy(); + expect(false).toBeFalsy(); + expect(Math.PI).toBeGreaterThan(3.14); + expect(Math.PI).toBeGreaterThan(3n); + expect(Math.PI).toBeGreaterThanOrEqual(3.14); + expect(Math.PI).toBeGreaterThanOrEqual(3n); + expect(NaN).toBeNaN(); + expect(null).toBeNull(); + expect(undefined).toBeUndefined(); + expect(undefined).not.toBeDefined(); + }); }); // inference should work when data is passed directly in test.each([ - ["a", true, 5], - ["b", false, 1234], + ["a", true, 5], + ["b", false, 1234], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([ - ["a", true, 5], - ["b", false, 5], + ["a", true, 5], + ["b", false, 5], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ])("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); describe.each([{ asdf: "asdf" }, { asdf: "asdf" }])("test.each", (a, b, c) => { - expectType<{ asdf: string }>(a); - expectType<{ asdf: string }>(c); + expectType<{ asdf: string }>(a); + expectType<{ asdf: string }>(c); }); // no inference on data const data = [ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ]; test.each(data)("test.each", (...args) => { - expectType(args[0]); + expectType(args[0]); }); describe.each(data)("test.each", (a, b, c) => { - expectType(a); - expectType(b); - expectType(c); + expectType(a); + expectType(b); + expectType(c); }); // as const const dataAsConst = [ - ["a", true, 5], - ["b", false, "asdf"], + ["a", true, 5], + ["b", false, "asdf"], ] as const; test.each(dataAsConst)("test.each", (...args) => { - expectType(args[0]); - expectType(args[1]); - expectType(args[2]); + expectType(args[0]); + expectType(args[1]); + expectType(args[2]); }); describe.each(dataAsConst)("test.each", (...args) => { - expectType(args[0]); - expectType(args[1]); - expectType(args[2]); + expectType(args[0]); + expectType(args[1]); + expectType(args[2]); }); describe.each(dataAsConst)("test.each", (a, b, c) => { - expectType<"a" | "b">(a); - expectType(b); - expectType<5 | "asdf">(c); + expectType<"a" | "b">(a); + expectType(b); + expectType<5 | "asdf">(c); }); diff --git a/packages/bun-types/test/tls.test.ts b/packages/bun-types/test/tls.test.ts index df6f1979c53b95..fb2aa7d9b885a1 100644 --- a/packages/bun-types/test/tls.test.ts +++ b/packages/bun-types/test/tls.test.ts @@ -3,30 +3,30 @@ import tls from "node:tls"; tls.getCiphers()[0]; tls.connect({ - host: "localhost", - port: 80, - ca: "asdf", - cert: "path to cert", + host: "localhost", + port: 80, + ca: "asdf", + cert: "path to cert", }); tls.connect({ - host: "localhost", - port: 80, - ca: Bun.file("asdf"), - cert: Bun.file("path to cert"), - ciphers: "adsf", + host: "localhost", + port: 80, + ca: Bun.file("asdf"), + cert: Bun.file("path to cert"), + ciphers: "adsf", }); tls.connect({ - host: "localhost", - port: 80, - ca: Buffer.from("asdf"), - cert: Buffer.from("asdf"), + host: "localhost", + port: 80, + ca: Buffer.from("asdf"), + cert: Buffer.from("asdf"), }); tls.connect({ - host: "localhost", - port: 80, - ca: new Uint8Array([1, 2, 3]), - cert: new Uint8Array([1, 2, 3]), + host: "localhost", + port: 80, + ca: new Uint8Array([1, 2, 3]), + cert: new Uint8Array([1, 2, 3]), }); diff --git a/packages/bun-types/test/tty.test.ts b/packages/bun-types/test/tty.test.ts index f6aff4b61e7e52..7e9f45115c731f 100644 --- a/packages/bun-types/test/tty.test.ts +++ b/packages/bun-types/test/tty.test.ts @@ -1,10 +1,10 @@ import * as tty from "tty"; const rs = new tty.ReadStream(234, { - allowHalfOpen: true, - readable: true, - signal: new AbortSignal(), - writable: true, + allowHalfOpen: true, + readable: true, + signal: new AbortSignal(), + writable: true, }); const ws = new tty.WriteStream(234); diff --git a/packages/bun-types/test/utilities.test.ts b/packages/bun-types/test/utilities.test.ts index ef198a27614e3d..9fb6f411160b93 100644 --- a/packages/bun-types/test/utilities.test.ts +++ b/packages/bun-types/test/utilities.test.ts @@ -5,6 +5,4 @@ export declare const expectAssignable: (expression: T) => void; // eslint-disable-next-line @definitelytyped/no-unnecessary-generics export declare const expectNotAssignable: (expression: any) => void; // eslint-disable-next-line @definitelytyped/no-unnecessary-generics -export declare const expectTypeEquals: ( - expression: T extends S ? (S extends T ? true : false) : false, -) => void; +export declare const expectTypeEquals: (expression: T extends S ? (S extends T ? true : false) : false) => void; diff --git a/packages/bun-types/test/wasm.test.ts b/packages/bun-types/test/wasm.test.ts index f745fbe84e94ec..3b8785ec732709 100644 --- a/packages/bun-types/test/wasm.test.ts +++ b/packages/bun-types/test/wasm.test.ts @@ -1,42 +1,42 @@ async () => { - // Fetch and compile a WebAssembly module - const response = await fetch("module.wasm"); - const buffer = await response.arrayBuffer(); - const module = await WebAssembly.compile(buffer); - - // Create a WebAssembly Memory object - const memory = new WebAssembly.Memory({ initial: 1 }); - - // Create a WebAssembly Table object - const table = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); - - // Instantiate the WebAssembly module - const instance = await WebAssembly.instantiate(module, { - js: { - log: (arg: any) => console.log("Logging from WASM:", arg), - tableFunc: () => console.log("Table function called"), - }, - env: { - memory: memory, - table: table, - }, - }); - - // Exported WebAssembly functions - const { exportedFunction } = instance.exports; - exportedFunction; - - // Call an exported WebAssembly function - // exportedFunction(); - - // Interact with WebAssembly memory - const uint8Array = new Uint8Array(memory.buffer); - uint8Array[0] = 1; // Modify memory - - // Use the WebAssembly Table - table.set(0, instance.exports.exportedTableFunction); - // eslint-disable-next-line - table.get(0)(); // Call a function stored in the table - - // Additional operations with instance, memory, and table can be performed here + // Fetch and compile a WebAssembly module + const response = await fetch("module.wasm"); + const buffer = await response.arrayBuffer(); + const module = await WebAssembly.compile(buffer); + + // Create a WebAssembly Memory object + const memory = new WebAssembly.Memory({ initial: 1 }); + + // Create a WebAssembly Table object + const table = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); + + // Instantiate the WebAssembly module + const instance = await WebAssembly.instantiate(module, { + js: { + log: (arg: any) => console.log("Logging from WASM:", arg), + tableFunc: () => console.log("Table function called"), + }, + env: { + memory: memory, + table: table, + }, + }); + + // Exported WebAssembly functions + const { exportedFunction } = instance.exports; + exportedFunction; + + // Call an exported WebAssembly function + // exportedFunction(); + + // Interact with WebAssembly memory + const uint8Array = new Uint8Array(memory.buffer); + uint8Array[0] = 1; // Modify memory + + // Use the WebAssembly Table + table.set(0, instance.exports.exportedTableFunction); + // eslint-disable-next-line + table.get(0)(); // Call a function stored in the table + + // Additional operations with instance, memory, and table can be performed here }; diff --git a/packages/bun-types/test/worker.test.ts b/packages/bun-types/test/worker.test.ts index a6a32787b4a99e..335f2652a9fe23 100644 --- a/packages/bun-types/test/worker.test.ts +++ b/packages/bun-types/test/worker.test.ts @@ -3,17 +3,17 @@ import * as tsd from "./utilities.test"; const webWorker = new Worker("./worker.js"); -webWorker.addEventListener("message", (event) => { - tsd.expectType(event); +webWorker.addEventListener("message", event => { + tsd.expectType(event); }); -webWorker.addEventListener("error", (event) => { - tsd.expectType(event); +webWorker.addEventListener("error", event => { + tsd.expectType(event); }); -webWorker.addEventListener("messageerror", (event) => { - tsd.expectType(event); +webWorker.addEventListener("messageerror", event => { + tsd.expectType(event); }); -webWorker.onmessage = (ev) => "asdf"; -webWorker.onmessageerror = (ev) => "asdf"; +webWorker.onmessage = ev => "asdf"; +webWorker.onmessageerror = ev => "asdf"; webWorker.postMessage("asdf", []); webWorker.terminate(); webWorker.addEventListener("close", () => {}); @@ -24,8 +24,8 @@ webWorker.unref(); webWorker.threadId; const nodeWorker = new NodeWorker("./worker.ts"); -nodeWorker.on("message", (event) => { - console.log("Message from worker:", event); +nodeWorker.on("message", event => { + console.log("Message from worker:", event); }); nodeWorker.postMessage("Hello from main thread!"); @@ -33,8 +33,8 @@ const workerURL = new URL("worker.ts", "/path/to/").href; const _worker2 = new Worker(workerURL); nodeWorker.postMessage("hello"); -webWorker.onmessage = (event) => { - console.log(event.data); +webWorker.onmessage = event => { + console.log(event.data); }; // On the worker thread, `postMessage` is automatically "routed" to the parent thread. @@ -49,13 +49,13 @@ await nodeWorker.terminate(); // Bun.pathToFileURL const _worker3 = new Worker(new URL("worker.ts", "/path/to/").href, { - ref: true, - smol: true, - credentials: "same-origin", - name: "a name", - env: { - envValue: "hello", - }, + ref: true, + smol: true, + credentials: "same-origin", + name: "a name", + env: { + envValue: "hello", + }, }); export { _worker2, _worker3, nodeWorker as worker }; diff --git a/packages/bun-types/test/ws.test.ts b/packages/bun-types/test/ws.test.ts index 83bfd0e4723b43..fdc4072af2403f 100644 --- a/packages/bun-types/test/ws.test.ts +++ b/packages/bun-types/test/ws.test.ts @@ -5,7 +5,7 @@ const ws = new WebSocket("ws://www.host.com/path"); ws.send("asdf"); const wss = new WebSocketServer({ - port: 8080, - perMessageDeflate: false, + port: 8080, + perMessageDeflate: false, }); wss; diff --git a/packages/bun-types/wasm.d.ts b/packages/bun-types/wasm.d.ts index ccbc0d1ef97d21..e0681ff8aba209 100644 --- a/packages/bun-types/wasm.d.ts +++ b/packages/bun-types/wasm.d.ts @@ -1,291 +1,269 @@ export {}; -type _Global = - typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; - } - ? T - : Bun.WebAssembly.Global; +type _Global = typeof globalThis extends { + onerror: any; + WebAssembly: { Global: infer T }; +} + ? T + : Bun.WebAssembly.Global; type _CompileError = typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; + onerror: any; + WebAssembly: { CompileError: infer T }; } - ? T - : Bun.WebAssembly.CompileError; + ? T + : Bun.WebAssembly.CompileError; type _LinkError = typeof globalThis extends { - onerror: any; - WebAssembly: { LinkError: infer T }; + onerror: any; + WebAssembly: { LinkError: infer T }; } - ? T - : Bun.WebAssembly.LinkError; + ? T + : Bun.WebAssembly.LinkError; type _RuntimeError = typeof globalThis extends { - onerror: any; - WebAssembly: { RuntimeError: infer T }; + onerror: any; + WebAssembly: { RuntimeError: infer T }; } - ? T - : Bun.WebAssembly.RuntimeError; + ? T + : Bun.WebAssembly.RuntimeError; type _Memory = typeof globalThis extends { - onerror: any; - WebAssembly: { Memory: infer T }; + onerror: any; + WebAssembly: { Memory: infer T }; } - ? T - : Bun.WebAssembly.Memory; + ? T + : Bun.WebAssembly.Memory; type _Instance = typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; + onerror: any; + WebAssembly: { Instance: infer T }; } - ? T - : Bun.WebAssembly.Instance; + ? T + : Bun.WebAssembly.Instance; type _Module = typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; + onerror: any; + WebAssembly: { Module: infer T }; } - ? T - : Bun.WebAssembly.Module; + ? T + : Bun.WebAssembly.Module; type _Table = typeof globalThis extends { - onerror: any; - WebAssembly: { Table: infer T }; + onerror: any; + WebAssembly: { Table: infer T }; } - ? T - : Bun.WebAssembly.Table; + ? T + : Bun.WebAssembly.Table; declare global { - namespace Bun { - namespace WebAssembly { - type ImportExportKind = "function" | "global" | "memory" | "table"; - type TableKind = "anyfunc" | "externref"; - // eslint-disable-next-line @typescript-eslint/ban-types - type ExportValue = - | Function - | Global - | WebAssembly.Memory - | WebAssembly.Table; - type Exports = Record; - type ImportValue = ExportValue | number; - type Imports = Record; - type ModuleImports = Record; - - interface ValueTypeMap { - // eslint-disable-next-line @typescript-eslint/ban-types - anyfunc: Function; - externref: any; - f32: number; - f64: number; - i32: number; - i64: bigint; - v128: never; - } - - type ValueType = keyof ValueTypeMap; - - interface GlobalDescriptor { - mutable?: boolean; - value: T; - } - - interface Global { - // { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ - value: ValueTypeMap[T]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ - valueOf(): ValueTypeMap[T]; - } - - interface CompileError extends Error {} - - interface LinkError extends Error {} - - interface RuntimeError extends Error {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ - interface Instance { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ - readonly exports: Exports; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ - interface Memory { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ - readonly buffer: ArrayBuffer; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ - grow(delta: number): number; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ - interface Module {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ - interface Table { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ - readonly length: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ - get(index: number): any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ - grow(delta: number, value?: any): number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ - set(index: number, value?: any): void; - } - - interface MemoryDescriptor { - initial: number; - maximum?: number; - shared?: boolean; - } - - interface ModuleExportDescriptor { - kind: ImportExportKind; - name: string; - } - - interface ModuleImportDescriptor { - kind: ImportExportKind; - module: string; - name: string; - } - - interface TableDescriptor { - element: TableKind; - initial: number; - maximum?: number; - } - - interface WebAssemblyInstantiatedSource { - instance: Instance; - module: Module; - } - } - } - - namespace WebAssembly { - interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} - interface GlobalDescriptor< - T extends keyof ValueTypeMap = keyof ValueTypeMap, - > extends Bun.WebAssembly.GlobalDescriptor {} - interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} - interface ModuleExportDescriptor - extends Bun.WebAssembly.ModuleExportDescriptor {} - interface ModuleImportDescriptor - extends Bun.WebAssembly.ModuleImportDescriptor {} - interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} - interface WebAssemblyInstantiatedSource - extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} - - interface LinkError extends _LinkError {} - var LinkError: { - prototype: LinkError; - new (message?: string): LinkError; - (message?: string): LinkError; - }; - - interface CompileError extends _CompileError {} - var CompileError: typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; - } - ? T - : { - prototype: CompileError; - new (message?: string): CompileError; - (message?: string): CompileError; - }; - - interface RuntimeError extends _RuntimeError {} - var RuntimeError: { - prototype: RuntimeError; - new (message?: string): RuntimeError; - (message?: string): RuntimeError; - }; - - interface Global - extends _Global {} - var Global: typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; - } - ? T - : { - prototype: Global; - new ( - descriptor: GlobalDescriptor, - v?: ValueTypeMap[T], - ): Global; - }; - - interface Instance extends _Instance {} - var Instance: typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; - } - ? T - : { - prototype: Instance; - new ( - module: Module, - importObject?: Bun.WebAssembly.Imports, - ): Instance; - }; - - interface Memory extends _Memory {} - var Memory: { - prototype: Memory; - new (descriptor: MemoryDescriptor): Memory; - }; - - interface Module extends _Module {} - var Module: typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; - } - ? T - : { - prototype: Module; - new (bytes: Bun.BufferSource): Module; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ - customSections( - moduleObject: Module, - sectionName: string, - ): ArrayBuffer[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ - exports(moduleObject: Module): ModuleExportDescriptor[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ - imports(moduleObject: Module): ModuleImportDescriptor[]; - }; - - interface Table extends _Table {} - var Table: { - prototype: Table; - new (descriptor: TableDescriptor, value?: any): Table; - }; - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ - function compile(bytes: Bun.BufferSource): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ - function compileStreaming( - source: Response | PromiseLike, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ - function instantiate( - bytes: Bun.BufferSource, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - function instantiate( - moduleObject: Module, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ - function instantiateStreaming( - source: Response | PromiseLike, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ - function validate(bytes: Bun.BufferSource): boolean; - } + namespace Bun { + namespace WebAssembly { + type ImportExportKind = "function" | "global" | "memory" | "table"; + type TableKind = "anyfunc" | "externref"; + + type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table; + type Exports = Record; + type ImportValue = ExportValue | number; + type Imports = Record; + type ModuleImports = Record; + + interface ValueTypeMap { + anyfunc: Function; + externref: any; + f32: number; + f64: number; + i32: number; + i64: bigint; + v128: never; + } + + type ValueType = keyof ValueTypeMap; + + interface GlobalDescriptor { + mutable?: boolean; + value: T; + } + + interface Global { + // { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ + value: ValueTypeMap[T]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ + valueOf(): ValueTypeMap[T]; + } + + interface CompileError extends Error {} + + interface LinkError extends Error {} + + interface RuntimeError extends Error {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ + interface Instance { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ + readonly exports: Exports; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ + interface Memory { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ + readonly buffer: ArrayBuffer; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ + grow(delta: number): number; + } + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ + interface Module {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ + interface Table { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ + readonly length: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ + get(index: number): any; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ + grow(delta: number, value?: any): number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ + set(index: number, value?: any): void; + } + + interface MemoryDescriptor { + initial: number; + maximum?: number; + shared?: boolean; + } + + interface ModuleExportDescriptor { + kind: ImportExportKind; + name: string; + } + + interface ModuleImportDescriptor { + kind: ImportExportKind; + module: string; + name: string; + } + + interface TableDescriptor { + element: TableKind; + initial: number; + maximum?: number; + } + + interface WebAssemblyInstantiatedSource { + instance: Instance; + module: Module; + } + } + } + + namespace WebAssembly { + interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} + interface GlobalDescriptor + extends Bun.WebAssembly.GlobalDescriptor {} + interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} + interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} + interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} + interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} + interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} + + interface LinkError extends _LinkError {} + var LinkError: { + prototype: LinkError; + new (message?: string): LinkError; + (message?: string): LinkError; + }; + + interface CompileError extends _CompileError {} + var CompileError: typeof globalThis extends { + onerror: any; + WebAssembly: { CompileError: infer T }; + } + ? T + : { + prototype: CompileError; + new (message?: string): CompileError; + (message?: string): CompileError; + }; + + interface RuntimeError extends _RuntimeError {} + var RuntimeError: { + prototype: RuntimeError; + new (message?: string): RuntimeError; + (message?: string): RuntimeError; + }; + + interface Global extends _Global {} + var Global: typeof globalThis extends { + onerror: any; + WebAssembly: { Global: infer T }; + } + ? T + : { + prototype: Global; + new ( + descriptor: GlobalDescriptor, + v?: ValueTypeMap[T], + ): Global; + }; + + interface Instance extends _Instance {} + var Instance: typeof globalThis extends { + onerror: any; + WebAssembly: { Instance: infer T }; + } + ? T + : { + prototype: Instance; + new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; + }; + + interface Memory extends _Memory {} + var Memory: { + prototype: Memory; + new (descriptor: MemoryDescriptor): Memory; + }; + + interface Module extends _Module {} + var Module: typeof globalThis extends { + onerror: any; + WebAssembly: { Module: infer T }; + } + ? T + : { + prototype: Module; + new (bytes: Bun.BufferSource): Module; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ + customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ + exports(moduleObject: Module): ModuleExportDescriptor[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + + interface Table extends _Table {} + var Table: { + prototype: Table; + new (descriptor: TableDescriptor, value?: any): Table; + }; + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ + function compile(bytes: Bun.BufferSource): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ + function compileStreaming(source: Response | PromiseLike): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ + function instantiate( + bytes: Bun.BufferSource, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ + function instantiateStreaming( + source: Response | PromiseLike, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ + function validate(bytes: Bun.BufferSource): boolean; + } } diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index 195c545b32a4fb..bda69c34e0a61e 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -14,7 +14,7 @@ "packages": { "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }], - "@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], + "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index c0bdeb2b59f07e..809915fd06f8b2 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -10,6 +10,32 @@ sqlite.Database; Bun satisfies typeof import("bun"); +type ConstructorOf = new (...args: any[]) => T; + +import * as NodeTLS from "node:tls"; +import * as TLS from "tls"; + +process.revision; + +NodeTLS satisfies typeof TLS; +TLS satisfies typeof NodeTLS; + +type NodeTLSOverrideTest = NodeTLS.BunConnectionOptions; +type TLSOverrideTest = TLS.BunConnectionOptions; + +WebAssembly.Global; +WebAssembly.Memory; +WebAssembly.compile; +WebAssembly.compileStreaming; +WebAssembly.instantiate; +WebAssembly.instantiateStreaming; +WebAssembly.validate; + +WebAssembly.Global satisfies ConstructorOf; +WebAssembly.Memory satisfies ConstructorOf; + +type wasmglobalthing = Bun.WebAssembly.Global; + type S3OptionsFromNamespace = Bun.S3Options; type S3OptionsFromImport = import("bun").S3Options; From 2b84554780ef3c631f4d00a147b46082dea627e8 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 19:09:01 +0000 Subject: [PATCH 16/72] rm formatting on eslint --- packages/bun-types/.eslintrc.cjs | 68 ++++++++++++++++---------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/packages/bun-types/.eslintrc.cjs b/packages/bun-types/.eslintrc.cjs index ab4bfc9a79b0a5..d4f69448614574 100644 --- a/packages/bun-types/.eslintrc.cjs +++ b/packages/bun-types/.eslintrc.cjs @@ -1,36 +1,36 @@ module.exports = { - root: true, - parser: "@typescript-eslint/parser", - parserOptions: { - tsconfigRootDir: __dirname, - project: ["./tsconfig.json"], - }, - plugins: ["@typescript-eslint"], - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "prettier", - "plugin:@definitelytyped/all", - ], - rules: { - "no-var": "off", // global variables - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-empty-interface": "off", - "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-misused-new": "off", - "@typescript-eslint/triple-slash-reference": "off", - "@typescript-eslint/no-empty-interface": "off", - "@definitelytyped/no-single-declare-module": "off", - "@definitelytyped/no-self-import": "off", - "@definitelytyped/no-unnecessary-generics": "off", - "@typescript-eslint/no-duplicate-enum-values": "off", - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-invalid-void-type": "off", - "@definitelytyped/no-single-element-tuple-type": "off", - "@typescript-eslint/no-non-null-asserted-optional-chain": "off", - "@typescript-eslint/unbound-method": "off", - }, + root: true, + parser: "@typescript-eslint/parser", + parserOptions: { + tsconfigRootDir: __dirname, + project: ["./tsconfig.json"], + }, + plugins: ["@typescript-eslint"], + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking", + "prettier", + "plugin:@definitelytyped/all", + ], + rules: { + "no-var": "off", // global variables + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-misused-new": "off", + "@typescript-eslint/triple-slash-reference": "off", + "@typescript-eslint/no-empty-interface": "off", + "@definitelytyped/no-single-declare-module": "off", + "@definitelytyped/no-self-import": "off", + "@definitelytyped/no-unnecessary-generics": "off", + "@typescript-eslint/no-duplicate-enum-values": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-invalid-void-type": "off", + "@definitelytyped/no-single-element-tuple-type": "off", + "@typescript-eslint/no-non-null-asserted-optional-chain": "off", + "@typescript-eslint/unbound-method": "off", + }, }; From 0a831045d813001fef5c1d9f6c42bd3e4c420fbf Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 19:17:40 +0000 Subject: [PATCH 17/72] remove all final `type _Name = ...` declarations --- packages/bun-types/new/bun.d.ts | 24 ---------- packages/bun-types/new/globals.d.ts | 51 +++++++++++++++------ test/integration/bun-types/fixture/index.ts | 6 +++ 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index d49d89cd5ceb86..c5350f9596dc80 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -70,30 +70,6 @@ declare module "bun" { type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; - type _TextEncoder = import("util").TextEncoder; - interface TextEncoder extends _TextEncoder { - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; - /** - * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object - * containing the read Unicode code units and written UTF-8 bytes. - * - * ```js - * const encoder = new TextEncoder(); - * const src = 'this is some data'; - * const dest = new Uint8Array(10); - * const { read, written } = encoder.encodeInto(src, dest); - * ``` - * @param src The text to encode. - * @param dest The array to hold the encode result. - */ - encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; - } - - type _TextDecoder = import("util").TextDecoder; - interface TextDecoder extends _TextDecoder { - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextDecoder; - } - interface ErrorEventInit extends EventInit { colno?: number; error?: any; diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index dc7ec942d43227..799a050e02a0ce 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -1,3 +1,14 @@ +declare module "bun" { + namespace __internal { + type NodeWorkerThreadsWorker = import("worker_threads").Worker; + type NodePerfHooksPerformance = import("perf_hooks").Performance; + type NodeCryptoWebcryptoSubtleCrypto = import("crypto").webcrypto.SubtleCrypto; + type NodeCryptoWebcryptoCryptoKey = import("crypto").webcrypto.CryptoKey; + type NodeUtilTextEncoder = import("util").TextEncoder; + type NodeUtilTextDecoder = import("util").TextDecoder; + } +} + interface ReadableStream {} declare var ReadableStream: { prototype: ReadableStream; @@ -11,12 +22,6 @@ declare var WritableStream: { new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; }; -declare module "bun" { - namespace __internal { - type NodeWorkerThreadsWorker = import("worker_threads").Worker; - } -} - interface Worker extends Bun.__internal.NodeWorkerThreadsWorker {} declare var Worker: { prototype: Worker; @@ -48,7 +53,23 @@ declare var crypto: Crypto; * const uint8array = encoder.encode('this is some data'); * ``` */ -interface TextEncoder extends Bun.TextEncoder {} +interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; + /** + * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object + * containing the read Unicode code units and written UTF-8 bytes. + * + * ```js + * const encoder = new TextEncoder(); + * const src = 'this is some data'; + * const dest = new Uint8Array(10); + * const { read, written } = encoder.encodeInto(src, dest); + * ``` + * @param src The text to encode. + * @param dest The array to hold the encode result. + */ + encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; +} declare var TextEncoder: { prototype: TextEncoder; new (): TextEncoder; @@ -62,14 +83,15 @@ declare var TextEncoder: { * const decoder = new TextDecoder(); * const uint8array = decoder.decode('this is some data'); */ -interface TextDecoder extends Bun.TextDecoder {} +interface TextDecoder extends Bun.__internal.NodeUtilTextDecoder { + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextDecoder; +} declare var TextDecoder: { prototype: TextDecoder; new (): TextDecoder; }; -type _Performance = import("perf_hooks").Performance; -interface Performance extends _Performance {} +interface Performance extends Bun.__internal.NodePerfHooksPerformance {} declare var performance: Performance; interface Event { @@ -733,14 +755,13 @@ declare function alert(message?: string): void; declare function confirm(message?: string): boolean; declare function prompt(message?: string, _default?: string): string | null; -type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; +interface SubtleCrypto extends Bun.__internal.NodeCryptoWebcryptoSubtleCrypto {} declare var SubtleCrypto: { - prototype: _SubtleCrypto; - new (): _SubtleCrypto; + prototype: SubtleCrypto; + new (): SubtleCrypto; }; -type _CryptoKey = import("crypto").webcrypto.CryptoKey; -interface CryptoKey extends _CryptoKey {} +interface CryptoKey extends Bun.__internal.NodeCryptoWebcryptoCryptoKey {} declare var CryptoKey: { prototype: CryptoKey; new (): CryptoKey; diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 809915fd06f8b2..5f582d72685e5d 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -5,6 +5,12 @@ import * as test from "bun:test"; test.describe; test.it; +new SubtleCrypto(); +declare const mySubtleCrypto: SubtleCrypto; + +new CryptoKey(); +declare const myCryptoKey: CryptoKey; + import * as sqlite from "bun:sqlite"; sqlite.Database; From 34d12c85d6fa3964551fa679a6fbc53d4e890658 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 19:22:51 +0000 Subject: [PATCH 18/72] Fix MessageEvent and Bun namespace redeclaration --- packages/bun-types/new/deprecated.d.ts | 74 +++++++++++++++++++++ packages/bun-types/new/index.d.ts | 1 + test/integration/bun-types/fixture/index.ts | 6 ++ 3 files changed, 81 insertions(+) create mode 100644 packages/bun-types/new/deprecated.d.ts diff --git a/packages/bun-types/new/deprecated.d.ts b/packages/bun-types/new/deprecated.d.ts new file mode 100644 index 00000000000000..600eebd9933949 --- /dev/null +++ b/packages/bun-types/new/deprecated.d.ts @@ -0,0 +1,74 @@ +declare module "bun" { + interface MessageEvent { + /** + * @deprecated + */ + initMessageEvent( + type: string, + bubbles?: boolean, + cancelable?: boolean, + data?: any, + origin?: string, + lastEventId?: string, + source?: null, + ): void; + } + + /** + * @deprecated Renamed to `ErrorLike` + */ + type Errorlike = ErrorLike; + interface TLSOptions { + /** + * File path to a TLS key + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. + */ + keyFile?: string; + /** + * File path to a TLS certificate + * + * To enable TLS, this option is required. + * + * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. + */ + certFile?: string; + /** + * File path to a .pem file for a custom root CA + * + * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. + */ + caFile?: string; + } +} + +declare namespace NodeJS { + interface Process { + /** + * @deprecated This is deprecated; use the "node:assert" module instead. + */ + assert(value: unknown, message?: string | Error): asserts value; + } +} + +interface CustomEvent { + /** @deprecated */ + initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void; +} + +interface DOMException { + /** @deprecated */ + readonly code: number; +} + +/** + * @deprecated Renamed to `BuildMessage` + */ +declare var BuildError: typeof BuildMessage; + +/** + * @deprecated Renamed to `ResolveMessage` + */ +declare var ResolveError: typeof ResolveMessage; diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index 1a42a7e4802d84..301eeba6d0a1d3 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -18,6 +18,7 @@ /// /// /// +/// /// diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 5f582d72685e5d..b7a3b5746140a4 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -5,6 +5,12 @@ import * as test from "bun:test"; test.describe; test.it; +const options: Bun.TLSOptions = { + keyFile: "", +}; + +process.assert; + new SubtleCrypto(); declare const mySubtleCrypto: SubtleCrypto; From eeeab082ca5690dbfc109c678a4ed7ac0b375db7 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 19:24:02 +0000 Subject: [PATCH 19/72] Remove type-only declaration for `'types'` specifier --- packages/bun-types/new/test.d.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/bun-types/new/test.d.ts b/packages/bun-types/new/test.d.ts index acd28c72153ef7..ba84eda2954ee4 100644 --- a/packages/bun-types/new/test.d.ts +++ b/packages/bun-types/new/test.d.ts @@ -1778,10 +1778,6 @@ declare module "bun:test" { type MatcherContext = MatcherUtils & MatcherState; } -declare module "test" { - export type * from "bun:test"; -} - declare namespace JestMock { /** * Copyright (c) Meta Platforms, Inc. and affiliates. From 733a57189db2b195f9d9a327d9a94d49a86cd59d Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 19:34:14 +0000 Subject: [PATCH 20/72] oops --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index ce1c608c3927d2..a1ff4f9f8b7ecb 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,5 @@ "prettier:extra": "bun run analysis:no-llvm --target prettier-extra", "prettier:diff": "bun run analysis:no-llvm --target prettier-diff", "node:test": "node ./scripts/runner.node.mjs --quiet --exec-path=$npm_execpath --node-tests " - }, - "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" + } } From 32f0080d187ec549619bdee4aa03504df22dedb7 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 20:10:20 +0000 Subject: [PATCH 21/72] make them pass --- packages/bun-types/new/globals.d.ts | 152 +++++++++++++++++++- test/integration/bun-types/fixture/index.ts | 24 ++-- 2 files changed, 161 insertions(+), 15 deletions(-) diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 799a050e02a0ce..4a093c2f6ecfda 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -1241,12 +1241,156 @@ declare var Blob: { new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; }; -interface URL {} +declare module "bun" { + namespace __internal { + type NodeURL = import("node:url").URL; + } +} + +interface URL extends Bun.__internal.NodeURL {} declare var URL: { prototype: URL; new (url: string | URL, base?: string | URL): URL; - canParse(url: string): boolean; - createObjectURL(object: any): string; + /** Not implemented yet */ + createObjectURL(obj: Blob): string; + /** Not implemented yet */ revokeObjectURL(url: string): void; - parse(url: string): URL; + + /** + * Check if `url` is a valid URL string + * + * @param url URL string to parse + * @param base URL to resolve against + */ + canParse(url: string, base?: string): boolean; +}; + +type URLSearchParamsInit = + | URLSearchParams + | string + | Record + | Iterable<[string, string]> + | ReadonlyArray<[string, string]>; + +declare var URLSearchParams: { + prototype: URLSearchParams; + new (init?: URLSearchParamsInit): URLSearchParams; +}; + +declare var AbortController: { + prototype: AbortController; + new (): AbortController; +}; + +declare var AbortSignal: { + prototype: AbortSignal; + new (): AbortSignal; +}; + +declare var FormData: { + prototype: FormData; + new (): FormData; +}; + +declare var EventSource: { + prototype: EventSource; + new (url: string | URL, eventSourceInitDict?: EventSourceInit): EventSource; +}; + +declare module "bun" { + namespace __internal { + type NodePerfHooksPerformanceMark = import("node:perf_hooks").PerformanceMark; + type NodePerfHooksPerformanceMeasure = import("node:perf_hooks").PerformanceMeasure; + type NodePerfHooksPerformanceObserver = import("node:perf_hooks").PerformanceObserver; + type NodePerfHooksPerformanceObserverEntryList = import("node:perf_hooks").PerformanceObserverEntryList; + type NodePerfHooksPerformanceResourceTiming = import("node:perf_hooks").PerformanceResourceTiming; + } +} + +declare var PerformanceEntry: { + prototype: import("node:perf_hooks").PerformanceEntry; + new (name: string, duration?: number, startTime?: number): import("node:perf_hooks").PerformanceEntry; +}; + +interface PerformanceMark extends Bun.__internal.NodePerfHooksPerformanceMark {} +declare var PerformanceMark: { + prototype: PerformanceMark; + new (name: string, duration?: number, startTime?: number): PerformanceMark; +}; + +interface PerformanceMeasure extends Bun.__internal.NodePerfHooksPerformanceMeasure {} +declare var PerformanceMeasure: { + prototype: PerformanceMeasure; + new (name: string, duration?: number, startTime?: number): PerformanceMeasure; +}; + +interface PerformanceObserver extends Bun.__internal.NodePerfHooksPerformanceObserver {} +declare var PerformanceObserver: { + prototype: PerformanceObserver; + new (callback: import("node:perf_hooks").PerformanceObserverCallback): PerformanceObserver; +}; + +interface PerformanceObserverEntryList extends Bun.__internal.NodePerfHooksPerformanceObserverEntryList {} +declare var PerformanceObserverEntryList: { + prototype: PerformanceObserverEntryList; + getEntries(): import("node:perf_hooks").PerformanceEntry[]; + getEntriesByName(name: string, type?: string): import("node:perf_hooks").PerformanceEntry[]; + getEntriesByType(type: string): import("node:perf_hooks").PerformanceEntry[]; +}; + +interface PerformanceResourceTiming extends Bun.__internal.NodePerfHooksPerformanceResourceTiming {} +declare var PerformanceResourceTiming: { + prototype: PerformanceResourceTiming; + new (name: string, duration?: number, startTime?: number): PerformanceResourceTiming; +}; + +declare var ReadableByteStreamController: { + prototype: ReadableByteStreamController; + new (): ReadableByteStreamController; +}; + +declare var ReadableStreamBYOBReader: { + prototype: ReadableStreamBYOBReader; + new (): ReadableStreamBYOBReader; +}; + +declare var ReadableStreamBYOBRequest: { + prototype: ReadableStreamBYOBRequest; + new (): ReadableStreamBYOBRequest; +}; + +declare var TextDecoderStream: { + prototype: TextDecoderStream; + new (): TextDecoderStream; +}; + +declare var TextEncoderStream: { + prototype: TextEncoderStream; + new (): TextEncoderStream; +}; + +declare module "bun" { + namespace __internal { + type NodeBroadcastChannel = import("node:worker_threads").BroadcastChannel; + type NodeMessageChannel = import("node:worker_threads").MessageChannel; + type NodeMessagePort = import("node:worker_threads").MessagePort; + } +} + +interface BroadcastChannel extends Bun.__internal.NodeBroadcastChannel {} +declare var BroadcastChannel: { + prototype: BroadcastChannel; + new (name: string): BroadcastChannel; +}; + +interface MessageChannel extends Bun.__internal.NodeMessageChannel {} +declare var MessageChannel: { + prototype: MessageChannel; + new (): MessageChannel; +}; + +interface MessagePort extends Bun.__internal.NodeMessagePort {} +declare var MessagePort: { + prototype: MessagePort; + new (): MessagePort; }; diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index b7a3b5746140a4..510e0be97add5d 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -188,23 +188,19 @@ Bun.serve({ }, }); +new URL("", ""); +const myUrl: URL = new URL(""); URL.canParse; URL.createObjectURL; URL.revokeObjectURL; -Response.json(); +Response.json(""); Response.redirect("bun.sh", 300); Response.error(); Response.redirect("bun.sh", { - status: 200, - headers: new Headers( - (() => { - const h = new Headers(); - h.set("key", "value"); - h.toJSON(); - return h; - })(), - ), + headers: { + "x-bun": "is cool", + }, }); Bun.fetch.preconnect; @@ -232,13 +228,19 @@ Bun.serve({ }, }); +import.meta.hot.accept(); +import.meta.hot.data; + fetch("", { tls: { rejectUnauthorized: false, }, }); -import.meta.hot?.data; +new AbortController(); +const myAbortController: AbortController = new AbortController(); +new AbortSignal(); +const myAbortSignal: AbortSignal = new AbortSignal(); import { serve } from "bun"; From b4d53d0e7721a85cd83a5257f0fbc93f89e6acdd Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 20:31:33 +0000 Subject: [PATCH 22/72] update tsconfig references --- bench/express/tsconfig.json | 2 +- bench/postgres/tsconfig.json | 2 +- docs/guides/runtime/typescript.md | 2 +- packages/bun-plugin-svelte/tsconfig.json | 2 +- packages/bun-types/package.json | 68 +++++++++++++----------- src/cli/init/tsconfig.default.json | 2 +- 6 files changed, 43 insertions(+), 35 deletions(-) diff --git a/bench/express/tsconfig.json b/bench/express/tsconfig.json index 238655f2ce24cd..0fef23a368018b 100644 --- a/bench/express/tsconfig.json +++ b/bench/express/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/bench/postgres/tsconfig.json b/bench/postgres/tsconfig.json index 238655f2ce24cd..0fef23a368018b 100644 --- a/bench/postgres/tsconfig.json +++ b/bench/postgres/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/docs/guides/runtime/typescript.md b/docs/guides/runtime/typescript.md index 67edcb83cea26f..034fd921b723d6 100644 --- a/docs/guides/runtime/typescript.md +++ b/docs/guides/runtime/typescript.md @@ -16,7 +16,7 @@ Below is the full set of recommended `compilerOptions` for a Bun project. With t { "compilerOptions": { // Enable latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/packages/bun-plugin-svelte/tsconfig.json b/packages/bun-plugin-svelte/tsconfig.json index a1e84e5d05dafe..70fc5a16e937d7 100644 --- a/packages/bun-plugin-svelte/tsconfig.json +++ b/packages/bun-plugin-svelte/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index 4078ec8835e103..54cceadd1440a5 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -1,32 +1,40 @@ { - "version": "1.2.5", - "name": "bun-types", - "license": "MIT", - "types": "./new/index.d.ts", - "description": "Type definitions and documentation for Bun, an incredibly fast JavaScript runtime", - "repository": { - "type": "git", - "url": "https://github.com/oven-sh/bun", - "directory": "packages/bun-types" - }, - "files": ["new/**/*.d.ts", "docs/**/*.md", "docs/*.md"], - "homepage": "https://bun.sh", - "dependencies": { - "@types/node": "*", - "@types/ws": "~8.5.10" - }, - "devDependencies": { - "@biomejs/biome": "^1.5.3", - "@definitelytyped/dtslint": "^0.0.199", - "@definitelytyped/eslint-plugin": "^0.0.197", - "typescript": "^5.0.2" - }, - "scripts": { - "prebuild": "echo $(pwd)", - "copy-docs": "rm -rf docs && cp -rL ../../docs/ ./docs && find ./docs -type f -name '*.md' -exec sed -i 's/\\$BUN_LATEST_VERSION/'\"${BUN_VERSION#bun-v}\"'/g' {} +", - "build": "bun run copy-docs && bun scripts/build.ts && bun run fmt", - "test": "tsc", - "fmt": "echo $(which biome) && biome format --write ." - }, - "keywords": ["bun", "bun.js", "types"] + "version": "1.2.5", + "name": "bun-types", + "license": "MIT", + "types": "./new/index.d.ts", + "description": "Type definitions and documentation for Bun, an incredibly fast JavaScript runtime", + "repository": { + "type": "git", + "url": "https://github.com/oven-sh/bun", + "directory": "packages/bun-types" + }, + "files": [ + "new/**/*.d.ts", + "docs/**/*.md", + "docs/*.md" + ], + "homepage": "https://bun.sh", + "dependencies": { + "@types/node": "*", + "@types/ws": "~8.5.10" + }, + "devDependencies": { + "@biomejs/biome": "^1.5.3", + "@definitelytyped/dtslint": "^0.0.199", + "@definitelytyped/eslint-plugin": "^0.0.197", + "typescript": "^5.0.2" + }, + "scripts": { + "prebuild": "echo $(pwd)", + "copy-docs": "rm -rf docs && cp -rL ../../docs/ ./docs && find ./docs -type f -name '*.md' -exec sed -i 's/\\$BUN_LATEST_VERSION/'\"${BUN_VERSION#bun-v}\"'/g' {} +", + "build": "bun run copy-docs && bun scripts/build.ts", + "test": "tsc", + "fmt": "echo $(which biome) && biome format --write ." + }, + "keywords": [ + "bun", + "bun.js", + "types" + ] } diff --git a/src/cli/init/tsconfig.default.json b/src/cli/init/tsconfig.default.json index df0868aa329314..abcb72bb52e1f8 100644 --- a/src/cli/init/tsconfig.default.json +++ b/src/cli/init/tsconfig.default.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Environment setup & latest features - "lib": ["esnext"], + "lib": ["esnext", "dom"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", From 6b1426c2b8ef156f19e5d098d20c08ebac93fd68 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 21:48:26 +0000 Subject: [PATCH 23/72] work on bringing back support for DOM --- packages/bun-types/new/globals.d.ts | 279 +++++++--------------------- 1 file changed, 62 insertions(+), 217 deletions(-) diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 4a093c2f6ecfda..68e2c8cd6f2c33 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -94,44 +94,48 @@ declare var TextDecoder: { interface Performance extends Bun.__internal.NodePerfHooksPerformance {} declare var performance: Performance; -interface Event { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; -} +// interface Event { +// /** This is not used in Node.js and is provided purely for completeness. */ +// readonly bubbles: boolean; +// /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ +// cancelBubble: () => void; +// /** True if the event was created with the cancelable option */ +// readonly cancelable: boolean; +// /** This is not used in Node.js and is provided purely for completeness. */ +// readonly composed: boolean; +// /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ +// composedPath(): [EventTarget?]; +// /** Alias for event.target. */ +// readonly currentTarget: EventTarget | null; +// /** Is true if cancelable is true and event.preventDefault() has been called. */ +// readonly defaultPrevented: boolean; +// /** This is not used in Node.js and is provided purely for completeness. */ +// readonly eventPhase: typeof globalThis extends { Event: infer T extends {eventPhase: number} } ? T['eventPhase'] : 0 | 2; +// /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ +// readonly isTrusted: boolean; +// /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ +// preventDefault(): void; +// /** This is not used in Node.js and is provided purely for completeness. */ +// returnValue: boolean; +// /** Alias for event.target. */ +// readonly srcElement: EventTarget | null; +// /** Stops the invocation of event listeners after the current one completes. */ +// stopImmediatePropagation(): void; +// /** This is not used in Node.js and is provided purely for completeness. */ +// stopPropagation(): void; +// /** The `EventTarget` dispatching the event */ +// readonly target: EventTarget | null; +// /** The millisecond timestamp when the Event object was created. */ +// readonly timeStamp: number; +// /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ +// readonly type: string; +// } declare var Event: { prototype: Event; + readonly NONE: 0; + readonly CAPTURING_PHASE: 1; + readonly AT_TARGET: 2; + readonly BUBBLING_PHASE: 3; new (type: string, eventInitDict?: Bun.EventInit): Event; }; @@ -169,17 +173,23 @@ interface File extends Blob { readonly name: string; } -declare var File: { - prototype: File; - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; -}; +declare var File: typeof globalThis extends { File: infer T } + ? T + : { + prototype: File; + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new ( + parts: Bun.BlobPart[], + name: string, + options?: BlobPropertyBag & { lastModified?: Date | number | undefined }, + ): File; + }; /** * ShadowRealms are a distinct global environment, with its own global object @@ -371,7 +381,7 @@ declare var CloseEvent: { interface MessageEvent extends Bun.MessageEvent {} declare var MessageEvent: { prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; + new (type: string, eventInitDict?: MessageEventInit): MessageEvent; }; interface CustomEvent extends Event { @@ -746,10 +756,10 @@ interface DOMException extends Error { readonly DATA_CLONE_ERR: 25; } -declare var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; -}; +// declare var DOMException: { +// prototype: DOMException; +// new (message?: string, name?: string): DOMException; +// }; declare function alert(message?: string): void; declare function confirm(message?: string): boolean; @@ -1229,168 +1239,3 @@ interface Blob { */ bytes(): Promise; } - -/** - * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - */ -declare var Blob: { - prototype: Blob; - new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; -}; - -declare module "bun" { - namespace __internal { - type NodeURL = import("node:url").URL; - } -} - -interface URL extends Bun.__internal.NodeURL {} -declare var URL: { - prototype: URL; - new (url: string | URL, base?: string | URL): URL; - /** Not implemented yet */ - createObjectURL(obj: Blob): string; - /** Not implemented yet */ - revokeObjectURL(url: string): void; - - /** - * Check if `url` is a valid URL string - * - * @param url URL string to parse - * @param base URL to resolve against - */ - canParse(url: string, base?: string): boolean; -}; - -type URLSearchParamsInit = - | URLSearchParams - | string - | Record - | Iterable<[string, string]> - | ReadonlyArray<[string, string]>; - -declare var URLSearchParams: { - prototype: URLSearchParams; - new (init?: URLSearchParamsInit): URLSearchParams; -}; - -declare var AbortController: { - prototype: AbortController; - new (): AbortController; -}; - -declare var AbortSignal: { - prototype: AbortSignal; - new (): AbortSignal; -}; - -declare var FormData: { - prototype: FormData; - new (): FormData; -}; - -declare var EventSource: { - prototype: EventSource; - new (url: string | URL, eventSourceInitDict?: EventSourceInit): EventSource; -}; - -declare module "bun" { - namespace __internal { - type NodePerfHooksPerformanceMark = import("node:perf_hooks").PerformanceMark; - type NodePerfHooksPerformanceMeasure = import("node:perf_hooks").PerformanceMeasure; - type NodePerfHooksPerformanceObserver = import("node:perf_hooks").PerformanceObserver; - type NodePerfHooksPerformanceObserverEntryList = import("node:perf_hooks").PerformanceObserverEntryList; - type NodePerfHooksPerformanceResourceTiming = import("node:perf_hooks").PerformanceResourceTiming; - } -} - -declare var PerformanceEntry: { - prototype: import("node:perf_hooks").PerformanceEntry; - new (name: string, duration?: number, startTime?: number): import("node:perf_hooks").PerformanceEntry; -}; - -interface PerformanceMark extends Bun.__internal.NodePerfHooksPerformanceMark {} -declare var PerformanceMark: { - prototype: PerformanceMark; - new (name: string, duration?: number, startTime?: number): PerformanceMark; -}; - -interface PerformanceMeasure extends Bun.__internal.NodePerfHooksPerformanceMeasure {} -declare var PerformanceMeasure: { - prototype: PerformanceMeasure; - new (name: string, duration?: number, startTime?: number): PerformanceMeasure; -}; - -interface PerformanceObserver extends Bun.__internal.NodePerfHooksPerformanceObserver {} -declare var PerformanceObserver: { - prototype: PerformanceObserver; - new (callback: import("node:perf_hooks").PerformanceObserverCallback): PerformanceObserver; -}; - -interface PerformanceObserverEntryList extends Bun.__internal.NodePerfHooksPerformanceObserverEntryList {} -declare var PerformanceObserverEntryList: { - prototype: PerformanceObserverEntryList; - getEntries(): import("node:perf_hooks").PerformanceEntry[]; - getEntriesByName(name: string, type?: string): import("node:perf_hooks").PerformanceEntry[]; - getEntriesByType(type: string): import("node:perf_hooks").PerformanceEntry[]; -}; - -interface PerformanceResourceTiming extends Bun.__internal.NodePerfHooksPerformanceResourceTiming {} -declare var PerformanceResourceTiming: { - prototype: PerformanceResourceTiming; - new (name: string, duration?: number, startTime?: number): PerformanceResourceTiming; -}; - -declare var ReadableByteStreamController: { - prototype: ReadableByteStreamController; - new (): ReadableByteStreamController; -}; - -declare var ReadableStreamBYOBReader: { - prototype: ReadableStreamBYOBReader; - new (): ReadableStreamBYOBReader; -}; - -declare var ReadableStreamBYOBRequest: { - prototype: ReadableStreamBYOBRequest; - new (): ReadableStreamBYOBRequest; -}; - -declare var TextDecoderStream: { - prototype: TextDecoderStream; - new (): TextDecoderStream; -}; - -declare var TextEncoderStream: { - prototype: TextEncoderStream; - new (): TextEncoderStream; -}; - -declare module "bun" { - namespace __internal { - type NodeBroadcastChannel = import("node:worker_threads").BroadcastChannel; - type NodeMessageChannel = import("node:worker_threads").MessageChannel; - type NodeMessagePort = import("node:worker_threads").MessagePort; - } -} - -interface BroadcastChannel extends Bun.__internal.NodeBroadcastChannel {} -declare var BroadcastChannel: { - prototype: BroadcastChannel; - new (name: string): BroadcastChannel; -}; - -interface MessageChannel extends Bun.__internal.NodeMessageChannel {} -declare var MessageChannel: { - prototype: MessageChannel; - new (): MessageChannel; -}; - -interface MessagePort extends Bun.__internal.NodeMessagePort {} -declare var MessagePort: { - prototype: MessagePort; - new (): MessagePort; -}; From acbe08709c45eb49c2c7fd121bfdb1723e9939cd Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 21:57:52 +0000 Subject: [PATCH 24/72] Don't conflict when `DOM` types are loaded. We can only prefer DOM types. --- packages/bun-types/new/globals.d.ts | 73 ++++++++++++++++------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 68e2c8cd6f2c33..05f3ba88818652 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -10,31 +10,37 @@ declare module "bun" { } interface ReadableStream {} -declare var ReadableStream: { - prototype: ReadableStream; - new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; -}; +declare var ReadableStream: typeof globalThis extends { ReadableStream: infer T } + ? T + : { + prototype: ReadableStream; + new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + }; interface WritableStream {} -declare var WritableStream: { - prototype: WritableStream; - new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; -}; +declare var WritableStream: typeof globalThis extends { WritableStream: infer T } + ? T + : { + prototype: WritableStream; + new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; + }; interface Worker extends Bun.__internal.NodeWorkerThreadsWorker {} -declare var Worker: { - prototype: Worker; - new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; -}; +declare var Worker: typeof globalThis extends { Worker: infer T } + ? T + : { + prototype: Worker; + new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; + }; -declare var WebSocket: typeof import("ws").WebSocket; +declare var WebSocket: typeof globalThis extends { WebSocket: infer T } ? T : typeof import("ws").WebSocket; interface Crypto {} declare var Crypto: { @@ -54,7 +60,6 @@ declare var crypto: Crypto; * ``` */ interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; /** * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object * containing the read Unicode code units and written UTF-8 bytes. @@ -70,10 +75,12 @@ interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { */ encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; } -declare var TextEncoder: { - prototype: TextEncoder; - new (): TextEncoder; -}; +declare var TextEncoder: typeof globalThis extends { TextEncoder: infer T } + ? T + : { + prototype: TextEncoder; + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; + }; /** * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextDecoder` API. All @@ -83,13 +90,15 @@ declare var TextEncoder: { * const decoder = new TextDecoder(); * const uint8array = decoder.decode('this is some data'); */ -interface TextDecoder extends Bun.__internal.NodeUtilTextDecoder { - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextDecoder; -} -declare var TextDecoder: { - prototype: TextDecoder; - new (): TextDecoder; -}; +declare var TextDecoder: typeof globalThis extends { TextDecoder: infer T } + ? T + : { + prototype: Bun.__internal.NodeUtilTextDecoder; + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): Bun.__internal.NodeUtilTextDecoder; + }; interface Performance extends Bun.__internal.NodePerfHooksPerformance {} declare var performance: Performance; From 6b385923ce7a20c18f616beca34f1f841671cfd0 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 21:59:29 +0000 Subject: [PATCH 25/72] update typescript guide --- docs/guides/runtime/typescript.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/guides/runtime/typescript.md b/docs/guides/runtime/typescript.md index 034fd921b723d6..684c33b1c9adc8 100644 --- a/docs/guides/runtime/typescript.md +++ b/docs/guides/runtime/typescript.md @@ -15,8 +15,8 @@ Below is the full set of recommended `compilerOptions` for a Bun project. With t ```jsonc { "compilerOptions": { - // Enable latest features - "lib": ["ESNext"], + // Environment setup & latest features + "lib": ["esnext", "dom"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", @@ -31,13 +31,14 @@ Below is the full set of recommended `compilerOptions` for a Bun project. With t // Best practices "strict": true, - "skipLibCheck": true, + "skipLibCheck": false, "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, - // Some stricter flags - "noUnusedLocals": true, - "noUnusedParameters": true, - "noPropertyAccessFromIndexSignature": true, + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false, }, } ``` From 02af6e7ff8d8ef082ee0d56217b2c80df17a3d4a Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Sun, 9 Mar 2025 23:03:49 +0000 Subject: [PATCH 26/72] add tests for DOM enabled and disabled --- packages/bun-types/new/bun.d.ts | 7 ---- packages/bun-types/new/globals.d.ts | 37 +++++++++---------- packages/bun-types/new/index.d.ts | 2 + test/integration/bun-types/bun-types.test.ts | 15 +++++++- .../bun-types/fixture/.vscode/settings.json | 3 ++ test/integration/bun-types/fixture/index.ts | 4 ++ 6 files changed, 40 insertions(+), 28 deletions(-) create mode 100644 test/integration/bun-types/fixture/.vscode/settings.json diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index c5350f9596dc80..795e6396f4a6ac 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -490,13 +490,6 @@ declare module "bun" { threadId: number; } - interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; - } - interface Env { NODE_ENV?: string; /** diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 05f3ba88818652..2bd3b07e7077f5 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -40,7 +40,7 @@ declare var Worker: typeof globalThis extends { Worker: infer T } data: any; }; -declare var WebSocket: typeof globalThis extends { WebSocket: infer T } ? T : typeof import("ws").WebSocket; +declare var WebSocket: typeof import("ws").WebSocket; interface Crypto {} declare var Crypto: { @@ -75,12 +75,10 @@ interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { */ encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; } -declare var TextEncoder: typeof globalThis extends { TextEncoder: infer T } - ? T - : { - prototype: TextEncoder; - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; - }; +declare var TextEncoder: { + prototype: TextEncoder; + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; +}; /** * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextDecoder` API. All @@ -90,15 +88,10 @@ declare var TextEncoder: typeof globalThis extends { TextEncoder: infer T } * const decoder = new TextDecoder(); * const uint8array = decoder.decode('this is some data'); */ -declare var TextDecoder: typeof globalThis extends { TextDecoder: infer T } - ? T - : { - prototype: Bun.__internal.NodeUtilTextDecoder; - new ( - encoding?: Bun.Encoding, - options?: { fatal?: boolean; ignoreBOM?: boolean }, - ): Bun.__internal.NodeUtilTextDecoder; - }; +declare var TextDecoder: { + prototype: Bun.__internal.NodeUtilTextDecoder; + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): Bun.__internal.NodeUtilTextDecoder; +}; interface Performance extends Bun.__internal.NodePerfHooksPerformance {} declare var performance: Performance; @@ -182,8 +175,10 @@ interface File extends Blob { readonly name: string; } -declare var File: typeof globalThis extends { File: infer T } - ? T +declare var File: typeof globalThis extends { onabort: any } + ? typeof globalThis extends { File: infer T } + ? T + : never : { prototype: File; /** @@ -390,7 +385,7 @@ declare var CloseEvent: { interface MessageEvent extends Bun.MessageEvent {} declare var MessageEvent: { prototype: MessageEvent; - new (type: string, eventInitDict?: MessageEventInit): MessageEvent; + new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; }; interface CustomEvent extends Event { @@ -1218,6 +1213,8 @@ interface BlobPropertyBag { // endings?: "transparent" | "native"; } +interface WorkerOptions extends Bun.WorkerOptions {} + interface Blob { /** * Read the data from the blob as a JSON object. @@ -1248,3 +1245,5 @@ interface Blob { */ bytes(): Promise; } + +declare var Blob: typeof globalThis extends { Blob: infer T } ? T : Blob; diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts index 301eeba6d0a1d3..0060cdd11a22b9 100644 --- a/packages/bun-types/new/index.d.ts +++ b/packages/bun-types/new/index.d.ts @@ -22,4 +22,6 @@ /// +// @ts-ignore Must disable this so it doesn't conflict with the DOM onmessage type, but still +// allows us to declare our own globals that Node's types can "see" and not conflict with declare var onmessage: never; diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 69952f3394989a..d8927922fab7a7 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -1,4 +1,4 @@ -import { fileURLToPath, $ as Shell, ShellError } from "bun"; +import { fileURLToPath, $ as Shell } from "bun"; import { beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test"; import { join } from "node:path"; @@ -55,7 +55,7 @@ beforeAll(() => { }); describe("@types/bun integration test", () => { - test("it typechecks successfully", async () => { + test("it typechecks successfully with DOM lib", async () => { const p = await $` cd ${FIXTURE_DIR} bun run check @@ -63,4 +63,15 @@ describe("@types/bun integration test", () => { expect(p.exitCode).toBe(0); }); + + test("it typechecks successfully with DOM lib", async () => { + const p = await $` + cd ${FIXTURE_DIR} + # modify tsconfig.json to remove dom lib + sed -i 's/"lib": \["esnext", "dom"\]/"lib": \["esnext"\]/' tsconfig.json + bun run check + `; + + expect(p.exitCode).toBe(0); + }); }); diff --git a/test/integration/bun-types/fixture/.vscode/settings.json b/test/integration/bun-types/fixture/.vscode/settings.json new file mode 100644 index 00000000000000..25fa6215fdd332 --- /dev/null +++ b/test/integration/bun-types/fixture/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 510e0be97add5d..3ceded33bf2fea 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -175,6 +175,8 @@ fetch; fetch.preconnect(new URL("")); +document.getElementById("id"); + Bun.serve({ port: 3000, fetch: () => new Response("ok"), @@ -194,6 +196,8 @@ URL.canParse; URL.createObjectURL; URL.revokeObjectURL; +new File(["code"], "name.ts"); + Response.json(""); Response.redirect("bun.sh", 300); Response.error(); From bb49f88ed9793d84f5bc567b3d076151bedeb21e Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 10 Mar 2025 00:10:46 +0000 Subject: [PATCH 27/72] make it pass without dom --- packages/bun-types/new/globals.d.ts | 219 ++++++++++++++++--- test/integration/bun-types/bun-types.test.ts | 2 +- test/integration/bun-types/fixture/index.ts | 2 - 3 files changed, 191 insertions(+), 32 deletions(-) diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 2bd3b07e7077f5..2281505d60c37d 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -9,36 +9,58 @@ declare module "bun" { } } +/** + * 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 = + // `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 + typeof globalThis extends { onabort: any } + ? 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 + interface ReadableStream {} -declare var ReadableStream: typeof globalThis extends { ReadableStream: infer T } - ? T - : { - prototype: ReadableStream; - new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - }; +declare var ReadableStream: UseLibDomIfAvailable< + "ReadableStream", + { + prototype: ReadableStream; + new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + } +>; interface WritableStream {} -declare var WritableStream: typeof globalThis extends { WritableStream: infer T } - ? T - : { - prototype: WritableStream; - new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; - }; +declare var WritableStream: UseLibDomIfAvailable< + "WritableStream", + { + prototype: WritableStream; + new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; + } +>; interface Worker extends Bun.__internal.NodeWorkerThreadsWorker {} -declare var Worker: typeof globalThis extends { Worker: infer T } - ? T - : { - prototype: Worker; - new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; - }; +declare var Worker: UseLibDomIfAvailable< + "Worker", + { + prototype: Worker; + new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; + /** + * This is the cloned value of the `data` property passed to `new Worker()` + * + * This is Bun's equivalent of `workerData` in Node.js. + */ + data: any; + } +>; declare var WebSocket: typeof import("ws").WebSocket; @@ -1223,7 +1245,6 @@ interface Blob { */ // eslint-disable-next-line @definitelytyped/no-unnecessary-generics json(): Promise; - /** * Read the data from the blob as a {@link FormData} object. * @@ -1237,13 +1258,153 @@ interface Blob { * closely to the `BodyMixin` API. */ formData(): Promise; - arrayBuffer(): Promise; - /** * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` */ bytes(): Promise; } -declare var Blob: typeof globalThis extends { Blob: infer T } ? T : Blob; +declare var Blob: UseLibDomIfAvailable< + "Blob", + { + prototype: Blob; + new (blobParts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; + } +>; + +interface BroadcastChannel {} +declare var BroadcastChannel: UseLibDomIfAvailable<"BroadcastChannel", import("node:worker_threads").BroadcastChannel>; + +declare var URL: UseLibDomIfAvailable< + "URL", + { + prototype: URL; + new (url: string | URL, base?: string | URL): URL; + /** + * Check if a URL can be parsed. + * + * @param url - The URL to check. + * @param base - The base URL to use. + */ + canParse(url: string, base?: string): boolean; + /** + * Create a URL from an object. + * + * @param object - The object to create a URL from. + */ + createObjectURL(object: Blob): `blob:${string}`; + /** + * Revoke a URL. + * + * @param url - The URL to revoke. + */ + revokeObjectURL(url: string): void; + } +>; + +declare var AbortController: UseLibDomIfAvailable< + "AbortController", + { + prototype: AbortController; + new (): AbortController; + } +>; + +declare var AbortSignal: UseLibDomIfAvailable< + "AbortSignal", + { + prototype: AbortSignal; + new (): AbortSignal; + } +>; + +interface DOMException {} +declare var DOMException: UseLibDomIfAvailable<"DOMException", { prototype: DOMException; new (): DOMException }>; + +interface FormData {} +declare var FormData: UseLibDomIfAvailable<"FormData", { prototype: FormData; new (): FormData }>; + +interface EventSource {} +declare var EventSource: UseLibDomIfAvailable<"EventSource", { prototype: EventSource; new (): EventSource }>; + +interface PerformanceEntry {} +declare var PerformanceEntry: UseLibDomIfAvailable< + "PerformanceEntry", + { prototype: PerformanceEntry; new (): PerformanceEntry } +>; + +interface PerformanceMark {} +declare var PerformanceMark: UseLibDomIfAvailable< + "PerformanceMark", + { prototype: PerformanceMark; new (): PerformanceMark } +>; + +interface PerformanceMeasure {} +declare var PerformanceMeasure: UseLibDomIfAvailable< + "PerformanceMeasure", + { prototype: PerformanceMeasure; new (): PerformanceMeasure } +>; + +interface PerformanceObserver {} +declare var PerformanceObserver: UseLibDomIfAvailable< + "PerformanceObserver", + { prototype: PerformanceObserver; new (): PerformanceObserver } +>; + +interface PerformanceObserverEntryList {} +declare var PerformanceObserverEntryList: UseLibDomIfAvailable< + "PerformanceObserverEntryList", + { prototype: PerformanceObserverEntryList; new (): PerformanceObserverEntryList } +>; + +interface PerformanceResourceTiming {} +declare var PerformanceResourceTiming: UseLibDomIfAvailable< + "PerformanceResourceTiming", + { prototype: PerformanceResourceTiming; new (): PerformanceResourceTiming } +>; + +interface ReadableByteStreamController {} +declare var ReadableByteStreamController: UseLibDomIfAvailable< + "ReadableByteStreamController", + { prototype: ReadableByteStreamController; new (): ReadableByteStreamController } +>; + +interface ReadableStreamBYOBReader {} +declare var ReadableStreamBYOBReader: UseLibDomIfAvailable< + "ReadableStreamBYOBReader", + { prototype: ReadableStreamBYOBReader; new (): ReadableStreamBYOBReader } +>; + +interface ReadableStreamBYOBRequest {} +declare var ReadableStreamBYOBRequest: UseLibDomIfAvailable< + "ReadableStreamBYOBRequest", + { prototype: ReadableStreamBYOBRequest; new (): ReadableStreamBYOBRequest } +>; + +interface TextDecoderStream {} +declare var TextDecoderStream: UseLibDomIfAvailable< + "TextDecoderStream", + { prototype: TextDecoderStream; new (): TextDecoderStream } +>; + +interface TextEncoderStream {} +declare var TextEncoderStream: UseLibDomIfAvailable< + "TextEncoderStream", + { prototype: TextEncoderStream; new (): TextEncoderStream } +>; + +interface URLSearchParams {} +declare var URLSearchParams: UseLibDomIfAvailable< + "URLSearchParams", + { prototype: URLSearchParams; new (): URLSearchParams } +>; + +interface MessageChannel {} +declare var MessageChannel: UseLibDomIfAvailable< + "MessageChannel", + { prototype: MessageChannel; new (): MessageChannel } +>; + +interface MessagePort {} +declare var MessagePort: UseLibDomIfAvailable<"MessagePort", { prototype: MessagePort; new (): MessagePort }>; diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index d8927922fab7a7..b3c28e36d4b780 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -42,7 +42,7 @@ beforeAll(async () => { rm ${BUN_TYPES_TARBALL_NAME} `; } catch (e) { - if (e instanceof ShellError) { + if (e instanceof Bun.$.ShellError) { console.log(e.stderr.toString()); } diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 3ceded33bf2fea..98c9a3e98e20af 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -175,8 +175,6 @@ fetch; fetch.preconnect(new URL("")); -document.getElementById("id"); - Bun.serve({ port: 3000, fetch: () => new Response("ok"), From d14668fd4e8c9435c0f61d3d8068ce6b5487aabb Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 10 Mar 2025 00:17:40 +0000 Subject: [PATCH 28/72] fix test name --- test/integration/bun-types/bun-types.test.ts | 2 +- test/integration/bun-types/fixture/index.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index b3c28e36d4b780..2fbbb21de385c5 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -64,7 +64,7 @@ describe("@types/bun integration test", () => { expect(p.exitCode).toBe(0); }); - test("it typechecks successfully with DOM lib", async () => { + test("it typechecks successfully without DOM lib", async () => { const p = await $` cd ${FIXTURE_DIR} # modify tsconfig.json to remove dom lib diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 98c9a3e98e20af..ff39ee424dbc3c 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -194,6 +194,8 @@ URL.canParse; URL.createObjectURL; URL.revokeObjectURL; +new MessagePort(); + new File(["code"], "name.ts"); Response.json(""); From a4d183ade19ce1e1687433b4c3598db60a44e10b Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 10 Mar 2025 00:32:01 +0000 Subject: [PATCH 29/72] nothrow --- packages/bun-types/new/globals.d.ts | 2 +- test/integration/bun-types/bun-types.test.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 2281505d60c37d..4dd0dc7fcd21f5 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -407,7 +407,7 @@ declare var CloseEvent: { interface MessageEvent extends Bun.MessageEvent {} declare var MessageEvent: { prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; + new (type: string, eventInitDict?: Bun.MessageEventInit): Bun.MessageEvent; }; interface CustomEvent extends Event { diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 2fbbb21de385c5..340454bc060e2c 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -9,7 +9,8 @@ const TSCONFIG_SOURCE_PATH = join(BUN_REPO_ROOT, "src/cli/init/tsconfig.default. const BUN_TYPES_PACKAGE_JSON_PATH = join(BUN_TYPES_PACKAGE_ROOT, "package.json"); const BUN_VERSION = (process.env.BUN_VERSION || Bun.version || process.versions.bun).replace(/^.*v/, ""); const BUN_TYPES_TARBALL_NAME = `types-bun-${BUN_VERSION}.tgz`; -const $ = Shell.cwd(BUN_REPO_ROOT); + +const $ = Shell.cwd(BUN_REPO_ROOT).nothrow(); beforeAll(async () => { try { From c53a9a923f508bc5ea68891a6c02f4c5366dea6a Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 10 Mar 2025 00:39:12 +0000 Subject: [PATCH 30/72] fix more types --- packages/bun-types/new/globals.d.ts | 40 +++++++++++++++++++---------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 4dd0dc7fcd21f5..bd3d0451650287 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -62,7 +62,7 @@ declare var Worker: UseLibDomIfAvailable< } >; -declare var WebSocket: typeof import("ws").WebSocket; +declare var WebSocket: UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>; interface Crypto {} declare var Crypto: { @@ -97,10 +97,13 @@ interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { */ encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; } -declare var TextEncoder: { - prototype: TextEncoder; - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; -}; +declare var TextEncoder: UseLibDomIfAvailable< + "TextEncoder", + { + prototype: TextEncoder; + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; + } +>; /** * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextDecoder` API. All @@ -110,13 +113,19 @@ declare var TextEncoder: { * const decoder = new TextDecoder(); * const uint8array = decoder.decode('this is some data'); */ -declare var TextDecoder: { - prototype: Bun.__internal.NodeUtilTextDecoder; - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): Bun.__internal.NodeUtilTextDecoder; -}; +declare var TextDecoder: UseLibDomIfAvailable< + "TextDecoder", + { + prototype: Bun.__internal.NodeUtilTextDecoder; + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): Bun.__internal.NodeUtilTextDecoder; + } +>; interface Performance extends Bun.__internal.NodePerfHooksPerformance {} -declare var performance: Performance; +declare var performance: UseLibDomIfAvailable<"performance", Performance>; // interface Event { // /** This is not used in Node.js and is provided purely for completeness. */ @@ -405,10 +414,13 @@ declare var CloseEvent: { }; interface MessageEvent extends Bun.MessageEvent {} -declare var MessageEvent: { - prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): Bun.MessageEvent; -}; +declare var MessageEvent: UseLibDomIfAvailable< + "MessageEvent", + { + prototype: MessageEvent; + new (type: string, eventInitDict?: Bun.MessageEventInit): Bun.MessageEvent; + } +>; interface CustomEvent extends Event { /** Returns any custom data event was created with. Typically used for synthetic events. */ From 7a9358ccb14fe3849c1a718deb5c32294553fe6b Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 10 Mar 2025 23:40:01 +0000 Subject: [PATCH 31/72] some changes --- docs/quickstart.md | 2 +- docs/typescript.md | 6 +- packages/bun-types/new/bun.d.ts | 43 ++- packages/bun-types/new/fetch.d.ts | 351 +++++++++--------- packages/bun-types/new/globals.d.ts | 118 +++--- packages/bun-vscode/example/tsconfig.json | 2 +- src/cli/init/tsconfig.default.json | 2 +- test/integration/bun-types/bun-types.test.ts | 2 +- test/integration/bun-types/fixture/bun.lock | 4 +- test/integration/bun-types/fixture/index.ts | 2 + .../bun-types/fixture/package.json | 2 +- test/integration/bun-types/fixture/test.d.ts | 1 + 12 files changed, 282 insertions(+), 253 deletions(-) create mode 100644 test/integration/bun-types/fixture/test.d.ts diff --git a/docs/quickstart.md b/docs/quickstart.md index 6e151b3fefd088..e93450f8c83c1b 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -56,7 +56,7 @@ Then add the following to your `compilerOptions` in `tsconfig.json`: ```json#tsconfig.json { "compilerOptions": { - "lib": ["ESNext"], + "lib": ["ESNext", "DOM"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/docs/typescript.md b/docs/typescript.md index 0790ceccf9fdfe..210f1bb19e076c 100644 --- a/docs/typescript.md +++ b/docs/typescript.md @@ -18,7 +18,7 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh { "compilerOptions": { // Enable latest features - "lib": ["ESNext"], + "lib": ["ESNext", "DOM"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", @@ -39,8 +39,8 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh // Some stricter flags "noUnusedLocals": true, "noUnusedParameters": true, - "noPropertyAccessFromIndexSignature": true - } + "noPropertyAccessFromIndexSignature": true, + }, } ``` diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 795e6396f4a6ac..6897e15b16c21d 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -14,6 +14,27 @@ * This module aliases `globalThis.Bun`. */ declare module "bun" { + /** + * 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. + * + * @internal + */ + type UseLibDomIfAvailable = + // `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 + typeof globalThis extends { onabort: any } + ? 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 + type DistributedOmit = T extends T ? Omit : never; type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; type ArrayBufferView = NodeJS.TypedArray | DataView; @@ -42,7 +63,6 @@ declare module "bun" { type BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; type DOMHighResTimeStamp = number; type EventListenerOrEventListenerObject = EventListener | EventListenerObject; - type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob; type Platform = @@ -114,7 +134,7 @@ declare module "bun" { /** 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 (typeof MessagePort)[]; // ReadonlyArray; + readonly ports: readonly MessagePort[]; // ReadonlyArray; readonly source: Bun.MessageEventSource | null; } @@ -126,7 +146,7 @@ declare module "bun" { } interface ResponseInit { - headers?: HeadersInit; + headers?: import("./fetch.d.ts").HeadersInit; /** @default 200 */ status?: number; @@ -940,7 +960,6 @@ declare module "bun" { * * On failure, throws a `ResolveMessage` */ - // tslint:disable-next-line:unified-signatures function resolveSync(moduleId: string, parent: string): string; /** @@ -950,7 +969,6 @@ declare module "bun" { * * 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; /** @@ -962,7 +980,6 @@ declare module "bun" { * @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 | S3File | PathLike, input: Blob | NodeJS.TypedArray | ArrayBufferLike | string | BlobPart[], @@ -1015,7 +1032,6 @@ declare module "bun" { * @param input - `Response` object * @returns A promise that resolves with the number of bytes written. */ - // tslint:disable-next-line:unified-signatures function write( destinationPath: PathLike, input: Response, @@ -1049,7 +1065,7 @@ declare module "bun" { * @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, @@ -1083,7 +1099,6 @@ declare module "bun" { * @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: PathLike, input: BunFile, @@ -3991,7 +4006,7 @@ declare module "bun" { /** * Send any additional headers while upgrading, like cookies */ - headers?: HeadersInit; + headers?: import("./fetch.d.ts").HeadersInit; /** * This value is passed to the {@link ServerWebSocket.data} property */ @@ -4350,7 +4365,7 @@ declare module "bun" { * ``` * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} */ - // tslint:disable-next-line:unified-signatures + function file(path: string | URL, options?: BlobPropertyBag): BunFile; /** @@ -4376,7 +4391,7 @@ declare module "bun" { * * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} */ - // tslint:disable-next-line:unified-signatures + function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; /** @@ -4393,7 +4408,7 @@ declare module "bun" { * * @param fileDescriptor The file descriptor of the file */ - // tslint:disable-next-line:unified-signatures + function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; /** @@ -4608,7 +4623,7 @@ declare module "bun" { * * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. */ - // tslint:disable-next-line:unified-signatures + arrayBufferToString(buffer: Uint16Array): string; /** diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts index a5352a9e02c37e..2fb7219adf46f0 100644 --- a/packages/bun-types/new/fetch.d.ts +++ b/packages/bun-types/new/fetch.d.ts @@ -1,13 +1,8 @@ -type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; +export {}; +type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; type HeadersInit = Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; -// Comes from @types/node as they're declared globally -interface RequestInit {} - -// Comes from @types/node as they're declared globally -interface ResponseInit {} - declare module "bun" { namespace __internal { /** @@ -27,192 +22,200 @@ declare module "bun" { } } -interface Headers extends Bun.__internal.UndiciHeaders { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; -} +declare global { + // Comes from @types/node as they're declared globally + interface RequestInit {} -declare var Headers: { - prototype: Headers; - new (init?: HeadersInit): Headers; -}; + // Comes from @types/node as they're declared globally + interface ResponseInit {} -interface Request extends Bun.__internal.UndiciRequest { - headers: Headers; -} + interface Headers extends Bun.__internal.UndiciHeaders { + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; + } -declare var Request: { - prototype: Request; - new (requestInfo: string, init?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, init?: RequestInit): Request; -}; + var Headers: { + prototype: Headers; + new (init?: HeadersInit): Headers; + }; -interface Response extends Bun.__internal.UndiciResponse { - headers: Headers; -} + interface Request extends Bun.__internal.UndiciRequest { + headers: Headers; + } -declare var Response: { - new (body?: BodyInit | null | undefined, init?: ResponseInit | undefined): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: ResponseInit | number): Response; + var Request: { + prototype: Request; + new (requestInfo: string, init?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, init?: RequestInit): Request; + }; - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, status?: number): Response; + interface Response extends Bun.__internal.UndiciResponse { + headers: Headers; + } + + var Response: { + new (body?: BodyInit | null | undefined, init?: ResponseInit | undefined): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, options?: ResponseInit | number): Response; + + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + + redirect(url: string, status?: number): Response; + + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + + redirect(url: string, options?: Bun.ResponseInit): Response; + + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; + }; + + interface BunFetchRequestInitTLS extends Bun.TLSOptions { + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable; + } /** - * Create a new {@link Response} that redirects to url + * BunFetchRequestInit represents additional options that Bun supports in `fetch()` only. * - * @param url - the URL to redirect to - * @param options - options to pass to the response + * Bun extends the `fetch` API with some additional options, except + * this interface is not quite a `RequestInit`, because they won't work + * if passed to `new Request()`. This is why it's a separate type. */ - // tslint:disable-next-line:unified-signatures - redirect(url: string, options?: Bun.ResponseInit): Response; + interface BunFetchRequestInit extends RequestInit { + /** + * Override the default TLS options + */ + tls?: BunFetchRequestInitTLS; - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; -}; + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; -interface BunFetchRequestInitTLS extends Bun.TLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable; -} + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; -/** - * BunFetchRequestInit represents additional options that Bun supports in `fetch()` only. - * - * Bun extends the `fetch` API with some additional options, except - * this interface is not quite a `RequestInit`, because they won't work - * if passed to `new Request()`. This is why it's a separate type. - */ -interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; + /** + * Override the default S3 options + */ + s3?: Bun.S3Options; + } /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. */ - verbose?: boolean; - + function fetch(request: Request, init?: BunFetchRequestInit): Promise; /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. */ - proxy?: string; + function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; /** - * Override the default S3 options + * Send a HTTP(s) request + * + * @param input URL string or Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. */ - s3?: Bun.S3Options; -} - -/** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(request: Request, init?: BunFetchRequestInit): Promise; -/** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; - -/** - * Send a HTTP(s) request - * - * @param input URL string or Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; - -declare namespace fetch { - export function preconnect( - url: string | URL, - options?: { - dns?: boolean; - tcp?: boolean; - http?: boolean; - https?: boolean; - }, - ): void; + function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; + + namespace fetch { + export function preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; + } } diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index bd3d0451650287..58e8f4d7b41e51 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -9,27 +9,8 @@ declare module "bun" { } } -/** - * 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 = - // `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 - typeof globalThis extends { onabort: any } - ? 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 - interface ReadableStream {} -declare var ReadableStream: UseLibDomIfAvailable< +declare var ReadableStream: Bun.UseLibDomIfAvailable< "ReadableStream", { prototype: ReadableStream; @@ -39,7 +20,7 @@ declare var ReadableStream: UseLibDomIfAvailable< >; interface WritableStream {} -declare var WritableStream: UseLibDomIfAvailable< +declare var WritableStream: Bun.UseLibDomIfAvailable< "WritableStream", { prototype: WritableStream; @@ -48,7 +29,7 @@ declare var WritableStream: UseLibDomIfAvailable< >; interface Worker extends Bun.__internal.NodeWorkerThreadsWorker {} -declare var Worker: UseLibDomIfAvailable< +declare var Worker: Bun.UseLibDomIfAvailable< "Worker", { prototype: Worker; @@ -62,7 +43,7 @@ declare var Worker: UseLibDomIfAvailable< } >; -declare var WebSocket: UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>; +declare var WebSocket: Bun.UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>; interface Crypto {} declare var Crypto: { @@ -97,7 +78,7 @@ interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { */ encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; } -declare var TextEncoder: UseLibDomIfAvailable< +declare var TextEncoder: Bun.UseLibDomIfAvailable< "TextEncoder", { prototype: TextEncoder; @@ -113,7 +94,7 @@ declare var TextEncoder: UseLibDomIfAvailable< * const decoder = new TextDecoder(); * const uint8array = decoder.decode('this is some data'); */ -declare var TextDecoder: UseLibDomIfAvailable< +declare var TextDecoder: Bun.UseLibDomIfAvailable< "TextDecoder", { prototype: Bun.__internal.NodeUtilTextDecoder; @@ -125,7 +106,7 @@ declare var TextDecoder: UseLibDomIfAvailable< >; interface Performance extends Bun.__internal.NodePerfHooksPerformance {} -declare var performance: UseLibDomIfAvailable<"performance", Performance>; +declare var performance: Bun.UseLibDomIfAvailable<"performance", Performance>; // interface Event { // /** This is not used in Node.js and is provided purely for completeness. */ @@ -414,13 +395,7 @@ declare var CloseEvent: { }; interface MessageEvent extends Bun.MessageEvent {} -declare var MessageEvent: UseLibDomIfAvailable< - "MessageEvent", - { - prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): Bun.MessageEvent; - } ->; +declare var MessageEvent: Bun.UseLibDomIfAvailable<"MessageEvent", MessageEvent>; interface CustomEvent extends Event { /** Returns any custom data event was created with. Typically used for synthetic events. */ @@ -1277,7 +1252,7 @@ interface Blob { bytes(): Promise; } -declare var Blob: UseLibDomIfAvailable< +declare var Blob: Bun.UseLibDomIfAvailable< "Blob", { prototype: Blob; @@ -1285,10 +1260,37 @@ declare var Blob: UseLibDomIfAvailable< } >; +interface Uint8Array { + /** + * Convert the Uint8Array to a base64 encoded string + * @returns The base64 encoded string representation of the Uint8Array + */ + toBase64(options?: { alphabet?: "base64" | "base64url"; omitPadding?: boolean }): string; + + /** + * Set the contents of the Uint8Array from a base64 encoded string + * @param base64 The base64 encoded string to decode into the array + * @param offset Optional starting index to begin setting the decoded bytes (default: 0) + */ + setFromBase64(base64: string, offset?: number): void; +} + +interface Uint8ArrayConstructor { + /** + * Create a new Uint8Array from a base64 encoded string + * @param base64 The base64 encoded string to convert to a Uint8Array + * @returns A new Uint8Array containing the decoded data + */ + fromBase64(base64: string): Uint8Array; +} + interface BroadcastChannel {} -declare var BroadcastChannel: UseLibDomIfAvailable<"BroadcastChannel", import("node:worker_threads").BroadcastChannel>; +declare var BroadcastChannel: Bun.UseLibDomIfAvailable< + "BroadcastChannel", + import("node:worker_threads").BroadcastChannel +>; -declare var URL: UseLibDomIfAvailable< +declare var URL: Bun.UseLibDomIfAvailable< "URL", { prototype: URL; @@ -1315,7 +1317,7 @@ declare var URL: UseLibDomIfAvailable< } >; -declare var AbortController: UseLibDomIfAvailable< +declare var AbortController: Bun.UseLibDomIfAvailable< "AbortController", { prototype: AbortController; @@ -1323,7 +1325,7 @@ declare var AbortController: UseLibDomIfAvailable< } >; -declare var AbortSignal: UseLibDomIfAvailable< +declare var AbortSignal: Bun.UseLibDomIfAvailable< "AbortSignal", { prototype: AbortSignal; @@ -1332,91 +1334,97 @@ declare var AbortSignal: UseLibDomIfAvailable< >; interface DOMException {} -declare var DOMException: UseLibDomIfAvailable<"DOMException", { prototype: DOMException; new (): DOMException }>; +declare var DOMException: Bun.UseLibDomIfAvailable<"DOMException", { prototype: DOMException; new (): DOMException }>; interface FormData {} -declare var FormData: UseLibDomIfAvailable<"FormData", { prototype: FormData; new (): FormData }>; +declare var FormData: Bun.UseLibDomIfAvailable<"FormData", { prototype: FormData; new (): FormData }>; interface EventSource {} -declare var EventSource: UseLibDomIfAvailable<"EventSource", { prototype: EventSource; new (): EventSource }>; +declare var EventSource: Bun.UseLibDomIfAvailable<"EventSource", { prototype: EventSource; new (): EventSource }>; interface PerformanceEntry {} -declare var PerformanceEntry: UseLibDomIfAvailable< +declare var PerformanceEntry: Bun.UseLibDomIfAvailable< "PerformanceEntry", { prototype: PerformanceEntry; new (): PerformanceEntry } >; interface PerformanceMark {} -declare var PerformanceMark: UseLibDomIfAvailable< +declare var PerformanceMark: Bun.UseLibDomIfAvailable< "PerformanceMark", { prototype: PerformanceMark; new (): PerformanceMark } >; interface PerformanceMeasure {} -declare var PerformanceMeasure: UseLibDomIfAvailable< +declare var PerformanceMeasure: Bun.UseLibDomIfAvailable< "PerformanceMeasure", { prototype: PerformanceMeasure; new (): PerformanceMeasure } >; interface PerformanceObserver {} -declare var PerformanceObserver: UseLibDomIfAvailable< +declare var PerformanceObserver: Bun.UseLibDomIfAvailable< "PerformanceObserver", { prototype: PerformanceObserver; new (): PerformanceObserver } >; interface PerformanceObserverEntryList {} -declare var PerformanceObserverEntryList: UseLibDomIfAvailable< +declare var PerformanceObserverEntryList: Bun.UseLibDomIfAvailable< "PerformanceObserverEntryList", { prototype: PerformanceObserverEntryList; new (): PerformanceObserverEntryList } >; interface PerformanceResourceTiming {} -declare var PerformanceResourceTiming: UseLibDomIfAvailable< +declare var PerformanceResourceTiming: Bun.UseLibDomIfAvailable< "PerformanceResourceTiming", { prototype: PerformanceResourceTiming; new (): PerformanceResourceTiming } >; interface ReadableByteStreamController {} -declare var ReadableByteStreamController: UseLibDomIfAvailable< +declare var ReadableByteStreamController: Bun.UseLibDomIfAvailable< "ReadableByteStreamController", { prototype: ReadableByteStreamController; new (): ReadableByteStreamController } >; interface ReadableStreamBYOBReader {} -declare var ReadableStreamBYOBReader: UseLibDomIfAvailable< +declare var ReadableStreamBYOBReader: Bun.UseLibDomIfAvailable< "ReadableStreamBYOBReader", { prototype: ReadableStreamBYOBReader; new (): ReadableStreamBYOBReader } >; interface ReadableStreamBYOBRequest {} -declare var ReadableStreamBYOBRequest: UseLibDomIfAvailable< +declare var ReadableStreamBYOBRequest: Bun.UseLibDomIfAvailable< "ReadableStreamBYOBRequest", { prototype: ReadableStreamBYOBRequest; new (): ReadableStreamBYOBRequest } >; interface TextDecoderStream {} -declare var TextDecoderStream: UseLibDomIfAvailable< +declare var TextDecoderStream: Bun.UseLibDomIfAvailable< "TextDecoderStream", { prototype: TextDecoderStream; new (): TextDecoderStream } >; interface TextEncoderStream {} -declare var TextEncoderStream: UseLibDomIfAvailable< +declare var TextEncoderStream: Bun.UseLibDomIfAvailable< "TextEncoderStream", { prototype: TextEncoderStream; new (): TextEncoderStream } >; interface URLSearchParams {} -declare var URLSearchParams: UseLibDomIfAvailable< +declare var URLSearchParams: Bun.UseLibDomIfAvailable< "URLSearchParams", { prototype: URLSearchParams; new (): URLSearchParams } >; interface MessageChannel {} -declare var MessageChannel: UseLibDomIfAvailable< +declare var MessageChannel: Bun.UseLibDomIfAvailable< "MessageChannel", { prototype: MessageChannel; new (): MessageChannel } >; interface MessagePort {} -declare var MessagePort: UseLibDomIfAvailable<"MessagePort", { prototype: MessagePort; new (): MessagePort }>; +declare var MessagePort: Bun.UseLibDomIfAvailable< + "MessagePort", + { + prototype: MessagePort; + new (): MessagePort; + } +>; diff --git a/packages/bun-vscode/example/tsconfig.json b/packages/bun-vscode/example/tsconfig.json index 7eff589c7420ff..fd276eb0ffe3c5 100644 --- a/packages/bun-vscode/example/tsconfig.json +++ b/packages/bun-vscode/example/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "lib": ["ESNext"], + "lib": ["ESNext", "DOM"], "module": "esnext", "target": "esnext", "moduleResolution": "bundler", diff --git a/src/cli/init/tsconfig.default.json b/src/cli/init/tsconfig.default.json index abcb72bb52e1f8..0c416efad6e0d3 100644 --- a/src/cli/init/tsconfig.default.json +++ b/src/cli/init/tsconfig.default.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Environment setup & latest features - "lib": ["esnext", "dom"], + "lib": ["ESNext", "DOM"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 340454bc060e2c..44536cfb3f2261 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -69,7 +69,7 @@ describe("@types/bun integration test", () => { const p = await $` cd ${FIXTURE_DIR} # modify tsconfig.json to remove dom lib - sed -i 's/"lib": \["esnext", "dom"\]/"lib": \["esnext"\]/' tsconfig.json + sed -i 's/"lib": \["ESNext", "DOM"\]/"lib": \["ESNext"\]/' tsconfig.json bun run check `; diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index bda69c34e0a61e..bcfb4ec1c3f699 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -7,7 +7,7 @@ "@types/bun": "types-bun-1.2.5.tgz", }, "peerDependencies": { - "typescript": "^5.0.0", + "typescript": "^5.8.2", }, }, }, @@ -18,7 +18,7 @@ "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], - "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], + "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], } diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index ff39ee424dbc3c..74027a769ed6f3 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -209,6 +209,8 @@ Response.redirect("bun.sh", { Bun.fetch.preconnect; +new Uint8Array().toBase64(); + type g = BodyInit; Bun.fetch("", { diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index 61fc6d115f617c..8d42eab946831f 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -2,7 +2,7 @@ "name": "fixture", "module": "index.ts", "peerDependencies": { - "typescript": "^5.0.0" + "typescript": "^5.8.2" }, "scripts": { "check": "tsc --noEmit" diff --git a/test/integration/bun-types/fixture/test.d.ts b/test/integration/bun-types/fixture/test.d.ts new file mode 100644 index 00000000000000..cb0ff5c3b541f6 --- /dev/null +++ b/test/integration/bun-types/fixture/test.d.ts @@ -0,0 +1 @@ +export {}; From 04110ac05fef7d69b8a802efb513e121d619fd45 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 11 Mar 2025 02:02:38 +0000 Subject: [PATCH 32/72] checkpoint --- packages/bun-types/new/bun.d.ts | 55 +-- packages/bun-types/new/fetch.d.ts | 362 ++++++++++--------- packages/bun-types/new/globals.d.ts | 66 ++-- test/integration/bun-types/bun-types.test.ts | 12 +- test/integration/bun-types/fixture/index.ts | 4 +- 5 files changed, 258 insertions(+), 241 deletions(-) diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 6897e15b16c21d..57a878688496a4 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -14,32 +14,12 @@ * This module aliases `globalThis.Bun`. */ declare module "bun" { - /** - * 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. - * - * @internal - */ - type UseLibDomIfAvailable = - // `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 - typeof globalThis extends { onabort: any } - ? 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 - type DistributedOmit = T extends T ? Omit : never; type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; type ArrayBufferView = NodeJS.TypedArray | DataView; + type BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData; + type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData | Iterable; type ReadableStreamController = ReadableStreamDefaultController; type ReadableStreamDefaultReadResult = | ReadableStreamDefaultReadValueResult @@ -60,11 +40,36 @@ declare module "bun" { type SignalsListener = (signal: NodeJS.Signals) => void; type BlobPart = string | Blob | BufferSource; type TimerHandler = (...args: any[]) => void; - type BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; + type DOMHighResTimeStamp = number; type EventListenerOrEventListenerObject = EventListener | EventListenerObject; type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob; + 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. + * + * @internal + */ + type UseLibDomIfAvailable = + // `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 + typeof globalThis extends { onabort: any } + ? 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 + } + type Platform = | "aix" | "android" @@ -146,7 +151,7 @@ declare module "bun" { } interface ResponseInit { - headers?: import("./fetch.d.ts").HeadersInit; + headers?: Bun.__internal.BunHeadersInit; /** @default 200 */ status?: number; @@ -4006,7 +4011,7 @@ declare module "bun" { /** * Send any additional headers while upgrading, like cookies */ - headers?: import("./fetch.d.ts").HeadersInit; + headers?: Bun.__internal.BunHeadersInit; /** * This value is passed to the {@link ServerWebSocket.data} property */ diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts index 2fb7219adf46f0..b18c88f96ffdc7 100644 --- a/packages/bun-types/new/fetch.d.ts +++ b/packages/bun-types/new/fetch.d.ts @@ -1,221 +1,227 @@ -export {}; - -type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; -type HeadersInit = Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; - declare module "bun" { namespace __internal { + type BunBodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; + + type BunHeadersInit = + | Headers + | Record + | Array<[string, string]> + | IterableIterator<[string, string]>; + /** * @internal */ - type UndiciRequest = import("undici-types").Request; + type LibOrUndiciHeaders = LibDomIsLoaded extends true ? typeof globalThis.Headers : import("undici-types").Headers; /** * @internal */ - type UndiciResponse = import("undici-types").Response; + type LibOrUndiciRequest = LibDomIsLoaded extends true ? {} : import("undici-types").Request; /** * @internal */ - type UndiciHeaders = import("undici-types").Headers; + type LibOrUndiciResponse = LibDomIsLoaded extends true ? {} : import("undici-types").Response; + + interface BunHeadersOverride extends LibOrUndiciHeaders { + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; + } + + interface BunResponseOverride extends LibOrUndiciResponse { + headers: BunHeadersOverride; + } + + interface BunRequestOverride extends LibOrUndiciRequest { + headers: BunHeadersOverride; + } } } -declare global { - // Comes from @types/node as they're declared globally - interface RequestInit {} - - // Comes from @types/node as they're declared globally - interface ResponseInit {} - - interface Headers extends Bun.__internal.UndiciHeaders { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; - } - - var Headers: { +interface Headers extends Bun.__internal.BunHeadersOverride {} +declare var Headers: Bun.__internal.UseLibDomIfAvailable< + "Headers", + { prototype: Headers; - new (init?: HeadersInit): Headers; - }; - - interface Request extends Bun.__internal.UndiciRequest { - headers: Headers; + new (init?: Bun.__internal.BunHeadersInit): Headers; } +>; + +interface Request extends Bun.__internal.BunRequestOverride {} - var Request: { +declare var Request: Bun.__internal.UseLibDomIfAvailable< + "Request", + { prototype: Request; new (requestInfo: string, init?: RequestInit): Request; new (requestInfo: RequestInit & { url: string }): Request; new (requestInfo: Request, init?: RequestInit): Request; - }; - - interface Response extends Bun.__internal.UndiciResponse { - headers: Headers; } +>; - var Response: { - new (body?: BodyInit | null | undefined, init?: ResponseInit | undefined): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: ResponseInit | number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - - redirect(url: string, status?: number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - - redirect(url: string, options?: Bun.ResponseInit): Response; +interface Response extends Bun.__internal.BunResponseOverride {} - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; - }; +interface ResponseConstructor { + new (body?: Bun.__internal.BunBodyInit | null | undefined, init?: ResponseInit | undefined): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, options?: ResponseInit | number): Response; - interface BunFetchRequestInitTLS extends Bun.TLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable; - } + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + redirect(url: string, status?: number): Response; /** - * BunFetchRequestInit represents additional options that Bun supports in `fetch()` only. + * Create a new {@link Response} that redirects to url * - * Bun extends the `fetch` API with some additional options, except - * this interface is not quite a `RequestInit`, because they won't work - * if passed to `new Request()`. This is why it's a separate type. + * @param url - the URL to redirect to + * @param options - options to pass to the response */ - interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; + redirect(url: string, options?: Bun.ResponseInit): Response; - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; +} - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; +declare var Response: Bun.__internal.UseLibDomIfAvailable<"Response", ResponseConstructor>; - /** - * Override the default S3 options - */ - s3?: Bun.S3Options; - } +interface BunFetchRequestInitTLS extends Bun.TLSOptions { + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable; +} +/** + * BunFetchRequestInit represents additional options that Bun supports in `fetch()` only. + * + * Bun extends the `fetch` API with some additional options, except + * this interface is not quite a `RequestInit`, because they won't work + * if passed to `new Request()`. This is why it's a separate type. + */ +interface BunFetchRequestInit extends RequestInit { /** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. + * Override the default TLS options */ - function fetch(request: Request, init?: BunFetchRequestInit): Promise; + tls?: BunFetchRequestInitTLS; + /** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool */ - function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; + verbose?: boolean; /** - * Send a HTTP(s) request - * - * @param input URL string or Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. */ - function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; - - namespace fetch { - export function preconnect( - url: string | URL, - options?: { - dns?: boolean; - tcp?: boolean; - http?: boolean; - https?: boolean; - }, - ): void; - } + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: Bun.S3Options; +} + +/** + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(request: Request, init?: BunFetchRequestInit): Promise; +/** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; + +/** + * Send a HTTP(s) request + * + * @param input URL string or Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; + +declare namespace fetch { + export function preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; } diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 58e8f4d7b41e51..50933766ed5b76 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -10,7 +10,7 @@ declare module "bun" { } interface ReadableStream {} -declare var ReadableStream: Bun.UseLibDomIfAvailable< +declare var ReadableStream: Bun.__internal.UseLibDomIfAvailable< "ReadableStream", { prototype: ReadableStream; @@ -20,7 +20,7 @@ declare var ReadableStream: Bun.UseLibDomIfAvailable< >; interface WritableStream {} -declare var WritableStream: Bun.UseLibDomIfAvailable< +declare var WritableStream: Bun.__internal.UseLibDomIfAvailable< "WritableStream", { prototype: WritableStream; @@ -29,7 +29,7 @@ declare var WritableStream: Bun.UseLibDomIfAvailable< >; interface Worker extends Bun.__internal.NodeWorkerThreadsWorker {} -declare var Worker: Bun.UseLibDomIfAvailable< +declare var Worker: Bun.__internal.UseLibDomIfAvailable< "Worker", { prototype: Worker; @@ -43,7 +43,7 @@ declare var Worker: Bun.UseLibDomIfAvailable< } >; -declare var WebSocket: Bun.UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>; +declare var WebSocket: Bun.__internal.UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>; interface Crypto {} declare var Crypto: { @@ -78,7 +78,7 @@ interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { */ encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; } -declare var TextEncoder: Bun.UseLibDomIfAvailable< +declare var TextEncoder: Bun.__internal.UseLibDomIfAvailable< "TextEncoder", { prototype: TextEncoder; @@ -94,7 +94,7 @@ declare var TextEncoder: Bun.UseLibDomIfAvailable< * const decoder = new TextDecoder(); * const uint8array = decoder.decode('this is some data'); */ -declare var TextDecoder: Bun.UseLibDomIfAvailable< +declare var TextDecoder: Bun.__internal.UseLibDomIfAvailable< "TextDecoder", { prototype: Bun.__internal.NodeUtilTextDecoder; @@ -106,7 +106,7 @@ declare var TextDecoder: Bun.UseLibDomIfAvailable< >; interface Performance extends Bun.__internal.NodePerfHooksPerformance {} -declare var performance: Bun.UseLibDomIfAvailable<"performance", Performance>; +declare var performance: Bun.__internal.UseLibDomIfAvailable<"performance", Performance>; // interface Event { // /** This is not used in Node.js and is provided purely for completeness. */ @@ -395,7 +395,7 @@ declare var CloseEvent: { }; interface MessageEvent extends Bun.MessageEvent {} -declare var MessageEvent: Bun.UseLibDomIfAvailable<"MessageEvent", MessageEvent>; +declare var MessageEvent: Bun.__internal.UseLibDomIfAvailable<"MessageEvent", MessageEvent>; interface CustomEvent extends Event { /** Returns any custom data event was created with. Typically used for synthetic events. */ @@ -1252,7 +1252,7 @@ interface Blob { bytes(): Promise; } -declare var Blob: Bun.UseLibDomIfAvailable< +declare var Blob: Bun.__internal.UseLibDomIfAvailable< "Blob", { prototype: Blob; @@ -1285,12 +1285,12 @@ interface Uint8ArrayConstructor { } interface BroadcastChannel {} -declare var BroadcastChannel: Bun.UseLibDomIfAvailable< +declare var BroadcastChannel: Bun.__internal.UseLibDomIfAvailable< "BroadcastChannel", import("node:worker_threads").BroadcastChannel >; -declare var URL: Bun.UseLibDomIfAvailable< +declare var URL: Bun.__internal.UseLibDomIfAvailable< "URL", { prototype: URL; @@ -1317,7 +1317,7 @@ declare var URL: Bun.UseLibDomIfAvailable< } >; -declare var AbortController: Bun.UseLibDomIfAvailable< +declare var AbortController: Bun.__internal.UseLibDomIfAvailable< "AbortController", { prototype: AbortController; @@ -1325,7 +1325,7 @@ declare var AbortController: Bun.UseLibDomIfAvailable< } >; -declare var AbortSignal: Bun.UseLibDomIfAvailable< +declare var AbortSignal: Bun.__internal.UseLibDomIfAvailable< "AbortSignal", { prototype: AbortSignal; @@ -1334,94 +1334,100 @@ declare var AbortSignal: Bun.UseLibDomIfAvailable< >; interface DOMException {} -declare var DOMException: Bun.UseLibDomIfAvailable<"DOMException", { prototype: DOMException; new (): DOMException }>; +declare var DOMException: Bun.__internal.UseLibDomIfAvailable< + "DOMException", + { prototype: DOMException; new (): DOMException } +>; interface FormData {} -declare var FormData: Bun.UseLibDomIfAvailable<"FormData", { prototype: FormData; new (): FormData }>; +declare var FormData: Bun.__internal.UseLibDomIfAvailable<"FormData", { prototype: FormData; new (): FormData }>; interface EventSource {} -declare var EventSource: Bun.UseLibDomIfAvailable<"EventSource", { prototype: EventSource; new (): EventSource }>; +declare var EventSource: Bun.__internal.UseLibDomIfAvailable< + "EventSource", + { prototype: EventSource; new (): EventSource } +>; interface PerformanceEntry {} -declare var PerformanceEntry: Bun.UseLibDomIfAvailable< +declare var PerformanceEntry: Bun.__internal.UseLibDomIfAvailable< "PerformanceEntry", { prototype: PerformanceEntry; new (): PerformanceEntry } >; interface PerformanceMark {} -declare var PerformanceMark: Bun.UseLibDomIfAvailable< +declare var PerformanceMark: Bun.__internal.UseLibDomIfAvailable< "PerformanceMark", { prototype: PerformanceMark; new (): PerformanceMark } >; interface PerformanceMeasure {} -declare var PerformanceMeasure: Bun.UseLibDomIfAvailable< +declare var PerformanceMeasure: Bun.__internal.UseLibDomIfAvailable< "PerformanceMeasure", { prototype: PerformanceMeasure; new (): PerformanceMeasure } >; interface PerformanceObserver {} -declare var PerformanceObserver: Bun.UseLibDomIfAvailable< +declare var PerformanceObserver: Bun.__internal.UseLibDomIfAvailable< "PerformanceObserver", { prototype: PerformanceObserver; new (): PerformanceObserver } >; interface PerformanceObserverEntryList {} -declare var PerformanceObserverEntryList: Bun.UseLibDomIfAvailable< +declare var PerformanceObserverEntryList: Bun.__internal.UseLibDomIfAvailable< "PerformanceObserverEntryList", { prototype: PerformanceObserverEntryList; new (): PerformanceObserverEntryList } >; interface PerformanceResourceTiming {} -declare var PerformanceResourceTiming: Bun.UseLibDomIfAvailable< +declare var PerformanceResourceTiming: Bun.__internal.UseLibDomIfAvailable< "PerformanceResourceTiming", { prototype: PerformanceResourceTiming; new (): PerformanceResourceTiming } >; interface ReadableByteStreamController {} -declare var ReadableByteStreamController: Bun.UseLibDomIfAvailable< +declare var ReadableByteStreamController: Bun.__internal.UseLibDomIfAvailable< "ReadableByteStreamController", { prototype: ReadableByteStreamController; new (): ReadableByteStreamController } >; interface ReadableStreamBYOBReader {} -declare var ReadableStreamBYOBReader: Bun.UseLibDomIfAvailable< +declare var ReadableStreamBYOBReader: Bun.__internal.UseLibDomIfAvailable< "ReadableStreamBYOBReader", { prototype: ReadableStreamBYOBReader; new (): ReadableStreamBYOBReader } >; interface ReadableStreamBYOBRequest {} -declare var ReadableStreamBYOBRequest: Bun.UseLibDomIfAvailable< +declare var ReadableStreamBYOBRequest: Bun.__internal.UseLibDomIfAvailable< "ReadableStreamBYOBRequest", { prototype: ReadableStreamBYOBRequest; new (): ReadableStreamBYOBRequest } >; interface TextDecoderStream {} -declare var TextDecoderStream: Bun.UseLibDomIfAvailable< +declare var TextDecoderStream: Bun.__internal.UseLibDomIfAvailable< "TextDecoderStream", { prototype: TextDecoderStream; new (): TextDecoderStream } >; interface TextEncoderStream {} -declare var TextEncoderStream: Bun.UseLibDomIfAvailable< +declare var TextEncoderStream: Bun.__internal.UseLibDomIfAvailable< "TextEncoderStream", { prototype: TextEncoderStream; new (): TextEncoderStream } >; interface URLSearchParams {} -declare var URLSearchParams: Bun.UseLibDomIfAvailable< +declare var URLSearchParams: Bun.__internal.UseLibDomIfAvailable< "URLSearchParams", { prototype: URLSearchParams; new (): URLSearchParams } >; interface MessageChannel {} -declare var MessageChannel: Bun.UseLibDomIfAvailable< +declare var MessageChannel: Bun.__internal.UseLibDomIfAvailable< "MessageChannel", { prototype: MessageChannel; new (): MessageChannel } >; interface MessagePort {} -declare var MessagePort: Bun.UseLibDomIfAvailable< +declare var MessagePort: Bun.__internal.UseLibDomIfAvailable< "MessagePort", { prototype: MessagePort; diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 44536cfb3f2261..b37b8c186247d3 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -1,5 +1,5 @@ import { fileURLToPath, $ as Shell } from "bun"; -import { beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test"; +import { beforeAll, beforeEach, describe, expect, setDefaultTimeout, test } from "bun:test"; import { join } from "node:path"; const BUN_REPO_ROOT = fileURLToPath(import.meta.resolve("../../../")); @@ -12,7 +12,7 @@ const BUN_TYPES_TARBALL_NAME = `types-bun-${BUN_VERSION}.tgz`; const $ = Shell.cwd(BUN_REPO_ROOT).nothrow(); -beforeAll(async () => { +beforeEach(async () => { try { await $` cd ${BUN_TYPES_PACKAGE_ROOT} @@ -56,20 +56,20 @@ beforeAll(() => { }); describe("@types/bun integration test", () => { - test("it typechecks successfully with DOM lib", async () => { + test("it typechecks successfully without DOM lib", async () => { const p = await $` cd ${FIXTURE_DIR} + # modify tsconfig.json to remove dom lib + sed -i 's/"lib": \["ESNext", "DOM"\]/"lib": \["ESNext"\]/' tsconfig.json bun run check `; expect(p.exitCode).toBe(0); }); - test("it typechecks successfully without DOM lib", async () => { + test("it typechecks successfully with DOM lib", async () => { const p = await $` cd ${FIXTURE_DIR} - # modify tsconfig.json to remove dom lib - sed -i 's/"lib": \["ESNext", "DOM"\]/"lib": \["ESNext"\]/' tsconfig.json bun run check `; diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 74027a769ed6f3..ab91ea1fc9fb46 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -211,8 +211,6 @@ Bun.fetch.preconnect; new Uint8Array().toBase64(); -type g = BodyInit; - Bun.fetch("", { proxy: "", s3: { @@ -220,6 +218,8 @@ Bun.fetch("", { }, }); +const myRequest: Request = new Request(""); + Bun.serve({ fetch(req) { req.headers; From 007a2bdca29707b4b86fe5c67708ce8cf6a70b50 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 11 Mar 2025 02:06:11 +0000 Subject: [PATCH 33/72] This works fine for overriding lib.dom.d.ts, and still works with node. --- bun.lock | 4 ++++ packages/bun-types/package.json | 3 ++- test/integration/bun-types/fixture/bun.lock | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/bun.lock b/bun.lock index ee4803a2907206..85556bf9379f56 100644 --- a/bun.lock +++ b/bun.lock @@ -27,9 +27,11 @@ }, "packages/bun-types": { "name": "bun-types", + "version": "1.2.5", "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10", + "@typescript/lib-dom": "https://github.com/alii/lib-dom-bun-testing", }, "devDependencies": { "@biomejs/biome": "^1.5.3", @@ -183,6 +185,8 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" } }, "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg=="], + "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#9ed8ccd", {}, "alii-lib-dom-bun-testing-9ed8ccd"], + "@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="], "@vscode/debugadapter": ["@vscode/debugadapter@1.66.0", "", { "dependencies": { "@vscode/debugprotocol": "1.66.0" } }, "sha512-U/m5l6igHtQ8rSMSKW9oWeco9ySPqGYjqW9NECGPGWZ/xnoYicpqUoXhGx3xUNsafrinzWvUWrSUL/Cdgj2V+w=="], diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index 54cceadd1440a5..be2476ea9003e7 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -17,7 +17,8 @@ "homepage": "https://bun.sh", "dependencies": { "@types/node": "*", - "@types/ws": "~8.5.10" + "@types/ws": "~8.5.10", + "@typescript/lib-dom": "https://github.com/alii/lib-dom-bun-testing" }, "devDependencies": { "@biomejs/biome": "^1.5.3", diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index bcfb4ec1c3f699..bc7a3c11b90eca 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -12,12 +12,14 @@ }, }, "packages": { - "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }], + "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10", "@typescript/lib-dom": "https://github.com/alii/lib-dom-bun-testing" } }], "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], + "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#9ed8ccd", {}, "alii-lib-dom-bun-testing-9ed8ccd"], + "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], From 26405b3f10610527adcf93106d384f73c0b5f84c Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 11 Mar 2025 09:08:25 +0000 Subject: [PATCH 34/72] Change how Bun's lib.dom.d.ts gets loaded --- bun.lock | 4 ++-- packages/bun-types/package.json | 4 ++-- test/integration/bun-types/fixture/bun.lock | 7 +++++-- test/integration/bun-types/fixture/package.json | 1 + 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/bun.lock b/bun.lock index 85556bf9379f56..9df2af8cc65f33 100644 --- a/bun.lock +++ b/bun.lock @@ -30,8 +30,8 @@ "version": "1.2.5", "dependencies": { "@types/node": "*", - "@types/ws": "~8.5.10", - "@typescript/lib-dom": "https://github.com/alii/lib-dom-bun-testing", + "@types/ws": "*", + "@typescript/lib-dom": "github:alii/lib-dom-bun-testing", }, "devDependencies": { "@biomejs/biome": "^1.5.3", diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index be2476ea9003e7..c4dc2219c60305 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -17,8 +17,8 @@ "homepage": "https://bun.sh", "dependencies": { "@types/node": "*", - "@types/ws": "~8.5.10", - "@typescript/lib-dom": "https://github.com/alii/lib-dom-bun-testing" + "@types/ws": "*", + "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" }, "devDependencies": { "@biomejs/biome": "^1.5.3", diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index bc7a3c11b90eca..5c22bb37c3db67 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -4,6 +4,7 @@ "": { "name": "fixture", "dependencies": { + "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing", "@types/bun": "types-bun-1.2.5.tgz", }, "peerDependencies": { @@ -12,11 +13,13 @@ }, }, "packages": { - "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10", "@typescript/lib-dom": "https://github.com/alii/lib-dom-bun-testing" } }], + "@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#9ed8ccd", {}, "alii-lib-dom-bun-testing-9ed8ccd"], + + "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" } }], "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], - "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], + "@types/ws": ["@types/ws@8.18.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw=="], "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#9ed8ccd", {}, "alii-lib-dom-bun-testing-9ed8ccd"], diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index 8d42eab946831f..ebfeb4c0ff0510 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -9,6 +9,7 @@ }, "type": "module", "dependencies": { + "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing", "@types/bun": "types-bun-1.2.5.tgz" } } From bdbf720882f8788e7ccec982a483f616529a96f0 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 11 Mar 2025 09:32:10 +0000 Subject: [PATCH 35/72] more type fixes --- packages/bun-types/new/fetch.d.ts | 3 ++- packages/bun-types/new/globals.d.ts | 4 ++-- test/integration/bun-types/fixture/bun.lock | 4 ++-- test/integration/bun-types/fixture/package.json | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts index b18c88f96ffdc7..bdee6570700e7a 100644 --- a/packages/bun-types/new/fetch.d.ts +++ b/packages/bun-types/new/fetch.d.ts @@ -140,7 +140,7 @@ interface ResponseConstructor { error(): Response; } -declare var Response: Bun.__internal.UseLibDomIfAvailable<"Response", ResponseConstructor>; +declare var Response: ResponseConstructor; interface BunFetchRequestInitTLS extends Bun.TLSOptions { /** @@ -194,6 +194,7 @@ interface BunFetchRequestInit extends RequestInit { * @returns A promise that resolves to {@link Response} object. */ declare function fetch(request: Request, init?: BunFetchRequestInit): Promise; + /** * Send a HTTP(s) request * diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index 50933766ed5b76..a61841bc60efc3 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -636,9 +636,9 @@ declare var WritableStreamDefaultController: { /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ interface WritableStreamDefaultWriter { - readonly closed: Promise; + readonly closed: Promise; readonly desiredSize: number | null; - readonly ready: Promise; + readonly ready: Promise; abort(reason?: any): Promise; close(): Promise; releaseLock(): void; diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index 5c22bb37c3db67..372173fefa6495 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -5,7 +5,7 @@ "name": "fixture", "dependencies": { "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing", - "@types/bun": "types-bun-1.2.5.tgz", + "@types/bun": "types-bun-1.2.6.tgz", }, "peerDependencies": { "typescript": "^5.8.2", @@ -15,7 +15,7 @@ "packages": { "@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#9ed8ccd", {}, "alii-lib-dom-bun-testing-9ed8ccd"], - "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" } }], + "@types/bun": ["@types/bun@types-bun-1.2.6.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" } }], "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index ebfeb4c0ff0510..8d124deb0c1554 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -10,6 +10,6 @@ "type": "module", "dependencies": { "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing", - "@types/bun": "types-bun-1.2.5.tgz" + "@types/bun": "types-bun-1.2.6.tgz" } } From f0098310feebf5754e1d9b37e78f6f48c6c956a0 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 11 Mar 2025 09:37:36 +0000 Subject: [PATCH 36/72] undefined->void --- packages/bun-types/new/bun.d.ts | 10 +++++----- packages/bun-types/new/globals.d.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 57a878688496a4..744c6a5ec30980 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -1771,12 +1771,12 @@ declare module "bun" { * @example * await sql.commitDistributed("my_distributed_transaction"); */ - commitDistributed(name: string): Promise; + commitDistributed(name: string): Promise; /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL * @example * await sql.rollbackDistributed("my_distributed_transaction"); */ - rollbackDistributed(name: string): Promise; + rollbackDistributed(name: string): Promise; /** Waits for the database connection to be established * @example * await sql.connect(); @@ -1786,13 +1786,13 @@ declare module "bun" { * @example * await sql.close({ timeout: 1 }); */ - close(options?: { timeout?: number }): Promise; + close(options?: { timeout?: number }): Promise; /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. * @alias close * @example * await sql.end({ timeout: 1 }); */ - end(options?: { timeout?: number }): Promise; + end(options?: { timeout?: number }): Promise; /** Flushes any pending operations */ flush(): void; /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. @@ -3427,7 +3427,7 @@ declare module "bun" { hmr?: boolean; }; - error?: (this: Server, error: ErrorLike) => Response | Promise | undefined | Promise; + error?: (this: Server, error: ErrorLike) => Response | Promise | void | Promise; /** * Uniquely identify a server instance with an ID diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index a61841bc60efc3..f9163da346b00d 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -601,7 +601,7 @@ declare var ReadableStreamDefaultReader: { }; interface ReadableStreamGenericReader { - readonly closed: Promise; + readonly closed: Promise; cancel(reason?: any): Promise; } From bec5844e192f71436824303062783457d13ae062 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 11 Mar 2025 10:25:43 +0000 Subject: [PATCH 37/72] make them pass --- packages/bun-types/new/bun.d.ts | 6 +++-- packages/bun-types/new/deprecated.d.ts | 2 +- packages/bun-types/new/globals.d.ts | 15 +++++++++---- packages/bun-types/new/wasm.d.ts | 25 ++++++++++++--------- test/integration/bun-types/fixture/index.ts | 5 ----- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 744c6a5ec30980..2178a545269311 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -26,7 +26,7 @@ declare module "bun" { | ReadableStreamDefaultReadDoneResult; type ReadableStreamReader = ReadableStreamDefaultReader; type Transferable = ArrayBuffer | import("worker_threads").MessagePort; - type MessageEventSource = undefined; + type MessageEventSource = Bun.__internal.UseLibDomIfAvailable<"MessageEventSource", undefined>; type Encoding = "utf-8" | "windows-1252" | "utf-16"; type UncaughtExceptionOrigin = "uncaughtException" | "unhandledRejection"; type MultipleResolveType = "resolve" | "reject"; @@ -131,7 +131,7 @@ declare module "bun" { } /** A message received by a target object. */ - interface MessageEvent extends Event { + interface BunMessageEvent extends Event { /** Returns the data of the message. */ readonly data: T; /** Returns the last event ID string, for server-sent events. */ @@ -143,6 +143,8 @@ declare module "bun" { readonly source: Bun.MessageEventSource | null; } + type MessageEvent = Bun.__internal.UseLibDomIfAvailable<"MessageEvent", BunMessageEvent>; + interface ReadableStreamDefaultReadManyResult { done: boolean; /** Number of bytes */ diff --git a/packages/bun-types/new/deprecated.d.ts b/packages/bun-types/new/deprecated.d.ts index 600eebd9933949..2fb502e4ad348e 100644 --- a/packages/bun-types/new/deprecated.d.ts +++ b/packages/bun-types/new/deprecated.d.ts @@ -1,5 +1,5 @@ declare module "bun" { - interface MessageEvent { + interface BunMessageEvent { /** * @deprecated */ diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts index f9163da346b00d..2df6e71b285d8c 100644 --- a/packages/bun-types/new/globals.d.ts +++ b/packages/bun-types/new/globals.d.ts @@ -1,7 +1,14 @@ declare module "bun" { namespace __internal { type NodeWorkerThreadsWorker = import("worker_threads").Worker; + type LibWorkerOrNodeWorkerThreadsWorker = Bun.__internal.UseLibDomIfAvailable<"Worker", NodeWorkerThreadsWorker>; + type NodePerfHooksPerformance = import("perf_hooks").Performance; + type LibPerformanceOrNodePerfHooksPerformance = Bun.__internal.UseLibDomIfAvailable< + "Performance", + NodePerfHooksPerformance + >; + type NodeCryptoWebcryptoSubtleCrypto = import("crypto").webcrypto.SubtleCrypto; type NodeCryptoWebcryptoCryptoKey = import("crypto").webcrypto.CryptoKey; type NodeUtilTextEncoder = import("util").TextEncoder; @@ -28,7 +35,7 @@ declare var WritableStream: Bun.__internal.UseLibDomIfAvailable< } >; -interface Worker extends Bun.__internal.NodeWorkerThreadsWorker {} +interface Worker extends Bun.__internal.LibWorkerOrNodeWorkerThreadsWorker {} declare var Worker: Bun.__internal.UseLibDomIfAvailable< "Worker", { @@ -105,9 +112,6 @@ declare var TextDecoder: Bun.__internal.UseLibDomIfAvailable< } >; -interface Performance extends Bun.__internal.NodePerfHooksPerformance {} -declare var performance: Bun.__internal.UseLibDomIfAvailable<"performance", Performance>; - // interface Event { // /** This is not used in Node.js and is provided purely for completeness. */ // readonly bubbles: boolean; @@ -1348,6 +1352,9 @@ declare var EventSource: Bun.__internal.UseLibDomIfAvailable< { prototype: EventSource; new (): EventSource } >; +interface Performance extends Bun.__internal.LibPerformanceOrNodePerfHooksPerformance {} +declare var performance: Bun.__internal.UseLibDomIfAvailable<"performance", Performance>; + interface PerformanceEntry {} declare var PerformanceEntry: Bun.__internal.UseLibDomIfAvailable< "PerformanceEntry", diff --git a/packages/bun-types/new/wasm.d.ts b/packages/bun-types/new/wasm.d.ts index aeec8d4aceaaa5..84c1a8fe4fba9f 100644 --- a/packages/bun-types/new/wasm.d.ts +++ b/packages/bun-types/new/wasm.d.ts @@ -151,16 +151,21 @@ declare namespace WebAssembly { }; interface Module extends Bun.WebAssembly.Module {} - var Module: { - prototype: Module; - new (bytes: Bun.BufferSource): Module; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ - customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ - exports(moduleObject: Module): ModuleExportDescriptor[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ - imports(moduleObject: Module): ModuleImportDescriptor[]; - }; + var Module: Bun.__internal.UseLibDomIfAvailable< + "WebAssembly", + { + Module: { + prototype: Module; + new (bytes: Bun.BufferSource): Module; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ + customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ + exports(moduleObject: Module): ModuleExportDescriptor[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + } + >["Module"]; interface Table extends Bun.WebAssembly.Table {} var Table: { diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index ab91ea1fc9fb46..3a00e17fe4cda1 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -250,11 +250,6 @@ const myAbortSignal: AbortSignal = new AbortSignal(); import { serve } from "bun"; -new Worker("").on("message", (e: MessageEvent) => { - e; - e.data satisfies string; -}); - new Worker("", { type: "module", preload: ["preload.ts"], From 99ea96a2ba39e599a43dce285c04b11292df3bb8 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 11 Mar 2025 10:58:39 +0000 Subject: [PATCH 38/72] bring back dom --- bench/express/tsconfig.json | 2 +- bench/postgres/tsconfig.json | 2 +- packages/bun-plugin-svelte/tsconfig.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bench/express/tsconfig.json b/bench/express/tsconfig.json index 0fef23a368018b..238655f2ce24cd 100644 --- a/bench/express/tsconfig.json +++ b/bench/express/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext"], + "lib": ["ESNext", "DOM"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/bench/postgres/tsconfig.json b/bench/postgres/tsconfig.json index 0fef23a368018b..238655f2ce24cd 100644 --- a/bench/postgres/tsconfig.json +++ b/bench/postgres/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext"], + "lib": ["ESNext", "DOM"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/packages/bun-plugin-svelte/tsconfig.json b/packages/bun-plugin-svelte/tsconfig.json index 70fc5a16e937d7..a1e84e5d05dafe 100644 --- a/packages/bun-plugin-svelte/tsconfig.json +++ b/packages/bun-plugin-svelte/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext"], + "lib": ["ESNext", "DOM"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", From 17dfe5bd083565c0db910df7311aba496c09c6ab Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Wed, 12 Mar 2025 01:28:50 +0000 Subject: [PATCH 39/72] both tests pass! --- bun.lock | 5 ++++- packages/bun-types/package.json | 1 + test/integration/bun-types/fixture/bun.lock | 6 ++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index 9df2af8cc65f33..bd862d199df4e5 100644 --- a/bun.lock +++ b/bun.lock @@ -32,6 +32,7 @@ "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing", + "@oven/typescript-bun-lib-dom": "https://github.com/alii/lib-dom-bun-testing", }, "devDependencies": { "@biomejs/biome": "^1.5.3", @@ -151,6 +152,8 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], + "@qiwi/npm-registry-client": ["@qiwi/npm-registry-client@8.9.1", "", { "dependencies": { "concat-stream": "^2.0.0", "graceful-fs": "^4.2.4", "normalize-package-data": "~1.0.1 || ^2.0.0 || ^3.0.0", "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^8.0.0", "once": "^1.4.0", "request": "^2.88.2", "retry": "^0.12.0", "safe-buffer": "^5.2.1", "semver": "2 >=2.2.1 || 3.x || 4 || 5 || 7", "slide": "^1.1.6", "ssri": "^8.0.0" }, "optionalDependencies": { "npmlog": "2 || ^3.1.0 || ^4.0.0" } }, "sha512-rZF+mG+NfijR0SHphhTLHRr4aM4gtfdwoAMY6we2VGQam8vkN1cxGG1Lg/Llrj8Dd0Mu6VjdFQRyMMRZxtZR2A=="], "@types/bun": ["@types/bun@1.2.2", "", { "dependencies": { "bun-types": "1.2.2" } }, "sha512-tr74gdku+AEDN5ergNiBnplr7hpDp3V1h7fqI2GcR/rsUaM39jpSeKH0TFibRvU0KwniRx5POgaYnaXbk0hU+w=="], @@ -185,7 +188,7 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" } }, "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg=="], - "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#9ed8ccd", {}, "alii-lib-dom-bun-testing-9ed8ccd"], + "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], "@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="], diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index c4dc2219c60305..f3db479d424c03 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -16,6 +16,7 @@ ], "homepage": "https://bun.sh", "dependencies": { + "@oven/typescript-bun-lib-dom": "https://github.com/alii/lib-dom-bun-testing", "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index 372173fefa6495..ecd509be8532fa 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -15,16 +15,18 @@ "packages": { "@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#9ed8ccd", {}, "alii-lib-dom-bun-testing-9ed8ccd"], - "@types/bun": ["@types/bun@types-bun-1.2.6.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" } }], + "@types/bun": ["@types/bun@types-bun-1.2.6.tgz", { "dependencies": { "@oven/typescript-bun-lib-dom": "https://github.com/alii/lib-dom-bun-testing", "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" } }], "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], "@types/ws": ["@types/ws@8.18.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw=="], - "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#9ed8ccd", {}, "alii-lib-dom-bun-testing-9ed8ccd"], + "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], + + "@types/bun/@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], } } From be61cd273ee4e63d0361185d4861c3e527fe38d9 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 02:47:46 +0000 Subject: [PATCH 40/72] test {body,headers}init exists --- packages/bun-types/globals.d.ts | 7 ++----- test/integration/bun-types/fixture/index.ts | 3 +++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 0bb82e10d6caaa..8c34df78e9ef5c 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1,4 +1,4 @@ -export { }; +export {}; type _Event = { /** This is not used in Node.js and is provided purely for completeness. */ @@ -1268,10 +1268,7 @@ declare global { * Convert the Uint8Array to a base64 encoded string * @returns The base64 encoded string representation of the Uint8Array */ - toBase64(options?: { - alphabet?: 'base64' | 'base64url'; - omitPadding?: boolean; - }): string; + toBase64(options?: { alphabet?: "base64" | "base64url"; omitPadding?: boolean }): string; /** * Set the contents of the Uint8Array from a base64 encoded string diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 3a00e17fe4cda1..868bc050788d83 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -194,6 +194,9 @@ URL.canParse; URL.createObjectURL; URL.revokeObjectURL; +declare const myBodyInit: BodyInit; +declare const myHeadersInit: HeadersInit; + new MessagePort(); new File(["code"], "name.ts"); From 6c9b82222ba4ec351977388adc45f869e43ff6c9 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 14:54:46 +0000 Subject: [PATCH 41/72] sync new types to `main` --- packages/bun-types/new/bun.d.ts | 469 +++++++++++++++----------- packages/bun-types/new/devserver.d.ts | 60 ++++ packages/bun-types/new/test.d.ts | 12 +- 3 files changed, 337 insertions(+), 204 deletions(-) diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts index 2178a545269311..4dbe674852b08c 100644 --- a/packages/bun-types/new/bun.d.ts +++ b/packages/bun-types/new/bun.d.ts @@ -730,6 +730,10 @@ declare module "bun" { interface Shell { (strings: TemplateStringsArray, ...expressions: ShellExpression[]): ShellPromise; + readonly Shell: ShellConstructor; + readonly ShellPromise: typeof ShellPromise; + readonly ShellError: typeof ShellError; + /** * Perform bash-like brace expansion on the given pattern. * @param pattern - Brace pattern to expand @@ -781,21 +785,9 @@ declare module "bun" { * Configure whether or not the shell should throw an exception on non-zero exit codes. */ throws(shouldThrow: boolean): this; - - readonly Shell: ShellConstructor; - - readonly ShellPromise: { - prototype: ShellPromise; - new (args: unknown, throws: boolean): ShellPromise; - }; - - readonly ShellError: { - prototype: ShellError; - new (): ShellError; - }; } - interface ShellError extends Error { + class ShellError extends Error implements ShellOutput { readonly stdout: Buffer; readonly stderr: Buffer; readonly exitCode: number; @@ -863,6 +855,16 @@ declare module "bun" { */ blob(): Blob; + /** + * 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; } @@ -1986,10 +1988,69 @@ declare module "bun" { */ interface SavepointSQL extends SQL {} + 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; + } + interface 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. + */ + 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. + */ + verify(token: string, options?: CSRFVerifyOptions): boolean; + } + var sql: SQL; var postgres: SQL; var SQL: SQL; + var CSRF: CSRF; + /** * This lets you use macros as regular imports * @example @@ -2343,7 +2404,7 @@ declare module "bun" { * - `"external"` - Generate a separate source map file for each input file. * No `//# sourceMappingURL` comment is added to the output file. * - * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. + * `true` and `false` are aliases for `"inline"` and `"none"`, respectively. * * @default "none" * @@ -3942,17 +4003,7 @@ declare module "bun" { * Passing other options such as `port` or `hostname` won't do anything. */ reload }>( - options: ( - | (Omit & { - routes: R; - fetch?: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | (Omit & { - routes?: never; - fetch: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | WebSocketServeOptions - ) & { + options: ServeFunctionOptions & { /** * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. */ @@ -4166,181 +4217,198 @@ declare module "bun" { | UnixWebSocketServeOptions | UnixTLSWebSocketServeOptions; - /** - Bun.serve provides a high-performance HTTP server with built-in routing support. - It enables both function-based and object-based route handlers with type-safe - parameters and method-specific handling. - - @example Basic Usage - ```ts - Bun.serve({ - port: 3000, - fetch(req) { - return new Response("Hello World"); - } - }); - ``` - - @example Route-based Handlers - ```ts - Bun.serve({ - routes: { - // Static responses - "/": new Response("Home page"), - - // Function handlers with type-safe parameters - "/users/:id": (req) => { - // req.params.id is typed as string - return new Response(`User ${req.params.id}`); - }, - - // Method-specific handlers - "/api/posts": { - GET: () => new Response("Get posts"), - POST: async (req) => { - const body = await req.json(); - return new Response("Created post"); - }, - DELETE: (req) => new Response("Deleted post") - }, - - // Wildcard routes - "/static/*": (req) => { - // Handle any path under /static/ - return new Response("Static file"); - }, - - // Disable route (fall through to fetch handler) - "/api/legacy": false - }, - - // Fallback handler for unmatched routes - fetch(req) { - return new Response("Not Found", { status: 404 }); - } - }); - ``` - - @example Path Parameters - ```ts - Bun.serve({ - routes: { - // Single parameter - "/users/:id": (req: BunRequest<"/users/:id">) => { - return new Response(`User ID: ${req.params.id}`); - }, - - // Multiple parameters - "/posts/:postId/comments/:commentId": ( - req: BunRequest<"/posts/:postId/comments/:commentId"> - ) => { - return new Response(JSON.stringify(req.params)); - // Output: {"postId": "123", "commentId": "456"} - } - } - }); - ``` - - @example Route Precedence - ```ts - // Routes are matched in the following order: - // 1. Exact static routes ("/about") - // 2. Parameter routes ("/users/:id") - // 3. Wildcard routes ("/api/*") - - Bun.serve({ - routes: { - "/api/users": () => new Response("Users list"), - "/api/users/:id": (req) => new Response(`User ${req.params.id}`), - "/api/*": () => new Response("API catchall"), - "/*": () => new Response("Root catchall") - } - }); - ``` - - @example Error Handling - ```ts - Bun.serve({ - routes: { - "/error": () => { - throw new Error("Something went wrong"); - } - }, - error(error) { - // Custom error handler - console.error(error); - return new Response(`Error: ${error.message}`, { - status: 500 - }); - } - }); - ``` - - @example Server Lifecycle - ```ts - const server = Bun.serve({ - // Server config... - }); - - // Update routes at runtime - server.reload({ - routes: { - "/": () => new Response("Updated route") - } - }); - - // Stop the server - server.stop(); - ``` - - @example Development Mode - ```ts - Bun.serve({ - development: true, // Enable hot reloading - routes: { - // Routes will auto-reload on changes - } - }); - ``` - - @example Type-Safe Request Handling - ```ts - type Post = { - id: string; - title: string; - }; + type ServeFunctionOptions }> = + | (DistributedOmit, WebSocketServeOptions>, "fetch"> & { + routes: R; + fetch?: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | (DistributedOmit, WebSocketServeOptions>, "routes"> & { + routes?: never; + fetch: (this: Server, request: Request, server: Server) => Response | Promise; + }) + | (Omit, "fetch"> & { + routes: R; + fetch?: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise | void | undefined; + }) + | (Omit, "fetch"> & { + routes?: never; + fetch: ( + this: Server, + request: Request, + server: Server, + ) => Response | Promise | void | undefined; + }); - Bun.serve({ - routes: { - "/api/posts/:id": async ( - req: BunRequest<"/api/posts/:id"> - ) => { - if (req.method === "POST") { - const body: Post = await req.json(); - return Response.json(body); - } - return new Response("Method not allowed", { - status: 405 - }); - } - } - }); - ``` - @param options - Server configuration options - @param options.routes - Route definitions mapping paths to handlers - */ + /** + * Bun.serve provides a high-performance HTTP server with built-in routing support. + * It enables both function-based and object-based route handlers with type-safe + * parameters and method-specific handling. + * + * @param options - Server configuration options + * @param options.routes - Route definitions mapping paths to handlers + * + * @example Basic Usage + * ```ts + * Bun.serve({ + * port: 3000, + * fetch(req) { + * return new Response("Hello World"); + * } + * }); + * ``` + * + * @example Route-based Handlers + * ```ts + * Bun.serve({ + * routes: { + * // Static responses + * "/": new Response("Home page"), + * + * // Function handlers with type-safe parameters + * "/users/:id": (req) => { + * // req.params.id is typed as string + * return new Response(`User ${req.params.id}`); + * }, + * + * // Method-specific handlers + * "/api/posts": { + * GET: () => new Response("Get posts"), + * POST: async (req) => { + * const body = await req.json(); + * return new Response("Created post"); + * }, + * DELETE: (req) => new Response("Deleted post") + * }, + * + * // Wildcard routes + * "/static/*": (req) => { + * // Handle any path under /static/ + * return new Response("Static file"); + * }, + * + * // Disable route (fall through to fetch handler) + * "/api/legacy": false + * }, + * + * // Fallback handler for unmatched routes + * fetch(req) { + * return new Response("Not Found", { status: 404 }); + * } + * }); + * ``` + * + * @example Path Parameters + * ```ts + * Bun.serve({ + * routes: { + * // Single parameter + * "/users/:id": (req: BunRequest<"/users/:id">) => { + * return new Response(`User ID: ${req.params.id}`); + * }, + * + * // Multiple parameters + * "/posts/:postId/comments/:commentId": ( + * req: BunRequest<"/posts/:postId/comments/:commentId"> + * ) => { + * return new Response(JSON.stringify(req.params)); + * // Output: {"postId": "123", "commentId": "456"} + * } + * } + * }); + * ``` + * + * @example Route Precedence + * ```ts + * // Routes are matched in the following order: + * // 1. Exact static routes ("/about") + * // 2. Parameter routes ("/users/:id") + * // 3. Wildcard routes ("/api/*") + * + * Bun.serve({ + * routes: { + * "/api/users": () => new Response("Users list"), + * "/api/users/:id": (req) => new Response(`User ${req.params.id}`), + * "/api/*": () => new Response("API catchall"), + * "/*": () => new Response("Root catchall") + * } + * }); + * ``` + * + * @example Error Handling + * ```ts + * Bun.serve({ + * routes: { + * "/error": () => { + * throw new Error("Something went wrong"); + * } + * }, + * error(error) { + * // Custom error handler + * console.error(error); + * return new Response(`Error: ${error.message}`, { + * status: 500 + * }); + * } + * }); + * ``` + * + * @example Server Lifecycle + * ```ts + * const server = Bun.serve({ + * // Server config... + * }); + * + * // Update routes at runtime + * server.reload({ + * routes: { + * "/": () => new Response("Updated route") + * } + * }); + * + * // Stop the server + * server.stop(); + * ``` + * + * @example Development Mode + * ```ts + * Bun.serve({ + * development: true, // Enable hot reloading + * routes: { + * // Routes will auto-reload on changes + * } + * }); + * ``` + * + * @example Type-Safe Request Handling + * ```ts + * type Post = { + * id: string; + * title: string; + * }; + * + * Bun.serve({ + * routes: { + * "/api/posts/:id": async ( + * req: BunRequest<"/api/posts/:id"> + * ) => { + * if (req.method === "POST") { + * const body: Post = await req.json(); + * return Response.json(body); + * } + * return new Response("Method not allowed", { + * status: 405 + * }); + * } + * } + * }); + * ``` + */ function serve }>( - options: ( - | (DistributedOmit & { - routes: R; - fetch?: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | (DistributedOmit & { - routes?: never; - fetch: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | WebSocketServeOptions - ) & { + options: ServeFunctionOptions & { /** * @deprecated Use `routes` instead in new code. This will continue to work for a while though. */ @@ -4372,7 +4440,6 @@ declare module "bun" { * ``` * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} */ - function file(path: string | URL, options?: BlobPropertyBag): BunFile; /** @@ -5916,7 +5983,7 @@ declare module "bun" { * @param socket */ open?(socket: Socket): void | Promise; - close?(socket: Socket): void | Promise; + close?(socket: Socket, error?: Error): void | Promise; error?(socket: Socket, error: Error): void | Promise; data?(socket: Socket, data: BinaryTypeList[DataBinaryType]): void | Promise; drain?(socket: Socket): void | Promise; @@ -6579,6 +6646,8 @@ declare module "bun" { resourceUsage: ResourceUsage; signalCode?: string; + exitedDueToTimeout?: true; + pid: number; } /** diff --git a/packages/bun-types/new/devserver.d.ts b/packages/bun-types/new/devserver.d.ts index e2fc9a9098fae4..cfb0ebe9eb5108 100644 --- a/packages/bun-types/new/devserver.d.ts +++ b/packages/bun-types/new/devserver.d.ts @@ -1,6 +1,23 @@ export {}; declare global { + namespace Bun { + type HMREventNames = + | "bun:beforeUpdate" + | "bun:afterUpdate" + | "bun:beforeFullReload" + | "bun:beforePrune" + | "bun:invalidate" + | "bun:error" + | "bun:ws:disconnect" + | "bun:ws:connect"; + + /** + * The event names for the dev server + */ + type HMREvent = `bun:${HMREventNames}` | (string & {}); + } + interface ImportMeta { /** * Hot module replacement APIs. This value is `undefined` in production and @@ -128,6 +145,49 @@ declare global { * @deprecated */ decline(): void; + + // NOTE TO CONTRIBUTORS //////////////////////////////////////// + // Callback is currently never called for `.prune()` // + // so the types are commented out until we support it. // + //////////////////////////////////////////////////////////////// + // /** + // * Attach a callback that is called when the module is removed from the module graph. + // * + // * This can be used to clean up resources that were created when the module was loaded. + // * Unlike `import.meta.hot.dispose()`, this pairs much better with `accept` and `data` to manage stateful resources. + // * + // * @example + // * ```ts + // * export const ws = (import.meta.hot.data.ws ??= new WebSocket(location.origin)); + // * + // * import.meta.hot.prune(() => { + // * ws.close(); + // * }); + // * ``` + // */ + // prune(callback: () => void): void; + + /** + * Listen for an event from the dev server + * + * For compatibility with Vite, event names are also available via vite:* prefix instead of bun:*. + * + * https://bun.sh/docs/bundler/hmr#import-meta-hot-on-and-off + * @param event The event to listen to + * @param callback The callback to call when the event is emitted + */ + on(event: Bun.HMREvent, callback: () => void): void; + + /** + * Stop listening for an event from the dev server + * + * For compatibility with Vite, event names are also available via vite:* prefix instead of bun:*. + * + * https://bun.sh/docs/bundler/hmr#import-meta-hot-on-and-off + * @param event The event to stop listening to + * @param callback The callback to stop listening to + */ + off(event: Bun.HMREvent, callback: () => void): void; }; } } diff --git a/packages/bun-types/new/test.d.ts b/packages/bun-types/new/test.d.ts index ba84eda2954ee4..8448317743fc6e 100644 --- a/packages/bun-types/new/test.d.ts +++ b/packages/bun-types/new/test.d.ts @@ -149,6 +149,10 @@ declare module "bun:test" { methodOrPropertyValue: K, ): Mock any ? T[K] : never>; + interface FunctionLike { + readonly name: string; + } + /** * Describes a group of related tests. * @@ -165,10 +169,6 @@ declare module "bun:test" { * @param label the label for the tests * @param fn the function that defines the tests */ - - interface FunctionLike { - readonly name: string; - } export interface Describe { (fn: () => void): void; @@ -1778,6 +1778,10 @@ declare module "bun:test" { type MatcherContext = MatcherUtils & MatcherState; } +declare module "test" { + export type * from "bun:test"; +} + declare namespace JestMock { /** * Copyright (c) Meta Platforms, Inc. and affiliates. From fc4fba450c4682b7e74717f5db1d8226597c7ff0 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 14:58:43 +0000 Subject: [PATCH 42/72] =?UTF-8?q?new=20=E2=86=92=20root?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/bun-types/ambient.d.ts | 31 - packages/bun-types/bun.d.ts | 1964 +++-- packages/bun-types/{new => }/bun.ns.d.ts | 0 packages/bun-types/deprecated.d.ts | 30 +- packages/bun-types/{new => }/extensions.d.ts | 0 packages/bun-types/fetch.d.ts | 229 +- packages/bun-types/globals.d.ts | 2362 +++--- packages/bun-types/index.d.ts | 25 +- packages/bun-types/new/bun.d.ts | 7178 ------------------ packages/bun-types/new/deprecated.d.ts | 74 - packages/bun-types/new/devserver.d.ts | 193 - packages/bun-types/new/fetch.d.ts | 228 - packages/bun-types/new/ffi.d.ts | 1150 --- packages/bun-types/new/globals.d.ts | 1443 ---- packages/bun-types/new/html-rewriter.d.ts | 184 - packages/bun-types/new/index.d.ts | 27 - packages/bun-types/new/jsc.d.ts | 229 - packages/bun-types/new/overrides.d.ts | 79 - packages/bun-types/new/sqlite.d.ts | 1141 --- packages/bun-types/new/test.d.ts | 2182 ------ packages/bun-types/new/wasm.d.ts | 193 - packages/bun-types/overrides.d.ts | 33 +- packages/bun-types/package.json | 4 +- packages/bun-types/{new => }/s3.d.ts | 0 packages/bun-types/{new => }/sink.d.ts | 0 packages/bun-types/test.d.ts | 8 +- packages/bun-types/wasm.d.ts | 420 +- 27 files changed, 2519 insertions(+), 16888 deletions(-) delete mode 100644 packages/bun-types/ambient.d.ts rename packages/bun-types/{new => }/bun.ns.d.ts (100%) rename packages/bun-types/{new => }/extensions.d.ts (100%) delete mode 100644 packages/bun-types/new/bun.d.ts delete mode 100644 packages/bun-types/new/deprecated.d.ts delete mode 100644 packages/bun-types/new/devserver.d.ts delete mode 100644 packages/bun-types/new/fetch.d.ts delete mode 100644 packages/bun-types/new/ffi.d.ts delete mode 100644 packages/bun-types/new/globals.d.ts delete mode 100644 packages/bun-types/new/html-rewriter.d.ts delete mode 100644 packages/bun-types/new/index.d.ts delete mode 100644 packages/bun-types/new/jsc.d.ts delete mode 100644 packages/bun-types/new/overrides.d.ts delete mode 100644 packages/bun-types/new/sqlite.d.ts delete mode 100644 packages/bun-types/new/test.d.ts delete mode 100644 packages/bun-types/new/wasm.d.ts rename packages/bun-types/{new => }/s3.d.ts (100%) rename packages/bun-types/{new => }/sink.d.ts (100%) diff --git a/packages/bun-types/ambient.d.ts b/packages/bun-types/ambient.d.ts deleted file mode 100644 index 05d908557716b6..00000000000000 --- a/packages/bun-types/ambient.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -declare module "*.txt" { - var text: string; - export = text; -} - -declare module "*.toml" { - var contents: any; - export = contents; -} - -declare module "*.jsonc" { - var contents: any; - export = contents; -} - -declare module "*/bun.lock" { - var contents: import("bun").BunLockFile; - export = contents; -} - -declare module "*.html" { - // In Bun v1.2, we might change this to Bun.HTMLBundle - var contents: any; - export = contents; -} - -declare module "*.svg" { - // Bun 1.2.3 added support for frontend dev server - var contents: `${string}.svg`; - export = contents; -} diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 0fbb653f27139d..4dbe674852b08c 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -14,14 +14,508 @@ * This module aliases `globalThis.Bun`. */ declare module "bun" { - import type { FFIFunctionCallableSymbol } from "bun:ffi"; - import type { Encoding as CryptoEncoding } from "crypto"; - import type { X509Certificate } from "node:crypto"; - import type { Stats } from "node:fs"; - import type { CipherNameAndProtocol, EphemeralKeyInfo, PeerCertificate } from "tls"; - - type DistributedOmit = T extends T ? Omit : never; + type DistributedOmit = T extends T ? Omit : never; type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; + type ArrayBufferView = NodeJS.TypedArray | DataView; + type BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; + type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; + type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData | Iterable; + type ReadableStreamController = ReadableStreamDefaultController; + type ReadableStreamDefaultReadResult = + | ReadableStreamDefaultReadValueResult + | ReadableStreamDefaultReadDoneResult; + type ReadableStreamReader = ReadableStreamDefaultReader; + type Transferable = ArrayBuffer | import("worker_threads").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) => 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; + + 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. + * + * @internal + */ + type UseLibDomIfAvailable = + // `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 + typeof globalThis extends { onabort: any } + ? 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 + } + + type Platform = + | "aix" + | "android" + | "darwin" + | "freebsd" + | "haiku" + | "linux" + | "openbsd" + | "sunos" + | "win32" + | "cygwin" + | "netbsd"; + type Architecture = "arm" | "arm64" | "ia32" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x" | "x64"; + + 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. + */ + type UnhandledRejectionListener = (reason: unknown, promise: Promise) => void; + + type MultipleResolveListener = (type: MultipleResolveType, promise: Promise, value: unknown) => void; + + type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; + + 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 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 extends Bun.EventInit { + detail?: T; + } + + /** A message received by a target object. */ + interface BunMessageEvent 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; + readonly source: Bun.MessageEventSource | null; + } + + type MessageEvent = Bun.__internal.UseLibDomIfAvailable<"MessageEvent", BunMessageEvent>; + + interface ReadableStreamDefaultReadManyResult { + done: boolean; + /** Number of bytes */ + size: number; + value: T[]; + } + + interface ResponseInit { + headers?: Bun.__internal.BunHeadersInit; + /** @default 200 */ + status?: number; + + /** @default "OK" */ + statusText?: string; + } + + interface EventSourceEventMap { + error: Event; + message: MessageEvent; + open: Event; + } + + interface EventInit { + bubbles?: boolean; + cancelable?: boolean; + composed?: boolean; + } + + interface EventListenerOptions { + /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ + capture?: boolean; + } + + 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): void; + respondWith(response: Response | Promise): 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( + 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( + 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 { + (controller: TransformStreamDefaultController): void | PromiseLike; + } + + interface TransformerStartCallback { + (controller: TransformStreamDefaultController): any; + } + + interface TransformerTransformCallback { + (chunk: I, controller: TransformStreamDefaultController): void | PromiseLike; + } + + interface UnderlyingSinkAbortCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSinkCloseCallback { + (): void | PromiseLike; + } + + interface UnderlyingSinkStartCallback { + (controller: WritableStreamDefaultController): any; + } + + interface UnderlyingSinkWriteCallback { + (chunk: W, controller: WritableStreamDefaultController): void | PromiseLike; + } + + interface UnderlyingSourceCancelCallback { + (reason?: any): void | PromiseLike; + } + + interface UnderlyingSink { + abort?: UnderlyingSinkAbortCallback; + close?: UnderlyingSinkCloseCallback; + start?: UnderlyingSinkStartCallback; + type?: undefined | "default" | "bytes"; + write?: UnderlyingSinkWriteCallback; + } + + interface UnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull?: UnderlyingSourcePullCallback; + start?: UnderlyingSourceStartCallback; + /** + * Mode "bytes" is not currently supported. + */ + type?: undefined; + } + + interface DirectUnderlyingSource { + cancel?: UnderlyingSourceCancelCallback; + pull: (controller: ReadableStreamDirectController) => void | PromiseLike; + type: "direct"; + } + + interface UnderlyingSourcePullCallback { + (controller: ReadableStreamController): void | PromiseLike; + } + + interface UnderlyingSourceStartCallback { + (controller: ReadableStreamController): 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( + type: K, + listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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 | (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( + type: K, + listener: (this: Worker, ev: WorkerEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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; @@ -102,9 +596,9 @@ declare module "bun" { }, ): number; - export type ShellFunction = (input: Uint8Array) => Uint8Array; + type ShellFunction = (input: Uint8Array) => Uint8Array; - export type ShellExpression = + type ShellExpression = | { toString(): string } | Array | string @@ -114,77 +608,6 @@ declare module "bun" { | 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; - - bytes(): Uint8Array; - } - class ShellPromise extends Promise { get stdin(): WritableStream; /** @@ -304,12 +727,12 @@ declare module "bun" { new (): Shell; } - export interface Shell { + interface Shell { (strings: TemplateStringsArray, ...expressions: ShellExpression[]): ShellPromise; readonly Shell: ShellConstructor; - readonly ShellError: typeof ShellError; readonly ShellPromise: typeof ShellPromise; + readonly ShellError: typeof ShellError; /** * Perform bash-like brace expansion on the given pattern. @@ -364,7 +787,7 @@ declare module "bun" { throws(shouldThrow: boolean): this; } - export interface ShellOutput { + class ShellError extends Error implements ShellOutput { readonly stdout: Buffer; readonly stderr: Buffer; readonly exitCode: number; @@ -421,51 +844,131 @@ declare module "bun" { arrayBuffer(): ArrayBuffer; /** - * Read from stdout as an Uint8Array + * Read from stdout as a Blob * - * @returns Stdout as an Uint8Array + * @returns Stdout as a blob * @example - * * ```ts * const output = await $`echo hello`; - * console.log(output.bytes()); // Uint8Array { byteLength: 6 } + * console.log(output.blob()); // Blob { size: 6, type: "" } * ``` */ - bytes(): Uint8Array; + blob(): Blob; /** - * Read from stdout as a Blob + * Read from stdout as an Uint8Array * - * @returns Stdout as a blob + * @returns Stdout as an Uint8Array * @example - * ```ts + *```ts * const output = await $`echo hello`; - * console.log(output.blob()); // Blob { size: 6, type: "" } + * console.log(output.bytes()); // Uint8Array { byteLength: 6 } * ``` */ - blob(): Blob; + bytes(): Uint8Array; } - const $: Shell; + interface ShellOutput { + readonly stdout: Buffer; + readonly stderr: Buffer; + readonly exitCode: number; - interface TOML { /** - * Parse a TOML string into a JavaScript object. + * Read from stdout as a string * - * @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; - + * @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; + } + + 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; + /** * 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; /** @@ -475,7 +978,6 @@ declare module "bun" { * * 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; /** @@ -487,10 +989,9 @@ declare module "bun" { * @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 | S3File | Bun.PathLike, - input: Blob | NodeJS.TypedArray | ArrayBufferLike | string | Bun.BlobPart[], + 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; @@ -540,9 +1041,8 @@ declare module "bun" { * @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, + destinationPath: PathLike, input: Response, options?: { /** @@ -574,7 +1074,7 @@ declare module "bun" { * @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, @@ -608,9 +1108,8 @@ declare module "bun" { * @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, + destinationPath: PathLike, input: BunFile, options?: { /** @@ -1045,803 +1544,103 @@ declare module "bun" { * ``` */ 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; - - /** - * 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; - - /** - * Deletes the file. - */ - unlink(): Promise; - - /** - * Deletes the file. ( same as unlink ) - */ - delete(): Promise; - - /** - * Provides useful information about the file. - */ - stat(): Promise; - } - - /** - * Configuration options for S3 operations - */ - interface S3Options extends BlobPropertyBag { - /** - * The Access Control List (ACL) policy for the file. - * Controls who can access the file and what permissions they have. - * - * @example - * // Setting public read access - * const file = s3("public-file.txt", { - * acl: "public-read", - * bucket: "my-bucket" - * }); - * - * @example - * // Using with presigned URLs - * const url = file.presign({ - * acl: "public-read", - * expiresIn: 3600 - * }); - */ - acl?: - | "private" - | "public-read" - | "public-read-write" - | "aws-exec-read" - | "authenticated-read" - | "bucket-owner-read" - | "bucket-owner-full-control" - | "log-delivery-write"; - - /** - * The S3 bucket name. Can be set via `S3_BUCKET` or `AWS_BUCKET` environment variables. - * - * @example - * // Using explicit bucket - * const file = s3("my-file.txt", { bucket: "my-bucket" }); - * - * @example - * // Using environment variables - * // With S3_BUCKET=my-bucket in .env - * const file = s3("my-file.txt"); - */ - bucket?: string; - - /** - * The AWS region. Can be set via `S3_REGION` or `AWS_REGION` environment variables. - * - * @example - * const file = s3("my-file.txt", { - * bucket: "my-bucket", - * region: "us-west-2" - * }); - */ - region?: string; - - /** - * The access key ID for authentication. - * Can be set via `S3_ACCESS_KEY_ID` or `AWS_ACCESS_KEY_ID` environment variables. - */ - accessKeyId?: string; - - /** - * The secret access key for authentication. - * Can be set via `S3_SECRET_ACCESS_KEY` or `AWS_SECRET_ACCESS_KEY` environment variables. - */ - secretAccessKey?: string; - - /** - * Optional session token for temporary credentials. - * Can be set via `S3_SESSION_TOKEN` or `AWS_SESSION_TOKEN` environment variables. - * - * @example - * // Using temporary credentials - * const file = s3("my-file.txt", { - * accessKeyId: tempAccessKey, - * secretAccessKey: tempSecretKey, - * sessionToken: tempSessionToken - * }); - */ - sessionToken?: string; - - /** - * The S3-compatible service endpoint URL. - * Can be set via `S3_ENDPOINT` or `AWS_ENDPOINT` environment variables. - * - * @example - * // AWS S3 - * const file = s3("my-file.txt", { - * endpoint: "https://s3.us-east-1.amazonaws.com" - * }); - * - * @example - * // Cloudflare R2 - * const file = s3("my-file.txt", { - * endpoint: "https://.r2.cloudflarestorage.com" - * }); - * - * @example - * // DigitalOcean Spaces - * const file = s3("my-file.txt", { - * endpoint: "https://.digitaloceanspaces.com" - * }); - * - * @example - * // MinIO (local development) - * const file = s3("my-file.txt", { - * endpoint: "http://localhost:9000" - * }); - */ - endpoint?: string; - - /** - * Use virtual hosted style endpoint. default to false, when true if `endpoint` is informed it will ignore the `bucket` - * - * @example - * // Using virtual hosted style - * const file = s3("my-file.txt", { - * virtualHostedStyle: true, - * endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com" - * }); - */ - virtualHostedStyle?: boolean; - - /** - * The size of each part in multipart uploads (in bytes). - * - Minimum: 5 MiB - * - Maximum: 5120 MiB - * - Default: 5 MiB - * - * @example - * // Configuring multipart uploads - * const file = s3("large-file.dat", { - * partSize: 10 * 1024 * 1024, // 10 MiB parts - * queueSize: 4 // Upload 4 parts in parallel - * }); - * - * const writer = file.writer(); - * // ... write large file in chunks - */ - partSize?: number; - - /** - * Number of parts to upload in parallel for multipart uploads. - * - Default: 5 - * - Maximum: 255 - * - * Increasing this value can improve upload speeds for large files - * but will use more memory. - */ - queueSize?: number; - - /** - * Number of retry attempts for failed uploads. - * - Default: 3 - * - Maximum: 255 - * - * @example - * // Setting retry attempts - * const file = s3("my-file.txt", { - * retry: 5 // Retry failed uploads up to 5 times - * }); - */ - retry?: number; - - /** - * The Content-Type of the file. - * Automatically set based on file extension when possible. - * - * @example - * // Setting explicit content type - * const file = s3("data.bin", { - * type: "application/octet-stream" - * }); - */ - type?: string; - - /** - * By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. - * - * @example - * // Setting explicit Storage class - * const file = s3("my-file.json", { - * storageClass: "STANDARD_IA" - * }); - */ - storageClass?: - | "STANDARD" - | "DEEP_ARCHIVE" - | "EXPRESS_ONEZONE" - | "GLACIER" - | "GLACIER_IR" - | "INTELLIGENT_TIERING" - | "ONEZONE_IA" - | "OUTPOSTS" - | "REDUCED_REDUNDANCY" - | "SNOW" - | "STANDARD_IA"; - - /** - * @deprecated The size of the internal buffer in bytes. Defaults to 5 MiB. use `partSize` and `queueSize` instead. - */ - highWaterMark?: number; - } - - /** - * Options for generating presigned URLs - */ - interface S3FilePresignOptions extends S3Options { - /** - * Number of seconds until the presigned URL expires. - * - Default: 86400 (1 day) - * - * @example - * // Short-lived URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); - * - * @example - * // Long-lived public URL - * const url = file.presign({ - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); - */ - expiresIn?: number; - - /** - * The HTTP method allowed for the presigned URL. - * - * @example - * // GET URL for downloads - * const downloadUrl = file.presign({ - * method: "GET", - * expiresIn: 3600 - * }); - * - * @example - * // PUT URL for uploads - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "application/json" - * }); - */ - method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD"; - } - - interface S3Stats { - size: number; - lastModified: Date; - etag: string; - type: string; - } - - /** - * Represents a file in an S3-compatible storage service. - * Extends the Blob interface for compatibility with web APIs. - */ - interface S3File extends Blob { - /** - * The size of the file in bytes. - * This is a Promise because it requires a network request to determine the size. - * - * @example - * // Getting file size - * const size = await file.size; - * console.log(`File size: ${size} bytes`); - * - * @example - * // Check if file is larger than 1MB - * if (await file.size > 1024 * 1024) { - * console.log("Large file detected"); - * } - */ - /** - * TODO: figure out how to get the typescript types to not error for this property. - */ - // size: Promise; - - /** - * Creates a new S3File representing a slice of the original file. - * Uses HTTP Range headers for efficient partial downloads. - * - * @param begin - Starting byte offset - * @param end - Ending byte offset (exclusive) - * @param contentType - Optional MIME type for the slice - * @returns A new S3File representing the specified range - * - * @example - * // Reading file header - * const header = file.slice(0, 1024); - * const headerText = await header.text(); - * - * @example - * // Reading with content type - * const jsonSlice = file.slice(1024, 2048, "application/json"); - * const data = await jsonSlice.json(); - * - * @example - * // Reading from offset to end - * const remainder = file.slice(1024); - * const content = await remainder.text(); - */ - slice(begin?: number, end?: number, contentType?: string): S3File; - slice(begin?: number, contentType?: string): S3File; - slice(contentType?: string): S3File; - - /** - * Creates a writable stream for uploading data. - * Suitable for large files as it uses multipart upload. - * - * @param options - Configuration for the upload - * @returns A NetworkSink for writing data - * - * @example - * // Basic streaming write - * const writer = file.writer({ - * type: "application/json" - * }); - * writer.write('{"hello": '); - * writer.write('"world"}'); - * await writer.end(); - * - * @example - * // Optimized large file upload - * const writer = file.writer({ - * partSize: 10 * 1024 * 1024, // 10MB parts - * queueSize: 4, // Upload 4 parts in parallel - * retry: 3 // Retry failed parts - * }); - * - * // Write large chunks of data efficiently - * for (const chunk of largeDataChunks) { - * writer.write(chunk); - * } - * await writer.end(); - * - * @example - * // Error handling - * const writer = file.writer(); - * try { - * writer.write(data); - * await writer.end(); - * } catch (err) { - * console.error('Upload failed:', err); - * // Writer will automatically abort multipart upload on error - * } - */ - writer(options?: S3Options): NetworkSink; - - /** - * Gets a readable stream of the file's content. - * Useful for processing large files without loading them entirely into memory. - * - * @returns A ReadableStream for the file content - * - * @example - * // Basic streaming read - * const stream = file.stream(); - * for await (const chunk of stream) { - * console.log('Received chunk:', chunk); - * } - * - * @example - * // Piping to response - * const stream = file.stream(); - * return new Response(stream, { - * headers: { 'Content-Type': file.type } - * }); - * - * @example - * // Processing large files - * const stream = file.stream(); - * const textDecoder = new TextDecoder(); - * for await (const chunk of stream) { - * const text = textDecoder.decode(chunk); - * // Process text chunk by chunk - * } - */ - readonly readable: ReadableStream; - stream(): ReadableStream; - - /** - * The name or path of the file in the bucket. - * - * @example - * const file = s3("folder/image.jpg"); - * console.log(file.name); // "folder/image.jpg" - */ - readonly name?: string; - - /** - * The bucket name containing the file. - * - * @example - * const file = s3("s3://my-bucket/file.txt"); - * console.log(file.bucket); // "my-bucket" - */ - readonly bucket?: string; - - /** - * Checks if the file exists in S3. - * Uses HTTP HEAD request to efficiently check existence without downloading. - * - * @returns Promise resolving to true if file exists, false otherwise - * - * @example - * // Basic existence check - * if (await file.exists()) { - * console.log("File exists in S3"); - * } - * - * @example - * // With error handling - * try { - * const exists = await file.exists(); - * if (!exists) { - * console.log("File not found"); - * } - * } catch (err) { - * console.error("Error checking file:", err); - * } - */ - exists(): Promise; - - /** - * Uploads data to S3. - * Supports various input types and automatically handles large files. - * - * @param data - The data to upload - * @param options - Upload configuration options - * @returns Promise resolving to number of bytes written - * - * @example - * // Writing string data - * await file.write("Hello World", { - * type: "text/plain" - * }); - * - * @example - * // Writing JSON - * const data = { hello: "world" }; - * await file.write(JSON.stringify(data), { - * type: "application/json" - * }); - * - * @example - * // Writing from Response - * const response = await fetch("https://example.com/data"); - * await file.write(response); - * - * @example - * // Writing with ACL - * await file.write(data, { - * acl: "public-read", - * type: "application/octet-stream" - * }); - */ - write( - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | Request | Response | BunFile | S3File | Blob, - options?: S3Options, - ): Promise; - - /** - * Generates a presigned URL for the file. - * Allows temporary access to the file without exposing credentials. - * - * @param options - Configuration for the presigned URL - * @returns Presigned URL string + /**.p + * Offset any operation on the file starting at `begin` and ending at `end`. `end` is relative to 0 * - * @example - * // Basic download URL - * const url = file.presign({ - * expiresIn: 3600 // 1 hour - * }); + * 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. * - * @example - * // Upload URL with specific content type - * const uploadUrl = file.presign({ - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); + * If `begin` > 0, {@link Bun.write()} will be slower on macOS * - * @example - * // URL with custom permissions - * const url = file.presign({ - * method: "GET", - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); + * @param begin - start offset in bytes + * @param end - absolute offset in bytes (relative to 0) + * @param contentType - MIME type for the new BunFile */ - presign(options?: S3FilePresignOptions): string; + slice(begin?: number, end?: number, contentType?: string): BunFile; + /** */ /** - * Deletes the file from S3. + * Offset any operation on the file starting at `begin` * - * @returns Promise that resolves when deletion is complete + * 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. * - * @example - * // Basic deletion - * await file.delete(); + * If `begin` > 0, {@link Bun.write()} will be slower on macOS * - * @example - * // With error handling - * try { - * await file.delete(); - * console.log("File deleted successfully"); - * } catch (err) { - * console.error("Failed to delete file:", err); - * } + * @param begin - start offset in bytes + * @param contentType - MIME type for the new BunFile */ - delete(): Promise; + slice(begin?: number, contentType?: string): BunFile; /** - * Alias for delete() method. - * Provided for compatibility with Node.js fs API naming. - * - * @example - * await file.unlink(); + * @param contentType - MIME type for the new BunFile */ - unlink: S3File["delete"]; + slice(contentType?: string): BunFile; /** - * Get the stat of a file in an S3-compatible storage service. - * - * @returns Promise resolving to S3Stat + * Incremental writer for files and pipes. */ - stat(): Promise; - } + writer(options?: { highWaterMark?: number }): FileSink; + + readonly readable: ReadableStream; + + // TODO: writable: WritableStream; - /** - * A configured S3 bucket instance for managing files. - * The instance is callable to create S3File instances and provides methods - * for common operations. - * - * @example - * // Basic bucket setup - * const bucket = new S3Client({ - * bucket: "my-bucket", - * accessKeyId: "key", - * secretAccessKey: "secret" - * }); - * - * // Get file instance - * const file = bucket("image.jpg"); - * - * // Common operations - * await bucket.write("data.json", JSON.stringify({hello: "world"})); - * const url = bucket.presign("file.pdf"); - * await bucket.unlink("old.txt"); - */ - type S3Client = { /** - * Creates an S3File instance for the given path. - * - * @example - * const file = bucket.file("image.jpg"); - * await file.write(imageData); - * const configFile = bucket("config.json", { - * type: "application/json", - * acl: "private" - * }); + * A UNIX timestamp indicating when the file was last modified. */ - file(path: string, options?: S3Options): S3File; - + lastModified: number; /** - * Writes data directly to a path in the bucket. - * Supports strings, buffers, streams, and web API types. - * - * @example - * // Write string - * await bucket.write("hello.txt", "Hello World"); - * - * // Write JSON with type - * await bucket.write( - * "data.json", - * JSON.stringify({hello: "world"}), - * {type: "application/json"} - * ); - * - * // Write from fetch - * const res = await fetch("https://example.com/data"); - * await bucket.write("data.bin", res); - * - * // Write with ACL - * await bucket.write("public.html", html, { - * acl: "public-read", - * type: "text/html" - * }); + * The name or path of the file, as specified in the constructor. */ - write( - path: string, - data: - | string - | ArrayBufferView - | ArrayBuffer - | SharedArrayBuffer - | Request - | Response - | BunFile - | S3File - | Blob - | File, - options?: S3Options, - ): Promise; + readonly name?: string; /** - * Generate a presigned URL for temporary access to a file. - * Useful for generating upload/download URLs without exposing credentials. + * Does the file exist? * - * @example - * // Download URL - * const downloadUrl = bucket.presign("file.pdf", { - * expiresIn: 3600 // 1 hour - * }); + * 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. * - * // Upload URL - * const uploadUrl = bucket.presign("uploads/image.jpg", { - * method: "PUT", - * expiresIn: 3600, - * type: "image/jpeg", - * acl: "public-read" - * }); + * This does a system call to check if the file exists, which can be + * slow. * - * // Long-lived public URL - * const publicUrl = bucket.presign("public/doc.pdf", { - * expiresIn: 7 * 24 * 60 * 60, // 7 days - * acl: "public-read" - * }); + * 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. */ - presign(path: string, options?: S3FilePresignOptions): string; + exists(): Promise; /** - * Delete a file from the bucket. - * - * @example - * // Simple delete - * await bucket.unlink("old-file.txt"); - * - * // With error handling - * try { - * await bucket.unlink("file.dat"); - * console.log("File deleted"); - * } catch (err) { - * console.error("Delete failed:", err); - * } + * 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. */ - unlink(path: string, options?: S3Options): Promise; - delete: S3Client["unlink"]; + write( + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | Request | Response | BunFile, + options?: { highWaterMark?: number }, + ): Promise; /** - * Get the size of a file in bytes. - * Uses HEAD request to efficiently get size. - * - * @example - * // Get size - * const bytes = await bucket.size("video.mp4"); - * console.log(`Size: ${bytes} bytes`); - * - * // Check if file is large - * if (await bucket.size("data.zip") > 100 * 1024 * 1024) { - * console.log("File is larger than 100MB"); - * } + * Deletes the file. */ - size(path: string, options?: S3Options): Promise; + unlink(): Promise; /** - * Check if a file exists in the bucket. - * Uses HEAD request to check existence. - * - * @example - * // Check existence - * if (await bucket.exists("config.json")) { - * const file = bucket("config.json"); - * const config = await file.json(); - * } - * - * // With error handling - * try { - * if (!await bucket.exists("required.txt")) { - * throw new Error("Required file missing"); - * } - * } catch (err) { - * console.error("Check failed:", err); - * } + * Deletes the file. ( same as unlink ) */ - exists(path: string, options?: S3Options): Promise; + delete(): Promise; + /** - * Get the stat of a file in an S3-compatible storage service. - * - * @param path The path to the file. - * @param options The options to use for the S3 client. + * Provides useful information about the file. */ - stat(path: string, options?: S3Options): Promise; - }; + stat(): Promise; + } + /** * Configuration options for SQL client connection and behavior * @example @@ -1976,12 +1775,12 @@ declare module "bun" { * @example * await sql.commitDistributed("my_distributed_transaction"); */ - commitDistributed(name: string): Promise; + commitDistributed(name: string): Promise; /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL * @example * await sql.rollbackDistributed("my_distributed_transaction"); */ - rollbackDistributed(name: string): Promise; + rollbackDistributed(name: string): Promise; /** Waits for the database connection to be established * @example * await sql.connect(); @@ -1991,13 +1790,13 @@ declare module "bun" { * @example * await sql.close({ timeout: 1 }); */ - close(options?: { timeout?: number }): Promise; + close(options?: { timeout?: number }): Promise; /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. * @alias close * @example * await sql.end({ timeout: 1 }); */ - end(options?: { timeout?: number }): Promise; + end(options?: { timeout?: number }): Promise; /** Flushes any pending operations */ flush(): void; /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. @@ -2251,6 +2050,7 @@ declare module "bun" { var SQL: SQL; var CSRF: CSRF; + /** * This lets you use macros as regular imports * @example @@ -2604,7 +2404,7 @@ declare module "bun" { * - `"external"` - Generate a separate source map file for each input file. * No `//# sourceMappingURL` comment is added to the output file. * - * `true` and `false` are aliasees for `"inline"` and `"none"`, respectively. + * `true` and `false` are aliases for `"inline"` and `"none"`, respectively. * * @default "none" * @@ -3240,7 +3040,7 @@ declare module "bun" { * ws.send("Compress this.", true); * ws.send(new Uint8Array([1, 2, 3, 4])); */ - send(data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + send(data: string | BufferSource, compress?: boolean): ServerWebSocketSendStatus; /** * Sends a text message to the client. @@ -3262,7 +3062,7 @@ declare module "bun" { * ws.send(new TextEncoder().encode("Hello!")); * ws.send(new Uint8Array([1, 2, 3, 4]), true); */ - sendBinary(data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + sendBinary(data: BufferSource, compress?: boolean): ServerWebSocketSendStatus; /** * Closes the connection. @@ -3294,14 +3094,14 @@ declare module "bun" { * * @param data The data to send */ - ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + ping(data?: string | BufferSource): ServerWebSocketSendStatus; /** * Sends a pong. * * @param data The data to send */ - pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; + pong(data?: string | BufferSource): ServerWebSocketSendStatus; /** * Sends a message to subscribers of the topic. @@ -3314,7 +3114,7 @@ declare module "bun" { * ws.publish("chat", "Compress this.", true); * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); */ - publish(topic: string, data: string | Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + publish(topic: string, data: string | BufferSource, compress?: boolean): ServerWebSocketSendStatus; /** * Sends a text message to subscribers of the topic. @@ -3338,7 +3138,7 @@ declare module "bun" { * ws.publish("chat", new TextEncoder().encode("Hello!")); * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); */ - publishBinary(topic: string, data: Bun.BufferSource, compress?: boolean): ServerWebSocketSendStatus; + publishBinary(topic: string, data: BufferSource, compress?: boolean): ServerWebSocketSendStatus; /** * Subscribes a client to the topic. @@ -3690,7 +3490,7 @@ declare module "bun" { hmr?: boolean; }; - error?: (this: Server, error: ErrorLike) => Response | Promise | undefined | Promise; + error?: (this: Server, error: ErrorLike) => Response | Promise | void | Promise; /** * Uniquely identify a server instance with an ID @@ -4264,7 +4064,7 @@ declare module "bun" { /** * Send any additional headers while upgrading, like cookies */ - headers?: Bun.HeadersInit; + headers?: Bun.__internal.BunHeadersInit; /** * This value is passed to the {@link ServerWebSocket.data} property */ @@ -4417,178 +4217,6 @@ declare module "bun" { | UnixWebSocketServeOptions | UnixTLSWebSocketServeOptions; - /** - Bun.serve provides a high-performance HTTP server with built-in routing support. - It enables both function-based and object-based route handlers with type-safe - parameters and method-specific handling. - - @example Basic Usage - ```ts - Bun.serve({ - port: 3000, - fetch(req) { - return new Response("Hello World"); - } - }); - ``` - - @example Route-based Handlers - ```ts - Bun.serve({ - routes: { - // Static responses - "/": new Response("Home page"), - - // Function handlers with type-safe parameters - "/users/:id": (req) => { - // req.params.id is typed as string - return new Response(`User ${req.params.id}`); - }, - - // Method-specific handlers - "/api/posts": { - GET: () => new Response("Get posts"), - POST: async (req) => { - const body = await req.json(); - return new Response("Created post"); - }, - DELETE: (req) => new Response("Deleted post") - }, - - // Wildcard routes - "/static/*": (req) => { - // Handle any path under /static/ - return new Response("Static file"); - }, - - // Disable route (fall through to fetch handler) - "/api/legacy": false - }, - - // Fallback handler for unmatched routes - fetch(req) { - return new Response("Not Found", { status: 404 }); - } - }); - ``` - - @example Path Parameters - ```ts - Bun.serve({ - routes: { - // Single parameter - "/users/:id": (req: BunRequest<"/users/:id">) => { - return new Response(`User ID: ${req.params.id}`); - }, - - // Multiple parameters - "/posts/:postId/comments/:commentId": ( - req: BunRequest<"/posts/:postId/comments/:commentId"> - ) => { - return new Response(JSON.stringify(req.params)); - // Output: {"postId": "123", "commentId": "456"} - } - } - }); - ``` - - @example Route Precedence - ```ts - // Routes are matched in the following order: - // 1. Exact static routes ("/about") - // 2. Parameter routes ("/users/:id") - // 3. Wildcard routes ("/api/*") - - Bun.serve({ - routes: { - "/api/users": () => new Response("Users list"), - "/api/users/:id": (req) => new Response(`User ${req.params.id}`), - "/api/*": () => new Response("API catchall"), - "/*": () => new Response("Root catchall") - } - }); - ``` - - @example Error Handling - ```ts - Bun.serve({ - routes: { - "/error": () => { - throw new Error("Something went wrong"); - } - }, - error(error) { - // Custom error handler - console.error(error); - return new Response(`Error: ${error.message}`, { - status: 500 - }); - } - }); - ``` - - @example Server Lifecycle - ```ts - const server = Bun.serve({ - // Server config... - }); - - // Update routes at runtime - server.reload({ - routes: { - "/": () => new Response("Updated route") - } - }); - - // Stop the server - server.stop(); - ``` - - @example Development Mode - ```ts - Bun.serve({ - development: true, // Enable hot reloading - routes: { - // Routes will auto-reload on changes - } - }); - ``` - - @example Type-Safe Request Handling - ```ts - type Post = { - id: string; - title: string; - }; - - Bun.serve({ - routes: { - "/api/posts/:id": async ( - req: BunRequest<"/api/posts/:id"> - ) => { - if (req.method === "POST") { - const body: Post = await req.json(); - return Response.json(body); - } - return new Response("Method not allowed", { - status: 405 - }); - } - } - }); - ``` - @param options - Server configuration options - @param options.routes - Route definitions mapping paths to handlers - */ - function serve }>( - options: ServeFunctionOptions & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for a while though. - */ - static?: R; - }, - ): Server; - type ServeFunctionOptions }> = | (DistributedOmit, WebSocketServeOptions>, "fetch"> & { routes: R; @@ -4598,7 +4226,7 @@ declare module "bun" { routes?: never; fetch: (this: Server, request: Request, server: Server) => Response | Promise; }) - | (WebSocketServeOptions & { + | (Omit, "fetch"> & { routes: R; fetch?: ( this: Server, @@ -4606,7 +4234,7 @@ declare module "bun" { server: Server, ) => Response | Promise | void | undefined; }) - | (WebSocketServeOptions & { + | (Omit, "fetch"> & { routes?: never; fetch: ( this: Server, @@ -4615,6 +4243,179 @@ declare module "bun" { ) => Response | Promise | void | undefined; }); + /** + * Bun.serve provides a high-performance HTTP server with built-in routing support. + * It enables both function-based and object-based route handlers with type-safe + * parameters and method-specific handling. + * + * @param options - Server configuration options + * @param options.routes - Route definitions mapping paths to handlers + * + * @example Basic Usage + * ```ts + * Bun.serve({ + * port: 3000, + * fetch(req) { + * return new Response("Hello World"); + * } + * }); + * ``` + * + * @example Route-based Handlers + * ```ts + * Bun.serve({ + * routes: { + * // Static responses + * "/": new Response("Home page"), + * + * // Function handlers with type-safe parameters + * "/users/:id": (req) => { + * // req.params.id is typed as string + * return new Response(`User ${req.params.id}`); + * }, + * + * // Method-specific handlers + * "/api/posts": { + * GET: () => new Response("Get posts"), + * POST: async (req) => { + * const body = await req.json(); + * return new Response("Created post"); + * }, + * DELETE: (req) => new Response("Deleted post") + * }, + * + * // Wildcard routes + * "/static/*": (req) => { + * // Handle any path under /static/ + * return new Response("Static file"); + * }, + * + * // Disable route (fall through to fetch handler) + * "/api/legacy": false + * }, + * + * // Fallback handler for unmatched routes + * fetch(req) { + * return new Response("Not Found", { status: 404 }); + * } + * }); + * ``` + * + * @example Path Parameters + * ```ts + * Bun.serve({ + * routes: { + * // Single parameter + * "/users/:id": (req: BunRequest<"/users/:id">) => { + * return new Response(`User ID: ${req.params.id}`); + * }, + * + * // Multiple parameters + * "/posts/:postId/comments/:commentId": ( + * req: BunRequest<"/posts/:postId/comments/:commentId"> + * ) => { + * return new Response(JSON.stringify(req.params)); + * // Output: {"postId": "123", "commentId": "456"} + * } + * } + * }); + * ``` + * + * @example Route Precedence + * ```ts + * // Routes are matched in the following order: + * // 1. Exact static routes ("/about") + * // 2. Parameter routes ("/users/:id") + * // 3. Wildcard routes ("/api/*") + * + * Bun.serve({ + * routes: { + * "/api/users": () => new Response("Users list"), + * "/api/users/:id": (req) => new Response(`User ${req.params.id}`), + * "/api/*": () => new Response("API catchall"), + * "/*": () => new Response("Root catchall") + * } + * }); + * ``` + * + * @example Error Handling + * ```ts + * Bun.serve({ + * routes: { + * "/error": () => { + * throw new Error("Something went wrong"); + * } + * }, + * error(error) { + * // Custom error handler + * console.error(error); + * return new Response(`Error: ${error.message}`, { + * status: 500 + * }); + * } + * }); + * ``` + * + * @example Server Lifecycle + * ```ts + * const server = Bun.serve({ + * // Server config... + * }); + * + * // Update routes at runtime + * server.reload({ + * routes: { + * "/": () => new Response("Updated route") + * } + * }); + * + * // Stop the server + * server.stop(); + * ``` + * + * @example Development Mode + * ```ts + * Bun.serve({ + * development: true, // Enable hot reloading + * routes: { + * // Routes will auto-reload on changes + * } + * }); + * ``` + * + * @example Type-Safe Request Handling + * ```ts + * type Post = { + * id: string; + * title: string; + * }; + * + * Bun.serve({ + * routes: { + * "/api/posts/:id": async ( + * req: BunRequest<"/api/posts/:id"> + * ) => { + * if (req.method === "POST") { + * const body: Post = await req.json(); + * return Response.json(body); + * } + * return new Response("Method not allowed", { + * status: 405 + * }); + * } + * } + * }); + * ``` + */ + function serve }>( + options: ServeFunctionOptions & { + /** + * @deprecated Use `routes` instead in new code. This will continue to work for a while though. + */ + static?: R; + }, + ): Server; + /** * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. * @@ -4639,7 +4440,6 @@ declare module "bun" { * ``` * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} */ - // tslint:disable-next-line:unified-signatures function file(path: string | URL, options?: BlobPropertyBag): BunFile; /** @@ -4665,7 +4465,7 @@ declare module "bun" { * * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} */ - // tslint:disable-next-line:unified-signatures + function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; /** @@ -4682,7 +4482,7 @@ declare module "bun" { * * @param fileDescriptor The file descriptor of the file */ - // tslint:disable-next-line:unified-signatures + function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; /** @@ -4752,7 +4552,7 @@ declare module "bun" { * * To close the file, set the array to `null` and it will be garbage collected eventually. */ - function mmap(path: Bun.PathLike, opts?: MMapOptions): Uint8Array; + function mmap(path: PathLike, opts?: MMapOptions): Uint8Array; /** Write to stdout */ const stdout: BunFile; @@ -4897,11 +4697,8 @@ declare module "bun" { * * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. */ - // tslint:disable-next-line:unified-signatures - arrayBufferToString(buffer: Uint16Array): string; - /** Mock bun's segfault handler. You probably don't want to use this */ - segfault(): void; + arrayBufferToString(buffer: Uint16Array): string; /** * Force the garbage collector to run extremely often, @@ -4919,6 +4716,11 @@ declare module "bun" { * @returns The previous level */ gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; + + /** + * Dump the mimalloc heap to the console + */ + mimallocDump(): void; } const unsafe: Unsafe; @@ -4932,7 +4734,7 @@ declare module "bun" { const enableANSIColors: boolean; /** - * What script launched bun? + * What script launched Bun? * * Absolute file path * @@ -5022,9 +4824,7 @@ declare module "bun" { */ function openInEditor(path: string, options?: EditorOptions): void; - var fetch: typeof globalThis.fetch & { - preconnect(url: string): void; - }; + var fetch: typeof globalThis.fetch; interface EditorOptions { editor?: "vscode" | "subl"; @@ -5125,7 +4925,7 @@ declare module "bun" { * * @param input */ - update(input: Bun.BlobOrStringOrBuffer, inputEncoding?: CryptoEncoding): CryptoHasher; + update(input: Bun.BlobOrStringOrBuffer, inputEncoding?: import("crypto").Encoding): CryptoHasher; /** * Perform a deep copy of the hasher @@ -5621,7 +5421,7 @@ declare module "bun" { type FFIFunctionCallable = Function & { // Making a nominally typed function so that the user must get it from dlopen - readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol; + readonly __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol; }; interface PluginBuilder { @@ -5850,7 +5650,7 @@ declare module "bun" { * will be slow. In the future, Bun will buffer writes and flush them at the * end of the tick, when the event loop is idle, or sooner if the buffer is full. */ - write(data: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; + write(data: string | BufferSource, byteOffset?: number, byteLength?: number): number; /** * The data context for the socket. @@ -5862,7 +5662,7 @@ declare module "bun" { * * Use it to send your last message and close the connection. */ - end(data?: string | Bun.BufferSource, byteOffset?: number, byteLength?: number): number; + end(data?: string | BufferSource, byteOffset?: number, byteLength?: number): number; /** * Close the socket immediately @@ -6003,8 +5803,8 @@ declare module "bun" { * If there is no local certificate, an empty object will be returned. If the * socket has been destroyed, `null` will be returned. */ - getCertificate(): PeerCertificate | object | null; - getX509Certificate(): X509Certificate | undefined; + getCertificate(): import("tls").PeerCertificate | object | null; + getX509Certificate(): import("node:crypto").X509Certificate | undefined; /** * Returns an object containing information on the negotiated cipher suite. @@ -6020,7 +5820,7 @@ declare module "bun" { * ``` * */ - getCipher(): CipherNameAndProtocol; + getCipher(): import("tls").CipherNameAndProtocol; /** * Returns an object representing the type, name, and size of parameter of @@ -6031,7 +5831,7 @@ declare module "bun" { * * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. */ - getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; + getEphemeralKeyInfo(): import("tls").EphemeralKeyInfo | object | null; /** * Returns an object representing the peer's certificate. If the peer does not @@ -6042,8 +5842,8 @@ declare module "bun" { * certificate. * @return A certificate object. */ - getPeerCertificate(): PeerCertificate; - getPeerX509Certificate(): X509Certificate; + getPeerCertificate(): import("tls").PeerCertificate; + getPeerX509Certificate(): import("node:crypto").X509Certificate; /** * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. diff --git a/packages/bun-types/new/bun.ns.d.ts b/packages/bun-types/bun.ns.d.ts similarity index 100% rename from packages/bun-types/new/bun.ns.d.ts rename to packages/bun-types/bun.ns.d.ts diff --git a/packages/bun-types/deprecated.d.ts b/packages/bun-types/deprecated.d.ts index 5a90164689ded8..2fb502e4ad348e 100644 --- a/packages/bun-types/deprecated.d.ts +++ b/packages/bun-types/deprecated.d.ts @@ -1,4 +1,19 @@ declare module "bun" { + interface BunMessageEvent { + /** + * @deprecated + */ + initMessageEvent( + type: string, + bubbles?: boolean, + cancelable?: boolean, + data?: any, + origin?: string, + lastEventId?: string, + source?: null, + ): void; + } + /** * @deprecated Renamed to `ErrorLike` */ @@ -38,21 +53,6 @@ declare namespace NodeJS { } } -declare namespace Bun { - interface MessageEvent { - /** @deprecated */ - initMessageEvent( - type: string, - bubbles?: boolean, - cancelable?: boolean, - data?: any, - origin?: string, - lastEventId?: string, - source?: null, - ): void; - } -} - interface CustomEvent { /** @deprecated */ initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void; diff --git a/packages/bun-types/new/extensions.d.ts b/packages/bun-types/extensions.d.ts similarity index 100% rename from packages/bun-types/new/extensions.d.ts rename to packages/bun-types/extensions.d.ts diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 58e138bbad8c93..bdee6570700e7a 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,56 +1,98 @@ -interface Headers { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; -} +declare module "bun" { + namespace __internal { + type BunBodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; + + type BunHeadersInit = + | Headers + | Record + | Array<[string, string]> + | IterableIterator<[string, string]>; + + /** + * @internal + */ + type LibOrUndiciHeaders = LibDomIsLoaded extends true ? typeof globalThis.Headers : import("undici-types").Headers; + + /** + * @internal + */ + type LibOrUndiciRequest = LibDomIsLoaded extends true ? {} : import("undici-types").Request; + + /** + * @internal + */ + type LibOrUndiciResponse = LibDomIsLoaded extends true ? {} : import("undici-types").Response; -var Headers: { - prototype: Headers; - new (init?: Bun.HeadersInit): Headers; -}; + interface BunHeadersOverride extends LibOrUndiciHeaders { + /** + * Convert {@link Headers} to a plain JavaScript object. + * + * About 10x faster than `Object.fromEntries(headers.entries())` + * + * Called when you run `JSON.stringify(headers)` + * + * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. + */ + toJSON(): Record; + /** + * Get the total number of headers + */ + readonly count: number; + /** + * Get all headers matching the name + * + * Only supports `"Set-Cookie"`. All other headers are empty arrays. + * + * @param name - The header name to get + * + * @returns An array of header values + * + * @example + * ```ts + * const headers = new Headers(); + * headers.append("Set-Cookie", "foo=bar"); + * headers.append("Set-Cookie", "baz=qux"); + * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] + * ``` + */ + getAll(name: "set-cookie" | "Set-Cookie"): string[]; + } -interface Request { - headers: Headers; + interface BunResponseOverride extends LibOrUndiciResponse { + headers: BunHeadersOverride; + } + + interface BunRequestOverride extends LibOrUndiciRequest { + headers: BunHeadersOverride; + } + } } -var Request: { - prototype: Request; - new (requestInfo: string, requestInit?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, requestInit?: RequestInit): Request; -}; +interface Headers extends Bun.__internal.BunHeadersOverride {} +declare var Headers: Bun.__internal.UseLibDomIfAvailable< + "Headers", + { + prototype: Headers; + new (init?: Bun.__internal.BunHeadersInit): Headers; + } +>; + +interface Request extends Bun.__internal.BunRequestOverride {} + +declare var Request: Bun.__internal.UseLibDomIfAvailable< + "Request", + { + prototype: Request; + new (requestInfo: string, init?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, init?: RequestInit): Request; + } +>; -var Response: { - new (body?: Bun.BodyInit | null | undefined, init?: Bun.ResponseInit | undefined): Response; +interface Response extends Bun.__internal.BunResponseOverride {} + +interface ResponseConstructor { + new (body?: Bun.__internal.BunBodyInit | null | undefined, init?: ResponseInit | undefined): Response; /** * Create a new {@link Response} with a JSON body * @@ -74,7 +116,7 @@ var Response: { * ``` * @link https://github.com/whatwg/fetch/issues/1389 */ - json(body?: any, options?: Bun.ResponseInit | number): Response; + json(body?: any, options?: ResponseInit | number): Response; /** * Create a new {@link Response} that redirects to url @@ -82,7 +124,6 @@ var Response: { * @param url - the URL to redirect to * @param status - the HTTP status code to use for the redirect */ - // tslint:disable-next-line:unified-signatures redirect(url: string, status?: number): Response; /** @@ -91,17 +132,17 @@ var Response: { * @param url - the URL to redirect to * @param options - options to pass to the response */ - // tslint:disable-next-line:unified-signatures redirect(url: string, options?: Bun.ResponseInit): Response; /** * Create a new {@link Response} that has a network error */ error(): Response; -}; +} + +declare var Response: ResponseConstructor; -type _BunTLSOptions = import("bun").TLSOptions; -interface BunFetchRequestInitTLS extends _BunTLSOptions { +interface BunFetchRequestInitTLS extends Bun.TLSOptions { /** * Custom function to check the server identity * @param hostname - The hostname of the server @@ -123,39 +164,65 @@ interface BunFetchRequestInit extends RequestInit { * Override the default TLS options */ tls?: BunFetchRequestInitTLS; -} -var fetch: { /** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool */ - (request: Request, init?: BunFetchRequestInit): Promise; + verbose?: boolean; /** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. */ - (url: string | URL | Request, init?: BunFetchRequestInit): Promise; - - (input: string | URL | globalThis.Request, init?: BunFetchRequestInit): Promise; + proxy?: string; /** - * Start the DNS resolution, TCP connection, and TLS handshake for a request - * before the request is actually sent. - * - * This can reduce the latency of a request when you know there's some - * long-running task that will delay the request starting. - * - * This is a bun-specific API and is not part of the Fetch API specification. + * Override the default S3 options */ - preconnect(url: string | URL): void; -}; + s3?: Bun.S3Options; +} + +/** + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(request: Request, init?: BunFetchRequestInit): Promise; + +/** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; + +/** + * Send a HTTP(s) request + * + * @param input URL string or Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; + +declare namespace fetch { + export function preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; +} diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 8c34df78e9ef5c..2df6e71b285d8c 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1,102 +1,44 @@ -export {}; - -type _Event = { - /** This is not used in Node.js and is provided purely for completeness. */ - readonly bubbles: boolean; - /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ - cancelBubble: () => void; - /** True if the event was created with the cancelable option */ - readonly cancelable: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly composed: boolean; - /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ - composedPath(): [EventTarget?]; - /** Alias for event.target. */ - readonly currentTarget: EventTarget | null; - /** Is true if cancelable is true and event.preventDefault() has been called. */ - readonly defaultPrevented: boolean; - /** This is not used in Node.js and is provided purely for completeness. */ - readonly eventPhase: 0 | 2; - /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ - readonly isTrusted: boolean; - /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ - preventDefault(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - returnValue: boolean; - /** Alias for event.target. */ - readonly srcElement: EventTarget | null; - /** Stops the invocation of event listeners after the current one completes. */ - stopImmediatePropagation(): void; - /** This is not used in Node.js and is provided purely for completeness. */ - stopPropagation(): void; - /** The `EventTarget` dispatching the event */ - readonly target: EventTarget | null; - /** The millisecond timestamp when the Event object was created. */ - readonly timeStamp: number; - /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ - readonly type: string; -}; - -type _EventTarget = { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; -}; - -declare global { - var Bun: typeof import("bun"); - - namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; +declare module "bun" { + namespace __internal { + type NodeWorkerThreadsWorker = import("worker_threads").Worker; + type LibWorkerOrNodeWorkerThreadsWorker = Bun.__internal.UseLibDomIfAvailable<"Worker", NodeWorkerThreadsWorker>; + + type NodePerfHooksPerformance = import("perf_hooks").Performance; + type LibPerformanceOrNodePerfHooksPerformance = Bun.__internal.UseLibDomIfAvailable< + "Performance", + NodePerfHooksPerformance + >; - /** Whether you are using Bun */ - isBun: true; - /** The current git sha of Bun **/ - revision: string; - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } + type NodeCryptoWebcryptoSubtleCrypto = import("crypto").webcrypto.SubtleCrypto; + type NodeCryptoWebcryptoCryptoKey = import("crypto").webcrypto.CryptoKey; + type NodeUtilTextEncoder = import("util").TextEncoder; + type NodeUtilTextDecoder = import("util").TextDecoder; } +} - type _ReadableStream = import("stream/web").ReadableStream; - interface ReadableStream extends _ReadableStream {} - var ReadableStream: { +interface ReadableStream {} +declare var ReadableStream: Bun.__internal.UseLibDomIfAvailable< + "ReadableStream", + { prototype: ReadableStream; new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - }; + } +>; - type _WritableStream = import("stream/web").WritableStream; - interface WritableStream extends _WritableStream {} - var WritableStream: { +interface WritableStream {} +declare var WritableStream: Bun.__internal.UseLibDomIfAvailable< + "WritableStream", + { prototype: WritableStream; new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; - }; + } +>; - type _Worker = import("worker_threads").Worker; - interface Worker extends _Worker {} - var Worker: { +interface Worker extends Bun.__internal.LibWorkerOrNodeWorkerThreadsWorker {} +declare var Worker: Bun.__internal.UseLibDomIfAvailable< + "Worker", + { prototype: Worker; new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; /** @@ -105,90 +47,212 @@ declare global { * This is Bun's equivalent of `workerData` in Node.js. */ data: any; - }; - - var WebSocket: typeof import("ws").WebSocket; + } +>; - type _Crypto = import("crypto").webcrypto.Crypto; - interface Crypto extends _Crypto {} - var Crypto: { - prototype: Crypto; - new (): Crypto; - }; +declare var WebSocket: Bun.__internal.UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>; - var crypto: Crypto; +interface Crypto {} +declare var Crypto: { + prototype: Crypto; + new (): Crypto; +}; +declare var crypto: Crypto; + +/** + * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All + * instances of `TextEncoder` only support UTF-8 encoding. + * + * ```js + * const encoder = new TextEncoder(); + * const uint8array = encoder.encode('this is some data'); + * ``` + */ +interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { /** - * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All - * instances of `TextEncoder` only support UTF-8 encoding. + * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object + * containing the read Unicode code units and written UTF-8 bytes. * * ```js * const encoder = new TextEncoder(); - * const uint8array = encoder.encode('this is some data'); + * const src = 'this is some data'; + * const dest = new Uint8Array(10); + * const { read, written } = encoder.encodeInto(src, dest); * ``` + * @param src The text to encode. + * @param dest The array to hold the encode result. */ - interface TextEncoder extends Bun.TextEncoder {} - var TextEncoder: typeof TextEncoder; - - interface TextDecoder extends Bun.TextDecoder {} - var TextDecoder: typeof TextDecoder; - - type _Performance = import("perf_hooks").Performance; - interface Performance extends _Performance {} - var performance: Performance; - - interface Event extends _Event {} - var Event: { - prototype: Event; - new (type: string, eventInitDict?: Bun.EventInit): Event; - }; - - interface EventTarget extends _EventTarget {} - var EventTarget: { - prototype: EventTarget; - new (): EventTarget; - }; - - interface File extends Blob { - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new (parts: Bun.BlobPart[], name: string, options?: BlobPropertyBag & { lastModified?: Date | number }): File; - readonly lastModified: number; - readonly name: string; + encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; +} +declare var TextEncoder: Bun.__internal.UseLibDomIfAvailable< + "TextEncoder", + { + prototype: TextEncoder; + new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; } +>; + +/** + * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextDecoder` API. All + * instances of `TextDecoder` only support UTF-8 decoding. + * + * ```js + * const decoder = new TextDecoder(); + * const uint8array = decoder.decode('this is some data'); + */ +declare var TextDecoder: Bun.__internal.UseLibDomIfAvailable< + "TextDecoder", + { + prototype: Bun.__internal.NodeUtilTextDecoder; + new ( + encoding?: Bun.Encoding, + options?: { fatal?: boolean; ignoreBOM?: boolean }, + ): Bun.__internal.NodeUtilTextDecoder; + } +>; + +// interface Event { +// /** This is not used in Node.js and is provided purely for completeness. */ +// readonly bubbles: boolean; +// /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ +// cancelBubble: () => void; +// /** True if the event was created with the cancelable option */ +// readonly cancelable: boolean; +// /** This is not used in Node.js and is provided purely for completeness. */ +// readonly composed: boolean; +// /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ +// composedPath(): [EventTarget?]; +// /** Alias for event.target. */ +// readonly currentTarget: EventTarget | null; +// /** Is true if cancelable is true and event.preventDefault() has been called. */ +// readonly defaultPrevented: boolean; +// /** This is not used in Node.js and is provided purely for completeness. */ +// readonly eventPhase: typeof globalThis extends { Event: infer T extends {eventPhase: number} } ? T['eventPhase'] : 0 | 2; +// /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ +// readonly isTrusted: boolean; +// /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ +// preventDefault(): void; +// /** This is not used in Node.js and is provided purely for completeness. */ +// returnValue: boolean; +// /** Alias for event.target. */ +// readonly srcElement: EventTarget | null; +// /** Stops the invocation of event listeners after the current one completes. */ +// stopImmediatePropagation(): void; +// /** This is not used in Node.js and is provided purely for completeness. */ +// stopPropagation(): void; +// /** The `EventTarget` dispatching the event */ +// readonly target: EventTarget | null; +// /** The millisecond timestamp when the Event object was created. */ +// readonly timeStamp: number; +// /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ +// readonly type: string; +// } +declare var Event: { + prototype: Event; + readonly NONE: 0; + readonly CAPTURING_PHASE: 1; + readonly AT_TARGET: 2; + readonly BUBBLING_PHASE: 3; + new (type: string, eventInitDict?: Bun.EventInit): Event; +}; - var File: typeof File; +interface EventTarget { + /** + * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. + * + * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. + * + * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. + * Specifically, the `capture` option is used as part of the key when registering a `listener`. + * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. + */ + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ + dispatchEvent(event: Event): boolean; + /** Removes the event listener in target's event listener list with the same type, callback, and options. */ + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: Bun.EventListenerOptions | boolean, + ): void; +} +declare var EventTarget: { + prototype: EventTarget; + new (): EventTarget; +}; - type _RequestInit = import("undici-types").RequestInit; - interface RequestInit extends _RequestInit { - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; +interface File extends Blob { + readonly lastModified: number; + readonly name: string; +} - /** - * Override the default S3 options - */ - s3?: import("bun").S3Options; - } +declare var File: typeof globalThis extends { onabort: any } + ? typeof globalThis extends { File: infer T } + ? T + : never + : { + prototype: File; + /** + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + * + * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects + * @param `name` - The name of the file + * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) + */ + new ( + parts: Bun.BlobPart[], + name: string, + options?: BlobPropertyBag & { lastModified?: Date | number | undefined }, + ): File; + }; +/** + * ShadowRealms are a distinct global environment, with its own global object + * containing its own intrinsics and built-ins (standard objects that are not + * bound to global variables, like the initial value of Object.prototype). + * + * @example + * + * ```js + * const red = new ShadowRealm(); + * + * // realms can import modules that will execute within it's own environment. + * // When the module is resolved, it captured the binding value, or creates a new + * // wrapped function that is connected to the callable binding. + * const redAdd = await red.importValue('./inside-code.js', 'add'); + * + * // redAdd is a wrapped function exotic object that chains it's call to the + * // respective imported binding. + * let result = redAdd(2, 3); + * + * console.assert(result === 5); // yields true + * + * // The evaluate method can provide quick code evaluation within the constructed + * // shadowRealm without requiring any module loading, while it still requires CSP + * // relaxing. + * globalThis.someValue = 1; + * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global + * console.assert(globalThis.someValue === 1); + * + * // The wrapped functions can also wrap other functions the other way around. + * const setUniqueValue = + * await red.importValue('./inside-code.js', 'setUniqueValue'); + * + * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); + * + * result = setUniqueValue((x) => x ** 3); + * + * console.assert(result === 16); // yields true + * ``` + */ +interface ShadowRealm { /** - * ShadowRealms are a distinct global environment, with its own global object - * containing its own intrinsics and built-ins (standard objects that are not - * bound to global variables, like the initial value of Object.prototype). + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) * * @example * @@ -224,1066 +288,1156 @@ declare global { * console.assert(result === 16); // yields true * ``` */ - interface ShadowRealm { - /** - * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; - } + importValue(specifier: string, bindingName: string): Promise; + evaluate(sourceText: string): any; +} - var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; - }; +declare var ShadowRealm: { + prototype: ShadowRealm; + new (): ShadowRealm; +}; - function queueMicrotask(callback: (...args: any[]) => void): void; - /** - * Log an error using the default exception handler - * @param error Error or string - */ - function reportError(error: any): void; +declare function queueMicrotask(callback: (...args: any[]) => void): void; +/** + * Log an error using the default exception handler + * @param error Error or string + */ +declare function reportError(error: any): void; - interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; +interface Timer { + ref(): Timer; + unref(): Timer; + hasRef(): boolean; + refresh(): Timer; - [Symbol.toPrimitive](): number; - } + [Symbol.toPrimitive](): number; +} +/** + * Cancel a repeating timer by its timer ID. + * @param id timer id + */ +declare function clearInterval(id?: number | Timer): void; +/** + * Cancel a delayed function call by its timer ID. + * @param id timer id + */ +declare function clearTimeout(id?: number | Timer): void; +/** + * Cancel an immediate function call by its immediate ID. + * @param id immediate id + */ +declare function clearImmediate(id?: number | Timer): void; +/** + * Run a function immediately after main event loop is vacant + * @param handler function to call + */ +declare function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; +/** + * Run a function every `interval` milliseconds + * @param handler function to call + * @param interval milliseconds to wait between calls + */ +declare function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; +/** + * Run a function after `timeout` (milliseconds) + * @param handler function to call + * @param timeout milliseconds to wait between calls + */ +declare function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; + +declare function addEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | AddEventListenerOptions, +): void; +declare function addEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, +): void; +declare function removeEventListener( + type: K, + listener: (this: object, ev: EventMap[K]) => any, + options?: boolean | Bun.EventListenerOptions, +): void; +declare function removeEventListener( + type: string, + listener: Bun.EventListenerOrEventListenerObject, + options?: boolean | Bun.EventListenerOptions, +): void; + +/** + * Events providing information related to errors in scripts or in files. + */ +interface ErrorEvent extends Event { + readonly colno: number; + readonly error: any; + readonly filename: string; + readonly lineno: number; + readonly message: string; +} + +declare var ErrorEvent: { + prototype: ErrorEvent; + new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; +}; + +/** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ +interface CloseEvent extends Event { + /** Returns the WebSocket connection close code provided by the server. */ + readonly code: number; + /** Returns the WebSocket connection close reason provided by the server. */ + readonly reason: string; + /** Returns true if the connection closed cleanly; false otherwise. */ + readonly wasClean: boolean; +} + +declare var CloseEvent: { + prototype: CloseEvent; + new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; +}; + +interface MessageEvent extends Bun.MessageEvent {} +declare var MessageEvent: Bun.__internal.UseLibDomIfAvailable<"MessageEvent", MessageEvent>; + +interface CustomEvent extends Event { + /** Returns any custom data event was created with. Typically used for synthetic events. */ + readonly detail: T; +} + +declare var CustomEvent: { + prototype: CustomEvent; + new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; +}; + +interface EventListener { + (evt: Event): void; +} + +interface EventListenerObject { + handleEvent(object: Event): void; +} + +interface FetchEvent extends Event { + readonly request: Request; + readonly url: string; + + waitUntil(promise: Promise): void; + respondWith(response: Response | Promise): void; +} + +interface EventMap { + fetch: FetchEvent; + message: MessageEvent; + messageerror: MessageEvent; + // exit: Event; +} + +interface AddEventListenerOptions extends Bun.EventListenerOptions { + once?: boolean; + passive?: boolean; + signal?: AbortSignal; +} + +/** + * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) + * + * Before using this, be aware of a few things: + * + * **Using this incorrectly will crash your application**. + * + * This API may change any time JavaScriptCore is updated. + * + * Bun may rewrite ESM import specifiers to point to bundled code. This will + * be confusing when using this API, as it will return a string like + * "/node_modules.server.bun". + * + * Bun may inject additional imports into your code. This usually has a `bun:` prefix. + */ +declare var Loader: { /** - * Cancel a repeating timer by its timer ID. - * @param id timer id - */ - function clearInterval(id?: number | Timer): void; - /** - * Cancel a delayed function call by its timer ID. - * @param id timer id - */ - function clearTimeout(id?: number | Timer): void; - /** - * Cancel an immediate function call by its immediate ID. - * @param id immediate id + * ESM module registry + * + * This lets you implement live reload in Bun. If you + * delete a module specifier from this map, the next time it's imported, it + * will be re-transpiled and loaded again. + * + * The keys are the module specifiers and the + * values are metadata about the module. + * + * The keys are an implementation detail for Bun that will change between + * versions. + * + * - Userland modules are an absolute file path + * - Virtual modules have a `bun:` prefix or `node:` prefix + * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill + * - If you have a `node_modules.bun` file, many modules will point to that file + * + * Virtual modules and JS polyfills are embedded in bun's binary. They don't + * point to anywhere in your local filesystem. */ - function clearImmediate(id?: number | Timer): void; + registry: Map< + string, + { + key: string; + /** + * This refers to the state the ESM module is in + * + * TODO: make an enum for this number + */ + state: number; + fetch: Promise; + instantiate: Promise; + satisfy: Promise; + dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; + /** + * Your application will probably crash if you mess with this. + */ + module: { + dependenciesMap: (typeof Loader)["registry"]; + }; + linkError?: any; + linkSucceeded: boolean; + evaluated: boolean; + then?: any; + isAsync: boolean; + } + >; /** - * Run a function immediately after main event loop is vacant - * @param handler function to call + * For an already-evaluated module, return the dependencies as module specifiers + * + * This list is already sorted and uniqued. + * + * @example + * + * For this code: + * ```js + * // /foo.js + * import classNames from 'classnames'; + * import React from 'react'; + * import {createElement} from 'react'; + * ``` + * + * This would return: + * ```js + * Loader.dependencyKeysIfEvaluated("/foo.js") + * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] + * ``` + * + * @param specifier - module specifier as it appears in transpiled source code */ - function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; + dependencyKeysIfEvaluated: (specifier: string) => string[]; /** - * Run a function every `interval` milliseconds - * @param handler function to call - * @param interval milliseconds to wait between calls + * The function JavaScriptCore internally calls when you use an import statement. + * + * This may return a path to `node_modules.server.bun`, which will be confusing. + * + * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} + * instead. + * + * @param specifier - module specifier as it appears in transpiled source code + * @param referrer - module specifier that is resolving this specifier */ - function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; + resolve: (specifier: string, referrer: string) => string; +}; + +interface QueuingStrategy { + highWaterMark?: number; + size?: QueuingStrategySize; +} + +interface QueuingStrategyInit { /** - * Run a function after `timeout` (milliseconds) - * @param handler function to call - * @param timeout milliseconds to wait between calls + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. */ - function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; + highWaterMark: number; +} - function addEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - function addEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - function removeEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | Bun.EventListenerOptions, - ): void; - function removeEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | Bun.EventListenerOptions, - ): void; +/** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ +interface ByteLengthQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + // changed from QueuingStrategySize + // to avoid conflict with lib.dom.d.ts + readonly size: QueuingStrategySize; +} + +declare var ByteLengthQueuingStrategy: { + prototype: ByteLengthQueuingStrategy; + new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; +}; + +interface ReadableStreamDefaultController { + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; +} + +interface ReadableStreamDirectController { + close(error?: Error): void; + write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; + end(): number | Promise; + flush(): number | Promise; + start(): void; +} + +declare var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; +}; +interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { + read(): Promise>; /** - * Events providing information related to errors in scripts or in files. + * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. + * Will only return a promise if the data is not immediately available. */ - interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; - } + readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; + releaseLock(): void; +} - var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; - }; +declare var ReadableStreamDefaultReader: { + prototype: ReadableStreamDefaultReader; + new (stream: ReadableStream): ReadableStreamDefaultReader; +}; - /** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ - interface CloseEvent extends Event { - /** Returns the WebSocket connection close code provided by the server. */ - readonly code: number; - /** Returns the WebSocket connection close reason provided by the server. */ - readonly reason: string; - /** Returns true if the connection closed cleanly; false otherwise. */ - readonly wasClean: boolean; - } +interface ReadableStreamGenericReader { + readonly closed: Promise; + cancel(reason?: any): Promise; +} - var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; - }; +interface ReadableStreamDefaultReadDoneResult { + done: true; + value?: undefined; +} - interface MessageEvent extends Bun.MessageEvent {} - var MessageEvent: { - prototype: MessageEvent; - new (type: string, eventInitDict?: Bun.MessageEventInit): MessageEvent; - }; +interface ReadableStreamDefaultReadValueResult { + done: false; + value: T; +} - interface CustomEvent extends Event { - /** Returns any custom data event was created with. Typically used for synthetic events. */ - readonly detail: T; - } +interface ReadableWritablePair { + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; +} - var CustomEvent: { - prototype: CustomEvent; - new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; - }; +interface WritableStreamDefaultController { + error(e?: any): void; +} - // /** - // * The URL interface represents an object providing static methods used for - // * creating object URLs. - // */ - // interface URL extends _URL { - // new (url: string | URL, base?: string | URL): URL; - // /** Not implemented yet */ - // createObjectURL(obj: Blob): string; - // /** Not implemented yet */ - // revokeObjectURL(url: string): void; - - // /** - // * Check if `url` is a valid URL string - // * - // * @param url URL string to parse - // * @param base URL to resolve against - // */ - // canParse(url: string, base?: string): boolean; - // } - - interface EventListener { - (evt: Event): void; - } +declare var WritableStreamDefaultController: { + prototype: WritableStreamDefaultController; + new (): WritableStreamDefaultController; +}; - interface EventListenerObject { - handleEvent(object: Event): void; - } +/** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ +interface WritableStreamDefaultWriter { + readonly closed: Promise; + readonly desiredSize: number | null; + readonly ready: Promise; + abort(reason?: any): Promise; + close(): Promise; + releaseLock(): void; + write(chunk?: W): Promise; +} - interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; +declare var WritableStreamDefaultWriter: { + prototype: WritableStreamDefaultWriter; + new (stream: WritableStream): WritableStreamDefaultWriter; +}; - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; - } +interface TransformStream { + readonly readable: ReadableStream; + readonly writable: WritableStream; +} - interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; - // exit: Event; - } +declare var TransformStream: { + prototype: TransformStream; + new ( + transformer?: Transformer, + writableStrategy?: QueuingStrategy, + readableStrategy?: QueuingStrategy, + ): TransformStream; +}; - interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; - } +interface TransformStreamDefaultController { + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; +} + +declare var TransformStreamDefaultController: { + prototype: TransformStreamDefaultController; + new (): TransformStreamDefaultController; +}; +interface StreamPipeOptions { + preventAbort?: boolean; + preventCancel?: boolean; /** - * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. * - * Before using this, be aware of a few things: + * Errors and closures of the source and destination streams propagate as follows: * - * **Using this incorrectly will crash your application**. + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. * - * This API may change any time JavaScriptCore is updated. + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. * - * Bun may rewrite ESM import specifiers to point to bundled code. This will - * be confusing when using this API, as it will return a string like - * "/node_modules.server.bun". + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. * - * Bun may inject additional imports into your code. This usually has a `bun:` prefix. + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. */ - var Loader: { - /** - * ESM module registry - * - * This lets you implement live reload in Bun. If you - * delete a module specifier from this map, the next time it's imported, it - * will be re-transpiled and loaded again. - * - * The keys are the module specifiers and the - * values are metadata about the module. - * - * The keys are an implementation detail for Bun that will change between - * versions. - * - * - Userland modules are an absolute file path - * - Virtual modules have a `bun:` prefix or `node:` prefix - * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill - * - If you have a `node_modules.bun` file, many modules will point to that file - * - * Virtual modules and JS polyfills are embedded in bun's binary. They don't - * point to anywhere in your local filesystem. - */ - registry: Map< - string, - { - key: string; - /** - * This refers to the state the ESM module is in - * - * TODO: make an enum for this number - */ - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; - /** - * Your application will probably crash if you mess with this. - */ - module: { - dependenciesMap: (typeof Loader)["registry"]; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - /** - * For an already-evaluated module, return the dependencies as module specifiers - * - * This list is already sorted and uniqued. - * - * @example - * - * For this code: - * ```js - * // /foo.js - * import classNames from 'classnames'; - * import React from 'react'; - * import {createElement} from 'react'; - * ``` - * - * This would return: - * ```js - * Loader.dependencyKeysIfEvaluated("/foo.js") - * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] - * ``` - * - * @param specifier - module specifier as it appears in transpiled source code - */ - dependencyKeysIfEvaluated: (specifier: string) => string[]; - /** - * The function JavaScriptCore internally calls when you use an import statement. - * - * This may return a path to `node_modules.server.bun`, which will be confusing. - * - * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} - * instead. - * - * @param specifier - module specifier as it appears in transpiled source code - * @param referrer - module specifier that is resolving this specifier - */ - resolve: (specifier: string, referrer: string) => string; - }; + preventClose?: boolean; + signal?: AbortSignal; +} - interface QueuingStrategy { - highWaterMark?: number; - size?: QueuingStrategySize; - } +/** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ +interface CountQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + readonly size: QueuingStrategySize; +} - interface QueuingStrategyInit { - /** - * Creates a new ByteLengthQueuingStrategy with the provided high water mark. - * - * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. - */ - highWaterMark: number; - } +declare var CountQueuingStrategy: { + prototype: CountQueuingStrategy; + new (init: QueuingStrategyInit): CountQueuingStrategy; +}; - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface ByteLengthQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - // changed from QueuingStrategySize - // to avoid conflict with lib.dom.d.ts - readonly size: QueuingStrategySize; - } +interface QueuingStrategySize { + (chunk?: T): number; +} - var ByteLengthQueuingStrategy: { - prototype: ByteLengthQueuingStrategy; - new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; - }; +interface Transformer { + flush?: Bun.TransformerFlushCallback; + readableType?: undefined; + start?: Bun.TransformerStartCallback; + transform?: Bun.TransformerTransformCallback; + writableType?: undefined; +} - interface ReadableStreamDefaultController { - readonly desiredSize: number | null; - close(): void; - enqueue(chunk?: R): void; - error(e?: any): void; - } +interface Dict { + [key: string]: T | undefined; +} - interface ReadableStreamDirectController { - close(error?: Error): void; - write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; - end(): number | Promise; - flush(): number | Promise; - start(): void; - } +interface ReadOnlyDict { + readonly [key: string]: T | undefined; +} - var ReadableStreamDefaultController: { - prototype: ReadableStreamDefaultController; - new (): ReadableStreamDefaultController; - }; +interface ErrnoException extends Error { + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; +} - interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { - read(): Promise>; - /** - * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. - * Will only return a promise if the data is not immediately available. - */ - readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; - releaseLock(): void; - } +/** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ +interface DOMException extends Error { + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; +} - var ReadableStreamDefaultReader: { - prototype: ReadableStreamDefaultReader; - new (stream: ReadableStream): ReadableStreamDefaultReader; - }; +// declare var DOMException: { +// prototype: DOMException; +// new (message?: string, name?: string): DOMException; +// }; - interface ReadableStreamGenericReader { - readonly closed: Promise; - cancel(reason?: any): Promise; - } +declare function alert(message?: string): void; +declare function confirm(message?: string): boolean; +declare function prompt(message?: string, _default?: string): string | null; - interface ReadableStreamDefaultReadDoneResult { - done: true; - value?: undefined; - } +interface SubtleCrypto extends Bun.__internal.NodeCryptoWebcryptoSubtleCrypto {} +declare var SubtleCrypto: { + prototype: SubtleCrypto; + new (): SubtleCrypto; +}; - interface ReadableStreamDefaultReadValueResult { - done: false; - value: T; - } +interface CryptoKey extends Bun.__internal.NodeCryptoWebcryptoCryptoKey {} +declare var CryptoKey: { + prototype: CryptoKey; + new (): CryptoKey; +}; - interface ReadableWritablePair { - readable: ReadableStream; - /** - * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - */ - writable: WritableStream; - } - - interface WritableStreamDefaultController { - error(e?: any): void; - } - - var WritableStreamDefaultController: { - prototype: WritableStreamDefaultController; - new (): WritableStreamDefaultController; - }; - - /** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ - interface WritableStreamDefaultWriter { - readonly closed: Promise; - readonly desiredSize: number | null; - readonly ready: Promise; - abort(reason?: any): Promise; - close(): Promise; - releaseLock(): void; - write(chunk?: W): Promise; - } - - var WritableStreamDefaultWriter: { - prototype: WritableStreamDefaultWriter; - new (stream: WritableStream): WritableStreamDefaultWriter; - }; - - interface TransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; - } - - var TransformStream: { - prototype: TransformStream; - new ( - transformer?: Transformer, - writableStrategy?: QueuingStrategy, - readableStrategy?: QueuingStrategy, - ): TransformStream; - }; - - interface TransformStreamDefaultController { - readonly desiredSize: number | null; - enqueue(chunk?: O): void; - error(reason?: any): void; - terminate(): void; - } - - var TransformStreamDefaultController: { - prototype: TransformStreamDefaultController; - new (): TransformStreamDefaultController; - }; - - interface StreamPipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - /** - * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - * - * Errors and closures of the source and destination streams propagate as follows: - * - * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. - * - * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. - * - * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. - * - * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. - * - * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. - */ - preventClose?: boolean; - signal?: AbortSignal; - } - - /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ - interface CountQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - readonly size: QueuingStrategySize; - } - - var CountQueuingStrategy: { - prototype: CountQueuingStrategy; - new (init: QueuingStrategyInit): CountQueuingStrategy; - }; - - interface QueuingStrategySize { - (chunk?: T): number; - } - - interface Transformer { - flush?: Bun.TransformerFlushCallback; - readableType?: undefined; - start?: Bun.TransformerStartCallback; - transform?: Bun.TransformerTransformCallback; - writableType?: undefined; - } - - interface Dict { - [key: string]: T | undefined; - } - - interface ReadOnlyDict { - readonly [key: string]: T | undefined; - } +interface Position { + lineText: string; + file: string; + namespace: string; + line: number; + column: number; + length: number; + offset: number; +} - interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; - } +declare class ResolveMessage { + readonly name: "ResolveMessage"; + readonly position: Position | null; + readonly code: string; + readonly message: string; + readonly referrer: string; + readonly specifier: string; + readonly importKind: + | "entry_point" + | "stmt" + | "require" + | "import" + | "dynamic" + | "require_resolve" + | "at" + | "at_conditional" + | "url" + | "internal"; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; + + toString(): string; +} - /** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ - interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; - } +declare class BuildMessage { + readonly name: "BuildMessage"; + readonly position: Position | null; + readonly message: string; + readonly level: "error" | "warning" | "info" | "debug" | "verbose"; +} - var DOMException: { - prototype: DOMException; - new (message?: string, name?: string): DOMException; - }; +// Declare "static" methods in Error +interface ErrorConstructor { + /** Create .stack property on a target object */ - function alert(message?: string): void; - function confirm(message?: string): boolean; - function prompt(message?: string, _default?: string): string | null; + captureStackTrace(targetObject: object, constructorOpt?: Function): void; - type _SubtleCrypto = import("crypto").webcrypto.SubtleCrypto; - var SubtleCrypto: { - prototype: _SubtleCrypto; - new (): _SubtleCrypto; - }; + /** + * Optional override for formatting stack traces + * + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; - type _CryptoKey = import("crypto").webcrypto.CryptoKey; - interface CryptoKey extends _CryptoKey {} - var CryptoKey: { - prototype: CryptoKey; - new (): CryptoKey; - }; + stackTraceLimit: number; +} - interface Position { - lineText: string; - file: string; - namespace: string; - line: number; - column: number; - length: number; - offset: number; - } +interface ArrayBufferConstructor { + new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; +} - class ResolveMessage { - readonly name: "ResolveMessage"; - readonly position: Position | null; - readonly code: string; - readonly message: string; - readonly referrer: string; - readonly specifier: string; - readonly importKind: - | "entry_point" - | "stmt" - | "require" - | "import" - | "dynamic" - | "require_resolve" - | "at" - | "at_conditional" - | "url" - | "internal"; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - - toString(): string; - } +interface ArrayBuffer { + /** + * Read-only. The length of the ArrayBuffer (in bytes). + */ + readonly byteLength: number; + /** + * Resize an ArrayBuffer in-place. + */ + resize(byteLength: number): ArrayBuffer; - class BuildMessage { - readonly name: "BuildMessage"; - readonly position: Position | null; - readonly message: string; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - } + /** + * Returns a section of an ArrayBuffer. + */ + slice(begin: number, end?: number): ArrayBuffer; + readonly [Symbol.toStringTag]: string; +} - // Declare "static" methods in Error - interface ErrorConstructor { - /** Create .stack property on a target object */ +interface SharedArrayBuffer { + /** + * Grow the SharedArrayBuffer in-place. + */ + grow(size: number): SharedArrayBuffer; +} - captureStackTrace(targetObject: object, constructorOpt?: Function): void; +interface ArrayConstructor { + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; - /** - * Optional override for formatting stack traces - * - * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces - */ - prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; + /** + * Create an array from an iterable or async iterable object. + * Values from the iterable are awaited. Results of the map function are also awaited. + * + * ```ts + * await Array.fromAsync([1]); // [1] + * await Array.fromAsync([Promise.resolve(1)]); // [1] + * await Array.fromAsync((async function*() { yield 1 })()); // [1] + * await Array.fromAsync([1], (n) => n + 1); // [2] + * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] + * ``` + * + * @param arrayLike - The iterable or async iterable to convert to an array. + * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. + * @param thisArg - The `this` to which `mapFn` is bound. + * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. + */ + fromAsync( + arrayLike: AsyncIterable | Iterable | ArrayLike, + mapFn?: (value: T, index: number) => U, + thisArg?: any, + ): Promise[]>; +} - stackTraceLimit: number; - } +interface ConsoleOptions { + stdout: import("stream").Writable; + stderr?: import("stream").Writable; + ignoreErrors?: boolean; + colorMode?: boolean | "auto"; + inspectOptions?: import("util").InspectOptions; + groupIndentation?: number; +} - interface ArrayBufferConstructor { - new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; - } +interface Console { + /** + * Asynchronously read lines from standard input (fd 0) + * + * ```ts + * for await (const line of console) { + * console.log(line); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterableIterator; - interface ArrayBuffer { - /** - * Read-only. The length of the ArrayBuffer (in bytes). - */ - readonly byteLength: number; - /** - * Resize an ArrayBuffer in-place. - */ - resize(byteLength: number): ArrayBuffer; + /** + * Write text or bytes to stdout + * + * Unlike {@link console.log}, this does no formatting and doesn't add a + * newline or spaces between arguments. You can pass it strings or bytes or + * any combination of the two. + * + * ```ts + * console.write("hello world!", "\n"); // "hello world\n" + * ``` + * + * @param data - The data to write + * @returns The number of bytes written + * + * This function is not available in the browser. + */ + write(...data: Array): number; - /** - * Returns a section of an ArrayBuffer. - */ - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; - } + /** + * Clear the console + */ + clear(): void; - interface SharedArrayBuffer { - /** - * Grow the SharedArrayBuffer in-place. - */ - grow(size: number): SharedArrayBuffer; - } + assert(condition?: boolean, ...data: any[]): void; - interface ArrayConstructor { - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; + /** + * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) + * @param label label counter + */ + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: any): void; + dirxml(...data: any[]): void; + /** + * Log to stderr in your terminal + * + * Appears in red + * + * @param data something to display + */ + error(...data: any[]): void; + /** Does nothing currently */ + group(...data: any[]): void; + /** Does nothing currently */ + groupCollapsed(...data: any[]): void; + /** Does nothing currently */ + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + /** + * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just + * logging the argument if it can't be parsed as tabular. + * + * ```js + * // These can't be parsed as tabular data + * console.table(Symbol()); + * // Symbol() + * + * console.table(undefined); + * // undefined + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ b โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * + * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); + * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” + * // โ”‚ โ”‚ a โ”‚ + * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค + * // โ”‚ 0 โ”‚ 1 โ”‚ + * // โ”‚ 1 โ”‚ 'Z' โ”‚ + * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ + * ``` + * @param properties Alternate properties for constructing the table. + */ + table(tabularData?: any, properties?: string[]): void; + /** + * Begin a timer to log with {@link console.timeEnd} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + time(label?: string): void; + /** + * End a timer to log with {@link console.time} + * + * @param label - The label to use for the timer + * + * ```ts + * console.time("how long????"); + * for (let i = 0; i < 999999; i++) { + * // do stuff + * let x = i * i; + * } + * console.timeEnd("how long????"); + * ``` + */ + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + timeStamp(label?: string): void; + trace(...data: any[]): void; + warn(...data: any[]): void; - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. Results of the map function are also awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * await Array.fromAsync([1], (n) => n + 1); // [2] - * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. - * @param thisArg - The `this` to which `mapFn` is bound. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; - } + /** + * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. + */ + // Console: { + // new (options: ConsoleOptions): Console; + // new ( + // stdout: import("stream").Writable, + // stderr?: import("stream").Writable, + // ignoreErrors?: boolean, + // ): Console; + // }; +} - interface ConsoleOptions { - stdout: import("stream").Writable; - stderr?: import("stream").Writable; - ignoreErrors?: boolean; - colorMode?: boolean | "auto"; - inspectOptions?: import("util").InspectOptions; - groupIndentation?: number; - } +declare var console: Console; - interface Console { - /** - * Asynchronously read lines from standard input (fd 0) - * - * ```ts - * for await (const line of console) { - * console.log(line); - * } - * ``` - */ - [Symbol.asyncIterator](): AsyncIterableIterator; +interface ImportMeta { + /** + * `file://` url string for the current module. + * + * @example + * ```ts + * console.log(import.meta.url); + * "file:///Users/me/projects/my-app/src/my-app.ts" + * ``` + */ + url: string; + /** + * Absolute path to the source file + */ + readonly path: string; + /** + * Absolute path to the directory containing the source file. + * + * Does not have a trailing slash + */ + readonly dir: string; + /** + * Filename of the source file + */ + readonly file: string; + /** + * The environment variables of the process + * + * ```ts + * import.meta.env === process.env + * ``` + */ + readonly env: NodeJS.ProcessEnv; - /** - * Write text or bytes to stdout - * - * Unlike {@link console.log}, this does no formatting and doesn't add a - * newline or spaces between arguments. You can pass it strings or bytes or - * any combination of the two. - * - * ```ts - * console.write("hello world!", "\n"); // "hello world\n" - * ``` - * - * @param data - The data to write - * @returns The number of bytes written - * - * This function is not available in the browser. - */ - write(...data: Array): number; + /** + * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead + * + * Resolve a module ID the same as if you imported it + * + * The `parent` argument is optional, and defaults to the current module's path. + */ + resolveSync(moduleId: string, parent?: string): string; - /** - * Clear the console - */ - clear(): void; + /** + * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all + * calls to `require` with `import.meta.require` when transpiling ES Modules + * for the runtime. + * + * Warning: **This API is not stable** and may change or be removed in the + * future. Use at your own risk. + */ + require: NodeJS.Require; - assert(condition?: boolean, ...data: any[]): void; + /** + * Did the current file start the process? + * + * @example + * ```ts + * if (import.meta.main) { + * console.log("I started the process!"); + * } + * ``` + * + * @example + * ```ts + * console.log( + * import.meta.main === (import.meta.path === Bun.main) + * ) + * ``` + */ + readonly main: boolean; - /** - * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) - * @param label label counter - */ - count(label?: string): void; - countReset(label?: string): void; - debug(...data: any[]): void; - dir(item?: any, options?: any): void; - dirxml(...data: any[]): void; - /** - * Log to stderr in your terminal - * - * Appears in red - * - * @param data something to display - */ - error(...data: any[]): void; - /** Does nothing currently */ - group(...data: any[]): void; - /** Does nothing currently */ - groupCollapsed(...data: any[]): void; - /** Does nothing currently */ - groupEnd(): void; - info(...data: any[]): void; - log(...data: any[]): void; - /** - * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just - * logging the argument if it can't be parsed as tabular. - * - * ```js - * // These can't be parsed as tabular data - * console.table(Symbol()); - * // Symbol() - * - * console.table(undefined); - * // undefined - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ b โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * ``` - * @param properties Alternate properties for constructing the table. - */ - table(tabularData?: any, properties?: string[]): void; - /** - * Begin a timer to log with {@link console.timeEnd} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - time(label?: string): void; - /** - * End a timer to log with {@link console.time} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - timeEnd(label?: string): void; - timeLog(label?: string, ...data: any[]): void; - timeStamp(label?: string): void; - trace(...data: any[]): void; - warn(...data: any[]): void; + /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ + dirname: string; - /** - * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. - */ - // Console: { - // new (options: ConsoleOptions): Console; - // new ( - // stdout: import("stream").Writable, - // stderr?: import("stream").Writable, - // ignoreErrors?: boolean, - // ): Console; - // }; - } + /** Alias of `import.meta.path`. Exists for Node.js compatibility */ + filename: string; +} - var console: Console; +/** + * NodeJS-style `require` function + * + * @param moduleId - The module ID to resolve + */ +declare var require: NodeJS.Require; - interface ImportMeta { - /** - * `file://` url string for the current module. - * - * @example - * ```ts - * console.log(import.meta.url); - * "file:///Users/me/projects/my-app/src/my-app.ts" - * ``` - */ - url: string; - /** - * Absolute path to the source file - */ - readonly path: string; - /** - * Absolute path to the directory containing the source file. - * - * Does not have a trailing slash - */ - readonly dir: string; - /** - * Filename of the source file - */ - readonly file: string; - /** - * The environment variables of the process - * - * ```ts - * import.meta.env === process.env - * ``` - */ - readonly env: NodeJS.ProcessEnv; +/** Same as module.exports */ +declare var exports: any; - /** - * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead - * - * Resolve a module ID the same as if you imported it - * - * The `parent` argument is optional, and defaults to the current module's path. - */ - resolveSync(moduleId: string, parent?: string): string; +interface NodeModule { + exports: any; +} - /** - * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all - * calls to `require` with `import.meta.require` when transpiling ES Modules - * for the runtime. - * - * Warning: **This API is not stable** and may change or be removed in the - * future. Use at your own risk. - */ - require: NodeJS.Require; +declare var module: NodeModule; - /** - * Did the current file start the process? - * - * @example - * ```ts - * if (import.meta.main) { - * console.log("I started the process!"); - * } - * ``` - * - * @example - * ```ts - * console.log( - * import.meta.main === (import.meta.path === Bun.main) - * ) - * ``` - */ - readonly main: boolean; +/** + * Creates a deep clone of an object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) + */ +declare function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; - /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ - dirname: string; +/** + * Post a message to the parent thread. + * + * Only useful in a worker thread; calling this from the main thread does nothing. + */ +declare function postMessage(message: any, transfer?: Bun.Transferable[]): void; - /** Alias of `import.meta.path`. Exists for Node.js compatibility */ - filename: string; - } +interface EventSourceInit { + withCredentials?: boolean; +} +interface PromiseConstructor { /** - * NodeJS-style `require` function + * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called + * separately. + * + * This is useful when you want to return a Promise and have code outside the Promise + * resolve or reject it. + * + * ## Example + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); * - * @param moduleId - The module ID to resolve + * setTimeout(() => { + * resolve("Hello world!"); + * }, 1000); + * + * await promise; // "Hello world!" + * ``` + * + * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). */ - var require: NodeJS.Require; + withResolvers(): { + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; +} + +interface Navigator { + readonly userAgent: string; + readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; + readonly hardwareConcurrency: number; +} - /** Same as module.exports */ - var exports: any; +declare var navigator: Navigator; - interface NodeModule { - exports: any; - } +interface BlobPropertyBag { + /** Set a default "type". Not yet implemented. */ + type?: string; + /** Not implemented in Bun yet. */ + // endings?: "transparent" | "native"; +} - var module: NodeModule; +interface WorkerOptions extends Bun.WorkerOptions {} +interface Blob { /** - * Creates a deep clone of an object. + * Read the data from the blob as a JSON object. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) + * This first decodes the data from UTF-8, then parses it as JSON. */ - function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; - + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + json(): Promise; /** - * Post a message to the parent thread. + * Read the data from the blob as a {@link FormData} object. + * + * This first decodes the data from UTF-8, then parses it as a + * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. * - * Only useful in a worker thread; calling this from the main thread does nothing. + * The `type` property of the blob is used to determine the format of the + * body. + * + * This is a non-standard addition to the `Blob` API, to make it conform more + * closely to the `BodyMixin` API. */ - function postMessage(message: any, transfer?: Bun.Transferable[]): void; - - interface EventSourceInit { - withCredentials?: boolean; - } + formData(): Promise; + arrayBuffer(): Promise; + /** + * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + */ + bytes(): Promise; +} - interface PromiseConstructor { - /** - * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called - * separately. - * - * This is useful when you want to return a Promise and have code outside the Promise - * resolve or reject it. - * - * ## Example - * ```ts - * const { promise, resolve, reject } = Promise.withResolvers(); - * - * setTimeout(() => { - * resolve("Hello world!"); - * }, 1000); - * - * await promise; // "Hello world!" - * ``` - * - * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). - */ - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; +declare var Blob: Bun.__internal.UseLibDomIfAvailable< + "Blob", + { + prototype: Blob; + new (blobParts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; } +>; - interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; - } +interface Uint8Array { + /** + * Convert the Uint8Array to a base64 encoded string + * @returns The base64 encoded string representation of the Uint8Array + */ + toBase64(options?: { alphabet?: "base64" | "base64url"; omitPadding?: boolean }): string; - var navigator: Navigator; + /** + * Set the contents of the Uint8Array from a base64 encoded string + * @param base64 The base64 encoded string to decode into the array + * @param offset Optional starting index to begin setting the decoded bytes (default: 0) + */ + setFromBase64(base64: string, offset?: number): void; +} - interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; - } +interface Uint8ArrayConstructor { + /** + * Create a new Uint8Array from a base64 encoded string + * @param base64 The base64 encoded string to convert to a Uint8Array + * @returns A new Uint8Array containing the decoded data + */ + fromBase64(base64: string): Uint8Array; +} - interface Blob { +interface BroadcastChannel {} +declare var BroadcastChannel: Bun.__internal.UseLibDomIfAvailable< + "BroadcastChannel", + import("node:worker_threads").BroadcastChannel +>; + +declare var URL: Bun.__internal.UseLibDomIfAvailable< + "URL", + { + prototype: URL; + new (url: string | URL, base?: string | URL): URL; /** - * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + * Check if a URL can be parsed. * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + * @param url - The URL to check. + * @param base - The base URL to use. */ - new (parts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; + canParse(url: string, base?: string): boolean; /** - * Read the data from the blob as a JSON object. + * Create a URL from an object. * - * This first decodes the data from UTF-8, then parses it as JSON. + * @param object - The object to create a URL from. */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - json(): Promise; - + createObjectURL(object: Blob): `blob:${string}`; /** - * Read the data from the blob as a {@link FormData} object. - * - * This first decodes the data from UTF-8, then parses it as a - * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. - * - * The `type` property of the blob is used to determine the format of the - * body. + * Revoke a URL. * - * This is a non-standard addition to the `Blob` API, to make it conform more - * closely to the `BodyMixin` API. - */ - formData(): Promise; - - arrayBuffer(): Promise; - - /** - * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` + * @param url - The URL to revoke. */ - bytes(): Promise; + revokeObjectURL(url: string): void; } - var Blob: typeof Blob; +>; - interface Uint8Array { - /** - * Convert the Uint8Array to a base64 encoded string - * @returns The base64 encoded string representation of the Uint8Array - */ - toBase64(options?: { alphabet?: "base64" | "base64url"; omitPadding?: boolean }): string; - - /** - * Set the contents of the Uint8Array from a base64 encoded string - * @param base64 The base64 encoded string to decode into the array - * @param offset Optional starting index to begin setting the decoded bytes (default: 0) - */ - setFromBase64(base64: string, offset?: number): void; +declare var AbortController: Bun.__internal.UseLibDomIfAvailable< + "AbortController", + { + prototype: AbortController; + new (): AbortController; } +>; - interface Uint8ArrayConstructor { - /** - * Create a new Uint8Array from a base64 encoded string - * @param base64 The base64 encoded string to convert to a Uint8Array - * @returns A new Uint8Array containing the decoded data - */ - fromBase64(base64: string): Uint8Array; +declare var AbortSignal: Bun.__internal.UseLibDomIfAvailable< + "AbortSignal", + { + prototype: AbortSignal; + new (): AbortSignal; } -} +>; + +interface DOMException {} +declare var DOMException: Bun.__internal.UseLibDomIfAvailable< + "DOMException", + { prototype: DOMException; new (): DOMException } +>; + +interface FormData {} +declare var FormData: Bun.__internal.UseLibDomIfAvailable<"FormData", { prototype: FormData; new (): FormData }>; + +interface EventSource {} +declare var EventSource: Bun.__internal.UseLibDomIfAvailable< + "EventSource", + { prototype: EventSource; new (): EventSource } +>; + +interface Performance extends Bun.__internal.LibPerformanceOrNodePerfHooksPerformance {} +declare var performance: Bun.__internal.UseLibDomIfAvailable<"performance", Performance>; + +interface PerformanceEntry {} +declare var PerformanceEntry: Bun.__internal.UseLibDomIfAvailable< + "PerformanceEntry", + { prototype: PerformanceEntry; new (): PerformanceEntry } +>; + +interface PerformanceMark {} +declare var PerformanceMark: Bun.__internal.UseLibDomIfAvailable< + "PerformanceMark", + { prototype: PerformanceMark; new (): PerformanceMark } +>; + +interface PerformanceMeasure {} +declare var PerformanceMeasure: Bun.__internal.UseLibDomIfAvailable< + "PerformanceMeasure", + { prototype: PerformanceMeasure; new (): PerformanceMeasure } +>; + +interface PerformanceObserver {} +declare var PerformanceObserver: Bun.__internal.UseLibDomIfAvailable< + "PerformanceObserver", + { prototype: PerformanceObserver; new (): PerformanceObserver } +>; + +interface PerformanceObserverEntryList {} +declare var PerformanceObserverEntryList: Bun.__internal.UseLibDomIfAvailable< + "PerformanceObserverEntryList", + { prototype: PerformanceObserverEntryList; new (): PerformanceObserverEntryList } +>; + +interface PerformanceResourceTiming {} +declare var PerformanceResourceTiming: Bun.__internal.UseLibDomIfAvailable< + "PerformanceResourceTiming", + { prototype: PerformanceResourceTiming; new (): PerformanceResourceTiming } +>; + +interface ReadableByteStreamController {} +declare var ReadableByteStreamController: Bun.__internal.UseLibDomIfAvailable< + "ReadableByteStreamController", + { prototype: ReadableByteStreamController; new (): ReadableByteStreamController } +>; + +interface ReadableStreamBYOBReader {} +declare var ReadableStreamBYOBReader: Bun.__internal.UseLibDomIfAvailable< + "ReadableStreamBYOBReader", + { prototype: ReadableStreamBYOBReader; new (): ReadableStreamBYOBReader } +>; + +interface ReadableStreamBYOBRequest {} +declare var ReadableStreamBYOBRequest: Bun.__internal.UseLibDomIfAvailable< + "ReadableStreamBYOBRequest", + { prototype: ReadableStreamBYOBRequest; new (): ReadableStreamBYOBRequest } +>; + +interface TextDecoderStream {} +declare var TextDecoderStream: Bun.__internal.UseLibDomIfAvailable< + "TextDecoderStream", + { prototype: TextDecoderStream; new (): TextDecoderStream } +>; + +interface TextEncoderStream {} +declare var TextEncoderStream: Bun.__internal.UseLibDomIfAvailable< + "TextEncoderStream", + { prototype: TextEncoderStream; new (): TextEncoderStream } +>; + +interface URLSearchParams {} +declare var URLSearchParams: Bun.__internal.UseLibDomIfAvailable< + "URLSearchParams", + { prototype: URLSearchParams; new (): URLSearchParams } +>; + +interface MessageChannel {} +declare var MessageChannel: Bun.__internal.UseLibDomIfAvailable< + "MessageChannel", + { prototype: MessageChannel; new (): MessageChannel } +>; + +interface MessagePort {} +declare var MessagePort: Bun.__internal.UseLibDomIfAvailable< + "MessagePort", + { + prototype: MessagePort; + new (): MessagePort; + } +>; diff --git a/packages/bun-types/index.d.ts b/packages/bun-types/index.d.ts index 7198791e3378fc..0060cdd11a22b9 100644 --- a/packages/bun-types/index.d.ts +++ b/packages/bun-types/index.d.ts @@ -1,24 +1,27 @@ // Project: https://github.com/oven-sh/bun -// Definitions by: Jarred Sumner +// Definitions by: Bun Contributors // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -/// -/// /// -// contributors: uncomment this to detect conflicts with lib.dom.d.ts -// /// - -/// /// +/// /// -/// +/// +/// +/// +/// /// -/// /// /// /// +/// /// +/// /// -/// -/// + +/// + +// @ts-ignore Must disable this so it doesn't conflict with the DOM onmessage type, but still +// allows us to declare our own globals that Node's types can "see" and not conflict with +declare var onmessage: never; diff --git a/packages/bun-types/new/bun.d.ts b/packages/bun-types/new/bun.d.ts deleted file mode 100644 index 4dbe674852b08c..00000000000000 --- a/packages/bun-types/new/bun.d.ts +++ /dev/null @@ -1,7178 +0,0 @@ -/** - * 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 extends T ? Omit : never; - type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; - type ArrayBufferView = NodeJS.TypedArray | DataView; - type BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; - type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData | Iterable; - type ReadableStreamController = ReadableStreamDefaultController; - type ReadableStreamDefaultReadResult = - | ReadableStreamDefaultReadValueResult - | ReadableStreamDefaultReadDoneResult; - type ReadableStreamReader = ReadableStreamDefaultReader; - type Transferable = ArrayBuffer | import("worker_threads").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) => 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; - - 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. - * - * @internal - */ - type UseLibDomIfAvailable = - // `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 - typeof globalThis extends { onabort: any } - ? 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 - } - - type Platform = - | "aix" - | "android" - | "darwin" - | "freebsd" - | "haiku" - | "linux" - | "openbsd" - | "sunos" - | "win32" - | "cygwin" - | "netbsd"; - type Architecture = "arm" | "arm64" | "ia32" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x" | "x64"; - - 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. - */ - type UnhandledRejectionListener = (reason: unknown, promise: Promise) => void; - - type MultipleResolveListener = (type: MultipleResolveType, promise: Promise, value: unknown) => void; - - type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; - - 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 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 extends Bun.EventInit { - detail?: T; - } - - /** A message received by a target object. */ - interface BunMessageEvent 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; - readonly source: Bun.MessageEventSource | null; - } - - type MessageEvent = Bun.__internal.UseLibDomIfAvailable<"MessageEvent", BunMessageEvent>; - - interface ReadableStreamDefaultReadManyResult { - done: boolean; - /** Number of bytes */ - size: number; - value: T[]; - } - - interface ResponseInit { - headers?: Bun.__internal.BunHeadersInit; - /** @default 200 */ - status?: number; - - /** @default "OK" */ - statusText?: string; - } - - interface EventSourceEventMap { - error: Event; - message: MessageEvent; - open: Event; - } - - interface EventInit { - bubbles?: boolean; - cancelable?: boolean; - composed?: boolean; - } - - interface EventListenerOptions { - /** Not directly used by Node.js. Added for API completeness. Default: `false`. */ - capture?: boolean; - } - - 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): void; - respondWith(response: Response | Promise): 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( - 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( - 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 { - (controller: TransformStreamDefaultController): void | PromiseLike; - } - - interface TransformerStartCallback { - (controller: TransformStreamDefaultController): any; - } - - interface TransformerTransformCallback { - (chunk: I, controller: TransformStreamDefaultController): void | PromiseLike; - } - - interface UnderlyingSinkAbortCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSinkCloseCallback { - (): void | PromiseLike; - } - - interface UnderlyingSinkStartCallback { - (controller: WritableStreamDefaultController): any; - } - - interface UnderlyingSinkWriteCallback { - (chunk: W, controller: WritableStreamDefaultController): void | PromiseLike; - } - - interface UnderlyingSourceCancelCallback { - (reason?: any): void | PromiseLike; - } - - interface UnderlyingSink { - abort?: UnderlyingSinkAbortCallback; - close?: UnderlyingSinkCloseCallback; - start?: UnderlyingSinkStartCallback; - type?: undefined | "default" | "bytes"; - write?: UnderlyingSinkWriteCallback; - } - - interface UnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull?: UnderlyingSourcePullCallback; - start?: UnderlyingSourceStartCallback; - /** - * Mode "bytes" is not currently supported. - */ - type?: undefined; - } - - interface DirectUnderlyingSource { - cancel?: UnderlyingSourceCancelCallback; - pull: (controller: ReadableStreamDirectController) => void | PromiseLike; - type: "direct"; - } - - interface UnderlyingSourcePullCallback { - (controller: ReadableStreamController): void | PromiseLike; - } - - interface UnderlyingSourceStartCallback { - (controller: ReadableStreamController): 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( - type: K, - listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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 | (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( - type: K, - listener: (this: Worker, ev: WorkerEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - 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: 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; - - type ShellFunction = (input: Uint8Array) => Uint8Array; - - type ShellExpression = - | { toString(): string } - | Array - | string - | { raw: string } - | Subprocess - | SpawnOptions.Readable - | SpawnOptions.Writable - | ReadableStream; - - class ShellPromise extends Promise { - 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 | 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - } - - interface Shell { - (strings: TemplateStringsArray, ...expressions: ShellExpression[]): ShellPromise; - - readonly Shell: ShellConstructor; - readonly ShellPromise: typeof ShellPromise; - readonly ShellError: typeof ShellError; - - /** - * 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): 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; - } - - 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; - - /** - * 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; - } - - 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; - } - - 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; - - /** - * 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; - - /** - * 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. - */ - 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - /** - * 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; - - 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, maxLength?: number): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - maxLength: number, - asUint8Array: false, - ): ArrayBuffer; - function concatArrayBuffers( - buffers: Array, - 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, - ): Promise | 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, - ): Promise | 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; - - /** - * 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, - multipartBoundaryExcludingDashes?: string | NodeJS.TypedArray | ArrayBufferView, - ): Promise; - - /** - * 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; - - /** - * 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; - - /** - * 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(stream: ReadableStream): Promise | T[]; - - /** - * Escape the following characters in a string: - * - * - `"` 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. - * - * @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 { - (promise: T | Promise): Promise | T; - status(promise: T | Promise): "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; - - /** - * - * **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; - }; - - ADDRCONFIG: number; - ALL: number; - 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 - * - * @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 { - /**.p - * 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; - - /** - * 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; - - /** - * Deletes the file. - */ - unlink(): Promise; - - /** - * Deletes the file. ( same as unlink ) - */ - delete(): Promise; - - /** - * Provides useful information about the file. - */ - stat(): Promise; - } - - /** - * Configuration options for SQL client connection and behavior - * @example - * const config: SQLOptions = { - * host: 'localhost', - * port: 5432, - * user: 'dbuser', - * password: 'secretpass', - * database: 'myapp', - * idleTimeout: 30000, - * max: 20, - * onconnect: (client) => { - * console.log('Connected to database'); - * } - * }; - */ - type 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); - /** Database password for authentication (alias for password) */ - pass?: string | (() => Promise); - /** 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 extends Promise { - /** Indicates if the query is currently executing */ - active: boolean; - /** Indicates if the query has been cancelled */ - cancelled: boolean; - /** Cancels the executing query */ - cancel(): SQLQuery; - /** Execute as a simple query, no parameters are allowed but can execute multiple commands separated by semicolons */ - simple(): SQLQuery; - /** Executes the query */ - execute(): SQLQuery; - /** Returns the raw query result */ - raw(): SQLQuery; - /** Returns only the values from the query result */ - values(): SQLQuery; - } - - /** - * Callback function type for transaction contexts - * @param sql Function to execute SQL queries within the transaction - */ - type SQLTransactionContextCallback = (sql: TransactionSQL) => Promise | Array; - /** - * Callback function type for savepoint contexts - * @param sql Function to execute SQL queries within the savepoint - */ - type SQLSavepointContextCallback = (sql: SavepointSQL) => Promise | Array; - - /** - * Main SQL client interface providing connection and transaction management - */ - interface SQL { - /** Creates a new SQL client instance - * @example - * const sql = new SQL("postgres://localhost:5432/mydb"); - * const sql = new SQL(new URL("postgres://localhost:5432/mydb")); - */ - new (connectionString: string | URL): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL("postgres://localhost:5432/mydb", { idleTimeout: 1000 }); - */ - new (connectionString: string | URL, options: SQLOptions): SQL; - /** Creates a new SQL client instance with options - * @example - * const sql = new SQL({ url: "postgres://localhost:5432/mydb", idleTimeout: 1000 }); - */ - new (options?: SQLOptions): SQL; - /** Executes a SQL query using template literals - * @example - * const [user] = await sql`select * from users where id = ${1}`; - */ - (strings: string | TemplateStringsArray, ...values: any[]): SQLQuery; - /** - * Helper function to allow easy use to insert values into a query - * @example - * const result = await sql`insert into users ${sql(users)} RETURNING *`; - */ - (obj: any): SQLQuery; - /** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.commitDistributed("my_distributed_transaction"); - */ - commitDistributed(name: string): Promise; - /** Rolls back a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL - * @example - * await sql.rollbackDistributed("my_distributed_transaction"); - */ - rollbackDistributed(name: string): Promise; - /** Waits for the database connection to be established - * @example - * await sql.connect(); - */ - connect(): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @example - * await sql.close({ timeout: 1 }); - */ - close(options?: { timeout?: number }): Promise; - /** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing. - * @alias close - * @example - * await sql.end({ timeout: 1 }); - */ - end(options?: { timeout?: number }): Promise; - /** Flushes any pending operations */ - flush(): void; - /** The reserve method pulls out a connection from the pool, and returns a client that wraps the single connection. - * This can be used for running queries on an isolated connection. - * Calling reserve in a reserved Sql will return a new reserved connection, not the same connection (behavior matches postgres package). - * @example - * const reserved = await sql.reserve(); - * await reserved`select * from users`; - * await reserved.release(); - * // with in a production scenario would be something more like - * const reserved = await sql.reserve(); - * try { - * // ... queries - * } finally { - * await reserved.release(); - * } - * //To make it simpler bun supportsSymbol.dispose and Symbol.asyncDispose - * { - * // always release after context (safer) - * using reserved = await sql.reserve() - * await reserved`select * from users` - * } - */ - reserve(): Promise; - /** Begins a new transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(fn: SQLTransactionContextCallback): Promise; - /** Begins a new transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @example - * const [user, account] = await sql.begin("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - begin(options: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction(async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a transaction with options - * Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function. - * BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue. - * @alias begin - * @example - * const [user, account] = await sql.transaction("read write", async sql => { - * const [user] = await sql` - * insert into users ( - * name - * ) values ( - * 'Murray' - * ) - * returning * - * ` - * const [account] = await sql` - * insert into accounts ( - * user_id - * ) values ( - * ${ user.user_id } - * ) - * returning * - * ` - * return [user, account] - * }) - */ - transaction(options: string, fn: SQLTransactionContextCallback): Promise; - /** Begins a distributed transaction - * Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks. - * In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks. - * beginDistributed will automatic rollback if any exception are not caught, and you can commit and rollback later if everything goes well. - * PostgreSQL natively supports distributed transactions using PREPARE TRANSACTION, while MySQL uses XA Transactions, and MSSQL also supports distributed/XA transactions. However, in MSSQL, distributed transactions are tied to the original session, the DTC coordinator, and the specific connection. - * These transactions are automatically committed or rolled back following the same rules as regular transactions, with no option for manual intervention from other sessions, in MSSQL distributed transactions are used to coordinate transactions using Linked Servers. - * @example - * await sql.beginDistributed("numbers", async sql => { - * await sql`create table if not exists numbers (a int)`; - * await sql`insert into numbers values(1)`; - * }); - * // later you can call - * await sql.commitDistributed("numbers"); - * // or await sql.rollbackDistributed("numbers"); - */ - beginDistributed(name: string, fn: SQLTransactionContextCallback): Promise; - /** Alternative method to begin a distributed transaction - * @alias beginDistributed - */ - distributed(name: string, fn: SQLTransactionContextCallback): Promise; - /**If you know what you're doing, you can use unsafe to pass any string you'd like. - * Please note that this can lead to SQL injection if you're not careful. - * You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements. - * @example - * const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`) - */ - unsafe(string: string, values?: any[]): SQLQuery; - /** - * Reads a file and uses the contents as a query. - * Optional parameters can be used if the file includes $1, $2, etc - * @example - * const result = await sql.file("query.sql", [1, 2, 3]); - */ - file(filename: string, values?: any[]): SQLQuery; - - /** Current client options */ - options: SQLOptions; - - [Symbol.asyncDispose](): Promise; - } - - /** - * Represents a reserved connection from the connection pool - * Extends SQL with additional release functionality - */ - interface ReservedSQL extends SQL { - /** Releases the client back to the connection pool */ - release(): void; - [Symbol.dispose](): void; - } - - /** - * Represents a client within a transaction context - * Extends SQL with savepoint functionality - */ - interface TransactionSQL extends SQL { - /** Creates a savepoint within the current transaction */ - savepoint(name: string, fn: SQLSavepointContextCallback): Promise; - savepoint(fn: SQLSavepointContextCallback): Promise; - } - /** - * Represents a savepoint within a transaction - */ - interface SavepointSQL extends SQL {} - - 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; - } - interface 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. - */ - 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. - */ - verify(token: string, options?: CSRFVerifyOptions): boolean; - } - - var sql: SQL; - var postgres: SQL; - var SQL: SQL; - - var CSRF: CSRF; - - /** - * This lets you use macros as regular imports - * @example - * ``` - * { - * "react-relay": { - * "graphql": "bun-macro-relay/bun-macro-relay.tsx" - * } - * } - * ``` - */ - type MacroMap = Record>; - - /** - * 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; - } - - 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; - 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; - - /** 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; - }; - 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 = () =>
Hello World
; - * 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; - /** - * 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-run" - | "entry-point-build"; - - interface Import { - path: string; - kind: ImportKind; - } - - /** - * @see [Bun.build API docs](https://bun.sh/docs/bundler#api) - */ - interface BuildConfig { - entrypoints: string[]; // list of file path - outdir?: string; // output directory - /** - * @default "browser" - */ - 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; - // origin?: string; // e.g. http://mydomain.com - loader?: { [k in string]: Loader }; - /** - * Specifies if and how to generate source maps. - * - * - `"none"` - No source maps are generated - * - `"linked"` - A separate `*.ext.map` file is generated alongside each - * `*.ext` file. A `//# sourceMappingURL` comment is added to the output - * file to link the two. Requires `outdir` to be set. - * - `"inline"` - an inline source map is appended to the output file. - * - `"external"` - Generate a separate source map file for each input file. - * No `//# sourceMappingURL` comment is added to the output file. - * - * `true` and `false` are aliases for `"inline"` and `"none"`, respectively. - * - * @default "none" - * - * @see {@link outdir} required for `"linked"` maps - * @see {@link publicPath} to customize the base url of linked source maps - */ - sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; - /** - * 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; - - /** - * Controls how environment variables are handled during bundling. - * - * Can be one of: - * - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO` - * references to string literals containing the actual environment variable values - * - `"disable"`: Disables environment variable injection entirely - * - A string ending in `*`: Inlines environment variables that match the given prefix. - * For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_" - * - * @example - * ```ts - * Bun.build({ - * env: "MY_PUBLIC_*", - * entrypoints: ["src/index.ts"], - * }) - * ``` - */ - env?: "inline" | "disable" | `${string}*`; - /** - * Whether to enable minification. - * - * Use `true`/`false` to enable/disable all minification options. Alternatively, - * you can pass an object for granular control over certain minifications. - * - * @default false - */ - 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; - - /** - * Drop function calls to matching property accesses. - */ - drop?: string[]; - - /** - * When set to `true`, the returned promise rejects with an AggregateError when a build failure happens. - * When set to `false`, the `success` property of the returned object will be `false` when a build failure happens. - * This defaults to `true`. - */ - throw?: boolean; - } - - 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 password. - * If empty, always returns false - */ - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - * - * If specified and the algorithm does not match the hash, this function - * throws an error. - */ - algorithm?: Password.AlgorithmLabel, - ): Promise; - /** - * Asynchronously hash a password using argon2 or bcrypt. The default is argon2. - * - * @returns A promise that resolves to the hashed password - * - * ## Example with argon2 - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world"); - * console.log(hash); // $argon2id$v=1... - * const verify = await password.verify("hello world", hash); - * ``` - * ## Example with bcrypt - * ```ts - * import {password} from "bun"; - * const hash = await password.hash("hello world", "bcrypt"); - * console.log(hash); // $2b$10$... - * const verify = await password.verify("hello world", hash); - * ``` - */ - hash( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA512'd before - */ - algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, - ): Promise; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.verify} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - verifySync( - password: Bun.StringOrBuffer, - hash: Bun.StringOrBuffer, - /** - * If not specified, the algorithm will be inferred from the hash. - */ - algorithm?: Password.AlgorithmLabel, - ): boolean; - - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password.hash} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig contributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world"); - * const verify = await password.verifySync("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hashSync("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verifySync("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - hashSync( - /** - * The password to hash - * - * If empty, this function throws an error. It is usually a programming - * mistake to hash an empty password. - */ - password: Bun.StringOrBuffer, - /** - * @default "argon2id" - * - * When using bcrypt, passwords exceeding 72 characters will be SHA256'd before - */ - algorithm?: Password.AlgorithmLabel | Password.Argon2Algorithm | Password.BCryptAlgorithm, - ): string; - }; - - interface BuildArtifact extends Blob { - path: string; - loader: Loader; - hash: string | null; - kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"; - sourcemap: BuildArtifact | null; - } - - interface BuildOutput { - outputs: BuildArtifact[]; - success: boolean; - logs: Array; - } - - /** - * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs. - * - * @param {Object} config - Build configuration options - * @returns {Promise} Promise that resolves to build output containing generated artifacts and build status - * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+) - * - * @example Basic usage - Bundle a single entrypoint and check results - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist' - }); - - if (!result.success) { - console.error('Build failed:', result.logs); - process.exit(1); - } - ``` - * - * @example Set up multiple entrypoints with code splitting enabled - ```ts - await Bun.build({ - entrypoints: ['./src/app.tsx', './src/admin.tsx'], - outdir: './dist', - splitting: true, - sourcemap: "external" - }); - ``` - * - * @example Configure minification and optimization settings - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - minify: { - whitespace: true, - identifiers: true, - syntax: true - }, - drop: ['console', 'debugger'] - }); - ``` - * - * @example Set up custom loaders and mark packages as external - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - loader: { - '.png': 'dataurl', - '.svg': 'file', - '.txt': 'text', - '.json': 'json' - }, - external: ['react', 'react-dom'] - }); - ``` - * - * @example Configure environment variable handling with different modes - ```ts - // Inline all environment variables - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'inline' - }); - - // Only include specific env vars - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - env: 'PUBLIC_*' - }); - ``` - * - * @example Set up custom naming patterns for all output types - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - naming: { - entry: '[dir]/[name]-[hash].[ext]', - chunk: 'chunks/[name]-[hash].[ext]', - asset: 'assets/[name]-[hash].[ext]' - } - }); - ``` - @example Work with build artifacts in different formats - ```ts - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'] - }); - - for (const artifact of result.outputs) { - const text = await artifact.text(); - const buffer = await artifact.arrayBuffer(); - const bytes = await artifact.bytes(); - - new Response(artifact); - await Bun.write(artifact.path, artifact); - } - ``` - @example Implement comprehensive error handling with position info - ```ts - try { - const result = await Bun.build({ - entrypoints: ['./src/index.tsx'], - }); - } catch (e) { - const error = e as AggregateError; - console.error('Build failed:'); - for (const msg of error.errors) { - if ('position' in msg) { - console.error( - `${msg.message} at ${msg.position?.file}:${msg.position?.line}:${msg.position?.column}` - ); - } else { - console.error(msg.message); - } - } - } - ``` - @example Set up Node.js target with specific configurations - ```ts - await Bun.build({ - entrypoints: ['./src/server.ts'], - outdir: './dist', - target: 'node', - format: 'cjs', - sourcemap: 'external', - minify: false, - packages: 'external' - }); - ``` - * - * @example Configure experimental CSS bundling with multiple themes - ```ts - await Bun.build({ - entrypoints: [ - './src/styles.css', - './src/themes/dark.css', - './src/themes/light.css' - ], - outdir: './dist/css', - }); - ``` - @example Define compile-time constants and version information - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - define: { - 'process.env.NODE_ENV': JSON.stringify('production'), - 'CONSTANTS.VERSION': JSON.stringify('1.0.0'), - 'CONSTANTS.BUILD_TIME': JSON.stringify(new Date().toISOString()) - } - }); - ``` - @example Create a custom plugin for handling special file types - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - plugins: [ - { - name: 'my-plugin', - setup(build) { - build.onLoad({ filter: /\.custom$/ }, async (args) => { - const content = await Bun.file(args.path).text(); - return { - contents: `export default ${JSON.stringify(content)}`, - loader: 'js' - }; - }); - } - } - ] - }); - ``` - @example Enable bytecode generation for faster startup - ```ts - await Bun.build({ - entrypoints: ['./src/server.ts'], - outdir: './dist', - target: 'bun', - format: 'cjs', - bytecode: true - }); - ``` - @example Add custom banner and footer to output files - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - banner: '"use client";\n// Built with Bun', - footer: '// Generated on ' + new Date().toISOString() - }); - ``` - @example Configure CDN public path for asset loading - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - publicPath: 'https://cdn.example.com/assets/', - loader: { - '.png': 'file', - '.svg': 'file' - } - }); - ``` - @example Set up package export conditions for different environments - ```ts - await Bun.build({ - entrypoints: ['./src/index.tsx'], - outdir: './dist', - conditions: ['production', 'browser', 'module'], - packages: 'external' - }); - ``` - */ - function build(config: BuildConfig): Promise; - /** - * A status that represents the outcome of a sent message. - * - * - if **0**, the message was **dropped**. - * - if **-1**, there is **backpressure** of messages. - * - if **>0**, it represents the **number of bytes sent**. - * - * @example - * ```js - * const status = ws.send("Hello!"); - * if (status === 0) { - * console.log("Message was dropped"); - * } else if (status === -1) { - * console.log("Backpressure was applied"); - * } else { - * console.log(`Success! Sent ${status} bytes`); - * } - * ``` - */ - type ServerWebSocketSendStatus = number; - - /** - * A state that represents if a WebSocket is connected. - * - * - `WebSocket.CONNECTING` is `0`, the connection is pending. - * - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible. - * - `WebSocket.CLOSING` is `2`, the connection is closing. - * - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened. - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState - */ - type WebSocketReadyState = 0 | 1 | 2 | 3; - - /** - * A fast WebSocket designed for servers. - * - * Features: - * - **Message compression** - Messages can be compressed - * - **Backpressure** - If the client is not ready to receive data, the server will tell you. - * - **Dropped messages** - If the client cannot receive data, the server will tell you. - * - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics - * - * This is slightly different than the browser {@link WebSocket} which Bun supports for clients. - * - * Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets). - * - * @example - * import { serve } from "bun"; - * - * serve({ - * websocket: { - * open(ws) { - * console.log("Connected", ws.remoteAddress); - * }, - * message(ws, data) { - * console.log("Received", data); - * ws.send(data); - * }, - * close(ws, code, reason) { - * console.log("Disconnected", code, reason); - * }, - * } - * }); - */ - interface ServerWebSocket { - /** - * Sends a message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - * ws.send(new Uint8Array([1, 2, 3, 4])); - */ - send(data: string | BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a text message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send("Hello!"); - * ws.send("Compress this.", true); - */ - sendText(data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to the client. - * - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.send(new TextEncoder().encode("Hello!")); - * ws.send(new Uint8Array([1, 2, 3, 4]), true); - */ - sendBinary(data: BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Closes the connection. - * - * Here is a list of close codes: - * - `1000` means "normal closure" **(default)** - * - `1009` means a message was too big and was rejected - * - `1011` means the server encountered an error - * - `1012` means the server is restarting - * - `1013` means the server is too busy or the client is rate-limited - * - `4000` through `4999` are reserved for applications (you can use it!) - * - * To close the connection abruptly, use `terminate()`. - * - * @param code The close code to send - * @param reason The close reason to send - */ - close(code?: number, reason?: string): void; - - /** - * Abruptly close the connection. - * - * To gracefully close the connection, use `close()`. - */ - terminate(): void; - - /** - * Sends a ping. - * - * @param data The data to send - */ - ping(data?: string | BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a pong. - * - * @param data The data to send - */ - pong(data?: string | BufferSource): ServerWebSocketSendStatus; - - /** - * Sends a message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4])); - */ - publish(topic: string, data: string | BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a text message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", "Hello!"); - * ws.publish("chat", "Compress this.", true); - */ - publishText(topic: string, data: string, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Sends a binary message to subscribers of the topic. - * - * @param topic The topic name. - * @param data The data to send. - * @param compress Should the data be compressed? If the client does not support compression, this is ignored. - * @example - * ws.publish("chat", new TextEncoder().encode("Hello!")); - * ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true); - */ - publishBinary(topic: string, data: BufferSource, compress?: boolean): ServerWebSocketSendStatus; - - /** - * Subscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - */ - subscribe(topic: string): void; - - /** - * Unsubscribes a client to the topic. - * - * @param topic The topic name. - * @example - * ws.unsubscribe("chat"); - */ - unsubscribe(topic: string): void; - - /** - * Is the client subscribed to a topic? - * - * @param topic The topic name. - * @example - * ws.subscribe("chat"); - * console.log(ws.isSubscribed("chat")); // true - */ - isSubscribed(topic: string): boolean; - - /** - * Batches `send()` and `publish()` operations, which makes it faster to send data. - * - * The `message`, `open`, and `drain` callbacks are automatically corked, so - * you only need to call this if you are sending messages outside of those - * callbacks or in async functions. - * - * @param callback The callback to run. - * @example - * ws.cork((ctx) => { - * ctx.send("These messages"); - * ctx.sendText("are sent"); - * ctx.sendBinary(new TextEncoder().encode("together!")); - * }); - */ - cork(callback: (ws: ServerWebSocket) => T): T; - - /** - * The IP address of the client. - * - * @example - * console.log(socket.remoteAddress); // "127.0.0.1" - */ - readonly remoteAddress: string; - - /** - * The ready state of the client. - * - * - if `0`, the client is connecting. - * - if `1`, the client is connected. - * - if `2`, the client is closing. - * - if `3`, the client is closed. - * - * @example - * console.log(socket.readyState); // 1 - */ - readonly readyState: WebSocketReadyState; - - /** - * Sets how binary data is returned in events. - * - * - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)** - * - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects. - * - if `uint8array`, binary data is returned as `Uint8Array` objects. - * - * @example - * let ws: WebSocket; - * ws.binaryType = "uint8array"; - * ws.addEventListener("message", ({ data }) => { - * console.log(data instanceof Uint8Array); // true - * }); - */ - binaryType?: "nodebuffer" | "arraybuffer" | "uint8array"; - - /** - * Custom data that you can assign to a client, can be read and written at any time. - * - * @example - * import { serve } from "bun"; - * - * serve({ - * fetch(request, server) { - * const data = { - * accessToken: request.headers.get("Authorization"), - * }; - * if (server.upgrade(request, { data })) { - * return; - * } - * return new Response(); - * }, - * websocket: { - * open(ws) { - * console.log(ws.data.accessToken); - * } - * } - * }); - */ - data: T; - - getBufferedAmount(): number; - } - - /** - * Compression options for WebSocket messages. - */ - type WebSocketCompressor = - | "disable" - | "shared" - | "dedicated" - | "3KB" - | "4KB" - | "8KB" - | "16KB" - | "32KB" - | "64KB" - | "128KB" - | "256KB"; - - /** - * Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve} - * - * @example - * ```ts - * import { websocket, serve } from "bun"; - * - * serve<{name: string}>({ - * port: 3000, - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log(`${ws.data.name}: ${message}`); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req, { - * data: { - * name: new URL(req.url).searchParams.get("name"), - * }, - * }); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * return; - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - */ - interface WebSocketHandler { - /** - * Called when the server receives an incoming message. - * - * If the message is not a `string`, its type is based on the value of `binaryType`. - * - if `nodebuffer`, then the message is a `Buffer`. - * - if `arraybuffer`, then the message is an `ArrayBuffer`. - * - if `uint8array`, then the message is a `Uint8Array`. - * - * @param ws The websocket that sent the message - * @param message The message received - */ - message(ws: ServerWebSocket, message: string | Buffer): void | Promise; - - /** - * Called when a connection is opened. - * - * @param ws The websocket that was opened - */ - open?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection was previously under backpressure, - * meaning it had too many queued messages, but is now ready to receive more data. - * - * @param ws The websocket that is ready for more data - */ - drain?(ws: ServerWebSocket): void | Promise; - - /** - * Called when a connection is closed. - * - * @param ws The websocket that was closed - * @param code The close code - * @param message The close message - */ - close?(ws: ServerWebSocket, code: number, reason: string): void | Promise; - - /** - * Called when a ping is sent. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - ping?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Called when a pong is received. - * - * @param ws The websocket that received the ping - * @param data The data sent with the ping - */ - pong?(ws: ServerWebSocket, data: Buffer): void | Promise; - - /** - * Sets the maximum size of messages in bytes. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - maxPayloadLength?: number; - - /** - * Sets the maximum number of bytes that can be buffered on a single connection. - * - * Default is 16 MB, or `1024 * 1024 * 16` in bytes. - */ - backpressureLimit?: number; - - /** - * Sets if the connection should be closed if `backpressureLimit` is reached. - * - * Default is `false`. - */ - closeOnBackpressureLimit?: boolean; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to no messages or pings. - * - * Default is 2 minutes, or `120` in seconds. - */ - idleTimeout?: number; - - /** - * Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed? - * - * Default is `false`. - */ - publishToSelf?: boolean; - - /** - * Should the server automatically send and respond to pings to clients? - * - * Default is `true`. - */ - sendPings?: boolean; - - /** - * Sets the compression level for messages, for clients that supports it. By default, compression is disabled. - * - * Default is `false`. - */ - perMessageDeflate?: - | boolean - | { - /** - * Sets the compression level. - */ - compress?: WebSocketCompressor | boolean; - /** - * Sets the decompression level. - */ - decompress?: WebSocketCompressor | boolean; - }; - } - - namespace RouterTypes { - type ExtractRouteParams = T extends `${string}:${infer Param}/${infer Rest}` - ? { [K in Param]: string } & ExtractRouteParams - : T extends `${string}:${infer Param}` - ? { [K in Param]: string } - : T extends `${string}*` - ? {} - : {}; - - type RouteHandler = (req: BunRequest, server: Server) => Response | Promise; - - type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; - - type RouteHandlerObject = { - [K in HTTPMethod]?: RouteHandler; - }; - - type RouteValue = Response | false | RouteHandler | RouteHandlerObject; - } - - interface BunRequest extends Request { - params: RouterTypes.ExtractRouteParams; - } - - interface GenericServeOptions { - /** - * What URI should be used to make {@link Request.url} absolute? - * - * By default, looks at {@link hostname}, {@link port}, and whether or not SSL is enabled to generate one - * - * @example - * ```js - * "http://my-app.com" - * ``` - * - * @example - * ```js - * "https://wongmjane.com/" - * ``` - * - * This should be the public, absolute URL โ€“ include the protocol and {@link hostname}. If the port isn't 80 or 443, then include the {@link port} too. - * - * @example - * "http://localhost:3000" - */ - // baseURI?: string; - - /** - * What is the maximum size of a request body? (in bytes) - * @default 1024 * 1024 * 128 // 128MB - */ - maxRequestBodySize?: number; - - /** - * Render contextual errors? This enables bun's error page - * @default process.env.NODE_ENV !== 'production' - */ - development?: - | boolean - | { - /** - * Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use) - * - * @default true if process.env.NODE_ENV !== 'production' - * - */ - hmr?: boolean; - }; - - error?: (this: Server, error: ErrorLike) => Response | Promise | void | Promise; - - /** - * Uniquely identify a server instance with an ID - * - * ### When bun is started with the `--hot` flag - * - * This string will be used to hot reload the server without interrupting - * pending requests or websockets. If not provided, a value will be - * generated. To disable hot reloading, set this value to `null`. - * - * ### When bun is not started with the `--hot` flag - * - * This string will currently do nothing. But in the future it could be useful for logs or metrics. - */ - id?: string | null; - } - - interface ServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * Whether the `SO_REUSEPORT` flag should be set. - * - * This allows multiple processes to bind to the same port, which is useful for load balancing. - * - * @default false - */ - reusePort?: boolean; - - /** - * Whether the `IPV6_V6ONLY` flag should be set. - * @default false - */ - ipv6Only?: boolean; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix?: never; - - /** - * Sets the the number of seconds to wait before timing out a connection - * due to inactivity. - * - * Default is `10` seconds. - */ - idleTimeout?: number; - - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | Promise; - } - - interface UnixServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - /** - * Handle HTTP requests - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | Promise; - } - - interface WebSocketServeOptions extends GenericServeOptions { - /** - * What port should the server listen on? - * @default process.env.PORT || "3000" - */ - port?: string | number; - - /** - * What hostname should the server listen on? - * - * @default - * ```js - * "0.0.0.0" // listen on all interfaces - * ``` - * @example - * ```js - * "127.0.0.1" // Only listen locally - * ``` - * @example - * ```js - * "remix.run" // Only listen on remix.run - * ```` - * - * note: hostname should not include a {@link port} - */ - hostname?: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch( - this: Server, - request: Request, - server: Server, - ): Response | undefined | void | Promise; - } - - interface UnixWebSocketServeOptions extends GenericServeOptions { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - - /** - * Enable websockets with {@link Bun.serve} - * - * For simpler type safety, see {@link Bun.websocket} - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade} - * - * Pass `data` in @{link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property - */ - websocket: WebSocketHandler; - - /** - * Handle HTTP requests or upgrade them to a {@link ServerWebSocket} - * - * Respond to {@link Request} objects with a {@link Response} object. - */ - fetch(this: Server, request: Request, server: Server): Response | undefined | Promise; - } - - interface TLSWebSocketServeOptions - extends WebSocketServeOptions, - TLSOptionsAsDeprecated { - unix?: never; - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSWebSocketServeOptions - extends UnixWebSocketServeOptions, - TLSOptionsAsDeprecated { - /** - * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) - */ - unix: string; - tls?: TLSOptions | TLSOptions[]; - } - - interface ErrorLike extends Error { - code?: string; - errno?: number; - syscall?: string; - } - - interface TLSOptions { - /** - * Passphrase for the TLS key - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: string | Buffer | BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: string | Buffer | BunFile | Array | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: string | Buffer | BunFile | Array | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - // Note for contributors: TLSOptionsAsDeprecated should be considered immutable - // and new TLS option keys should only be supported on the `.tls` property (which comes - // from the TLSOptions interface above). - /** - * This exists because Bun.serve() extends the TLSOptions object, but - * they're now considered deprecated. You should be passing the - * options on `.tls` instead. - * - * @example - * ```ts - * //// OLD //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * passphrase: "secret", - * }); - * - * //// NEW //// - * Bun.serve({ - * fetch: () => new Response("Hello World"), - * tls: { - * passphrase: "secret", - * }, - * }); - * ``` - */ - interface TLSOptionsAsDeprecated { - /** - * Passphrase for the TLS key - * - * @deprecated Use `.tls.passphrase` instead - */ - passphrase?: string; - - /** - * File path to a .pem file custom Diffie Helman parameters - * - * @deprecated Use `.tls.dhParamsFile` instead - */ - dhParamsFile?: string; - - /** - * Explicitly set a server name - * - * @deprecated Use `.tls.serverName` instead - */ - serverName?: string; - - /** - * This sets `OPENSSL_RELEASE_BUFFERS` to 1. - * It reduces overall performance but saves some memory. - * @default false - * - * @deprecated Use `.tls.lowMemoryMode` instead - */ - lowMemoryMode?: boolean; - - /** - * If set to `false`, any certificate is accepted. - * Default is `$NODE_TLS_REJECT_UNAUTHORIZED` environment variable, or `true` if it is not set. - * - * @deprecated Use `.tls.rejectUnauthorized` instead - */ - rejectUnauthorized?: boolean; - - /** - * If set to `true`, the server will request a client certificate. - * - * Default is `false`. - * - * @deprecated Use `.tls.requestCert` instead - */ - requestCert?: boolean; - - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - * - * @deprecated Use `.tls.ca` instead - */ - ca?: string | Buffer | BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - * - * @deprecated Use `.tls.cert` instead - */ - cert?: string | Buffer | BunFile | Array | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - * - * @deprecated Use `.tls.key` instead - */ - key?: string | Buffer | BunFile | Array | undefined; - /** - * Optionally affect the OpenSSL protocol behavior, which is not - * usually necessary. This should be used carefully if at all! Value is - * a numeric bitmask of the SSL_OP_* options from OpenSSL Options - * - * @deprecated `Use .tls.secureOptions` instead - */ - secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options - } - - interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface UnixTLSServeOptions extends UnixServeOptions, TLSOptionsAsDeprecated { - tls?: TLSOptions | TLSOptions[]; - } - - interface SocketAddress { - /** - * The IP address of the client. - */ - address: string; - /** - * The port of the client. - */ - port: number; - /** - * The IP family ("IPv4" or "IPv6"). - */ - family: "IPv4" | "IPv6"; - } - - /** - * HTTP & HTTPS Server - * - * To start the server, see {@link serve} - * - * For performance, Bun pre-allocates most of the data for 2048 concurrent requests. - * That means starting a new server allocates about 500 KB of memory. Try to - * avoid starting and stopping the server often (unless it's a new instance of bun). - * - * Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you @alexhultman. - */ - interface Server extends Disposable { - /** - * Stop listening to prevent new connections from being accepted. - * - * By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. - * - * @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections. - * @default false - */ - stop(closeActiveConnections?: boolean): Promise; - - /** - * Update the `fetch` and `error` handlers without restarting the server. - * - * This is useful if you want to change the behavior of your server without - * restarting it or for hot reloading. - * - * @example - * - * ```js - * // create the server - * const server = Bun.serve({ - * fetch(request) { - * return new Response("Hello World v1") - * } - * }); - * - * // Update the server to return a different response - * server.reload({ - * fetch(request) { - * return new Response("Hello World v2") - * } - * }); - * ``` - * - * Passing other options such as `port` or `hostname` won't do anything. - */ - reload }>( - options: ServeFunctionOptions & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for awhile though. - */ - static?: R; - }, - ): Server; - - /** - * Mock the fetch handler for a running server. - * - * This feature is not fully implemented yet. It doesn't normalize URLs - * consistently in all cases and it doesn't yet call the `error` handler - * consistently. This needs to be fixed - */ - fetch(request: Request | string): Response | Promise; - - /** - * Upgrade a {@link Request} to a {@link ServerWebSocket} - * - * @param request The {@link Request} to upgrade - * @param options Pass headers or attach data to the {@link ServerWebSocket} - * - * @returns `true` if the upgrade was successful and `false` if it failed - * - * @example - * ```js - * import { serve } from "bun"; - * serve({ - * websocket: { - * open: (ws) => { - * console.log("Client connected"); - * }, - * message: (ws, message) => { - * console.log("Client sent message", message); - * }, - * close: (ws) => { - * console.log("Client disconnected"); - * }, - * }, - * fetch(req, server) { - * const url = new URL(req.url); - * if (url.pathname === "/chat") { - * const upgraded = server.upgrade(req); - * if (!upgraded) { - * return new Response("Upgrade failed", { status: 400 }); - * } - * } - * return new Response("Hello World"); - * }, - * }); - * ``` - * What you pass to `data` is available on the {@link ServerWebSocket.data} property - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - upgrade( - request: Request, - options?: { - /** - * Send any additional headers while upgrading, like cookies - */ - headers?: Bun.__internal.BunHeadersInit; - /** - * This value is passed to the {@link ServerWebSocket.data} property - */ - data?: T; - }, - ): boolean; - - /** - * Send a message to all connected {@link ServerWebSocket} subscribed to a topic - * - * @param topic The topic to publish to - * @param data The data to send - * @param compress Should the data be compressed? Ignored if the client does not support compression. - * - * @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent. - * - * @example - * - * ```js - * server.publish("chat", "Hello World"); - * ``` - * - * @example - * ```js - * server.publish("chat", new Uint8Array([1, 2, 3, 4])); - * ``` - * - * @example - * ```js - * server.publish("chat", new ArrayBuffer(4), true); - * ``` - * - * @example - * ```js - * server.publish("chat", new DataView(new ArrayBuffer(4))); - * ``` - */ - publish( - topic: string, - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - compress?: boolean, - ): ServerWebSocketSendStatus; - - /** - * A count of connections subscribed to a given topic - * - * This operation will loop through each topic internally to get the count. - * - * @param topic the websocket topic to check how many subscribers are connected to - * @returns the number of subscribers - */ - subscriberCount(topic: string): number; - - /** - * Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * return new Response(server.requestIP(request)); - * } - * } - * ``` - */ - requestIP(request: Request): SocketAddress | null; - - /** - * Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout. - * - * @example - * ```js - * export default { - * async fetch(request, server) { - * server.timeout(request, 60); - * await Bun.sleep(30000); - * return new Response("30 seconds have passed"); - * } - * } - * ``` - */ - timeout(request: Request, seconds: number): void; - /** - * Undo a call to {@link Server.unref} - * - * If the Server has already been stopped, this does nothing. - * - * If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle. - */ - ref(): void; - - /** - * Don't keep the process alive if this server is the only thing left. - * Active connections may continue to keep the process alive. - * - * By default, the server is ref'd. - * - * To prevent new connections from being accepted, use {@link Server.stop} - */ - unref(): void; - - /** - * How many requests are in-flight right now? - */ - readonly pendingRequests: number; - - /** - * How many {@link ServerWebSocket}s are in-flight right now? - */ - readonly pendingWebSockets: number; - - readonly url: URL; - - readonly port: number; - /** - * The hostname the server is listening on. Does not include the port - * @example - * ```js - * "localhost" - * ``` - */ - readonly hostname: string; - /** - * Is the server running in development mode? - * - * In development mode, `Bun.serve()` returns rendered error messages with - * stack traces instead of a generic 500 error. This makes debugging easier, - * but development mode shouldn't be used in production or you will risk - * leaking sensitive information. - */ - readonly development: boolean; - - /** - * An identifier of the server instance - * - * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets. - * - * When bun is not started with the `--hot` flag, this ID is currently unused. - */ - readonly id: string; - } - - type Serve = - | ServeOptions - | TLSServeOptions - | UnixServeOptions - | UnixTLSServeOptions - | WebSocketServeOptions - | TLSWebSocketServeOptions - | UnixWebSocketServeOptions - | UnixTLSWebSocketServeOptions; - - type ServeFunctionOptions }> = - | (DistributedOmit, WebSocketServeOptions>, "fetch"> & { - routes: R; - fetch?: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | (DistributedOmit, WebSocketServeOptions>, "routes"> & { - routes?: never; - fetch: (this: Server, request: Request, server: Server) => Response | Promise; - }) - | (Omit, "fetch"> & { - routes: R; - fetch?: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise | void | undefined; - }) - | (Omit, "fetch"> & { - routes?: never; - fetch: ( - this: Server, - request: Request, - server: Server, - ) => Response | Promise | void | undefined; - }); - - /** - * Bun.serve provides a high-performance HTTP server with built-in routing support. - * It enables both function-based and object-based route handlers with type-safe - * parameters and method-specific handling. - * - * @param options - Server configuration options - * @param options.routes - Route definitions mapping paths to handlers - * - * @example Basic Usage - * ```ts - * Bun.serve({ - * port: 3000, - * fetch(req) { - * return new Response("Hello World"); - * } - * }); - * ``` - * - * @example Route-based Handlers - * ```ts - * Bun.serve({ - * routes: { - * // Static responses - * "/": new Response("Home page"), - * - * // Function handlers with type-safe parameters - * "/users/:id": (req) => { - * // req.params.id is typed as string - * return new Response(`User ${req.params.id}`); - * }, - * - * // Method-specific handlers - * "/api/posts": { - * GET: () => new Response("Get posts"), - * POST: async (req) => { - * const body = await req.json(); - * return new Response("Created post"); - * }, - * DELETE: (req) => new Response("Deleted post") - * }, - * - * // Wildcard routes - * "/static/*": (req) => { - * // Handle any path under /static/ - * return new Response("Static file"); - * }, - * - * // Disable route (fall through to fetch handler) - * "/api/legacy": false - * }, - * - * // Fallback handler for unmatched routes - * fetch(req) { - * return new Response("Not Found", { status: 404 }); - * } - * }); - * ``` - * - * @example Path Parameters - * ```ts - * Bun.serve({ - * routes: { - * // Single parameter - * "/users/:id": (req: BunRequest<"/users/:id">) => { - * return new Response(`User ID: ${req.params.id}`); - * }, - * - * // Multiple parameters - * "/posts/:postId/comments/:commentId": ( - * req: BunRequest<"/posts/:postId/comments/:commentId"> - * ) => { - * return new Response(JSON.stringify(req.params)); - * // Output: {"postId": "123", "commentId": "456"} - * } - * } - * }); - * ``` - * - * @example Route Precedence - * ```ts - * // Routes are matched in the following order: - * // 1. Exact static routes ("/about") - * // 2. Parameter routes ("/users/:id") - * // 3. Wildcard routes ("/api/*") - * - * Bun.serve({ - * routes: { - * "/api/users": () => new Response("Users list"), - * "/api/users/:id": (req) => new Response(`User ${req.params.id}`), - * "/api/*": () => new Response("API catchall"), - * "/*": () => new Response("Root catchall") - * } - * }); - * ``` - * - * @example Error Handling - * ```ts - * Bun.serve({ - * routes: { - * "/error": () => { - * throw new Error("Something went wrong"); - * } - * }, - * error(error) { - * // Custom error handler - * console.error(error); - * return new Response(`Error: ${error.message}`, { - * status: 500 - * }); - * } - * }); - * ``` - * - * @example Server Lifecycle - * ```ts - * const server = Bun.serve({ - * // Server config... - * }); - * - * // Update routes at runtime - * server.reload({ - * routes: { - * "/": () => new Response("Updated route") - * } - * }); - * - * // Stop the server - * server.stop(); - * ``` - * - * @example Development Mode - * ```ts - * Bun.serve({ - * development: true, // Enable hot reloading - * routes: { - * // Routes will auto-reload on changes - * } - * }); - * ``` - * - * @example Type-Safe Request Handling - * ```ts - * type Post = { - * id: string; - * title: string; - * }; - * - * Bun.serve({ - * routes: { - * "/api/posts/:id": async ( - * req: BunRequest<"/api/posts/:id"> - * ) => { - * if (req.method === "POST") { - * const body: Post = await req.json(); - * return Response.json(body); - * } - * return new Response("Method not allowed", { - * status: 405 - * }); - * } - * } - * }); - * ``` - */ - function serve }>( - options: ServeFunctionOptions & { - /** - * @deprecated Use `routes` instead in new code. This will continue to work for a while though. - */ - static?: R; - }, - ): Server; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - `type` is auto-set based on the file extension when possible - * - * @example - * ```js - * const file = Bun.file("./hello.json"); - * console.log(file.type); // "application/json" - * console.log(await file.json()); // { hello: "world" } - * ``` - * - * @example - * ```js - * await Bun.write( - * Bun.file("./hello.txt"), - * "Hello, world!" - * ); - * ``` - * @param path The path to the file (lazily loaded) if the path starts with `s3://` it will behave like {@link S3File} - */ - function file(path: string | URL, options?: BlobPropertyBag): BunFile; - - /** - * A list of files embedded into the standalone executable. Lexigraphically sorted by name. - * - * If the process is not a standalone executable, this returns an empty array. - */ - const embeddedFiles: ReadonlyArray; - - /** - * `Blob` that leverages the fastest system calls available to operate on files. - * - * This Blob is lazy. It won't do any work until you read from it. Errors propagate as promise rejections. - * - * `Blob.size` will not be valid until the contents of the file are read at least once. - * `Blob.type` will have a default set based on the file extension - * - * @example - * ```js - * const file = Bun.file(new TextEncoder.encode("./hello.json")); - * console.log(file.type); // "application/json" - * ``` - * - * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} - */ - - function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; - - /** - * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. - * - * This Blob is lazy. That means it won't do any work until you read from it. - * - * - `size` will not be valid until the contents of the file are read at least once. - * - * @example - * ```js - * const file = Bun.file(fd); - * ``` - * - * @param fileDescriptor The file descriptor of the file - */ - - function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; - - /** - * Allocate a new [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) without zeroing the bytes. - * - * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. - */ - function allocUnsafe(size: number): Uint8Array; - - interface BunInspectOptions { - colors?: boolean; - depth?: number; - sorted?: boolean; - compact?: boolean; - } - - /** - * Pretty-print an object the same as {@link console.log} to a `string` - * - * Supports JSX - * - * @param args - */ - function inspect(arg: any, options?: BunInspectOptions): string; - namespace inspect { - /** - * That can be used to declare custom inspect functions. - */ - const custom: typeof import("util").inspect.custom; - - /** - * Pretty-print an object or array as a table - * - * Like {@link console.table}, except it returns a string - */ - function table(tabularData: object | unknown[], properties?: string[], options?: { colors?: boolean }): string; - function table(tabularData: object | unknown[], options?: { colors?: boolean }): string; - } - - interface MMapOptions { - /** - * Sets MAP_SYNC flag on Linux. Ignored on macOS due to lack of support. - */ - sync?: boolean; - /** - * Allow other processes to see results instantly? - * This enables MAP_SHARED. If false, it enables MAP_PRIVATE. - * @default true - */ - shared?: boolean; - } - /** - * Open a file as a live-updating `Uint8Array` without copying memory - * - Writing to the array writes to the file. - * - Reading from the array reads from the file. - * - * This uses the [`mmap()`](https://man7.org/linux/man-pages/man2/mmap.2.html) syscall under the hood. - * - * --- - * - * This API inherently has some rough edges: - * - It does not support empty files. It will throw a `SystemError` with `EINVAL` - * - Usage on shared/networked filesystems is discouraged. It will be very slow. - * - If you delete or truncate the file, that will crash bun. This is called a segmentation fault. - * - * --- - * - * To close the file, set the array to `null` and it will be garbage collected eventually. - */ - function mmap(path: PathLike, opts?: MMapOptions): Uint8Array; - - /** Write to stdout */ - const stdout: BunFile; - /** Write to stderr */ - const stderr: BunFile; - /** - * Read from stdin - * - * This is read-only - */ - const stdin: BunFile; - - type StringLike = string | { toString(): string }; - - type ColorInput = - | { r: number; g: number; b: number; a?: number } - | [number, number, number] - | [number, number, number, number] - | Uint8Array - | Uint8ClampedArray - | Float32Array - | Float64Array - | string - | number - | { toString(): string }; - - function color( - input: ColorInput, - outputFormat?: /** - * True color ANSI color string, for use in terminals - * @example \x1b[38;2;100;200;200m - */ - | "ansi" - | "ansi-16" - | "ansi-16m" - /** - * 256 color ANSI color string, for use in terminals which don't support true color - * - * Tries to match closest 24-bit color to 256 color palette - */ - | "ansi-256" - /** - * Picks the format that produces the shortest output - */ - | "css" - /** - * Lowercase hex color string without alpha - * @example #ff9800 - */ - | "hex" - /** - * Uppercase hex color string without alpha - * @example #FF9800 - */ - | "HEX" - /** - * @example hsl(35.764706, 1, 0.5) - */ - | "hsl" - /** - * @example lab(0.72732764, 33.938198, -25.311619) - */ - | "lab" - /** - * @example 16750592 - */ - | "number" - /** - * RGB color string without alpha - * @example rgb(255, 152, 0) - */ - | "rgb" - /** - * RGB color string with alpha - * @example rgba(255, 152, 0, 1) - */ - | "rgba", - ): string | null; - - function color( - input: ColorInput, - /** - * An array of numbers representing the RGB color - * @example [100, 200, 200] - */ - outputFormat: "[rgb]", - ): [number, number, number] | null; - function color( - input: ColorInput, - /** - * An array of numbers representing the RGBA color - * @example [100, 200, 200, 255] - */ - outputFormat: "[rgba]", - ): [number, number, number, number] | null; - function color( - input: ColorInput, - /** - * An object representing the RGB color - * @example { r: 100, g: 200, b: 200 } - */ - outputFormat: "{rgb}", - ): { r: number; g: number; b: number } | null; - function color( - input: ColorInput, - /** - * An object representing the RGBA color - * @example { r: 100, g: 200, b: 200, a: 0.5 } - */ - outputFormat: "{rgba}", - ): { r: number; g: number; b: number; a: number } | null; - function color(input: ColorInput, outputFormat: "number"): number | null; - - interface Semver { - /** - * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. - */ - satisfies(version: StringLike, range: StringLike): boolean; - - /** - * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. - * Throws an error if either version is invalid. - */ - order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; - } - var semver: Semver; - - interface Unsafe { - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint8Array` or `ArrayBuffer`. - * - * **Only use this for ASCII strings**. If there are non-ascii characters, your application may crash and/or very confusing bugs will happen such as `"foo" !== "foo"`. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; - - /** - * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` - * - * **The input must be a UTF-16 encoded string**. This API does no validation whatsoever. - * - * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. - */ - - arrayBufferToString(buffer: Uint16Array): string; - - /** - * Force the garbage collector to run extremely often, - * especially inside `bun:test`. - * - * - `0`: default, disable - * - `1`: asynchronously call the garbage collector more often - * - `2`: synchronously call the garbage collector more often. - * - * This is a global setting. It's useful for debugging seemingly random crashes. - * - * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. - * - * @param level - * @returns The previous level - */ - gcAggressionLevel(level?: 0 | 1 | 2): 0 | 1 | 2; - - /** - * Dump the mimalloc heap to the console - */ - mimallocDump(): void; - } - const unsafe: Unsafe; - - type DigestEncoding = "utf8" | "ucs2" | "utf16le" | "latin1" | "ascii" | "base64" | "base64url" | "hex"; - - /** - * Are ANSI colors enabled for stdin and stdout? - * - * Used for {@link console.log} - */ - const enableANSIColors: boolean; - - /** - * What script launched Bun? - * - * Absolute file path - * - * @example "/never-gonna-give-you-up.js" - */ - const main: string; - - /** - * Manually trigger the garbage collector - * - * This does two things: - * 1. It tells JavaScriptCore to run the garbage collector - * 2. It tells [mimalloc](https://github.com/microsoft/mimalloc) to clean up fragmented memory. Mimalloc manages the heap not used in JavaScriptCore. - * - * @param force Synchronously run the garbage collector - */ - function gc(force: boolean): void; - - /** - * JavaScriptCore engine's internal heap snapshot - * - * I don't know how to make this something Chrome or Safari can read. - * - * If you have any ideas, please file an issue https://github.com/oven-sh/bun - */ - interface HeapSnapshot { - /** 2 */ - version: number; - - /** "Inspector" */ - type: string; - - nodes: number[]; - - nodeClassNames: string[]; - edges: number[]; - edgeTypes: string[]; - edgeNames: string[]; - } - - /** - * Returns the number of nanoseconds since the process was started. - * - * This function uses a high-resolution monotonic system timer to provide precise time measurements. - * In JavaScript, numbers are represented as double-precision floating-point values (IEEE 754), - * which can safely represent integers up to 2^53 - 1 (Number.MAX_SAFE_INTEGER). - * - * Due to this limitation, while the internal counter may continue beyond this point, - * the precision of the returned value will degrade after 14.8 weeks of uptime (when the nanosecond - * count exceeds Number.MAX_SAFE_INTEGER). Beyond this point, the function will continue to count but - * with reduced precision, which might affect time calculations and comparisons in long-running applications. - * - * @returns {number} The number of nanoseconds since the process was started, with precise values up to - * Number.MAX_SAFE_INTEGER. - */ - function nanoseconds(): number; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a heap snapshot in JavaScriptCore's format that can be viewed with `bun --inspect` or Safari's Web Inspector - */ - function generateHeapSnapshot(format?: "jsc"): HeapSnapshot; - - /** - * Show precise statistics about memory usage of your application - * - * Generate a V8 Heap Snapshot that can be used with Chrome DevTools & Visual Studio Code - * - * This is a JSON string that can be saved to a file. - * ```ts - * const snapshot = Bun.generateHeapSnapshot("v8"); - * await Bun.write("heap.heapsnapshot", snapshot); - * ``` - */ - function generateHeapSnapshot(format: "v8"): string; - - /** - * The next time JavaScriptCore is idle, clear unused memory and attempt to reduce the heap size. - */ - function shrink(): void; - - /** - * Open a file in your local editor. Auto-detects via `$VISUAL` || `$EDITOR` - * - * @param path path to open - */ - function openInEditor(path: string, options?: EditorOptions): void; - - var fetch: typeof globalThis.fetch; - - interface EditorOptions { - editor?: "vscode" | "subl"; - line?: number; - column?: number; - } - - /** - * This class only exists in types - */ - abstract class CryptoHashInterface { - /** - * Update the hash with data - * - * @param data - */ - update(data: Bun.BlobOrStringOrBuffer): T; - - /** - * Finalize the hash - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash(input: Bun.BlobOrStringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash(input: Bun.BlobOrStringOrBuffer, encoding: DigestEncoding): string; - } - - type SupportedCryptoAlgorithms = - | "blake2b256" - | "blake2b512" - | "md4" - | "md5" - | "ripemd160" - | "sha1" - | "sha224" - | "sha256" - | "sha384" - | "sha512" - | "sha512-224" - | "sha512-256" - | "sha3-224" - | "sha3-256" - | "sha3-384" - | "sha3-512" - | "shake128" - | "shake256"; - - /** - * Hardware-accelerated cryptographic hash functions - * - * Used for `crypto.createHash()` - */ - class CryptoHasher { - /** - * The algorithm chosen to hash the data - */ - readonly algorithm: SupportedCryptoAlgorithms; - - /** - * The length of the output hash in bytes - */ - readonly byteLength: number; - - /** - * Create a new hasher - * - * @param algorithm The algorithm to use. See {@link algorithms} for a list of supported algorithms - * @param hmacKey Optional key for HMAC. Must be a string or `TypedArray`. If not provided, the hasher will be a non-HMAC hasher. - */ - constructor(algorithm: SupportedCryptoAlgorithms, hmacKey?: string | NodeJS.TypedArray); - - /** - * Update the hash with data - * - * @param input - */ - update(input: Bun.BlobOrStringOrBuffer, inputEncoding?: import("crypto").Encoding): CryptoHasher; - - /** - * Perform a deep copy of the hasher - */ - copy(): CryptoHasher; - - /** - * Finalize the hash. Resets the CryptoHasher so it can be reused. - * - * @param encoding `DigestEncoding` to return the hash in. If none is provided, it will return a `Uint8Array`. - */ - digest(encoding: DigestEncoding): string; - - /** - * Finalize the hash - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - digest(): Buffer; - digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time - */ - static hash(algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer): Buffer; - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - hashInto: NodeJS.TypedArray, - ): NodeJS.TypedArray; - - /** - * Run the hash over the given data - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. - * - * @param encoding `DigestEncoding` to return the hash in - */ - static hash( - algorithm: SupportedCryptoAlgorithms, - input: Bun.BlobOrStringOrBuffer, - encoding: DigestEncoding, - ): string; - - /** - * List of supported hash algorithms - * - * These are hardware accelerated with BoringSSL - */ - static readonly algorithms: SupportedCryptoAlgorithms[]; - } - - /** - * Resolve a `Promise` after milliseconds. This is like - * {@link setTimeout} except it returns a `Promise`. - * - * @param ms milliseconds to delay resolving the promise. This is a minimum - * number. It may take longer. If a {@link Date} is passed, it will sleep until the - * {@link Date} is reached. - * - * @example - * ## Sleep for 1 second - * ```ts - * import { sleep } from "bun"; - * - * await sleep(1000); - * ``` - * ## Sleep for 10 milliseconds - * ```ts - * await Bun.sleep(10); - * ``` - * ## Sleep until `Date` - * - * ```ts - * const target = new Date(); - * target.setSeconds(target.getSeconds() + 1); - * await Bun.sleep(target); - * ``` - * Internally, `Bun.sleep` is the equivalent of - * ```ts - * await new Promise((resolve) => setTimeout(resolve, ms)); - * ``` - * As always, you can use `Bun.sleep` or the imported `sleep` function interchangeably. - */ - function sleep(ms: number | Date): Promise; - - /** - * Sleep the thread for a given number of milliseconds - * - * This is a blocking function. - * - * Internally, it calls [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) - */ - function sleepSync(ms: number): void; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param hashInto optional `Uint8Array` to write the hash to. 32 bytes minimum. - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, hashInto?: NodeJS.TypedArray): NodeJS.TypedArray; - - /** - * Hash `input` using [SHA-2 512/256](https://en.wikipedia.org/wiki/SHA-2#Comparison_of_SHA_functions) - * - * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` will be faster - * @param encoding `DigestEncoding` to return the hash in - * - * This hashing function balances speed with cryptographic strength. This does not encrypt or decrypt data. - * - * The implementation uses [BoringSSL](https://boringssl.googlesource.com/boringssl) (used in Chromium & Go) - * - * The equivalent `openssl` command is: - * - * ```bash - * # You will need OpenSSL 3 or later - * openssl sha512-256 /path/to/file - * ``` - */ - function sha(input: Bun.StringOrBuffer, encoding: DigestEncoding): string; - - /** - * This is not the default because it's not cryptographically secure and it's slower than {@link SHA512} - * - * Consider using the ugly-named {@link SHA512_256} instead - */ - class SHA1 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 20; - } - class MD5 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class MD4 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 16; - } - class SHA224 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 28; - } - class SHA512 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 64; - } - class SHA384 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 48; - } - class SHA256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - /** - * See also {@link sha} - */ - class SHA512_256 extends CryptoHashInterface { - constructor(); - - /** - * The number of bytes the hash will produce - */ - static readonly byteLength: 32; - } - - /** Compression options for `Bun.deflateSync` and `Bun.gzipSync` */ - interface ZlibCompressionOptions { - /** - * The compression level to use. Must be between `-1` and `9`. - * - A value of `-1` uses the default compression level (Currently `6`) - * - A value of `0` gives no compression - * - A value of `1` gives least compression, fastest speed - * - A value of `9` gives best compression, slowest speed - */ - level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * How much memory should be allocated for the internal compression state. - * - * A value of `1` uses minimum memory but is slow and reduces compression ratio. - * - * A value of `9` uses maximum memory for optimal speed. The default is `8`. - */ - memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; - /** - * The base 2 logarithm of the window size (the size of the history buffer). - * - * Larger values of this parameter result in better compression at the expense of memory usage. - * - * The following value ranges are supported: - * - `9..15`: The output will have a zlib header and footer (Deflate) - * - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate) - * - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip) - * - * The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC. - */ - windowBits?: - | -9 - | -10 - | -11 - | -12 - | -13 - | -14 - | -15 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 25 - | 26 - | 27 - | 28 - | 29 - | 30 - | 31; - /** - * Tunes the compression algorithm. - * - * - `Z_DEFAULT_STRATEGY`: For normal data **(Default)** - * - `Z_FILTERED`: For data produced by a filter or predictor - * - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match) - * - `Z_RLE`: Limit match distances to one (run-length encoding) - * - `Z_FIXED` prevents the use of dynamic Huffman codes - * - * `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data. - * - * `Z_FILTERED` forces more Huffman coding and less string matching, it is - * somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`. - * Filtered data consists mostly of small values with a somewhat random distribution. - */ - strategy?: number; - - library?: "zlib"; - } - - interface LibdeflateCompressionOptions { - level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; - library?: "libdeflate"; - } - - /** - * Compresses a chunk of data with `zlib` DEFLATE algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function deflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Compresses a chunk of data with `zlib` GZIP algorithm. - * @param data The buffer of data to compress - * @param options Compression options to use - * @returns The output buffer with the compressed data - */ - function gzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` INFLATE algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function inflateSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - /** - * Decompresses a chunk of data with `zlib` GUNZIP algorithm. - * @param data The buffer of data to decompress - * @returns The output buffer with the decompressed data - */ - function gunzipSync( - data: Uint8Array | string | ArrayBuffer, - options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; - - type Target = - /** - * For generating bundles that are intended to be run by the Bun runtime. In many cases, - * it isn't necessary to bundle server-side code; you can directly execute the source code - * without modification. However, bundling your server code can reduce startup times and - * improve running performance. - * - * All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which - * indicates to the Bun runtime that there's no need to re-transpile the file before execution. - */ - | "bun" - /** - * The plugin will be applied to Node.js builds - */ - | "node" - /** - * The plugin will be applied to browser builds - */ - | "browser"; - - /** https://bun.sh/docs/bundler/loaders */ - type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "file" | "napi" | "wasm" | "text" | "css" | "html"; - - interface PluginConstraints { - /** - * Only apply the plugin when the import specifier matches this regular expression - * - * @example - * ```ts - * // Only apply the plugin when the import specifier matches the regex - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /node_modules\/underscore/ }, (args) => { - * return { contents: "throw new Error('Please use lodash instead of underscore.')" }; - * }); - * } - * }) - * ``` - */ - filter: RegExp; - - /** - * Only apply the plugin when the import specifier has a namespace matching - * this string - * - * Namespaces are prefixes in import specifiers. For example, `"bun:ffi"` - * has the namespace `"bun"`. - * - * The default namespace is `"file"` and it can be omitted from import - * specifiers. - */ - namespace?: string; - } - - interface OnLoadResultSourceCode { - /** - * The source code of the module - */ - contents: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer; - /** - * The loader to use for this file - * - * "css" will be added in a future version of Bun. - */ - loader?: Loader; - } - - interface OnLoadResultObject { - /** - * The object to use as the module - * @example - * ```ts - * // In your loader - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * - * // In your script - * import {foo} from "hello:world"; - * console.log(foo); // "bar" - * ``` - */ - exports: Record; - /** - * The loader to use for this file - */ - loader: "object"; - } - - interface OnLoadArgs { - /** - * The resolved import specifier of the module being loaded - * @example - * ```ts - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * console.log(args.path); // "hello:world" - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * ``` - */ - path: string; - /** - * The namespace of the module being loaded - */ - namespace: string; - /** - * The default loader for this file extension - */ - loader: Loader; - /** - * Defer the execution of this callback until all other modules have been parsed. - * - * @returns Promise which will be resolved when all modules have been parsed - */ - defer: () => Promise; - } - - type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject | undefined | void; - type OnLoadCallback = (args: OnLoadArgs) => OnLoadResult | Promise; - type OnStartCallback = () => void | Promise; - - interface OnResolveArgs { - /** - * The import specifier of the module being loaded - */ - path: string; - /** - * The module that imported the module being resolved - */ - importer: string; - /** - * The namespace of the importer. - */ - namespace: string; - /** - * The directory to perform file-based resolutions in. - */ - resolveDir: string; - /** - * The kind of import this resolve is for. - */ - kind: ImportKind; - // resolveDir: string; - // pluginData: any; - } - - interface OnResolveResult { - /** - * The destination of the import - */ - path: string; - /** - * The namespace of the destination - * It will be concatenated with `path` to form the final import specifier - * @example - * ```ts - * "foo" // "foo:bar" - * ``` - */ - namespace?: string; - external?: boolean; - } - - type OnResolveCallback = ( - args: OnResolveArgs, - ) => OnResolveResult | Promise | undefined | null; - - type FFIFunctionCallable = Function & { - // Making a nominally typed function so that the user must get it from dlopen - readonly __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol; - }; - - interface PluginBuilder { - /** - * Register a callback which will be invoked when bundling starts. When - * using hot module reloading, this is called at the start of each - * incremental rebuild. - * - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onStart(() => { - * console.log("bundle just started!!") - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onStart(callback: OnStartCallback): this; - onBeforeParse( - constraints: PluginConstraints, - callback: { - napiModule: unknown; - symbol: string; - external?: unknown | undefined; - }, - ): this; - /** - * Register a callback to load imports with a specific import specifier - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /^hello:world$/ }, (args) => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onLoad(constraints: PluginConstraints, callback: OnLoadCallback): this; - /** - * Register a callback to resolve imports matching a filter and/or namespace - * @param constraints The constraints to apply the plugin to - * @param callback The callback to handle the import - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.onResolve({ filter: /^wat$/ }, (args) => { - * return { path: "/tmp/woah.js" }; - * }); - * }, - * }); - * ``` - * - * @returns `this` for method chaining - */ - onResolve(constraints: PluginConstraints, callback: OnResolveCallback): this; - /** - * The config object passed to `Bun.build` as is. Can be mutated. - */ - config: BuildConfig & { plugins: BunPlugin[] }; - - /** - * Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules - * - * @param specifier The module specifier to register the callback for - * @param callback The function to run when the module is imported or required - * - * ### Example - * @example - * ```ts - * Bun.plugin({ - * setup(builder) { - * builder.module("hello:world", () => { - * return { exports: { foo: "bar" }, loader: "object" }; - * }); - * }, - * }); - * - * // sometime later - * const { foo } = await import("hello:world"); - * console.log(foo); // "bar" - * - * // or - * const { foo } = require("hello:world"); - * console.log(foo); // "bar" - * ``` - * - * @returns `this` for method chaining - */ - module(specifier: string, callback: () => OnLoadResult | Promise): this; - } - - interface BunPlugin { - /** - * Human-readable name of the plugin - * - * In a future version of Bun, this will be used in error messages. - */ - name: string; - - /** - * The target JavaScript environment the plugin should be applied to. - * - `bun`: The default environment when using `bun run` or `bun` to load a script - * - `browser`: The plugin will be applied to browser builds - * - `node`: The plugin will be applied to Node.js builds - * - * If unspecified, it is assumed that the plugin is compatible with all targets. - * - * This field is not read by {@link Bun.plugin} - */ - target?: Target; - /** - * A function that will be called when the plugin is loaded. - * - * This function may be called in the same tick that it is registered, or it - * may be called later. It could potentially be called multiple times for - * different targets. - */ - setup( - /** - * A builder object that can be used to register plugin hooks - * @example - * ```ts - * builder.onLoad({ filter: /\.yaml$/ }, ({ path }) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")), - * })); - * ``` - */ - build: PluginBuilder, - ): void | Promise; - } - - /** - * Extend Bun's module resolution and loading behavior - * - * Plugins are applied in the order they are defined. - * - * Today, there are two kinds of hooks: - * - `onLoad` lets you return source code or an object that will become the module's exports - * - `onResolve` lets you redirect a module specifier to another module specifier. It does not chain. - * - * Plugin hooks must define a `filter` RegExp and will only be matched if the - * import specifier contains a "." or a ":". - * - * ES Module resolution semantics mean that plugins may be initialized _after_ - * a module is resolved. You might need to load plugins at the very beginning - * of the application and then use a dynamic import to load the rest of the - * application. A future version of Bun may also support specifying plugins - * via `bunfig.toml`. - * - * @example - * A YAML loader plugin - * - * ```js - * Bun.plugin({ - * setup(builder) { - * builder.onLoad({ filter: /\.yaml$/ }, ({path}) => ({ - * loader: "object", - * exports: require("js-yaml").load(fs.readFileSync(path, "utf8")) - * })); - * }); - * - * // You can use require() - * const {foo} = require("./file.yaml"); - * - * // Or import - * await import("./file.yaml"); - * - * ``` - */ - interface BunRegisterPlugin { - (options: T): ReturnType; - - /** - * Deactivate all plugins - * - * This prevents registered plugins from being applied to future builds. - */ - clearAll(): void; - } - - const plugin: BunRegisterPlugin; - - /** - * Is the current global scope the main thread? - */ - const isMainThread: boolean; - - /** - * Used when importing an HTML file at runtime. - * - * @example - * - * ```ts - * import app from "./index.html"; - * ``` - * - * Bun.build support for this isn't imlpemented yet. - */ - interface HTMLBundle { - index: string; - } - - interface Socket extends Disposable { - /** - * Write `data` to the socket - * - * @param data The data to write to the socket - * @param byteOffset The offset in the buffer to start writing from (defaults to 0) - * @param byteLength The number of bytes to write (defaults to the length of the buffer) - * - * When passed a string, `byteOffset` and `byteLength` refer to the UTF-8 offset, not the string character offset. - * - * This is unbuffered as of Bun v0.2.2. That means individual write() calls - * will be slow. In the future, Bun will buffer writes and flush them at the - * end of the tick, when the event loop is idle, or sooner if the buffer is full. - */ - write(data: string | BufferSource, byteOffset?: number, byteLength?: number): number; - - /** - * The data context for the socket. - */ - data: Data; - - /** - * Like {@link Socket.write} except it includes a TCP FIN packet - * - * Use it to send your last message and close the connection. - */ - end(data?: string | BufferSource, byteOffset?: number, byteLength?: number): number; - - /** - * Close the socket immediately - */ - end(): void; - - /** - * Keep Bun's process alive at least until this socket is closed - * - * After the socket has closed, the socket is unref'd, the process may exit, - * and this becomes a no-op - */ - ref(): void; - - /** - * Set a timeout until the socket automatically closes. - * - * To reset the timeout, call this function again. - * - * When a timeout happens, the `timeout` callback is called and the socket is closed. - */ - timeout(seconds: number): void; - - /** - * Forcefully close the socket. The other end may not receive all data, and - * the socket will be closed immediately. - * - * This passes `SO_LINGER` with `l_onoff` set to `1` and `l_linger` set to - * `0` and then calls `close(2)`. - */ - terminate(): void; - - /** - * Shutdown writes to a socket - * - * This makes the socket a half-closed socket. It can still receive data. - * - * This calls [shutdown(2)](https://man7.org/linux/man-pages/man2/shutdown.2.html) internally - */ - shutdown(halfClose?: boolean): void; - - readonly readyState: "open" | "closing" | "closed"; - - /** - * Allow Bun's process to exit even if this socket is still open - * - * After the socket has closed, this function does nothing. - */ - unref(): void; - - /** - * Flush any buffered data to the socket - */ - flush(): void; - - /** - * Reset the socket's callbacks. This is useful with `bun --hot` to facilitate hot reloading. - * - * This will apply to all sockets from the same {@link Listener}. it is per socket only for {@link Bun.connect}. - */ - reload(handler: SocketHandler): void; - - /** - * Get the server that created this socket - * - * This will return undefined if the socket was created by {@link Bun.connect} or if the listener has already closed. - */ - readonly listener?: SocketListener; - - /** - * Remote IP address connected to the socket - */ - readonly remoteAddress: string; - - /** - * local port connected to the socket - */ - readonly localPort: number; - - /** - * This property is `true` if the peer certificate was signed by one of the CAs - * specified when creating the `Socket` instance, otherwise `false`. - */ - readonly authorized: boolean; - - /** - * String containing the selected ALPN protocol. - * Before a handshake has completed, this value is always null. - * When a handshake is completed but not ALPN protocol was selected, socket.alpnProtocol equals false. - */ - readonly alpnProtocol: string | false | null; - - /** - * Disables TLS renegotiation for this `Socket` instance. Once called, attempts - * to renegotiate will trigger an `error` handler on the `Socket`. - * - * There is no support for renegotiation as a server. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.) - */ - disableRenegotiation(): void; - - /** - * Keying material is used for validations to prevent different kind of attacks in - * network protocols, for example in the specifications of IEEE 802.1X. - * - * Example - * - * ```js - * const keyingMaterial = socket.exportKeyingMaterial( - * 128, - * 'client finished'); - * - * /* - * Example return value of keyingMaterial: - * - * - * ``` - * - * @param length number of bytes to retrieve from keying material - * @param label an application specific label, typically this will be a value from the [IANA Exporter Label - * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). - * @param context Optionally provide a context. - * @return requested bytes of the keying material - */ - exportKeyingMaterial(length: number, label: string, context: Buffer): Buffer; - - /** - * Returns the reason why the peer's certificate was not been verified. This - * property is set only when `socket.authorized === false`. - */ - getAuthorizationError(): Error | null; - - /** - * Returns an object representing the local certificate. The returned object has - * some properties corresponding to the fields of the certificate. - * - * If there is no local certificate, an empty object will be returned. If the - * socket has been destroyed, `null` will be returned. - */ - getCertificate(): import("tls").PeerCertificate | object | null; - getX509Certificate(): import("node:crypto").X509Certificate | undefined; - - /** - * Returns an object containing information on the negotiated cipher suite. - * - * For example, a TLSv1.2 protocol with AES256-SHA cipher: - * - * ```json - * { - * "name": "AES256-SHA", - * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", - * "version": "SSLv3" - * } - * ``` - * - */ - getCipher(): import("tls").CipherNameAndProtocol; - - /** - * Returns an object representing the type, name, and size of parameter of - * an ephemeral key exchange in `perfect forward secrecy` on a client - * connection. It returns an empty object when the key exchange is not - * ephemeral. As this is only supported on a client socket; `null` is returned - * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The`name` property is available only when type is `'ECDH'`. - * - * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. - */ - getEphemeralKeyInfo(): import("tls").EphemeralKeyInfo | object | null; - - /** - * Returns an object representing the peer's certificate. If the peer does not - * provide a certificate, an empty object will be returned. If the socket has been - * destroyed, `null` will be returned. - * - * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's - * certificate. - * @return A certificate object. - */ - getPeerCertificate(): import("tls").PeerCertificate; - getPeerX509Certificate(): import("node:crypto").X509Certificate; - - /** - * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. - * @since v12.11.0 - * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. - */ - getSharedSigalgs(): string[]; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. - */ - getTLSFinishedMessage(): Buffer | undefined; - - /** - * As the `Finished` messages are message digests of the complete handshake - * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - * be used for external authentication procedures when the authentication - * provided by SSL/TLS is not desired or is not enough. - * - * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so - * far. - */ - getTLSPeerFinishedMessage(): Buffer | undefined; - - /** - * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. - * - * It may be useful for debugging. - * - * See `Session Resumption` for more information. - */ - getTLSTicket(): Buffer | undefined; - - /** - * Returns a string containing the negotiated SSL/TLS protocol version of the - * current connection. The value `'unknown'` will be returned for connected - * sockets that have not completed the handshaking process. The value `null` will - * be returned for server sockets or disconnected client sockets. - * - * Protocol versions are: - * - * * `'SSLv3'` - * * `'TLSv1'` - * * `'TLSv1.1'` - * * `'TLSv1.2'` - * * `'TLSv1.3'` - * - */ - getTLSVersion(): string; - - /** - * See `Session Resumption` for more information. - * @return `true` if the session was reused, `false` otherwise. - */ - isSessionReused(): boolean; - - /** - * The `socket.setMaxSendFragment()` method sets the maximum TLS fragment size. - * Returns `true` if setting the limit succeeded; `false` otherwise. - * - * Smaller fragment sizes decrease the buffering latency on the client: larger - * fragments are buffered by the TLS layer until the entire fragment is received - * and its integrity is verified; large fragments can span multiple roundtrips - * and their processing can be delayed due to packet loss or reordering. However, - * smaller fragments add extra TLS framing bytes and CPU overhead, which may - * decrease overall server throughput. - * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. - */ - setMaxSendFragment(size: number): boolean; - - /** - * Enable/disable the use of Nagle's algorithm. - * Only available for already connected sockets, will return false otherwise - * @param noDelay Default: `true` - * @returns true if is able to setNoDelay and false if it fails. - */ - setNoDelay(noDelay?: boolean): boolean; - - /** - * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. - * Set `initialDelay` (in milliseconds) to set the delay between the last data packet received and the first keepalive probe. - * Only available for already connected sockets, will return false otherwise. - * - * Enabling the keep-alive functionality will set the following socket options: - * SO_KEEPALIVE=1 - * TCP_KEEPIDLE=initialDelay - * TCP_KEEPCNT=10 - * TCP_KEEPINTVL=1 - * @param enable Default: `false` - * @param initialDelay Default: `0` - * @returns true if is able to setNoDelay and false if it fails. - */ - setKeepAlive(enable?: boolean, initialDelay?: number): boolean; - - /** - * The number of bytes written to the socket. - */ - readonly bytesWritten: number; - } - - interface SocketListener extends Disposable { - stop(closeActiveConnections?: boolean): void; - ref(): void; - unref(): void; - reload(options: Pick, "socket">): void; - data: Data; - } - interface TCPSocketListener extends SocketListener { - readonly port: number; - readonly hostname: string; - } - interface UnixSocketListener extends SocketListener { - readonly unix: string; - } - - interface TCPSocket extends Socket {} - interface TLSSocket extends Socket {} - - interface BinaryTypeList { - arraybuffer: ArrayBuffer; - buffer: Buffer; - uint8array: Uint8Array; - // TODO: DataView - // dataview: DataView; - } - type BinaryType = keyof BinaryTypeList; - - interface SocketHandler { - /** - * Is called when the socket connects, or in case of TLS if no handshake is provided - * this will be called only after handshake - * @param socket - */ - open?(socket: Socket): void | Promise; - close?(socket: Socket, error?: Error): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - data?(socket: Socket, data: BinaryTypeList[DataBinaryType]): void | Promise; - drain?(socket: Socket): void | Promise; - - /** - * When handshake is completed, this functions is called. - * @param socket - * @param success Indicates if the server authorized despite the authorizationError. - * @param authorizationError Certificate Authorization Error or null. - */ - handshake?(socket: Socket, success: boolean, authorizationError: Error | null): void; - - /** - * When the socket has been shutdown from the other end, this function is - * called. This is a TCP FIN packet. - */ - end?(socket: Socket): void | Promise; - - /** - * When the socket fails to be created, this function is called. - * - * The promise returned by `Bun.connect` rejects **after** this function is - * called. - * - * When `connectError` is specified, the rejected promise will not be - * added to the promise rejection queue (so it won't be reported as an - * unhandled promise rejection, since connectError handles it). - * - * When `connectError` is not specified, the rejected promise will be added - * to the promise rejection queue. - */ - connectError?(socket: Socket, error: Error): void | Promise; - - /** - * Called when a message times out. - */ - timeout?(socket: Socket): void | Promise; - /** - * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. - * - * @default "buffer" - * - * @remarks - * This lets you select the desired binary type for the `data` callback. - * It's a small performance optimization to let you avoid creating extra - * ArrayBufferView objects when possible. - * - * Bun originally defaulted to `Uint8Array` but when dealing with network - * data, it's more useful to be able to directly read from the bytes which - * `Buffer` allows. - */ - binaryType?: BinaryType; - } - - interface SocketOptions { - socket: SocketHandler; - data?: Data; - } - // interface TCPSocketOptions extends SocketOptions { - // hostname: string; - // port: number; - // } - - interface TCPSocketListenOptions extends SocketOptions { - hostname: string; - port: number; - tls?: TLSOptions; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface TCPSocketConnectOptions extends SocketOptions { - hostname: string; - port: number; - tls?: boolean; - exclusive?: boolean; - allowHalfOpen?: boolean; - } - - interface UnixSocketOptions extends SocketOptions { - tls?: TLSOptions; - unix: string; - } - - interface FdSocketOptions extends SocketOptions { - tls?: TLSOptions; - fd: number; - } - - /** - * Create a TCP client that connects to a server - * - * @param options The options to use when creating the client - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function connect(options: TCPSocketConnectOptions): Promise>; - function connect(options: UnixSocketOptions): Promise>; - - /** - * Create a TCP server that listens on a port - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.data The per-instance data context - * @param options.hostname The hostname to connect to - * @param options.port The port to connect to - * @param options.tls The TLS configuration object - * @param options.unix The unix socket to connect to - */ - function listen(options: TCPSocketListenOptions): TCPSocketListener; - function listen(options: UnixSocketOptions): UnixSocketListener; - - namespace udp { - type Data = string | ArrayBufferView | ArrayBufferLike; - - export interface SocketHandler { - data?( - socket: Socket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: Socket): void | Promise; - error?(socket: Socket, error: Error): void | Promise; - } - - export interface ConnectedSocketHandler { - data?( - socket: ConnectedSocket, - data: BinaryTypeList[DataBinaryType], - port: number, - address: string, - ): void | Promise; - drain?(socket: ConnectedSocket): void | Promise; - error?(socket: ConnectedSocket, error: Error): void | Promise; - } - - export interface SocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: SocketHandler; - } - - export interface ConnectSocketOptions { - hostname?: string; - port?: number; - binaryType?: DataBinaryType; - socket?: ConnectedSocketHandler; - connect: { - hostname: string; - port: number; - }; - } - - export interface BaseUDPSocket { - readonly hostname: string; - readonly port: number; - readonly address: SocketAddress; - readonly binaryType: BinaryType; - readonly closed: boolean; - ref(): void; - unref(): void; - close(): void; - } - - export interface ConnectedSocket extends BaseUDPSocket { - readonly remoteAddress: SocketAddress; - sendMany(packets: readonly Data[]): number; - send(data: Data): boolean; - reload(handler: ConnectedSocketHandler): void; - } - - export interface Socket extends BaseUDPSocket { - sendMany(packets: readonly (Data | string | number)[]): number; - send(data: Data, port: number, address: string): boolean; - reload(handler: SocketHandler): void; - } - } - - /** - * Create a UDP socket - * - * @param options The options to use when creating the server - * @param options.socket The socket handler to use - * @param options.hostname The hostname to listen on - * @param options.port The port to listen on - * @param options.binaryType The binary type to use for the socket - * @param options.connect The hostname and port to connect to - */ - export function udpSocket( - options: udp.SocketOptions, - ): Promise>; - export function udpSocket( - options: udp.ConnectSocketOptions, - ): Promise>; - - namespace SpawnOptions { - /** - * Option for stdout/stderr - */ - type Readable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number; - - /** - * Option for stdin - */ - type Writable = - | "pipe" - | "inherit" - | "ignore" - | null // equivalent to "ignore" - | undefined // to use default - | BunFile - | ArrayBufferView - | number - | ReadableStream - | Blob - | Response - | Request; - - interface OptionsObject< - In extends Writable = Writable, - Out extends Readable = Readable, - Err extends Readable = Readable, - > { - /** - * The current working directory of the process - * - * Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * The environment variables of the process - * - * Defaults to `process.env` as it was when the current Bun process launched. - * - * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. - */ - env?: Record; - - /** - * The standard file descriptors of the process, in the form [stdin, stdout, stderr]. - * This overrides the `stdin`, `stdout`, and `stderr` properties. - * - * For stdin you may pass: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input (default) - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`, `Bun.file()`, `Response`, `Request`: The process will read from buffer/stream. - * - `number`: The process will read from the file descriptor - * - * For stdout and stdin you may pass: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default ["ignore", "pipe", "inherit"] for `spawn` - * ["ignore", "pipe", "pipe"] for `spawnSync` - */ - stdio?: [In, Out, Err]; - /** - * The file descriptor for the standard input. It may be: - * - * - `"ignore"`, `null`, `undefined`: The process will have no standard input - * - `"pipe"`: The process will have a new {@link FileSink} for standard input - * - `"inherit"`: The process will inherit the standard input of the current process - * - `ArrayBufferView`, `Blob`: The process will read from the buffer - * - `number`: The process will read from the file descriptor - * - * @default "ignore" - */ - stdin?: In; - /** - * The file descriptor for the standard output. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "pipe" - */ - stdout?: Out; - /** - * The file descriptor for the standard error. It may be: - * - * - `"pipe"`, `undefined`: The process will have a {@link ReadableStream} for standard output/error - * - `"ignore"`, `null`: The process will have no standard output/error - * - `"inherit"`: The process will inherit the standard output/error of the current process - * - `ArrayBufferView`: The process write to the preallocated buffer. Not implemented. - * - `number`: The process will write to the file descriptor - * - * @default "inherit" for `spawn` - * "pipe" for `spawnSync` - */ - stderr?: Err; - - /** - * Callback that runs when the {@link Subprocess} exits - * - * This is called even if the process exits with a non-zero exit code. - * - * Warning: this may run before the `Bun.spawn` function returns. - * - * A simple alternative is `await subprocess.exited`. - * - * @example - * - * ```ts - * const subprocess = spawn({ - * cmd: ["echo", "hello"], - * onExit: (subprocess, code) => { - * console.log(`Process exited with code ${code}`); - * }, - * }); - * ``` - */ - onExit?( - subprocess: Subprocess, - exitCode: number | null, - signalCode: number | null, - /** - * If an error occurred in the call to waitpid2, this will be the error. - */ - error?: ErrorLike, - ): void | Promise; - - /** - * When specified, Bun will open an IPC channel to the subprocess. The passed callback is called for - * incoming messages, and `subprocess.send` can send messages to the subprocess. Messages are serialized - * using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - * - * The subprocess can send and recieve messages by using `process.send` and `process.on("message")`, - * respectively. This is the same API as what Node.js exposes when `child_process.fork()` is used. - * - * Currently, this is only compatible with processes that are other `bun` instances. - */ - ipc?( - message: any, - /** - * The {@link Subprocess} that sent the message - */ - subprocess: Subprocess, - ): void; - - /** - * The serialization format to use for IPC messages. Defaults to `"advanced"`. - * - * To communicate with Node.js processes, use `"json"`. - * - * When `ipc` is not specified, this is ignored. - */ - serialization?: "json" | "advanced"; - - /** - * If true, the subprocess will have a hidden window. - */ - windowsHide?: boolean; - - /** - * If true, no quoting or escaping of arguments is done on Windows. - */ - windowsVerbatimArguments?: boolean; - - /** - * Path to the executable to run in the subprocess. This defaults to `cmds[0]`. - * - * One use-case for this is for applications which wrap other applications or to simulate a symlink. - * - * @default cmds[0] - */ - argv0?: string; - - /** - * An {@link AbortSignal} that can be used to abort the subprocess. - * - * This is useful for aborting a subprocess when some other part of the - * program is aborted, such as a `fetch` response. - * - * Internally, this works by calling `subprocess.kill(1)`. - * - * @example - * ```ts - * const controller = new AbortController(); - * const { signal } = controller; - * const start = performance.now(); - * const subprocess = Bun.spawn({ - * cmd: ["sleep", "100"], - * signal, - * }); - * await Bun.sleep(1); - * controller.abort(); - * await subprocess.exited; - * const end = performance.now(); - * console.log(end - start); // 1ms instead of 101ms - * ``` - */ - signal?: AbortSignal; - } - - type OptionsToSubprocess = - Opts extends OptionsObject - ? Subprocess< - // "Writable extends In" means "if In === Writable", - // aka if true that means the user didn't specify anything - Writable extends In ? "ignore" : In, - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "inherit" : Err - > - : Subprocess; - - type OptionsToSyncSubprocess = - Opts extends OptionsObject - ? SyncSubprocess - : SyncSubprocess; - - type ReadableIO = ReadableStream | number | undefined; - - type ReadableToIO = X extends "pipe" | undefined - ? ReadableStream - : X extends BunFile | ArrayBufferView | number - ? number - : undefined; - - type ReadableToSyncIO = X extends "pipe" | undefined ? Buffer : undefined; - - type WritableIO = FileSink | number | undefined; - - type WritableToIO = X extends "pipe" - ? FileSink - : X extends BunFile | ArrayBufferView | Blob | Request | Response | number - ? number - : undefined; - } - - interface ResourceUsage { - /** - * The number of voluntary and involuntary context switches that the process made. - */ - contextSwitches: { - /** - * Voluntary context switches (context switches that the process initiated). - */ - voluntary: number; - /** - * Involuntary context switches (context switches initiated by the system scheduler). - */ - involuntary: number; - }; - - /** - * The amount of CPU time used by the process, in microseconds. - */ - cpuTime: { - /** - * User CPU time used by the process, in microseconds. - */ - user: number; - /** - * System CPU time used by the process, in microseconds. - */ - system: number; - /** - * Total CPU time used by the process, in microseconds. - */ - total: number; - }; - /** - * The maximum amount of resident set size (in bytes) used by the process during its lifetime. - */ - maxRSS: number; - - /** - * IPC messages sent and received by the process. - */ - messages: { - /** - * The number of IPC messages sent. - */ - sent: number; - /** - * The number of IPC messages received. - */ - received: number; - }; - /** - * The number of IO operations done by the process. - */ - ops: { - /** - * The number of input operations via the file system. - */ - in: number; - /** - * The number of output operations via the file system. - */ - out: number; - }; - /** - * The amount of shared memory that the process used. - */ - shmSize: number; - /** - * The number of signals delivered to the process. - */ - signalCount: number; - /** - * The number of times the process was swapped out of main memory. - */ - swapCount: number; - } - - /** - * A process created by {@link Bun.spawn}. - * - * This type accepts 3 optional type parameters which correspond to the `stdio` array from the options object. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSubprocess} (any, pipe, pipe) - * - {@link WritableSubprocess} (pipe, any, any) - * - {@link PipedSubprocess} (pipe, pipe, pipe) - * - {@link NullSubprocess} (ignore, ignore, ignore) - */ - interface Subprocess< - In extends SpawnOptions.Writable = SpawnOptions.Writable, - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > extends AsyncDisposable { - readonly stdin: SpawnOptions.WritableToIO; - readonly stdout: SpawnOptions.ReadableToIO; - readonly stderr: SpawnOptions.ReadableToIO; - - /** - * This returns the same value as {@link Subprocess.stdout} - * - * It exists for compatibility with {@link ReadableStream.pipeThrough} - */ - readonly readable: SpawnOptions.ReadableToIO; - - /** - * The process ID of the child process - * @example - * ```ts - * const { pid } = Bun.spawn({ cmd: ["echo", "hello"] }); - * console.log(pid); // 1234 - * ``` - */ - readonly pid: number; - /** - * The exit code of the process - * - * The promise will resolve when the process exits - */ - readonly exited: Promise; - - /** - * Synchronously get the exit code of the process - * - * If the process hasn't exited yet, this will return `null` - */ - readonly exitCode: number | null; - - /** - * Synchronously get the signal code of the process - * - * If the process never sent a signal code, this will return `null` - * - * To receive signal code changes, use the `onExit` callback. - * - * If the signal code is unknown, it will return the original signal code - * number, but that case should essentially never happen. - */ - readonly signalCode: NodeJS.Signals | null; - - /** - * Has the process exited? - */ - readonly killed: boolean; - - /** - * Kill the process - * @param exitCode The exitCode to send to the process - */ - kill(exitCode?: number | NodeJS.Signals): void; - - /** - * This method will tell Bun to wait for this process to exit after you already - * called `unref()`. - * - * Before shutting down, Bun will wait for all subprocesses to exit by default - */ - ref(): void; - - /** - * Before shutting down, Bun will wait for all subprocesses to exit by default - * - * This method will tell Bun to not wait for this process to exit before shutting down. - */ - unref(): void; - - /** - * Send a message to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option, and is another instance of `bun`. - * - * Messages are serialized using the JSC serialize API, which allows for the same types that `postMessage`/`structuredClone` supports. - */ - send(message: any): void; - - /** - * Disconnect the IPC channel to the subprocess. This is only supported if the subprocess - * was created with the `ipc` option. - */ - disconnect(): void; - - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - * - * Only available after the process has exited - * - * If the process hasn't exited yet, this will return `undefined` - */ - resourceUsage(): ResourceUsage | undefined; - } - - /** - * A process created by {@link Bun.spawnSync}. - * - * This type accepts 2 optional type parameters which correspond to the `stdout` and `stderr` options. Instead of specifying these, you should use one of the following utility types instead: - * - {@link ReadableSyncSubprocess} (pipe, pipe) - * - {@link NullSyncSubprocess} (ignore, ignore) - */ - interface SyncSubprocess< - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > { - stdout: SpawnOptions.ReadableToSyncIO; - stderr: SpawnOptions.ReadableToSyncIO; - exitCode: number; - success: boolean; - /** - * Get the resource usage information of the process (max RSS, CPU time, etc) - */ - resourceUsage: ResourceUsage; - - signalCode?: string; - exitedDueToTimeout?: true; - pid: number; - } - - /** - * Spawn a new process - * - * ```js - * const subprocess = Bun.spawn({ - * cmd: ["echo", "hello"], - * stdout: "pipe", - * }); - * const text = await readableStreamToText(subprocess.stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmd: string[]; // to support dynamically constructed commands - }, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawn(["echo", "hello"]); - * const text = await readableStreamToText(stdout); - * console.log(text); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawn( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawn(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSubprocess; - - /** - * Spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync({ - * cmd: ["echo", "hello"], - * }); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - options: Opts & { - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync({ cmd: ["echo", "hello"] }); - * ``` - */ - cmd: string[]; - - onExit?: never; - }, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** - * Synchronously spawn a new process - * - * ```js - * const {stdout} = Bun.spawnSync(["echo", "hello"]); - * console.log(stdout.toString()); // "hello\n" - * ``` - * - * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) - */ - function spawnSync( - /** - * The command to run - * - * The first argument will be resolved to an absolute executable path. It must be a file, not a directory. - * - * If you explicitly set `PATH` in `env`, that `PATH` will be used to resolve the executable instead of the default `PATH`. - * - * To check if the command exists before running it, use `Bun.which(bin)`. - * - * @example - * ```ts - * const subprocess = Bun.spawnSync(["echo", "hello"]); - * ``` - */ - cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSyncSubprocess; - - /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ - type ReadableSubprocess = Subprocess; - /** Utility type for any process from {@link Bun.spawn()} with stdin set to `"pipe"` */ - type WritableSubprocess = Subprocess<"pipe", any, any>; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `"pipe"`. A combination of {@link ReadableSubprocess} and {@link WritableSubprocess} */ - type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawn()} with stdin, stdout, stderr all set to `null` or similar. */ - type NullSubprocess = Subprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `"pipe"` */ - type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">; - /** Utility type for any process from {@link Bun.spawnSync()} with both stdout and stderr set to `null` or similar */ - type NullSyncSubprocess = SyncSubprocess< - "ignore" | "inherit" | null | undefined, - "ignore" | "inherit" | null | undefined - >; - - // Blocked on https://github.com/oven-sh/bun/issues/8329 - // /** - // * - // * Count the visible width of a string, as it would be displayed in a terminal. - // * - // * By default, strips ANSI escape codes before measuring the string. This is - // * because ANSI escape codes are not visible characters. If passed a non-string, - // * it will return 0. - // * - // * @param str The string to measure - // * @param options - // */ - // function stringWidth( - // str: string, - // options?: { - // /** - // * Whether to include ANSI escape codes in the width calculation - // * - // * Slightly faster if set to `false`, but less accurate if the string contains ANSI escape codes. - // * @default false - // */ - // countAnsiEscapeCodes?: boolean; - // }, - // ): number; - - class FileSystemRouter { - /** - * Create a new {@link FileSystemRouter}. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: process.cwd() + "/pages", - * style: "nextjs", - * }); - * - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params); // {year: "2020", month: "01", day: "01", slug: "hello-world"} - * ``` - * @param options The options to use when creating the router - * @param options.dir The root directory containing the files to route - * @param options.style The style of router to use (only "nextjs" supported - * for now) - */ - constructor(options: { - /** - * The root directory containing the files to route - * - * There is no default value for this option. - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: - */ - dir: string; - style: "nextjs"; - - /** The base path to use when routing */ - assetPrefix?: string; - origin?: string; - /** Limit the pages to those with particular file extensions. */ - fileExtensions?: string[]; - }); - - // todo: URL - match(input: string | Request | Response): MatchedRoute | null; - - readonly assetPrefix: string; - readonly origin: string; - readonly style: string; - readonly routes: Record; - - reload(): void; - } - - interface MatchedRoute { - /** - * A map of the parameters from the route - * - * @example - * ```ts - * const router = new FileSystemRouter({ - * dir: "/path/to/files", - * style: "nextjs", - * }); - * const {params} = router.match("/blog/2020/01/01/hello-world"); - * console.log(params.year); // "2020" - * console.log(params.month); // "01" - * console.log(params.day); // "01" - * console.log(params.slug); // "hello-world" - * ``` - */ - readonly params: Record; - readonly filePath: string; - readonly pathname: string; - readonly query: Record; - readonly name: string; - readonly kind: "exact" | "catch-all" | "optional-catch-all" | "dynamic"; - readonly src: string; - } - - /** - * The current version of Bun - * @example - * "0.2.0" - */ - const version: string; - - /** - * The current version of Bun with the shortened commit sha of the build - * @example "v1.1.30 (d09df1af)" - */ - const version_with_sha: string; - - /** - * The git sha at the time the currently-running version of Bun was compiled - * @example - * "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" - */ - const revision: string; - - /** - * Find the index of a newline character in potentially ill-formed UTF-8 text. - * - * This is sort of like readline() except without the IO. - */ - function indexOfLine(buffer: ArrayBufferView | ArrayBufferLike, offset?: number): number; - - interface GlobScanOptions { - /** - * The root directory to start matching from. Defaults to `process.cwd()` - */ - cwd?: string; - - /** - * Allow patterns to match entries that begin with a period (`.`). - * - * @default false - */ - dot?: boolean; - - /** - * Return the absolute path for entries. - * - * @default false - */ - absolute?: boolean; - - /** - * Indicates whether to traverse descendants of symbolic link directories. - * - * @default false - */ - followSymlinks?: boolean; - - /** - * Throw an error when symbolic link is broken - * - * @default false - */ - throwErrorOnBrokenSymlink?: boolean; - - /** - * Return only files. - * - * @default true - */ - onlyFiles?: boolean; - } - - /** - * Match files using [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)). - * - * The supported pattern syntax for is: - * - * - `?` - * Matches any single character. - * - `*` - * Matches zero or more characters, except for path separators ('/' or '\'). - * - `**` - * Matches zero or more characters, including path separators. - * Must match a complete path segment, i.e. followed by a path separator or - * at the end of the pattern. - * - `[ab]` - * Matches one of the characters contained in the brackets. - * Character ranges (e.g. "[a-z]") are also supported. - * Use "[!ab]" or "[^ab]" to match any character *except* those contained - * in the brackets. - * - `{a,b}` - * Match one of the patterns contained in the braces. - * Any of the wildcards listed above can be used in the sub patterns. - * Braces may be nested up to 10 levels deep. - * - `!` - * Negates the result when at the start of the pattern. - * Multiple "!" characters negate the pattern multiple times. - * - `\` - * Used to escape any of the special characters above. - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - */ - export class Glob { - constructor(pattern: string); - - /** - * Scan a root directory recursively for files that match this glob pattern. Returns an async iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = await Array.fromAsync(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for await (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scan(optionsOrCwd?: string | GlobScanOptions): AsyncIterableIterator; - - /** - * Synchronously scan a root directory recursively for files that match this glob pattern. Returns an iterator. - * - * @throws {ENOTDIR} Given root cwd path must be a directory - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * const scannedFiles = Array.from(glob.scan({ cwd: './src' })) - * ``` - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * for (const path of glob.scan()) { - * // do something - * } - * ``` - */ - scanSync(optionsOrCwd?: string | GlobScanOptions): IterableIterator; - - /** - * Match the glob against a string - * - * @example - * ```js - * const glob = new Glob("*.{ts,tsx}"); - * expect(glob.match('foo.ts')).toBeTrue(); - * ``` - */ - match(str: string): boolean; - } - - /** - * Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component. - * - * When the same timestamp is used multiple times, a monotonically increasing - * counter is appended to allow sorting. The final 8 bytes are - * cryptographically random. When the timestamp changes, the counter resets to - * a psuedo-random integer. - * - * @param encoding "hex" | "base64" | "base64url" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - * - * @example - * ```js - * import { randomUUIDv7 } from "bun"; - * const array = [ - * randomUUIDv7(), - * randomUUIDv7(), - * randomUUIDv7(), - * ] - * [ - * "0192ce07-8c4f-7d66-afec-2482b5c9b03c", - * "0192ce07-8c4f-7d67-805f-0f71581b5622", - * "0192ce07-8c4f-7d68-8170-6816e4451a58" - * ] - * ``` - */ - function randomUUIDv7( - /** - * @default "hex" - */ - encoding?: "hex" | "base64" | "base64url", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): string; - - /** - * Generate a UUIDv7 as a Buffer - * - * @param encoding "buffer" - * @param timestamp Unix timestamp in milliseconds, defaults to `Date.now()` - */ - function randomUUIDv7( - encoding: "buffer", - /** - * @default Date.now() - */ - timestamp?: number | Date, - ): Buffer; - - /** - * Types for `bun.lock` - */ - type BunLockFile = { - lockfileVersion: 0 | 1; - workspaces: { - [workspace: string]: BunLockFileWorkspacePackage; - }; - overrides?: Record; - patchedDependencies?: Record; - trustedDependencies?: string[]; - - /** - * ``` - * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } - * - * // first index is resolution for each type of package - * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] - * symlink -> [ "name@link:path", INFO ] - * folder -> [ "name@file:path", INFO ] - * workspace -> [ "name@workspace:path" ] // workspace is only path - * tarball -> [ "name@tarball", INFO ] - * root -> [ "name@root:", { bin, binDir } ] - * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] - * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ] - * ``` - * */ - packages: { - [pkg: string]: BunLockFilePackageArray; - }; - }; - - type BunLockFileBasePackageInfo = { - dependencies?: Record; - devDependencies?: Record; - optionalDependencies?: Record; - peerDependencies?: Record; - optionalPeers?: string[]; - bin?: string | Record; - binDir?: string; - }; - - type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { - name?: string; - version?: string; - }; - - type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { - os?: string | string[]; - cpu?: string | string[]; - bundled?: true; - }; - - /** @see {@link BunLockFile.packages} for more info */ - type BunLockFilePackageArray = - /** npm */ - | [pkg: string, registry: string, info: BunLockFilePackageInfo, integrity: string] - /** symlink, folder, tarball */ - | [pkg: string, info: BunLockFilePackageInfo] - /** workspace */ - | [pkg: string] - /** git, github */ - | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] - /** root */ - | [pkg: string, info: Pick]; -} diff --git a/packages/bun-types/new/deprecated.d.ts b/packages/bun-types/new/deprecated.d.ts deleted file mode 100644 index 2fb502e4ad348e..00000000000000 --- a/packages/bun-types/new/deprecated.d.ts +++ /dev/null @@ -1,74 +0,0 @@ -declare module "bun" { - interface BunMessageEvent { - /** - * @deprecated - */ - initMessageEvent( - type: string, - bubbles?: boolean, - cancelable?: boolean, - data?: any, - origin?: string, - lastEventId?: string, - source?: null, - ): void; - } - - /** - * @deprecated Renamed to `ErrorLike` - */ - type Errorlike = ErrorLike; - interface TLSOptions { - /** - * File path to a TLS key - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `key: Bun.file(path)` instead. - */ - keyFile?: string; - /** - * File path to a TLS certificate - * - * To enable TLS, this option is required. - * - * @deprecated since v0.6.3 - Use `cert: Bun.file(path)` instead. - */ - certFile?: string; - /** - * File path to a .pem file for a custom root CA - * - * @deprecated since v0.6.3 - Use `ca: Bun.file(path)` instead. - */ - caFile?: string; - } -} - -declare namespace NodeJS { - interface Process { - /** - * @deprecated This is deprecated; use the "node:assert" module instead. - */ - assert(value: unknown, message?: string | Error): asserts value; - } -} - -interface CustomEvent { - /** @deprecated */ - initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void; -} - -interface DOMException { - /** @deprecated */ - readonly code: number; -} - -/** - * @deprecated Renamed to `BuildMessage` - */ -declare var BuildError: typeof BuildMessage; - -/** - * @deprecated Renamed to `ResolveMessage` - */ -declare var ResolveError: typeof ResolveMessage; diff --git a/packages/bun-types/new/devserver.d.ts b/packages/bun-types/new/devserver.d.ts deleted file mode 100644 index cfb0ebe9eb5108..00000000000000 --- a/packages/bun-types/new/devserver.d.ts +++ /dev/null @@ -1,193 +0,0 @@ -export {}; - -declare global { - namespace Bun { - type HMREventNames = - | "bun:beforeUpdate" - | "bun:afterUpdate" - | "bun:beforeFullReload" - | "bun:beforePrune" - | "bun:invalidate" - | "bun:error" - | "bun:ws:disconnect" - | "bun:ws:connect"; - - /** - * The event names for the dev server - */ - type HMREvent = `bun:${HMREventNames}` | (string & {}); - } - - interface ImportMeta { - /** - * Hot module replacement APIs. This value is `undefined` in production and - * can be used in an `if` statement to check if HMR APIs are available - * - * ```ts - * if (import.meta.hot) { - * // HMR APIs are available - * } - * ``` - * - * However, this check is usually not needed as Bun will dead-code-eliminate - * calls to all of the HMR APIs in production builds. - * - * https://bun.sh/docs/bundler/hmr - */ - hot: { - /** - * `import.meta.hot.data` maintains state between module instances during - * hot replacement, enabling data transfer from previous to new versions. - * When `import.meta.hot.data` is written to, Bun will mark this module as - * capable of self-accepting (equivalent of calling `accept()`). - * - * @example - * ```ts - * const root = import.meta.hot.data.root ??= createRoot(elem); - * root.render(); // re-use an existing root - * ``` - * - * In production, `data` is inlined to be `{}`. This is handy because Bun - * knows it can minify `{}.prop ??= value` into `value` in production. - * - * - */ - data: any; - - /** - * Indicate that this module can be replaced simply by re-evaluating the - * file. After a hot update, importers of this module will be - * automatically patched. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * import { getCount } from "./foo"; - * - * console.log("count is ", getCount()); - * - * import.meta.hot.accept(); - * ``` - */ - accept(): void; - - /** - * Indicate that this module can be replaced by evaluating the new module, - * and then calling the callback with the new module. In this mode, the - * importers do not get patched. This is to match Vite, which is unable - * to patch their import statements. Prefer using `import.meta.hot.accept()` - * without an argument as it usually makes your code easier to understand. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * export const count = 0; - * - * import.meta.hot.accept((newModule) => { - * if (newModule) { - * // newModule is undefined when SyntaxError happened - * console.log('updated: count is now ', newModule.count) - * } - * }); - * ``` - * - * In production, calls to this are dead-code-eliminated. - */ - accept(cb: (newModule: any | undefined) => void): void; - - /** - * Indicate that a dependency's module can be accepted. When the dependency - * is updated, the callback will be called with the new module. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * import.meta.hot.accept('./foo', (newModule) => { - * if (newModule) { - * // newModule is undefined when SyntaxError happened - * console.log('updated: count is now ', newModule.count) - * } - * }); - * ``` - */ - accept(specifier: string, callback: (newModule: any) => void): void; - - /** - * Indicate that a dependency's module can be accepted. This variant - * accepts an array of dependencies, where the callback will receive - * the one updated module, and `undefined` for the rest. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - */ - accept(specifiers: string[], callback: (newModules: (any | undefined)[]) => void): void; - - /** - * Attach an on-dispose callback. This is called: - * - Just before the module is replaced with another copy (before the next is loaded) - * - After the module is detached (removing all imports to this module) - * - * This callback is not called on route navigation or when the browser tab closes. - * - * Returning a promise will delay module replacement until the module is - * disposed. All dispose callbacks are called in parallel. - */ - dispose(cb: (data: any) => void | Promise): void; - - /** - * No-op - * @deprecated - */ - decline(): void; - - // NOTE TO CONTRIBUTORS //////////////////////////////////////// - // Callback is currently never called for `.prune()` // - // so the types are commented out until we support it. // - //////////////////////////////////////////////////////////////// - // /** - // * Attach a callback that is called when the module is removed from the module graph. - // * - // * This can be used to clean up resources that were created when the module was loaded. - // * Unlike `import.meta.hot.dispose()`, this pairs much better with `accept` and `data` to manage stateful resources. - // * - // * @example - // * ```ts - // * export const ws = (import.meta.hot.data.ws ??= new WebSocket(location.origin)); - // * - // * import.meta.hot.prune(() => { - // * ws.close(); - // * }); - // * ``` - // */ - // prune(callback: () => void): void; - - /** - * Listen for an event from the dev server - * - * For compatibility with Vite, event names are also available via vite:* prefix instead of bun:*. - * - * https://bun.sh/docs/bundler/hmr#import-meta-hot-on-and-off - * @param event The event to listen to - * @param callback The callback to call when the event is emitted - */ - on(event: Bun.HMREvent, callback: () => void): void; - - /** - * Stop listening for an event from the dev server - * - * For compatibility with Vite, event names are also available via vite:* prefix instead of bun:*. - * - * https://bun.sh/docs/bundler/hmr#import-meta-hot-on-and-off - * @param event The event to stop listening to - * @param callback The callback to stop listening to - */ - off(event: Bun.HMREvent, callback: () => void): void; - }; - } -} diff --git a/packages/bun-types/new/fetch.d.ts b/packages/bun-types/new/fetch.d.ts deleted file mode 100644 index bdee6570700e7a..00000000000000 --- a/packages/bun-types/new/fetch.d.ts +++ /dev/null @@ -1,228 +0,0 @@ -declare module "bun" { - namespace __internal { - type BunBodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; - - type BunHeadersInit = - | Headers - | Record - | Array<[string, string]> - | IterableIterator<[string, string]>; - - /** - * @internal - */ - type LibOrUndiciHeaders = LibDomIsLoaded extends true ? typeof globalThis.Headers : import("undici-types").Headers; - - /** - * @internal - */ - type LibOrUndiciRequest = LibDomIsLoaded extends true ? {} : import("undici-types").Request; - - /** - * @internal - */ - type LibOrUndiciResponse = LibDomIsLoaded extends true ? {} : import("undici-types").Response; - - interface BunHeadersOverride extends LibOrUndiciHeaders { - /** - * Convert {@link Headers} to a plain JavaScript object. - * - * About 10x faster than `Object.fromEntries(headers.entries())` - * - * Called when you run `JSON.stringify(headers)` - * - * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. - */ - toJSON(): Record; - /** - * Get the total number of headers - */ - readonly count: number; - /** - * Get all headers matching the name - * - * Only supports `"Set-Cookie"`. All other headers are empty arrays. - * - * @param name - The header name to get - * - * @returns An array of header values - * - * @example - * ```ts - * const headers = new Headers(); - * headers.append("Set-Cookie", "foo=bar"); - * headers.append("Set-Cookie", "baz=qux"); - * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"] - * ``` - */ - getAll(name: "set-cookie" | "Set-Cookie"): string[]; - } - - interface BunResponseOverride extends LibOrUndiciResponse { - headers: BunHeadersOverride; - } - - interface BunRequestOverride extends LibOrUndiciRequest { - headers: BunHeadersOverride; - } - } -} - -interface Headers extends Bun.__internal.BunHeadersOverride {} -declare var Headers: Bun.__internal.UseLibDomIfAvailable< - "Headers", - { - prototype: Headers; - new (init?: Bun.__internal.BunHeadersInit): Headers; - } ->; - -interface Request extends Bun.__internal.BunRequestOverride {} - -declare var Request: Bun.__internal.UseLibDomIfAvailable< - "Request", - { - prototype: Request; - new (requestInfo: string, init?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, init?: RequestInit): Request; - } ->; - -interface Response extends Bun.__internal.BunResponseOverride {} - -interface ResponseConstructor { - new (body?: Bun.__internal.BunBodyInit | null | undefined, init?: ResponseInit | undefined): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: ResponseInit | number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - redirect(url: string, status?: number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - redirect(url: string, options?: Bun.ResponseInit): Response; - - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; -} - -declare var Response: ResponseConstructor; - -interface BunFetchRequestInitTLS extends Bun.TLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable; -} - -/** - * BunFetchRequestInit represents additional options that Bun supports in `fetch()` only. - * - * Bun extends the `fetch` API with some additional options, except - * this interface is not quite a `RequestInit`, because they won't work - * if passed to `new Request()`. This is why it's a separate type. - */ -interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; - - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: Bun.S3Options; -} - -/** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(request: Request, init?: BunFetchRequestInit): Promise; - -/** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; - -/** - * Send a HTTP(s) request - * - * @param input URL string or Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; - -declare namespace fetch { - export function preconnect( - url: string | URL, - options?: { - dns?: boolean; - tcp?: boolean; - http?: boolean; - https?: boolean; - }, - ): void; -} diff --git a/packages/bun-types/new/ffi.d.ts b/packages/bun-types/new/ffi.d.ts deleted file mode 100644 index 6a684678e209d3..00000000000000 --- a/packages/bun-types/new/ffi.d.ts +++ /dev/null @@ -1,1150 +0,0 @@ -/** - * `bun:ffi` lets you efficiently call C functions & FFI functions from JavaScript - * without writing bindings yourself. - * - * ```js - * import {dlopen, CString, ptr} from 'bun:ffi'; - * - * const lib = dlopen('libsqlite3', { - * }); - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ -declare module "bun:ffi" { - enum FFIType { - char = 0, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int8_t = 1, - /** - * 8-bit signed integer - * - * Must be a value between -127 and 127 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * signed char - * char // on x64 & aarch64 macOS - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i8 = 1, - - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint8_t = 2, - /** - * 8-bit unsigned integer - * - * Must be a value between 0 and 255 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * unsigned char - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u8 = 2, - - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - int16_t = 3, - /** - * 16-bit signed integer - * - * Must be a value between -32768 and 32767 - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * in16_t - * short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - i16 = 3, - - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - uint16_t = 4, - /** - * 16-bit unsigned integer - * - * Must be a value between 0 and 65535, inclusive. - * - * When passing to a FFI function (C ABI), type coercion is not performed. - * - * In C: - * ```c - * uint16_t - * unsigned short // on arm64 & x64 - * ``` - * - * In JavaScript: - * ```js - * var num = 0; - * ``` - */ - u16 = 4, - - /** - * 32-bit signed integer - */ - int32_t = 5, - - /** - * 32-bit signed integer - * - * Alias of {@link FFIType.int32_t} - */ - i32 = 5, - /** - * 32-bit signed integer - * - * The same as `int` in C - * - * ```c - * int - * ``` - */ - int = 5, - - /** - * 32-bit unsigned integer - * - * The same as `unsigned int` in C (on x64 & arm64) - * - * C: - * ```c - * unsigned int - * ``` - * JavaScript: - * ```js - * ptr(new Uint32Array(1)) - * ``` - */ - uint32_t = 6, - /** - * 32-bit unsigned integer - * - * Alias of {@link FFIType.uint32_t} - */ - u32 = 6, - - /** - * int64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - int64_t = 7, - /** - * i64 is a 64-bit signed integer - * - * This is not implemented yet! - */ - i64 = 7, - - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - uint64_t = 8, - /** - * 64-bit unsigned integer - * - * This is not implemented yet! - */ - u64 = 8, - - /** - * Doubles are not supported yet! - */ - double = 9, - /** - * Doubles are not supported yet! - */ - f64 = 9, - /** - * Floats are not supported yet! - */ - float = 10, - /** - * Floats are not supported yet! - */ - f32 = 10, - - /** - * Boolean value - * - * Must be `true` or `false`. `0` and `1` type coercion is not supported. - * - * In C, this corresponds to: - * ```c - * bool - * _Bool - * ``` - */ - bool = 11, - - /** - * Pointer value - * - * See {@link Bun.FFI.ptr} for more information - * - * In C: - * ```c - * void* - * ``` - * - * In JavaScript: - * ```js - * ptr(new Uint8Array(1)) - * ``` - */ - ptr = 12, - /** - * Pointer value - * - * alias of {@link FFIType.ptr} - */ - pointer = 12, - - /** - * void value - * - * void arguments are not supported - * - * void return type is the default return type - * - * In C: - * ```c - * void - * ``` - */ - void = 13, - - /** - * When used as a `returns`, this will automatically become a {@link CString}. - * - * When used in `args` it is equivalent to {@link FFIType.pointer} - */ - cstring = 14, - - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `int64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - i64_fast = 15, - - /** - * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance - * but means you might get a `BigInt` or you might get a `number`. - * - * In C, this always becomes `uint64_t` - * - * In JavaScript, this could be number or it could be BigInt, depending on what - * value is passed in. - */ - u64_fast = 16, - function = 17, - - napi_env = 18, - napi_value = 19, - buffer = 20, - } - - type Pointer = number & { __pointer__: null }; - - interface FFITypeToArgsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: number | bigint; - [FFIType.i64]: number | bigint; - [FFIType.uint64_t]: number | bigint; - [FFIType.u64]: number | bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.pointer]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.void]: undefined; - [FFIType.cstring]: NodeJS.TypedArray | Pointer | CString | null; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | JSCallback; // cannot be null - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeToReturnsType { - [FFIType.char]: number; - [FFIType.int8_t]: number; - [FFIType.i8]: number; - [FFIType.uint8_t]: number; - [FFIType.u8]: number; - [FFIType.int16_t]: number; - [FFIType.i16]: number; - [FFIType.uint16_t]: number; - [FFIType.u16]: number; - [FFIType.int32_t]: number; - [FFIType.i32]: number; - [FFIType.int]: number; - [FFIType.uint32_t]: number; - [FFIType.u32]: number; - [FFIType.int64_t]: bigint; - [FFIType.i64]: bigint; - [FFIType.uint64_t]: bigint; - [FFIType.u64]: bigint; - [FFIType.double]: number; - [FFIType.f64]: number; - [FFIType.float]: number; - [FFIType.f32]: number; - [FFIType.bool]: boolean; - [FFIType.ptr]: Pointer | null; - [FFIType.pointer]: Pointer | null; - [FFIType.void]: undefined; - [FFIType.cstring]: CString; - [FFIType.i64_fast]: number | bigint; - [FFIType.u64_fast]: number | bigint; - [FFIType.function]: Pointer | null; - [FFIType.napi_env]: unknown; - [FFIType.napi_value]: unknown; - [FFIType.buffer]: NodeJS.TypedArray | DataView; - } - interface FFITypeStringToType { - ["char"]: FFIType.char; - ["int8_t"]: FFIType.int8_t; - ["i8"]: FFIType.i8; - ["uint8_t"]: FFIType.uint8_t; - ["u8"]: FFIType.u8; - ["int16_t"]: FFIType.int16_t; - ["i16"]: FFIType.i16; - ["uint16_t"]: FFIType.uint16_t; - ["u16"]: FFIType.u16; - ["int32_t"]: FFIType.int32_t; - ["i32"]: FFIType.i32; - ["int"]: FFIType.int; - ["uint32_t"]: FFIType.uint32_t; - ["u32"]: FFIType.u32; - ["int64_t"]: FFIType.int64_t; - ["i64"]: FFIType.i64; - ["uint64_t"]: FFIType.uint64_t; - ["u64"]: FFIType.u64; - ["double"]: FFIType.double; - ["f64"]: FFIType.f64; - ["float"]: FFIType.float; - ["f32"]: FFIType.f32; - ["bool"]: FFIType.bool; - ["ptr"]: FFIType.ptr; - ["pointer"]: FFIType.pointer; - ["void"]: FFIType.void; - ["cstring"]: FFIType.cstring; - ["function"]: FFIType.pointer; // for now - ["usize"]: FFIType.uint64_t; // for now - ["callback"]: FFIType.pointer; // for now - ["napi_env"]: FFIType.napi_env; - ["napi_value"]: FFIType.napi_value; - ["buffer"]: FFIType.buffer; - } - - type FFITypeOrString = FFIType | keyof FFITypeStringToType; - - interface FFIFunction { - /** - * Arguments to a FFI function (C ABI) - * - * Defaults to an empty array, which means no arguments. - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, FFIType, suffix } from "bun:ffi" - * - * const lib = dlopen(`adder.${suffix}`, { - * add: { - * // FFIType can be used or you can pass string labels. - * args: [FFIType.i32, "i32"], - * returns: "i32", - * }, - * }) - * lib.symbols.add(1, 2) - * ``` - * In C: - * ```c - * int add(int a, int b) { - * return a + b; - * } - * ``` - */ - readonly args?: readonly FFITypeOrString[]; - /** - * Return type to a FFI function (C ABI) - * - * Defaults to {@link FFIType.void} - * - * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. - * - * @example - * From JavaScript: - * ```ts - * import { dlopen, CString } from "bun:ffi" - * - * const lib = dlopen('z', { - * version: { - * returns: "ptr", - * } - * }); - * console.log(new CString(lib.symbols.version())); - * ``` - * In C: - * ```c - * char* version() - * { - * return "1.0.0"; - * } - * ``` - */ - readonly returns?: FFITypeOrString; - - /** - * Function pointer to the native function - * - * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. - * This pointer should not be null (0). - * - * This is useful if the library has already been loaded - * or if the module is also using Node-API. - */ - readonly ptr?: Pointer | bigint; - - /** - * Can C/FFI code call this function from a separate thread? - * - * Only supported with {@link JSCallback}. - * - * This does not make the function run in a separate thread. It is still up to the application/library - * to run their code in a separate thread. - * - * By default, {@link JSCallback} calls are not thread-safe. Turning this on - * incurs a small performance penalty for every function call. That small - * performance penalty needs to be less than the performance gain from - * running the function in a separate thread. - * - * @default false - */ - readonly threadsafe?: boolean; - } - - type Symbols = Readonly>; - - interface Library { - symbols: ConvertFns; - - /** - * `dlclose` the library, unloading the symbols and freeing allocated memory. - * - * Once called, the library is no longer usable. - * - * Calling a function from a library that has been closed is undefined behavior. - */ - close(): void; - } - - type ToFFIType = T extends FFIType ? T : T extends string ? FFITypeStringToType[T] : never; - - const FFIFunctionCallableSymbol: unique symbol; - type ConvertFns = { - [K in keyof Fns]: { - ( - ...args: Fns[K]["args"] extends infer A extends readonly FFITypeOrString[] - ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } - : // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - [unknown] extends [Fns[K]["args"]] - ? [] - : never - ): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - ? undefined - : FFITypeToReturnsType[ToFFIType>]; - __ffi_function_callable: typeof FFIFunctionCallableSymbol; - }; - }; - - /** - * Open a library using `"bun:ffi"` - * - * @param name The name of the library or file path. This will be passed to `dlopen()` - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import {dlopen} from 'bun:ffi'; - * - * const lib = dlopen("duckdb.dylib", { - * get_version: { - * returns: "cstring", - * args: [], - * }, - * }); - * lib.symbols.get_version(); - * // "1.0.0" - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function dlopen>( - name: string | import("bun").BunFile | URL, - symbols: Fns, - ): Library; - - /** - * **Experimental:** Compile ISO C11 source code using TinyCC, and make {@link symbols} available as functions to JavaScript. - * - * @param options - * @returns Library - * - * @example - * ## Hello, World! - * - * JavaScript: - * ```js - * import { cc } from "bun:ffi"; - * import hello from "./hello.c" with {type: "file"}; - * const {symbols: {hello}} = cc({ - * source: hello, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * // "Hello, World!" - * console.log(hello()); - * ``` - * - * `./hello.c`: - * ```c - * #include - * const char* hello() { - * return "Hello, World!"; - * } - * ``` - */ - function cc>(options: { - /** - * File path to an ISO C11 source file to compile and link - */ - source: string | import("bun").BunFile | URL; - - /** - * Library names to link against - * - * Equivalent to `-l` option in gcc/clang. - */ - library?: string[] | string; - - /** - * Include directories to pass to the compiler - * - * Equivalent to `-I` option in gcc/clang. - */ - include?: string[] | string; - - /** - * Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - */ - symbols: Fns; - - /** - * Map of symbols to define where the key is the symbol name and the value is the symbol value - * - * Equivalent to `-D` option in gcc/clang. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * define: { - * "NDEBUG": "1", - * }, - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - define?: Record; - - /** - * Flags to pass to the compiler. Note: we do not make gurantees about which specific version of the compiler is used. - * - * @default "-std=c11 -Wl,--export-all-symbols -g -O2" - * - * This is useful for passing macOS frameworks to link against. Or if there are other options you want to pass to the compiler. - * - * @example - * ```js - * import { cc } from "bun:ffi"; - * const {symbols: {hello}} = cc({ - * source: hello, - * flags: ["-framework CoreFoundation", "-framework Security"], - * symbols: { - * hello: { - * returns: "cstring", - * args: [], - * }, - * }, - * }); - * ``` - */ - flags?: string | string[]; - }): Library; - - /** - * Turn a native library's function pointer into a JavaScript function - * - * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. - * - * @param fn {@link FFIFunction} declaration. `ptr` is required - * - * @example - * - * ```js - * import {CFunction} from 'bun:ffi'; - * - * const getVersion = new CFunction({ - * returns: "cstring", - * args: [], - * ptr: myNativeLibraryGetVersion, - * }); - * getVersion(); - * getVersion.close(); - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function CFunction(fn: FFIFunction & { ptr: Pointer }): CallableFunction & { - /** - * Free the memory allocated by the wrapping function - */ - close(): void; - }; - - /** - * Link a map of symbols to JavaScript functions - * - * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. - * - * You could use this with Node-API to skip loading a second time. - * - * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} - * - * @example - * - * ```js - * import { linkSymbols } from "bun:ffi"; - * - * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); - * - * const lib = linkSymbols({ - * // Unlike with dlopen(), the names here can be whatever you want - * getMajor: { - * returns: "cstring", - * args: [], - * - * // Since this doesn't use dlsym(), you have to provide a valid ptr - * // That ptr could be a number or a bigint - * // An invalid pointer will crash your program. - * ptr: majorPtr, - * }, - * getMinor: { - * returns: "cstring", - * args: [], - * ptr: minorPtr, - * }, - * getPatch: { - * returns: "cstring", - * args: [], - * ptr: patchPtr, - * }, - * }); - * - * const [major, minor, patch] = [ - * lib.symbols.getMajor(), - * lib.symbols.getMinor(), - * lib.symbols.getPatch(), - * ]; - * ``` - * - * This is powered by just-in-time compiling C wrappers - * that convert JavaScript types to C types and back. Internally, - * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks - * goes to Fabrice Bellard and TinyCC maintainers for making this possible. - */ - function linkSymbols>(symbols: Fns): Library; - - /** - * Read a pointer as a {@link Buffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): Buffer; - - /** - * Read a pointer as an {@link ArrayBuffer} - * - * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function toArrayBuffer(ptr: Pointer, byteOffset?: number, byteLength?: number): ArrayBuffer; - - namespace read { - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i8(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i16(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f32(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function u64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function i64(ptr: Pointer, byteOffset?: number): bigint; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function f64(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function ptr(ptr: Pointer, byteOffset?: number): number; - /** - * The read function behaves similarly to DataView, - * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. - * - * @param ptr The memory address to read - * @param byteOffset bytes to skip before reading - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - function intptr(ptr: Pointer, byteOffset?: number): number; - } - - /** - * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} - * - * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. - * - * This is for use with FFI functions. For performance reasons, FFI will - * not automatically convert typed arrays to C pointers. - * - * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for - * @param {number} byteOffset optional offset into the view in bytes - * - * @example - * - * From JavaScript: - * ```js - * const array = new Uint8Array(10); - * const rawPtr = ptr(array); - * myFFIFunction(rawPtr); - * ``` - * To C: - * ```c - * void myFFIFunction(char* rawPtr) { - * // Do something with rawPtr - * } - * ``` - */ - function ptr(view: NodeJS.TypedArray | ArrayBufferLike | DataView, byteOffset?: number): Pointer; - - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - - class CString extends String { - /** - * Get a string from a UTF-8 encoded C string - * If `byteLength` is not provided, the string is assumed to be null-terminated. - * - * @param ptr The pointer to the C string - * @param byteOffset bytes to skip before reading - * @param byteLength bytes to read - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * console.log(new CString(ptr)); - * ``` - * - * @example - * ```js - * var ptr = lib.symbols.getVersion(); - * // print the first 4 characters - * console.log(new CString(ptr, 0, 4)); - * ``` - * - * While there are some checks to catch invalid pointers, this is a difficult - * thing to do safely. Passing an invalid pointer can crash the program and - * reading beyond the bounds of the pointer will crash the program or cause - * undefined behavior. Use with care! - */ - constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); - - /** - * The ptr to the C string - * - * This `CString` instance is a clone of the string, so it - * is safe to continue using this instance after the `ptr` has been - * freed. - */ - ptr: Pointer; - byteOffset?: number; - byteLength?: number; - - /** - * Get the {@link ptr} as an `ArrayBuffer` - * - * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 - */ - get arrayBuffer(): ArrayBuffer; - } - - /** - * Pass a JavaScript function to FFI (Foreign Function Interface) - */ - class JSCallback { - /** - * Enable a JavaScript callback function to be passed to C with bun:ffi - * - * @param callback The JavaScript function to be called - * @param definition The C function definition - */ - constructor(callback: (...args: any[]) => any, definition: FFIFunction); - - /** - * The pointer to the C function - * - * Becomes `null` once {@link JSCallback.prototype.close} is called - */ - readonly ptr: Pointer | null; - - /** - * Can the callback be called from a different thread? - */ - readonly threadsafe: boolean; - - /** - * Free the memory allocated for the callback - * - * If called multiple times, does nothing after the first call. - */ - close(): void; - } - - /** - * View the generated C code for FFI bindings - * - * You probably won't need this unless there's a bug in the FFI bindings - * generator or you're just curious. - */ - function viewSource(symbols: Symbols, is_callback?: false): string[]; - function viewSource(callback: FFIFunction, is_callback: true): string; - - /** - * Platform-specific file extension name for dynamic libraries - * - * "." is not included - * - * @example - * ```js - * "dylib" // macOS - * ``` - * - * @example - * ```js - * "so" // linux - * ``` - */ - const suffix: string; -} diff --git a/packages/bun-types/new/globals.d.ts b/packages/bun-types/new/globals.d.ts deleted file mode 100644 index 2df6e71b285d8c..00000000000000 --- a/packages/bun-types/new/globals.d.ts +++ /dev/null @@ -1,1443 +0,0 @@ -declare module "bun" { - namespace __internal { - type NodeWorkerThreadsWorker = import("worker_threads").Worker; - type LibWorkerOrNodeWorkerThreadsWorker = Bun.__internal.UseLibDomIfAvailable<"Worker", NodeWorkerThreadsWorker>; - - type NodePerfHooksPerformance = import("perf_hooks").Performance; - type LibPerformanceOrNodePerfHooksPerformance = Bun.__internal.UseLibDomIfAvailable< - "Performance", - NodePerfHooksPerformance - >; - - type NodeCryptoWebcryptoSubtleCrypto = import("crypto").webcrypto.SubtleCrypto; - type NodeCryptoWebcryptoCryptoKey = import("crypto").webcrypto.CryptoKey; - type NodeUtilTextEncoder = import("util").TextEncoder; - type NodeUtilTextDecoder = import("util").TextDecoder; - } -} - -interface ReadableStream {} -declare var ReadableStream: Bun.__internal.UseLibDomIfAvailable< - "ReadableStream", - { - prototype: ReadableStream; - new (underlyingSource?: Bun.UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - new (underlyingSource?: Bun.DirectUnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - } ->; - -interface WritableStream {} -declare var WritableStream: Bun.__internal.UseLibDomIfAvailable< - "WritableStream", - { - prototype: WritableStream; - new (underlyingSink?: Bun.UnderlyingSink, strategy?: QueuingStrategy): WritableStream; - } ->; - -interface Worker extends Bun.__internal.LibWorkerOrNodeWorkerThreadsWorker {} -declare var Worker: Bun.__internal.UseLibDomIfAvailable< - "Worker", - { - prototype: Worker; - new (scriptURL: string | URL, options?: Bun.WorkerOptions | undefined): Worker; - /** - * This is the cloned value of the `data` property passed to `new Worker()` - * - * This is Bun's equivalent of `workerData` in Node.js. - */ - data: any; - } ->; - -declare var WebSocket: Bun.__internal.UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>; - -interface Crypto {} -declare var Crypto: { - prototype: Crypto; - new (): Crypto; -}; - -declare var crypto: Crypto; - -/** - * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextEncoder` API. All - * instances of `TextEncoder` only support UTF-8 encoding. - * - * ```js - * const encoder = new TextEncoder(); - * const uint8array = encoder.encode('this is some data'); - * ``` - */ -interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder { - /** - * UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object - * containing the read Unicode code units and written UTF-8 bytes. - * - * ```js - * const encoder = new TextEncoder(); - * const src = 'this is some data'; - * const dest = new Uint8Array(10); - * const { read, written } = encoder.encodeInto(src, dest); - * ``` - * @param src The text to encode. - * @param dest The array to hold the encode result. - */ - encodeInto(src?: string, dest?: Bun.BufferSource): import("util").EncodeIntoResult; -} -declare var TextEncoder: Bun.__internal.UseLibDomIfAvailable< - "TextEncoder", - { - prototype: TextEncoder; - new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextEncoder; - } ->; - -/** - * An implementation of the [WHATWG Encoding Standard](https://encoding.spec.whatwg.org/) `TextDecoder` API. All - * instances of `TextDecoder` only support UTF-8 decoding. - * - * ```js - * const decoder = new TextDecoder(); - * const uint8array = decoder.decode('this is some data'); - */ -declare var TextDecoder: Bun.__internal.UseLibDomIfAvailable< - "TextDecoder", - { - prototype: Bun.__internal.NodeUtilTextDecoder; - new ( - encoding?: Bun.Encoding, - options?: { fatal?: boolean; ignoreBOM?: boolean }, - ): Bun.__internal.NodeUtilTextDecoder; - } ->; - -// interface Event { -// /** This is not used in Node.js and is provided purely for completeness. */ -// readonly bubbles: boolean; -// /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */ -// cancelBubble: () => void; -// /** True if the event was created with the cancelable option */ -// readonly cancelable: boolean; -// /** This is not used in Node.js and is provided purely for completeness. */ -// readonly composed: boolean; -// /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */ -// composedPath(): [EventTarget?]; -// /** Alias for event.target. */ -// readonly currentTarget: EventTarget | null; -// /** Is true if cancelable is true and event.preventDefault() has been called. */ -// readonly defaultPrevented: boolean; -// /** This is not used in Node.js and is provided purely for completeness. */ -// readonly eventPhase: typeof globalThis extends { Event: infer T extends {eventPhase: number} } ? T['eventPhase'] : 0 | 2; -// /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */ -// readonly isTrusted: boolean; -// /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */ -// preventDefault(): void; -// /** This is not used in Node.js and is provided purely for completeness. */ -// returnValue: boolean; -// /** Alias for event.target. */ -// readonly srcElement: EventTarget | null; -// /** Stops the invocation of event listeners after the current one completes. */ -// stopImmediatePropagation(): void; -// /** This is not used in Node.js and is provided purely for completeness. */ -// stopPropagation(): void; -// /** The `EventTarget` dispatching the event */ -// readonly target: EventTarget | null; -// /** The millisecond timestamp when the Event object was created. */ -// readonly timeStamp: number; -// /** Returns the type of event, e.g. "click", "hashchange", or "submit". */ -// readonly type: string; -// } -declare var Event: { - prototype: Event; - readonly NONE: 0; - readonly CAPTURING_PHASE: 1; - readonly AT_TARGET: 2; - readonly BUBBLING_PHASE: 3; - new (type: string, eventInitDict?: Bun.EventInit): Event; -}; - -interface EventTarget { - /** - * Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value. - * - * If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched. - * - * The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification. - * Specifically, the `capture` option is used as part of the key when registering a `listener`. - * Any individual `listener` may be added once with `capture = false`, and once with `capture = true`. - */ - addEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: AddEventListenerOptions | boolean, - ): void; - /** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ - dispatchEvent(event: Event): boolean; - /** Removes the event listener in target's event listener list with the same type, callback, and options. */ - removeEventListener( - type: string, - listener: EventListener | EventListenerObject, - options?: Bun.EventListenerOptions | boolean, - ): void; -} -declare var EventTarget: { - prototype: EventTarget; - new (): EventTarget; -}; - -interface File extends Blob { - readonly lastModified: number; - readonly name: string; -} - -declare var File: typeof globalThis extends { onabort: any } - ? typeof globalThis extends { File: infer T } - ? T - : never - : { - prototype: File; - /** - * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - * - * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects - * @param `name` - The name of the file - * @param `options` - An object containing properties to be added to the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) - */ - new ( - parts: Bun.BlobPart[], - name: string, - options?: BlobPropertyBag & { lastModified?: Date | number | undefined }, - ): File; - }; - -/** - * ShadowRealms are a distinct global environment, with its own global object - * containing its own intrinsics and built-ins (standard objects that are not - * bound to global variables, like the initial value of Object.prototype). - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ -interface ShadowRealm { - /** - * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) - * - * @example - * - * ```js - * const red = new ShadowRealm(); - * - * // realms can import modules that will execute within it's own environment. - * // When the module is resolved, it captured the binding value, or creates a new - * // wrapped function that is connected to the callable binding. - * const redAdd = await red.importValue('./inside-code.js', 'add'); - * - * // redAdd is a wrapped function exotic object that chains it's call to the - * // respective imported binding. - * let result = redAdd(2, 3); - * - * console.assert(result === 5); // yields true - * - * // The evaluate method can provide quick code evaluation within the constructed - * // shadowRealm without requiring any module loading, while it still requires CSP - * // relaxing. - * globalThis.someValue = 1; - * red.evaluate('globalThis.someValue = 2'); // Affects only the ShadowRealm's global - * console.assert(globalThis.someValue === 1); - * - * // The wrapped functions can also wrap other functions the other way around. - * const setUniqueValue = - * await red.importValue('./inside-code.js', 'setUniqueValue'); - * - * // setUniqueValue = (cb) => (cb(globalThis.someValue) * 2); - * - * result = setUniqueValue((x) => x ** 3); - * - * console.assert(result === 16); // yields true - * ``` - */ - importValue(specifier: string, bindingName: string): Promise; - evaluate(sourceText: string): any; -} - -declare var ShadowRealm: { - prototype: ShadowRealm; - new (): ShadowRealm; -}; - -declare function queueMicrotask(callback: (...args: any[]) => void): void; -/** - * Log an error using the default exception handler - * @param error Error or string - */ -declare function reportError(error: any): void; - -interface Timer { - ref(): Timer; - unref(): Timer; - hasRef(): boolean; - refresh(): Timer; - - [Symbol.toPrimitive](): number; -} - -/** - * Cancel a repeating timer by its timer ID. - * @param id timer id - */ -declare function clearInterval(id?: number | Timer): void; -/** - * Cancel a delayed function call by its timer ID. - * @param id timer id - */ -declare function clearTimeout(id?: number | Timer): void; -/** - * Cancel an immediate function call by its immediate ID. - * @param id immediate id - */ -declare function clearImmediate(id?: number | Timer): void; -/** - * Run a function immediately after main event loop is vacant - * @param handler function to call - */ -declare function setImmediate(handler: Bun.TimerHandler, ...arguments: any[]): Timer; -/** - * Run a function every `interval` milliseconds - * @param handler function to call - * @param interval milliseconds to wait between calls - */ -declare function setInterval(handler: Bun.TimerHandler, interval?: number, ...arguments: any[]): Timer; -/** - * Run a function after `timeout` (milliseconds) - * @param handler function to call - * @param timeout milliseconds to wait between calls - */ -declare function setTimeout(handler: Bun.TimerHandler, timeout?: number, ...arguments: any[]): Timer; - -declare function addEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | AddEventListenerOptions, -): void; -declare function addEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, -): void; -declare function removeEventListener( - type: K, - listener: (this: object, ev: EventMap[K]) => any, - options?: boolean | Bun.EventListenerOptions, -): void; -declare function removeEventListener( - type: string, - listener: Bun.EventListenerOrEventListenerObject, - options?: boolean | Bun.EventListenerOptions, -): void; - -/** - * Events providing information related to errors in scripts or in files. - */ -interface ErrorEvent extends Event { - readonly colno: number; - readonly error: any; - readonly filename: string; - readonly lineno: number; - readonly message: string; -} - -declare var ErrorEvent: { - prototype: ErrorEvent; - new (type: string, eventInitDict?: Bun.ErrorEventInit): ErrorEvent; -}; - -/** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */ -interface CloseEvent extends Event { - /** Returns the WebSocket connection close code provided by the server. */ - readonly code: number; - /** Returns the WebSocket connection close reason provided by the server. */ - readonly reason: string; - /** Returns true if the connection closed cleanly; false otherwise. */ - readonly wasClean: boolean; -} - -declare var CloseEvent: { - prototype: CloseEvent; - new (type: string, eventInitDict?: Bun.CloseEventInit): CloseEvent; -}; - -interface MessageEvent extends Bun.MessageEvent {} -declare var MessageEvent: Bun.__internal.UseLibDomIfAvailable<"MessageEvent", MessageEvent>; - -interface CustomEvent extends Event { - /** Returns any custom data event was created with. Typically used for synthetic events. */ - readonly detail: T; -} - -declare var CustomEvent: { - prototype: CustomEvent; - new (type: string, eventInitDict?: Bun.CustomEventInit): CustomEvent; -}; - -interface EventListener { - (evt: Event): void; -} - -interface EventListenerObject { - handleEvent(object: Event): void; -} - -interface FetchEvent extends Event { - readonly request: Request; - readonly url: string; - - waitUntil(promise: Promise): void; - respondWith(response: Response | Promise): void; -} - -interface EventMap { - fetch: FetchEvent; - message: MessageEvent; - messageerror: MessageEvent; - // exit: Event; -} - -interface AddEventListenerOptions extends Bun.EventListenerOptions { - once?: boolean; - passive?: boolean; - signal?: AbortSignal; -} - -/** - * Low-level JavaScriptCore API for accessing the native ES Module loader (not a Bun API) - * - * Before using this, be aware of a few things: - * - * **Using this incorrectly will crash your application**. - * - * This API may change any time JavaScriptCore is updated. - * - * Bun may rewrite ESM import specifiers to point to bundled code. This will - * be confusing when using this API, as it will return a string like - * "/node_modules.server.bun". - * - * Bun may inject additional imports into your code. This usually has a `bun:` prefix. - */ -declare var Loader: { - /** - * ESM module registry - * - * This lets you implement live reload in Bun. If you - * delete a module specifier from this map, the next time it's imported, it - * will be re-transpiled and loaded again. - * - * The keys are the module specifiers and the - * values are metadata about the module. - * - * The keys are an implementation detail for Bun that will change between - * versions. - * - * - Userland modules are an absolute file path - * - Virtual modules have a `bun:` prefix or `node:` prefix - * - JS polyfills start with `"/bun-vfs/"`. `"buffer"` is an example of a JS polyfill - * - If you have a `node_modules.bun` file, many modules will point to that file - * - * Virtual modules and JS polyfills are embedded in bun's binary. They don't - * point to anywhere in your local filesystem. - */ - registry: Map< - string, - { - key: string; - /** - * This refers to the state the ESM module is in - * - * TODO: make an enum for this number - */ - state: number; - fetch: Promise; - instantiate: Promise; - satisfy: Promise; - dependencies: Array<(typeof Loader)["registry"] extends Map ? V : any>; - /** - * Your application will probably crash if you mess with this. - */ - module: { - dependenciesMap: (typeof Loader)["registry"]; - }; - linkError?: any; - linkSucceeded: boolean; - evaluated: boolean; - then?: any; - isAsync: boolean; - } - >; - /** - * For an already-evaluated module, return the dependencies as module specifiers - * - * This list is already sorted and uniqued. - * - * @example - * - * For this code: - * ```js - * // /foo.js - * import classNames from 'classnames'; - * import React from 'react'; - * import {createElement} from 'react'; - * ``` - * - * This would return: - * ```js - * Loader.dependencyKeysIfEvaluated("/foo.js") - * ["bun:wrap", "/path/to/node_modules/classnames/index.js", "/path/to/node_modules/react/index.js"] - * ``` - * - * @param specifier - module specifier as it appears in transpiled source code - */ - dependencyKeysIfEvaluated: (specifier: string) => string[]; - /** - * The function JavaScriptCore internally calls when you use an import statement. - * - * This may return a path to `node_modules.server.bun`, which will be confusing. - * - * Consider {@link Bun.resolve} or {@link ImportMeta.resolve} - * instead. - * - * @param specifier - module specifier as it appears in transpiled source code - * @param referrer - module specifier that is resolving this specifier - */ - resolve: (specifier: string, referrer: string) => string; -}; - -interface QueuingStrategy { - highWaterMark?: number; - size?: QueuingStrategySize; -} - -interface QueuingStrategyInit { - /** - * Creates a new ByteLengthQueuingStrategy with the provided high water mark. - * - * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. - */ - highWaterMark: number; -} - -/** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ -interface ByteLengthQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - // changed from QueuingStrategySize - // to avoid conflict with lib.dom.d.ts - readonly size: QueuingStrategySize; -} - -declare var ByteLengthQueuingStrategy: { - prototype: ByteLengthQueuingStrategy; - new (init: QueuingStrategyInit): ByteLengthQueuingStrategy; -}; - -interface ReadableStreamDefaultController { - readonly desiredSize: number | null; - close(): void; - enqueue(chunk?: R): void; - error(e?: any): void; -} - -interface ReadableStreamDirectController { - close(error?: Error): void; - write(data: Bun.BufferSource | ArrayBuffer | string): number | Promise; - end(): number | Promise; - flush(): number | Promise; - start(): void; -} - -declare var ReadableStreamDefaultController: { - prototype: ReadableStreamDefaultController; - new (): ReadableStreamDefaultController; -}; - -interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { - read(): Promise>; - /** - * Only available in Bun. If there are multiple chunks in the queue, this will return all of them at the same time. - * Will only return a promise if the data is not immediately available. - */ - readMany(): Promise> | Bun.ReadableStreamDefaultReadManyResult; - releaseLock(): void; -} - -declare var ReadableStreamDefaultReader: { - prototype: ReadableStreamDefaultReader; - new (stream: ReadableStream): ReadableStreamDefaultReader; -}; - -interface ReadableStreamGenericReader { - readonly closed: Promise; - cancel(reason?: any): Promise; -} - -interface ReadableStreamDefaultReadDoneResult { - done: true; - value?: undefined; -} - -interface ReadableStreamDefaultReadValueResult { - done: false; - value: T; -} - -interface ReadableWritablePair { - readable: ReadableStream; - /** - * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - */ - writable: WritableStream; -} - -interface WritableStreamDefaultController { - error(e?: any): void; -} - -declare var WritableStreamDefaultController: { - prototype: WritableStreamDefaultController; - new (): WritableStreamDefaultController; -}; - -/** This Streams API interface is the object returned by WritableStream.getWriter() and once created locks the < writer to the WritableStream ensuring that no other streams can write to the underlying sink. */ -interface WritableStreamDefaultWriter { - readonly closed: Promise; - readonly desiredSize: number | null; - readonly ready: Promise; - abort(reason?: any): Promise; - close(): Promise; - releaseLock(): void; - write(chunk?: W): Promise; -} - -declare var WritableStreamDefaultWriter: { - prototype: WritableStreamDefaultWriter; - new (stream: WritableStream): WritableStreamDefaultWriter; -}; - -interface TransformStream { - readonly readable: ReadableStream; - readonly writable: WritableStream; -} - -declare var TransformStream: { - prototype: TransformStream; - new ( - transformer?: Transformer, - writableStrategy?: QueuingStrategy, - readableStrategy?: QueuingStrategy, - ): TransformStream; -}; - -interface TransformStreamDefaultController { - readonly desiredSize: number | null; - enqueue(chunk?: O): void; - error(reason?: any): void; - terminate(): void; -} - -declare var TransformStreamDefaultController: { - prototype: TransformStreamDefaultController; - new (): TransformStreamDefaultController; -}; - -interface StreamPipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - /** - * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. - * - * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. - * - * Errors and closures of the source and destination streams propagate as follows: - * - * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. - * - * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. - * - * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. - * - * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. - * - * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. - */ - preventClose?: boolean; - signal?: AbortSignal; -} - -/** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ -interface CountQueuingStrategy extends QueuingStrategy { - readonly highWaterMark: number; - readonly size: QueuingStrategySize; -} - -declare var CountQueuingStrategy: { - prototype: CountQueuingStrategy; - new (init: QueuingStrategyInit): CountQueuingStrategy; -}; - -interface QueuingStrategySize { - (chunk?: T): number; -} - -interface Transformer { - flush?: Bun.TransformerFlushCallback; - readableType?: undefined; - start?: Bun.TransformerStartCallback; - transform?: Bun.TransformerTransformCallback; - writableType?: undefined; -} - -interface Dict { - [key: string]: T | undefined; -} - -interface ReadOnlyDict { - readonly [key: string]: T | undefined; -} - -interface ErrnoException extends Error { - errno?: number | undefined; - code?: string | undefined; - path?: string | undefined; - syscall?: string | undefined; -} - -/** An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. */ -interface DOMException extends Error { - readonly message: string; - readonly name: string; - readonly INDEX_SIZE_ERR: 1; - readonly DOMSTRING_SIZE_ERR: 2; - readonly HIERARCHY_REQUEST_ERR: 3; - readonly WRONG_DOCUMENT_ERR: 4; - readonly INVALID_CHARACTER_ERR: 5; - readonly NO_DATA_ALLOWED_ERR: 6; - readonly NO_MODIFICATION_ALLOWED_ERR: 7; - readonly NOT_FOUND_ERR: 8; - readonly NOT_SUPPORTED_ERR: 9; - readonly INUSE_ATTRIBUTE_ERR: 10; - readonly INVALID_STATE_ERR: 11; - readonly SYNTAX_ERR: 12; - readonly INVALID_MODIFICATION_ERR: 13; - readonly NAMESPACE_ERR: 14; - readonly INVALID_ACCESS_ERR: 15; - readonly VALIDATION_ERR: 16; - readonly TYPE_MISMATCH_ERR: 17; - readonly SECURITY_ERR: 18; - readonly NETWORK_ERR: 19; - readonly ABORT_ERR: 20; - readonly URL_MISMATCH_ERR: 21; - readonly QUOTA_EXCEEDED_ERR: 22; - readonly TIMEOUT_ERR: 23; - readonly INVALID_NODE_TYPE_ERR: 24; - readonly DATA_CLONE_ERR: 25; -} - -// declare var DOMException: { -// prototype: DOMException; -// new (message?: string, name?: string): DOMException; -// }; - -declare function alert(message?: string): void; -declare function confirm(message?: string): boolean; -declare function prompt(message?: string, _default?: string): string | null; - -interface SubtleCrypto extends Bun.__internal.NodeCryptoWebcryptoSubtleCrypto {} -declare var SubtleCrypto: { - prototype: SubtleCrypto; - new (): SubtleCrypto; -}; - -interface CryptoKey extends Bun.__internal.NodeCryptoWebcryptoCryptoKey {} -declare var CryptoKey: { - prototype: CryptoKey; - new (): CryptoKey; -}; - -interface Position { - lineText: string; - file: string; - namespace: string; - line: number; - column: number; - length: number; - offset: number; -} - -declare class ResolveMessage { - readonly name: "ResolveMessage"; - readonly position: Position | null; - readonly code: string; - readonly message: string; - readonly referrer: string; - readonly specifier: string; - readonly importKind: - | "entry_point" - | "stmt" - | "require" - | "import" - | "dynamic" - | "require_resolve" - | "at" - | "at_conditional" - | "url" - | "internal"; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; - - toString(): string; -} - -declare class BuildMessage { - readonly name: "BuildMessage"; - readonly position: Position | null; - readonly message: string; - readonly level: "error" | "warning" | "info" | "debug" | "verbose"; -} - -// Declare "static" methods in Error -interface ErrorConstructor { - /** Create .stack property on a target object */ - - captureStackTrace(targetObject: object, constructorOpt?: Function): void; - - /** - * Optional override for formatting stack traces - * - * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces - */ - prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined; - - stackTraceLimit: number; -} - -interface ArrayBufferConstructor { - new (byteLength: number, options: { maxByteLength?: number }): ArrayBuffer; -} - -interface ArrayBuffer { - /** - * Read-only. The length of the ArrayBuffer (in bytes). - */ - readonly byteLength: number; - /** - * Resize an ArrayBuffer in-place. - */ - resize(byteLength: number): ArrayBuffer; - - /** - * Returns a section of an ArrayBuffer. - */ - slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; -} - -interface SharedArrayBuffer { - /** - * Grow the SharedArrayBuffer in-place. - */ - grow(size: number): SharedArrayBuffer; -} - -interface ArrayConstructor { - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync(arrayLike: AsyncIterable | Iterable | ArrayLike): Promise[]>; - - /** - * Create an array from an iterable or async iterable object. - * Values from the iterable are awaited. Results of the map function are also awaited. - * - * ```ts - * await Array.fromAsync([1]); // [1] - * await Array.fromAsync([Promise.resolve(1)]); // [1] - * await Array.fromAsync((async function*() { yield 1 })()); // [1] - * await Array.fromAsync([1], (n) => n + 1); // [2] - * await Array.fromAsync([1], (n) => Promise.resolve(n + 1)); // [2] - * ``` - * - * @param arrayLike - The iterable or async iterable to convert to an array. - * @param mapFn - A mapper function that transforms each element of `arrayLike` after awaiting them. - * @param thisArg - The `this` to which `mapFn` is bound. - * @returns A {@link Promise} whose fulfillment is a new {@link Array} instance containing the values from the iterator. - */ - fromAsync( - arrayLike: AsyncIterable | Iterable | ArrayLike, - mapFn?: (value: T, index: number) => U, - thisArg?: any, - ): Promise[]>; -} - -interface ConsoleOptions { - stdout: import("stream").Writable; - stderr?: import("stream").Writable; - ignoreErrors?: boolean; - colorMode?: boolean | "auto"; - inspectOptions?: import("util").InspectOptions; - groupIndentation?: number; -} - -interface Console { - /** - * Asynchronously read lines from standard input (fd 0) - * - * ```ts - * for await (const line of console) { - * console.log(line); - * } - * ``` - */ - [Symbol.asyncIterator](): AsyncIterableIterator; - - /** - * Write text or bytes to stdout - * - * Unlike {@link console.log}, this does no formatting and doesn't add a - * newline or spaces between arguments. You can pass it strings or bytes or - * any combination of the two. - * - * ```ts - * console.write("hello world!", "\n"); // "hello world\n" - * ``` - * - * @param data - The data to write - * @returns The number of bytes written - * - * This function is not available in the browser. - */ - write(...data: Array): number; - - /** - * Clear the console - */ - clear(): void; - - assert(condition?: boolean, ...data: any[]): void; - - /** - * Increment a [count](https://www.youtube.com/watch?v=2AoxCkySv34&t=22s) - * @param label label counter - */ - count(label?: string): void; - countReset(label?: string): void; - debug(...data: any[]): void; - dir(item?: any, options?: any): void; - dirxml(...data: any[]): void; - /** - * Log to stderr in your terminal - * - * Appears in red - * - * @param data something to display - */ - error(...data: any[]): void; - /** Does nothing currently */ - group(...data: any[]): void; - /** Does nothing currently */ - groupCollapsed(...data: any[]): void; - /** Does nothing currently */ - groupEnd(): void; - info(...data: any[]): void; - log(...data: any[]): void; - /** - * Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just - * logging the argument if it can't be parsed as tabular. - * - * ```js - * // These can't be parsed as tabular data - * console.table(Symbol()); - * // Symbol() - * - * console.table(undefined); - * // undefined - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ b โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ 'Y' โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ 2 โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * - * console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']); - * // โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ” - * // โ”‚ โ”‚ a โ”‚ - * // โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค - * // โ”‚ 0 โ”‚ 1 โ”‚ - * // โ”‚ 1 โ”‚ 'Z' โ”‚ - * // โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜ - * ``` - * @param properties Alternate properties for constructing the table. - */ - table(tabularData?: any, properties?: string[]): void; - /** - * Begin a timer to log with {@link console.timeEnd} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - time(label?: string): void; - /** - * End a timer to log with {@link console.time} - * - * @param label - The label to use for the timer - * - * ```ts - * console.time("how long????"); - * for (let i = 0; i < 999999; i++) { - * // do stuff - * let x = i * i; - * } - * console.timeEnd("how long????"); - * ``` - */ - timeEnd(label?: string): void; - timeLog(label?: string, ...data: any[]): void; - timeStamp(label?: string): void; - trace(...data: any[]): void; - warn(...data: any[]): void; - - /** - * Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr. - */ - // Console: { - // new (options: ConsoleOptions): Console; - // new ( - // stdout: import("stream").Writable, - // stderr?: import("stream").Writable, - // ignoreErrors?: boolean, - // ): Console; - // }; -} - -declare var console: Console; - -interface ImportMeta { - /** - * `file://` url string for the current module. - * - * @example - * ```ts - * console.log(import.meta.url); - * "file:///Users/me/projects/my-app/src/my-app.ts" - * ``` - */ - url: string; - /** - * Absolute path to the source file - */ - readonly path: string; - /** - * Absolute path to the directory containing the source file. - * - * Does not have a trailing slash - */ - readonly dir: string; - /** - * Filename of the source file - */ - readonly file: string; - /** - * The environment variables of the process - * - * ```ts - * import.meta.env === process.env - * ``` - */ - readonly env: NodeJS.ProcessEnv; - - /** - * @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead - * - * Resolve a module ID the same as if you imported it - * - * The `parent` argument is optional, and defaults to the current module's path. - */ - resolveSync(moduleId: string, parent?: string): string; - - /** - * Load a CommonJS module within an ES Module. Bun's transpiler rewrites all - * calls to `require` with `import.meta.require` when transpiling ES Modules - * for the runtime. - * - * Warning: **This API is not stable** and may change or be removed in the - * future. Use at your own risk. - */ - require: NodeJS.Require; - - /** - * Did the current file start the process? - * - * @example - * ```ts - * if (import.meta.main) { - * console.log("I started the process!"); - * } - * ``` - * - * @example - * ```ts - * console.log( - * import.meta.main === (import.meta.path === Bun.main) - * ) - * ``` - */ - readonly main: boolean; - - /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ - dirname: string; - - /** Alias of `import.meta.path`. Exists for Node.js compatibility */ - filename: string; -} - -/** - * NodeJS-style `require` function - * - * @param moduleId - The module ID to resolve - */ -declare var require: NodeJS.Require; - -/** Same as module.exports */ -declare var exports: any; - -interface NodeModule { - exports: any; -} - -declare var module: NodeModule; - -/** - * Creates a deep clone of an object. - * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone) - */ -declare function structuredClone(value: T, options?: Bun.StructuredSerializeOptions): T; - -/** - * Post a message to the parent thread. - * - * Only useful in a worker thread; calling this from the main thread does nothing. - */ -declare function postMessage(message: any, transfer?: Bun.Transferable[]): void; - -interface EventSourceInit { - withCredentials?: boolean; -} - -interface PromiseConstructor { - /** - * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called - * separately. - * - * This is useful when you want to return a Promise and have code outside the Promise - * resolve or reject it. - * - * ## Example - * ```ts - * const { promise, resolve, reject } = Promise.withResolvers(); - * - * setTimeout(() => { - * resolve("Hello world!"); - * }, 1000); - * - * await promise; // "Hello world!" - * ``` - * - * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers). - */ - withResolvers(): { - promise: Promise; - resolve: (value?: T | PromiseLike) => void; - reject: (reason?: any) => void; - }; -} - -interface Navigator { - readonly userAgent: string; - readonly platform: "MacIntel" | "Win32" | "Linux x86_64"; - readonly hardwareConcurrency: number; -} - -declare var navigator: Navigator; - -interface BlobPropertyBag { - /** Set a default "type". Not yet implemented. */ - type?: string; - /** Not implemented in Bun yet. */ - // endings?: "transparent" | "native"; -} - -interface WorkerOptions extends Bun.WorkerOptions {} - -interface Blob { - /** - * Read the data from the blob as a JSON object. - * - * This first decodes the data from UTF-8, then parses it as JSON. - */ - // eslint-disable-next-line @definitelytyped/no-unnecessary-generics - json(): Promise; - /** - * Read the data from the blob as a {@link FormData} object. - * - * This first decodes the data from UTF-8, then parses it as a - * `multipart/form-data` body or a `application/x-www-form-urlencoded` body. - * - * The `type` property of the blob is used to determine the format of the - * body. - * - * This is a non-standard addition to the `Blob` API, to make it conform more - * closely to the `BodyMixin` API. - */ - formData(): Promise; - arrayBuffer(): Promise; - /** - * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` - */ - bytes(): Promise; -} - -declare var Blob: Bun.__internal.UseLibDomIfAvailable< - "Blob", - { - prototype: Blob; - new (blobParts?: Bun.BlobPart[], options?: BlobPropertyBag): Blob; - } ->; - -interface Uint8Array { - /** - * Convert the Uint8Array to a base64 encoded string - * @returns The base64 encoded string representation of the Uint8Array - */ - toBase64(options?: { alphabet?: "base64" | "base64url"; omitPadding?: boolean }): string; - - /** - * Set the contents of the Uint8Array from a base64 encoded string - * @param base64 The base64 encoded string to decode into the array - * @param offset Optional starting index to begin setting the decoded bytes (default: 0) - */ - setFromBase64(base64: string, offset?: number): void; -} - -interface Uint8ArrayConstructor { - /** - * Create a new Uint8Array from a base64 encoded string - * @param base64 The base64 encoded string to convert to a Uint8Array - * @returns A new Uint8Array containing the decoded data - */ - fromBase64(base64: string): Uint8Array; -} - -interface BroadcastChannel {} -declare var BroadcastChannel: Bun.__internal.UseLibDomIfAvailable< - "BroadcastChannel", - import("node:worker_threads").BroadcastChannel ->; - -declare var URL: Bun.__internal.UseLibDomIfAvailable< - "URL", - { - prototype: URL; - new (url: string | URL, base?: string | URL): URL; - /** - * Check if a URL can be parsed. - * - * @param url - The URL to check. - * @param base - The base URL to use. - */ - canParse(url: string, base?: string): boolean; - /** - * Create a URL from an object. - * - * @param object - The object to create a URL from. - */ - createObjectURL(object: Blob): `blob:${string}`; - /** - * Revoke a URL. - * - * @param url - The URL to revoke. - */ - revokeObjectURL(url: string): void; - } ->; - -declare var AbortController: Bun.__internal.UseLibDomIfAvailable< - "AbortController", - { - prototype: AbortController; - new (): AbortController; - } ->; - -declare var AbortSignal: Bun.__internal.UseLibDomIfAvailable< - "AbortSignal", - { - prototype: AbortSignal; - new (): AbortSignal; - } ->; - -interface DOMException {} -declare var DOMException: Bun.__internal.UseLibDomIfAvailable< - "DOMException", - { prototype: DOMException; new (): DOMException } ->; - -interface FormData {} -declare var FormData: Bun.__internal.UseLibDomIfAvailable<"FormData", { prototype: FormData; new (): FormData }>; - -interface EventSource {} -declare var EventSource: Bun.__internal.UseLibDomIfAvailable< - "EventSource", - { prototype: EventSource; new (): EventSource } ->; - -interface Performance extends Bun.__internal.LibPerformanceOrNodePerfHooksPerformance {} -declare var performance: Bun.__internal.UseLibDomIfAvailable<"performance", Performance>; - -interface PerformanceEntry {} -declare var PerformanceEntry: Bun.__internal.UseLibDomIfAvailable< - "PerformanceEntry", - { prototype: PerformanceEntry; new (): PerformanceEntry } ->; - -interface PerformanceMark {} -declare var PerformanceMark: Bun.__internal.UseLibDomIfAvailable< - "PerformanceMark", - { prototype: PerformanceMark; new (): PerformanceMark } ->; - -interface PerformanceMeasure {} -declare var PerformanceMeasure: Bun.__internal.UseLibDomIfAvailable< - "PerformanceMeasure", - { prototype: PerformanceMeasure; new (): PerformanceMeasure } ->; - -interface PerformanceObserver {} -declare var PerformanceObserver: Bun.__internal.UseLibDomIfAvailable< - "PerformanceObserver", - { prototype: PerformanceObserver; new (): PerformanceObserver } ->; - -interface PerformanceObserverEntryList {} -declare var PerformanceObserverEntryList: Bun.__internal.UseLibDomIfAvailable< - "PerformanceObserverEntryList", - { prototype: PerformanceObserverEntryList; new (): PerformanceObserverEntryList } ->; - -interface PerformanceResourceTiming {} -declare var PerformanceResourceTiming: Bun.__internal.UseLibDomIfAvailable< - "PerformanceResourceTiming", - { prototype: PerformanceResourceTiming; new (): PerformanceResourceTiming } ->; - -interface ReadableByteStreamController {} -declare var ReadableByteStreamController: Bun.__internal.UseLibDomIfAvailable< - "ReadableByteStreamController", - { prototype: ReadableByteStreamController; new (): ReadableByteStreamController } ->; - -interface ReadableStreamBYOBReader {} -declare var ReadableStreamBYOBReader: Bun.__internal.UseLibDomIfAvailable< - "ReadableStreamBYOBReader", - { prototype: ReadableStreamBYOBReader; new (): ReadableStreamBYOBReader } ->; - -interface ReadableStreamBYOBRequest {} -declare var ReadableStreamBYOBRequest: Bun.__internal.UseLibDomIfAvailable< - "ReadableStreamBYOBRequest", - { prototype: ReadableStreamBYOBRequest; new (): ReadableStreamBYOBRequest } ->; - -interface TextDecoderStream {} -declare var TextDecoderStream: Bun.__internal.UseLibDomIfAvailable< - "TextDecoderStream", - { prototype: TextDecoderStream; new (): TextDecoderStream } ->; - -interface TextEncoderStream {} -declare var TextEncoderStream: Bun.__internal.UseLibDomIfAvailable< - "TextEncoderStream", - { prototype: TextEncoderStream; new (): TextEncoderStream } ->; - -interface URLSearchParams {} -declare var URLSearchParams: Bun.__internal.UseLibDomIfAvailable< - "URLSearchParams", - { prototype: URLSearchParams; new (): URLSearchParams } ->; - -interface MessageChannel {} -declare var MessageChannel: Bun.__internal.UseLibDomIfAvailable< - "MessageChannel", - { prototype: MessageChannel; new (): MessageChannel } ->; - -interface MessagePort {} -declare var MessagePort: Bun.__internal.UseLibDomIfAvailable< - "MessagePort", - { - prototype: MessagePort; - new (): MessagePort; - } ->; diff --git a/packages/bun-types/new/html-rewriter.d.ts b/packages/bun-types/new/html-rewriter.d.ts deleted file mode 100644 index 4b2b2954cff397..00000000000000 --- a/packages/bun-types/new/html-rewriter.d.ts +++ /dev/null @@ -1,184 +0,0 @@ -declare namespace HTMLRewriterTypes { - interface HTMLRewriterElementContentHandlers { - element?(element: Element): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - } - - interface HTMLRewriterDocumentContentHandlers { - doctype?(doctype: Doctype): void | Promise; - comments?(comment: Comment): void | Promise; - text?(text: Text): void | Promise; - end?(end: DocumentEnd): void | Promise; - } - - interface Text { - /** The text content */ - readonly text: string; - /** Whether this chunk is the last piece of text in a text node */ - readonly lastInTextNode: boolean; - /** Whether this chunk was removed */ - readonly removed: boolean; - /** Insert content before this chunk */ - before(content: Content, options?: ContentOptions): Text; - /** Insert content after this chunk */ - after(content: Content, options?: ContentOptions): Text; - /** Replace this chunk with new content */ - replace(content: Content, options?: ContentOptions): Text; - /** Remove this chunk */ - remove(): Text; - } - - interface Doctype { - /** The doctype name (e.g. "html" for ) */ - readonly name: string | null; - /** The doctype public identifier */ - readonly publicId: string | null; - /** The doctype system identifier */ - readonly systemId: string | null; - /** Whether this doctype was removed */ - readonly removed: boolean; - /** Remove this doctype */ - remove(): Doctype; - } - - interface DocumentEnd { - /** Append content at the end of the document */ - append(content: Content, options?: ContentOptions): DocumentEnd; - } - - interface ContentOptions { - /** Whether to parse the content as HTML */ - html?: boolean; - } - - type Content = string; - - interface Comment { - /** The comment text */ - text: string; - /** Whether this comment was removed */ - readonly removed: boolean; - /** Insert content before this comment */ - before(content: Content, options?: ContentOptions): Comment; - /** Insert content after this comment */ - after(content: Content, options?: ContentOptions): Comment; - /** Replace this comment with new content */ - replace(content: Content, options?: ContentOptions): Comment; - /** Remove this comment */ - remove(): Comment; - } - - interface Element { - /** The tag name in lowercase (e.g. "div", "span") */ - tagName: string; - /** Iterator for the element's attributes */ - readonly attributes: IterableIterator<[string, string]>; - /** Whether this element was removed */ - readonly removed: boolean; - /** Whether the element is explicitly self-closing, e.g. */ - readonly selfClosing: boolean; - /** - * Whether the element can have inner content. Returns `true` unless - * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements) - * - or it's self-closing in a foreign context (eg. in SVG, MathML). - */ - readonly canHaveContent: boolean; - /** The element's namespace URI */ - readonly namespaceURI: string; - /** Get an attribute value by name */ - getAttribute(name: string): string | null; - /** Check if an attribute exists */ - hasAttribute(name: string): boolean; - /** Set an attribute value */ - setAttribute(name: string, value: string): Element; - /** Remove an attribute */ - removeAttribute(name: string): Element; - /** Insert content before this element */ - before(content: Content, options?: ContentOptions): Element; - /** Insert content after this element */ - after(content: Content, options?: ContentOptions): Element; - /** Insert content at the start of this element */ - prepend(content: Content, options?: ContentOptions): Element; - /** Insert content at the end of this element */ - append(content: Content, options?: ContentOptions): Element; - /** Replace this element with new content */ - replace(content: Content, options?: ContentOptions): Element; - /** Remove this element and its contents */ - remove(): Element; - /** Remove this element but keep its contents */ - removeAndKeepContent(): Element; - /** Set the inner content of this element */ - setInnerContent(content: Content, options?: ContentOptions): Element; - /** Add a handler for the end tag of this element */ - onEndTag(handler: (tag: EndTag) => void | Promise): void; - } - - interface EndTag { - /** The tag name in lowercase */ - name: string; - /** Insert content before this end tag */ - before(content: Content, options?: ContentOptions): EndTag; - /** Insert content after this end tag */ - after(content: Content, options?: ContentOptions): EndTag; - /** Remove this end tag */ - remove(): EndTag; - } -} - -/** - * [HTMLRewriter](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter?bun) is a fast API for transforming HTML. - * - * Bun leverages a native implementation powered by [lol-html](https://github.com/cloudflare/lol-html). - * - * HTMLRewriter can be used to transform HTML in a variety of ways, including: - * * Rewriting URLs - * * Adding meta tags - * * Removing elements - * * Adding elements to the head - * - * @example - * ```ts - * const rewriter = new HTMLRewriter().on('a[href]', { - * element(element: Element) { - * // Rewrite all the URLs to this youtube video - * element.setAttribute('href', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); - * } - * }); - * rewriter.transform(await fetch("https://remix.run")); - * ``` - */ -declare class HTMLRewriter { - constructor(); - /** - * Add handlers for elements matching a CSS selector - * @param selector - A CSS selector (e.g. "div", "a[href]", ".class") - * @param handlers - Object containing handler functions for elements, comments, and text nodes - */ - on(selector: string, handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers): HTMLRewriter; - - /** - * Add handlers for document-level events - * @param handlers - Object containing handler functions for doctype, comments, text nodes and document end - */ - onDocument(handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers): HTMLRewriter; - - /** - * Transform HTML content - * @param input - The HTML to transform - * @returns A new {@link Response} with the transformed HTML - */ - transform(input: Response | Blob | Bun.BufferSource): Response; - /** - * Transform HTML content - * @param input - The HTML string to transform - * @returns A new {@link String} containing the transformed HTML - */ - transform(input: string): string; - /** - * Transform HTML content - * @param input - The HTML to transform as a {@link ArrayBuffer} - * @returns A new {@link ArrayBuffer} with the transformed HTML - */ - transform(input: ArrayBuffer): ArrayBuffer; -} diff --git a/packages/bun-types/new/index.d.ts b/packages/bun-types/new/index.d.ts deleted file mode 100644 index 0060cdd11a22b9..00000000000000 --- a/packages/bun-types/new/index.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Project: https://github.com/oven-sh/bun -// Definitions by: Bun Contributors -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - -/// - -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// - -/// - -// @ts-ignore Must disable this so it doesn't conflict with the DOM onmessage type, but still -// allows us to declare our own globals that Node's types can "see" and not conflict with -declare var onmessage: never; diff --git a/packages/bun-types/new/jsc.d.ts b/packages/bun-types/new/jsc.d.ts deleted file mode 100644 index 2a07534586516c..00000000000000 --- a/packages/bun-types/new/jsc.d.ts +++ /dev/null @@ -1,229 +0,0 @@ -declare module "bun:jsc" { - /** - * This used to be called "describe" but it could be confused with the test runner. - */ - function jscDescribe(value: any): string; - function jscDescribeArray(args: any[]): string; - function gcAndSweep(): number; - function fullGC(): number; - function edenGC(): number; - function heapSize(): number; - function heapStats(): { - heapSize: number; - heapCapacity: number; - extraMemorySize: number; - objectCount: number; - protectedObjectCount: number; - globalObjectCount: number; - protectedGlobalObjectCount: number; - objectTypeCounts: Record; - protectedObjectTypeCounts: Record; - }; - function memoryUsage(): { - current: number; - peak: number; - currentCommit: number; - peakCommit: number; - pageFaults: number; - }; - function getRandomSeed(): number; - function setRandomSeed(value: number): void; - function isRope(input: string): boolean; - function callerSourceOrigin(): string; - function noFTL(func: (...args: any[]) => any): (...args: any[]) => any; - function noOSRExitFuzzing(func: (...args: any[]) => any): (...args: any[]) => any; - function optimizeNextInvocation(func: (...args: any[]) => any): void; - function numberOfDFGCompiles(func: (...args: any[]) => any): number; - function releaseWeakRefs(): void; - function totalCompileTime(func: (...args: any[]) => any): number; - function reoptimizationRetryCount(func: (...args: any[]) => any): number; - function drainMicrotasks(): void; - - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A SharedArrayBuffer that can be sent to another Bun instance. - */ - function serialize(value: any, options?: { binaryType?: "arraybuffer" }): SharedArrayBuffer; - - /** - * Convert a JavaScript value to a binary representation that can be sent to another Bun instance. - * - * Internally, this uses the serialization format from WebKit/Safari. - * - * @param value A JavaScript value, usually an object or array, to be converted. - * @returns A Buffer that can be sent to another Bun instance. - */ - function serialize(value: any, options?: { binaryType: "nodebuffer" }): Buffer; - - /** - * Convert an ArrayBuffer or Buffer to a JavaScript value compatible with the HTML Structured Clone Algorithm. - * - * @param value A serialized value, usually an ArrayBuffer or Buffer, to be converted. - */ - function deserialize(value: ArrayBufferLike | NodeJS.TypedArray | Buffer): any; - - /** - * Set the timezone used by Intl, Date, etc. - * - * @param timeZone A string representing the time zone to use, such as "America/Los_Angeles" - * - * @returns The normalized time zone string - * - * You can also set process.env.TZ to the time zone you want to use. - * You can also view the current timezone with `Intl.DateTimeFormat().resolvedOptions().timeZone` - */ - function setTimeZone(timeZone: string): string; - - interface SamplingProfile { - /** - * A formatted summary of the top functions - * - * Example output: - * ```js - * - * Sampling rate: 100.000000 microseconds. Total samples: 6858 - * Top functions as - * 2948 '#:8' - * 393 'visit#:8' - * 263 'push#:8' - * 164 'scan_ref_scoped#:8' - * 164 'walk#:8' - * 144 'pop#:8' - * 107 'extract_candidates#:8' - * 94 'get#:8' - * 82 'Function#:4294967295' - * 79 'set#:8' - * 67 'forEach#:5' - * 58 'collapse#:8' - * ``` - */ - functions: string; - /** - * A formatted summary of the top bytecodes - * - * Example output: - * ```js - * Tier breakdown: - * ----------------------------------- - * LLInt: 106 (1.545640%) - * Baseline: 2355 (34.339458%) - * DFG: 3290 (47.973170%) - * FTL: 833 (12.146398%) - * js builtin: 132 (1.924759%) - * Wasm: 0 (0.000000%) - * Host: 111 (1.618548%) - * RegExp: 15 (0.218723%) - * C/C++: 0 (0.000000%) - * Unknown Executable: 148 (2.158064%) - * - * Hottest bytecodes as - * 273 'visit#:DFG:bc#63' - * 121 'walk#:DFG:bc#7' - * 119 '#:Baseline:bc#1' - * 82 'Function#:None:' - * 66 '#:DFG:bc#11' - * 65 '#:DFG:bc#33' - * 58 '#:Baseline:bc#7' - * 53 '#:Baseline:bc#23' - * 50 'forEach#:DFG:bc#83' - * 49 'pop#:FTL:bc#65' - * 47 '#:DFG:bc#99' - * 45 '#:DFG:bc#16' - * 44 '#:DFG:bc#7' - * 44 '#:Baseline:bc#30' - * 44 'push#:FTL:bc#214' - * 41 '#:DFG:bc#50' - * 39 'get#:DFG:bc#27' - * 39 '#:Baseline:bc#0' - * 36 '#:DFG:bc#27' - * 36 'Dictionary#:DFG:bc#41' - * 36 'visit#:DFG:bc#81' - * 36 'get#:FTL:bc#11' - * 32 'push#:FTL:bc#49' - * 31 '#:DFG:bc#76' - * 31 '#:DFG:bc#10' - * 31 '#:DFG:bc#73' - * 29 'set#:DFG:bc#28' - * 28 'in_boolean_context#:DFG:bc#104' - * 28 '#:Baseline:' - * 28 'regExpSplitFast#:None:' - * 26 'visit#:DFG:bc#95' - * 26 'pop#:FTL:bc#120' - * 25 '#:DFG:bc#23' - * 25 'push#:FTL:bc#152' - * 24 'push#:FTL:bc#262' - * 24 '#:FTL:bc#10' - * 23 'is_identifier_char#:DFG:bc#22' - * 23 'visit#:DFG:bc#22' - * 22 '#:FTL:bc#27' - * 22 'indexOf#:None:' - * ``` - */ - bytecodes: string; - - /** - * Stack traces of the top functions - */ - stackTraces: string[]; - } - - /** - * Run JavaScriptCore's sampling profiler for a particular function - * - * This is pretty low-level. - * - * Things to know: - * - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation - * - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile - * - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile - * - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile - */ - function profile any>( - callback: T, - sampleInterval?: number, - ...args: Parameters - ): ReturnType extends Promise ? Promise : SamplingProfile; - - /** - * This returns objects which native code has explicitly protected from being - * garbage collected - * - * By calling this function you create another reference to the object, which - * will further prevent it from being garbage collected - * - * This function is mostly a debugging tool for bun itself. - * - * Warning: not all objects returned are supposed to be observable from JavaScript - */ - function getProtectedObjects(): any[]; - - /** - * Start a remote debugging socket server on the given port. - * - * This exposes JavaScriptCore's built-in debugging server. - * - * This is untested. May not be supported yet on macOS - */ - function startRemoteDebugger(host?: string, port?: number): void; - - /** - * Run JavaScriptCore's sampling profiler - */ - function startSamplingProfiler(optionalDirectory?: string): void; - - /** - * Non-recursively estimate the memory usage of an object, excluding the memory usage of - * properties or other objects it references. For more accurate per-object - * memory usage, use {@link Bun.generateHeapSnapshot}. - * - * This is a best-effort estimate. It may not be 100% accurate. When it's - * wrong, it may mean the memory is non-contiguous (such as a large array). - * - * Passing a primitive type that isn't heap allocated returns 0. - */ - function estimateShallowMemoryUsageOf(value: object | CallableFunction | bigint | symbol | string): number; -} diff --git a/packages/bun-types/new/overrides.d.ts b/packages/bun-types/new/overrides.d.ts deleted file mode 100644 index 03ad7b0bf2cff4..00000000000000 --- a/packages/bun-types/new/overrides.d.ts +++ /dev/null @@ -1,79 +0,0 @@ -export {}; - -declare global { - namespace NodeJS { - interface Process { - readonly version: string; - browser: boolean; - - /** - * Whether you are using Bun - */ - isBun: true; - - /** - * The current git sha of Bun - */ - revision: string; - - reallyExit(code?: number): never; - dlopen(module: { exports: any }, filename: string, flags?: number): void; - } - - interface ProcessVersions extends Dict { - bun: string; - } - } -} - -declare module "fs/promises" { - function exists(path: Bun.PathLike): Promise; -} - -declare module "tls" { - interface BunConnectionOptions extends Omit { - /** - * Optionally override the trusted CA certificates. Default is to trust - * the well-known CAs curated by Mozilla. Mozilla's CAs are completely - * replaced when CAs are explicitly specified using this option. - */ - ca?: string | Buffer | NodeJS.TypedArray | Bun.BunFile | Array | undefined; - /** - * Cert chains in PEM format. One cert chain should be provided per - * private key. Each cert chain should consist of the PEM formatted - * certificate for a provided private key, followed by the PEM - * formatted intermediate certificates (if any), in order, and not - * including the root CA (the root CA must be pre-known to the peer, - * see ca). When providing multiple cert chains, they do not have to - * be in the same order as their private keys in key. If the - * intermediate certificates are not provided, the peer will not be - * able to validate the certificate, and the handshake will fail. - */ - cert?: - | string - | Buffer - | NodeJS.TypedArray - | Bun.BunFile - | Array - | undefined; - /** - * Private keys in PEM format. PEM allows the option of private keys - * being encrypted. Encrypted keys will be decrypted with - * options.passphrase. Multiple keys using different algorithms can be - * provided either as an array of unencrypted key strings or buffers, - * or an array of objects in the form {pem: [, - * passphrase: ]}. The object form can only occur in an array. - * object.passphrase is optional. Encrypted keys will be decrypted with - * object.passphrase if provided, or options.passphrase if it is not. - */ - key?: - | string - | Buffer - | Bun.BunFile - | NodeJS.TypedArray - | Array - | undefined; - } - - function connect(options: BunConnectionOptions, secureConnectListener?: () => void): TLSSocket; -} diff --git a/packages/bun-types/new/sqlite.d.ts b/packages/bun-types/new/sqlite.d.ts deleted file mode 100644 index dd370d3f46bcc2..00000000000000 --- a/packages/bun-types/new/sqlite.d.ts +++ /dev/null @@ -1,1141 +0,0 @@ -/** - * Fast SQLite3 driver for Bun.js - * @since v0.0.83 - * - * @example - * ```ts - * import { Database } from 'bun:sqlite'; - * - * var db = new Database('app.db'); - * db.query('SELECT * FROM users WHERE name = ?').all('John'); - * // => [{ id: 1, name: 'John' }] - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ -declare module "bun:sqlite" { - export class Database implements Disposable { - /** - * Open or create a SQLite3 database - * - * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database. - * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags. - * - * @example - * - * ```ts - * const db = new Database("mydb.sqlite"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open an in-memory database - * - * ```ts - * const db = new Database(":memory:"); - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]); - * console.log(db.query("SELECT * FROM foo").all()); - * ``` - * - * @example - * - * Open read-only - * - * ```ts - * const db = new Database("mydb.sqlite", {readonly: true}); - * ``` - */ - constructor( - filename?: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; - - /** - * When set to `true`, integers are returned as `bigint` types. - * - * When set to `false`, integers are returned as `number` types and truncated to 52 bits. - * - * @default false - * @since v1.1.14 - */ - safeIntegers?: boolean; - - /** - * When set to `false` or `undefined`: - * - Queries missing bound parameters will NOT throw an error - * - Bound named parameters in JavaScript need to exactly match the SQL query. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: false }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" }); - * ``` - * - * When set to `true`: - * - Queries missing bound parameters will throw an error - * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed. - * - * @example - * ```ts - * const db = new Database(":memory:", { strict: true }); - * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" }); - * ``` - * @since v1.1.14 - */ - strict?: boolean; - }, - ); - - /** - * This is an alias of `new Database()` - * - * See {@link Database} - */ - static open( - filename: string, - options?: - | number - | { - /** - * Open the database as read-only (no write operations, no create). - * - * Equivalent to {@link constants.SQLITE_OPEN_READONLY} - */ - readonly?: boolean; - /** - * Allow creating a new database - * - * Equivalent to {@link constants.SQLITE_OPEN_CREATE} - */ - create?: boolean; - /** - * Open the database as read-write - * - * Equivalent to {@link constants.SQLITE_OPEN_READWRITE} - */ - readwrite?: boolean; - }, - ): Database; - - /** - * Execute a SQL query **without returning any results**. - * - * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead. - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * ``` - * - * Useful for queries like: - * - `CREATE TABLE` - * - `INSERT INTO` - * - `UPDATE` - * - `DELETE FROM` - * - `DROP TABLE` - * - `PRAGMA` - * - `ATTACH DATABASE` - * - `DETACH DATABASE` - * - `REINDEX` - * - `VACUUM` - * - `EXPLAIN ANALYZE` - * - `CREATE INDEX` - * - `CREATE TRIGGER` - * - `CREATE VIEW` - * - `CREATE VIRTUAL TABLE` - * - `CREATE TEMPORARY TABLE` - * - * @param sql The SQL query to run - * - * @param bindings Optional bindings for the query - * - * @returns `Database` instance - * - * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`. - * - * * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(sqlQuery: string, ...bindings: ParamsType[]): Changes; - /** - This is an alias of {@link Database.prototype.run} - */ - exec(sqlQuery: string, ...bindings: ParamsType[]): Changes; - - /** - * Compile a SQL query and return a {@link Statement} object. This is the - * same as {@link prepare} except that it caches the compiled query. - * - * This **does not execute** the query, but instead prepares it for later - * execution and caches the compiled query if possible. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * - * // run the query again - * stmt.all(); - * ``` - * - * @param sql The SQL query to compile - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - query( - sqlQuery: string, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; - - /** - * Compile a SQL query and return a {@link Statement} object. - * - * This does not cache the compiled query and does not execute the query. - * - * @example - * ```ts - * // compile the query - * const stmt = db.query("SELECT * FROM foo WHERE bar = ?"); - * // run the query - * stmt.all("baz"); - * ``` - * - * @param sql The SQL query to compile - * @param params Optional bindings for the query - * - * @returns `Statment` instance - * - * Under the hood, this calls `sqlite3_prepare_v3`. - */ - prepare( - sqlQuery: string, - params?: ParamsType, - ): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type - Statement; - - /** - * Is the database in a transaction? - * - * @returns `true` if the database is in a transaction, `false` otherwise - * - * @example - * ```ts - * db.run("CREATE TABLE foo (bar TEXT)"); - * db.run("INSERT INTO foo VALUES (?)", ["baz"]); - * db.run("BEGIN"); - * db.run("INSERT INTO foo VALUES (?)", ["qux"]); - * console.log(db.inTransaction()); - * ``` - */ - get inTransaction(): boolean; - - /** - * Close the database connection. - * - * It is safe to call this method multiple times. If the database is already - * closed, this is a no-op. Running queries after the database has been - * closed will throw an error. - * - * @example - * ```ts - * db.close(); - * ``` - * This is called automatically when the database instance is garbage collected. - * - * Internally, this calls `sqlite3_close_v2`. - */ - close( - /** - * If `true`, then the database will throw an error if it is in use - * @default false - * - * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`. - * - * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html). - * - * Bun will automatically call close by default when the database instance is garbage collected. - * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default. - */ - throwOnError?: boolean, - ): void; - - /** - * The filename passed when `new Database()` was called - * @example - * ```ts - * const db = new Database("mydb.sqlite"); - * console.log(db.filename); - * // => "mydb.sqlite" - * ``` - */ - readonly filename: string; - - /** - * The underlying `sqlite3` database handle - * - * In native code, this is not a file descriptor, but an index into an array of database handles - */ - readonly handle: number; - - /** - * Load a SQLite3 extension - * - * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite} - * - * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement. - * - * @param extension name/path of the extension to load - * @param entryPoint optional entry point of the extension - */ - loadExtension(extension: string, entryPoint?: string): void; - - /** - * Change the dynamic library path to SQLite - * - * @note macOS-only - * - * This only works before SQLite is loaded, so - * that's before you call `new Database()`. - * - * It can only be run once because this will load - * the SQLite library into the process. - * - * @param path The path to the SQLite library - */ - static setCustomSQLite(path: string): boolean; - - [Symbol.dispose](): void; - - /** - * Creates a function that always runs inside a transaction. When the - * function is invoked, it will begin a new transaction. When the function - * returns, the transaction will be committed. If an exception is thrown, - * the transaction will be rolled back (and the exception will propagate as - * usual). - * - * @param insideTransaction The callback which runs inside a transaction - * - * @example - * ```ts - * // setup - * import { Database } from "bun:sqlite"; - * const db = Database.open(":memory:"); - * db.exec( - * "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)" - * ); - * - * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); - * const insertMany = db.transaction((cats) => { - * for (const cat of cats) insert.run(cat); - * }); - * - * insertMany([ - * { $name: "Joey", $age: 2 }, - * { $name: "Sally", $age: 4 }, - * { $name: "Junior", $age: 1 }, - * ]); - * ``` - */ - transaction(insideTransaction: (...args: any) => void): CallableFunction & { - /** - * uses "BEGIN DEFERRED" - */ - deferred: (...args: any) => void; - /** - * uses "BEGIN IMMEDIATE" - */ - immediate: (...args: any) => void; - /** - * uses "BEGIN EXCLUSIVE" - */ - exclusive: (...args: any) => void; - }; - - /** - * Save the database to an in-memory {@link Buffer} object. - * - * Internally, this calls `sqlite3_serialize`. - * - * @param name Name to save the database as @default "main" - * @returns Buffer containing the serialized database - */ - serialize(name?: string): Buffer; - - /** - * Load a serialized SQLite3 database - * - * Internally, this calls `sqlite3_deserialize`. - * - * @param serialized Data to load - * @returns `Database` instance - * - * @example - * ```ts - * test("supports serialize/deserialize", () => { - * const db = Database.open(":memory:"); - * db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); - * db.exec('INSERT INTO test (name) VALUES ("Hello")'); - * db.exec('INSERT INTO test (name) VALUES ("World")'); - * - * const input = db.serialize(); - * const db2 = new Database(input); - * - * const stmt = db2.prepare("SELECT * FROM test"); - * expect(JSON.stringify(stmt.get())).toBe( - * JSON.stringify({ - * id: 1, - * name: "Hello", - * }), - * ); - * - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * ]), - * ); - * db2.exec("insert into test (name) values ('foo')"); - * expect(JSON.stringify(stmt.all())).toBe( - * JSON.stringify([ - * { - * id: 1, - * name: "Hello", - * }, - * { - * id: 2, - * name: "World", - * }, - * { - * id: 3, - * name: "foo", - * }, - * ]), - * ); - * - * const db3 = Database.deserialize(input, true); - * try { - * db3.exec("insert into test (name) values ('foo')"); - * throw new Error("Expected error"); - * } catch (e) { - * expect(e.message).toBe("attempt to write a readonly database"); - * } - * }); - * ``` - */ - static deserialize(serialized: NodeJS.TypedArray | ArrayBufferLike, isReadOnly?: boolean): Database; - - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(op: number, arg?: ArrayBufferView | number): number; - /** - * See `sqlite3_file_control` for more information. - * @link https://www.sqlite.org/c3ref/file_control.html - */ - fileControl(zDbName: string, op: number, arg?: ArrayBufferView | number): number; - } - - /** - * A prepared statement. - * - * This is returned by {@link Database.prepare} and {@link Database.query}. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.all("baz"); - * // => [{bar: "baz"}] - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.get("baz"); - * // => {bar: "baz"} - * ``` - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * stmt.run("baz"); - * // => undefined - * ``` - */ - export class Statement implements Disposable { - /** - * Creates a new prepared statement from native code. - * - * This is used internally by the {@link Database} class. Probably you don't need to call this yourself. - */ - constructor(nativeHandle: any); - - /** - * Execute the prepared statement and return all results as objects. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.all("baz"); - * // => [{bar: "baz"}] - * - * stmt.all(); - * // => [] - * - * stmt.all("foo"); - * // => [{bar: "foo"}] - * ``` - */ - all(...params: ParamsType): ReturnType[]; - - /** - * Execute the prepared statement and return **the first** result. - * - * If no result is returned, this returns `null`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.get("baz"); - * // => {bar: "baz"} - * - * stmt.get(); - * // => null - * - * stmt.get("foo"); - * // => {bar: "foo"} - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - get(...params: ParamsType): ReturnType | null; - - /** - * Execute the prepared statement and return an - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - */ - iterate(...params: ParamsType): IterableIterator; - [Symbol.iterator](): IterableIterator; - - /** - * Execute the prepared statement. This returns `undefined`. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("UPDATE foo SET bar = ?"); - * stmt.run("baz"); - * // => undefined - * - * stmt.run(); - * // => undefined - * - * stmt.run("foo"); - * // => undefined - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | -------------- | ----------- | - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - run(...params: ParamsType): Changes; - - /** - * Execute the prepared statement and return the results as an array of arrays. - * - * In Bun v0.6.7 and earlier, this method returned `null` if there were no - * results instead of `[]`. This was changed in v0.6.8 to align - * more with what people expect. - * - * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * - * stmt.values("baz"); - * // => [['baz']] - * - * stmt.values(); - * // => [['baz']] - * - * stmt.values("foo"); - * // => [['foo']] - * - * stmt.values("not-found"); - * // => [] - * ``` - * - * The following types can be used when binding parameters: - * - * | JavaScript type | SQLite type | - * | ---------------|-------------| - * | `string` | `TEXT` | - * | `number` | `INTEGER` or `DECIMAL` | - * | `boolean` | `INTEGER` (1 or 0) | - * | `Uint8Array` | `BLOB` | - * | `Buffer` | `BLOB` | - * | `bigint` | `INTEGER` | - * | `null` | `NULL` | - */ - values(...params: ParamsType): Array>; - - /** - * The names of the columns returned by the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?"); - * - * console.log(stmt.columnNames); - * // => ["bar"] - * ``` - */ - readonly columnNames: string[]; - - /** - * The number of parameters expected in the prepared statement. - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?"); - * console.log(stmt.paramsCount); - * // => 1 - * ``` - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?"); - * console.log(stmt.paramsCount); - * // => 2 - * ``` - */ - readonly paramsCount: number; - - /** - * Finalize the prepared statement, freeing the resources used by the - * statement and preventing it from being executed again. - * - * This is called automatically when the prepared statement is garbage collected. - * - * It is safe to call this multiple times. Calling this on a finalized - * statement has no effect. - * - * Internally, this calls `sqlite3_finalize`. - */ - finalize(): void; - - /** - * Calls {@link finalize} if it wasn't already called. - */ - [Symbol.dispose](): void; - - /** - * Return the expanded SQL string for the prepared statement. - * - * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`. - * - * @example - * ```ts - * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz"); - * console.log(stmt.toString()); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * console.log(stmt); - * // => "SELECT * FROM foo WHERE bar = 'baz'" - * ``` - */ - toString(): string; - - /** - * - * Make {@link get} and {@link all} return an instance of the provided - * `Class` instead of the default `Object`. - * - * @param Class A class to use - * @returns The same statement instance, modified to return an instance of `Class` - * - * This lets you attach methods, getters, and setters to the returned - * objects. - * - * For performance reasons, constructors for classes are not called, which means - * initializers will not be called and private fields will not be - * accessible. - * - * @example - * - * ## Custom class - * ```ts - * class User { - * rawBirthdate: string; - * get birthdate() { - * return new Date(this.rawBirthdate); - * } - * } - * - * const db = new Database(":memory:"); - * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)"); - * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')"); - * const query = db.query("SELECT * FROM users"); - * query.as(User); - * const user = query.get(); - * console.log(user.birthdate); - * // => Date(1995, 12, 19) - * ``` - */ - as(Class: new (...args: any[]) => T): Statement; - - /** - * Native object representing the underlying `sqlite3_stmt` - * - * This is left untyped because the ABI of the native bindings may change at any time. - */ - readonly native: any; - } - - /** - * Constants from `sqlite3.h` - * - * This list isn't exhaustive, but some of the ones which are relevant - */ - export const constants: { - /** - * Open the database as read-only (no write operations, no create). - * @constant 0x00000001 - */ - SQLITE_OPEN_READONLY: number; - /** - * Open the database for reading and writing - * @constant 0x00000002 - */ - SQLITE_OPEN_READWRITE: number; - /** - * Allow creating a new database - * @constant 0x00000004 - */ - SQLITE_OPEN_CREATE: number; - /** - * @constant 0x00000008 - */ - SQLITE_OPEN_DELETEONCLOSE: number; - /** - * @constant 0x00000010 - */ - SQLITE_OPEN_EXCLUSIVE: number; - /** - * @constant 0x00000020 - */ - SQLITE_OPEN_AUTOPROXY: number; - /** - * @constant 0x00000040 - */ - SQLITE_OPEN_URI: number; - /** - * @constant 0x00000080 - */ - SQLITE_OPEN_MEMORY: number; - /** - * @constant 0x00000100 - */ - SQLITE_OPEN_MAIN_DB: number; - /** - * @constant 0x00000200 - */ - SQLITE_OPEN_TEMP_DB: number; - /** - * @constant 0x00000400 - */ - SQLITE_OPEN_TRANSIENT_DB: number; - /** - * @constant 0x00000800 - */ - SQLITE_OPEN_MAIN_JOURNAL: number; - /** - * @constant 0x00001000 - */ - SQLITE_OPEN_TEMP_JOURNAL: number; - /** - * @constant 0x00002000 - */ - SQLITE_OPEN_SUBJOURNAL: number; - /** - * @constant 0x00004000 - */ - SQLITE_OPEN_SUPER_JOURNAL: number; - /** - * @constant 0x00008000 - */ - SQLITE_OPEN_NOMUTEX: number; - /** - * @constant 0x00010000 - */ - SQLITE_OPEN_FULLMUTEX: number; - /** - * @constant 0x00020000 - */ - SQLITE_OPEN_SHAREDCACHE: number; - /** - * @constant 0x00040000 - */ - SQLITE_OPEN_PRIVATECACHE: number; - /** - * @constant 0x00080000 - */ - SQLITE_OPEN_WAL: number; - /** - * @constant 0x01000000 - */ - SQLITE_OPEN_NOFOLLOW: number; - /** - * @constant 0x02000000 - */ - SQLITE_OPEN_EXRESCODE: number; - /** - * @constant 0x01 - */ - SQLITE_PREPARE_PERSISTENT: number; - /** - * @constant 0x02 - */ - SQLITE_PREPARE_NORMALIZE: number; - /** - * @constant 0x04 - */ - SQLITE_PREPARE_NO_VTAB: number; - - /** - * @constant 1 - */ - SQLITE_FCNTL_LOCKSTATE: number; - /** - * @constant 2 - */ - SQLITE_FCNTL_GET_LOCKPROXYFILE: number; - /** - * @constant 3 - */ - SQLITE_FCNTL_SET_LOCKPROXYFILE: number; - /** - * @constant 4 - */ - SQLITE_FCNTL_LAST_ERRNO: number; - /** - * @constant 5 - */ - SQLITE_FCNTL_SIZE_HINT: number; - /** - * @constant 6 - */ - SQLITE_FCNTL_CHUNK_SIZE: number; - /** - * @constant 7 - */ - SQLITE_FCNTL_FILE_POINTER: number; - /** - * @constant 8 - */ - SQLITE_FCNTL_SYNC_OMITTED: number; - /** - * @constant 9 - */ - SQLITE_FCNTL_WIN32_AV_RETRY: number; - /** - * @constant 10 - * - * Control whether or not the WAL is persisted - * Some versions of macOS configure WAL to be persistent by default. - * - * You can change this with code like the below: - * ```ts - * import { Database } from "bun:sqlite"; - * - * const db = Database.open("mydb.sqlite"); - * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0); - * // enable WAL - * db.exec("PRAGMA journal_mode = WAL"); - * // .. do some work - * db.close(); - * ``` - * - */ - SQLITE_FCNTL_PERSIST_WAL: number; - /** - * @constant 11 - */ - SQLITE_FCNTL_OVERWRITE: number; - /** - * @constant 12 - */ - SQLITE_FCNTL_VFSNAME: number; - /** - * @constant 13 - */ - SQLITE_FCNTL_POWERSAFE_OVERWRITE: number; - /** - * @constant 14 - */ - SQLITE_FCNTL_PRAGMA: number; - /** - * @constant 15 - */ - SQLITE_FCNTL_BUSYHANDLER: number; - /** - * @constant 16 - */ - SQLITE_FCNTL_TEMPFILENAME: number; - /** - * @constant 18 - */ - SQLITE_FCNTL_MMAP_SIZE: number; - /** - * @constant 19 - */ - SQLITE_FCNTL_TRACE: number; - /** - * @constant 20 - */ - SQLITE_FCNTL_HAS_MOVED: number; - /** - * @constant 21 - */ - SQLITE_FCNTL_SYNC: number; - /** - * @constant 22 - */ - SQLITE_FCNTL_COMMIT_PHASETWO: number; - /** - * @constant 23 - */ - SQLITE_FCNTL_WIN32_SET_HANDLE: number; - /** - * @constant 24 - */ - SQLITE_FCNTL_WAL_BLOCK: number; - /** - * @constant 25 - */ - SQLITE_FCNTL_ZIPVFS: number; - /** - * @constant 26 - */ - SQLITE_FCNTL_RBU: number; - /** - * @constant 27 - */ - SQLITE_FCNTL_VFS_POINTER: number; - /** - * @constant 28 - */ - SQLITE_FCNTL_JOURNAL_POINTER: number; - /** - * @constant 29 - */ - SQLITE_FCNTL_WIN32_GET_HANDLE: number; - /** - * @constant 30 - */ - SQLITE_FCNTL_PDB: number; - /** - * @constant 31 - */ - SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number; - /** - * @constant 32 - */ - SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number; - /** - * @constant 33 - */ - SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number; - /** - * @constant 34 - */ - SQLITE_FCNTL_LOCK_TIMEOUT: number; - /** - * @constant 35 - */ - SQLITE_FCNTL_DATA_VERSION: number; - /** - * @constant 36 - */ - SQLITE_FCNTL_SIZE_LIMIT: number; - /** - * @constant 37 - */ - SQLITE_FCNTL_CKPT_DONE: number; - /** - * @constant 38 - */ - SQLITE_FCNTL_RESERVE_BYTES: number; - /** - * @constant 39 - */ - SQLITE_FCNTL_CKPT_START: number; - /** - * @constant 40 - */ - SQLITE_FCNTL_EXTERNAL_READER: number; - /** - * @constant 41 - */ - SQLITE_FCNTL_CKSM_FILE: number; - /** - * @constant 42 - */ - SQLITE_FCNTL_RESET_CACHE: number; - }; - - /** - * The native module implementing the sqlite3 C bindings - * - * It is lazily-initialized, so this will return `undefined` until the first - * call to new Database(). - * - * The native module makes no gurantees about ABI stability, so it is left - * untyped - * - * If you need to use it directly for some reason, please let us know because - * that probably points to a deficiency in this API. - */ - export var native: any; - - export type SQLQueryBindings = - | string - | bigint - | NodeJS.TypedArray - | number - | boolean - | null - | Record; - - export default Database; - - /** - * Errors from SQLite have a name `SQLiteError`. - * - */ - export class SQLiteError extends Error { - readonly name: "SQLiteError"; - - /** - * The SQLite3 extended error code - * - * This corresponds to `sqlite3_extended_errcode`. - * - * @since v1.0.21 - */ - errno: number; - - /** - * The name of the SQLite3 error code - * - * @example - * "SQLITE_CONSTRAINT_UNIQUE" - * - * @since v1.0.21 - */ - code?: string; - - /** - * The UTF-8 byte offset of the sqlite3 query that failed, if known - * - * This corresponds to `sqlite3_error_offset`. - * - * @since v1.0.21 - */ - readonly byteOffset: number; - } - - /** - * An object representing the changes made to the database since the last `run` or `exec` call. - * - * @since Bun v1.1.14 - */ - export interface Changes { - /** - * The number of rows changed by the last `run` or `exec` call. - */ - changes: number; - - /** - * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`. - */ - lastInsertRowid: number | bigint; - } -} diff --git a/packages/bun-types/new/test.d.ts b/packages/bun-types/new/test.d.ts deleted file mode 100644 index 8448317743fc6e..00000000000000 --- a/packages/bun-types/new/test.d.ts +++ /dev/null @@ -1,2182 +0,0 @@ -/** - * - * To run tests, run `bun test` - * - * @example - * - * ```bash - * $ bun test - * ``` - * - * @example - * ```bash - * $ bun test - * ``` - */ -declare module "bun:test" { - /** - * -- Mocks -- - */ - export type Mock any> = JestMock.Mock; - - export const mock: { - any>(Function?: T): Mock; - - /** - * Replace the module `id` with the return value of `factory`. - * - * This is useful for mocking modules. - * - * @param id module ID to mock - * @param factory a function returning an object that will be used as the exports of the mocked module - * - * @example - * ## Example - * ```ts - * import { mock } from "bun:test"; - * - * mock.module("fs/promises", () => { - * return { - * readFile: () => Promise.resolve("hello world"), - * }; - * }); - * - * import { readFile } from "fs/promises"; - * - * console.log(await readFile("hello.txt", "utf8")); // hello world - * ``` - * - * ## More notes - * - * If the module is already loaded, exports are overwritten with the return - * value of `factory`. If the export didn't exist before, it will not be - * added to existing import statements. This is due to how ESM works. - */ - module(id: string, factory: () => any): void | Promise; - /** - * Restore the previous value of mocks. - */ - restore(): void; - }; - - /** - * Control the system time used by: - * - `Date.now()` - * - `new Date()` - * - `Intl.DateTimeFormat().format()` - * - * In the future, we may add support for more functions, but we haven't done that yet. - * - * @param now The time to set the system time to. If not provided, the system time will be reset. - * @returns `this` - * @since v0.6.13 - * - * ## Set Date to a specific time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); - * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z - * ``` - * ## Reset Date to the current time - * - * ```js - * import { setSystemTime } from 'bun:test'; - * - * setSystemTime(); - * ``` - */ - export function setSystemTime(now?: Date | number): ThisType; - - interface Jest { - restoreAllMocks(): void; - clearAllMocks(): void; - fn any>(func?: T): Mock; - setSystemTime(now?: number | Date): void; - setTimeout(milliseconds: number): void; - } - export const jest: Jest; - export namespace jest { - /** - * Constructs the type of a mock function, e.g. the return type of `jest.fn()`. - */ - type Mock any = (...args: any[]) => any> = JestMock.Mock; - /** - * Wraps a class, function or object type with Jest mock type definitions. - */ - // type Mocked = JestMock.Mocked; - /** - * Wraps a class type with Jest mock type definitions. - */ - // type MockedClass = JestMock.MockedClass; - /** - * Wraps a function type with Jest mock type definitions. - */ - // type MockedFunction any> = JestMock.MockedFunction; - /** - * Wraps an object type with Jest mock type definitions. - */ - // type MockedObject = JestMock.MockedObject; - /** - * Constructs the type of a replaced property. - */ - type Replaced = JestMock.Replaced; - /** - * Constructs the type of a spied class or function. - */ - type Spied any)> = JestMock.Spied; - /** - * Constructs the type of a spied class. - */ - type SpiedClass = JestMock.SpiedClass; - /** - * Constructs the type of a spied function. - */ - type SpiedFunction any> = JestMock.SpiedFunction; - /** - * Constructs the type of a spied getter. - */ - type SpiedGetter = JestMock.SpiedGetter; - /** - * Constructs the type of a spied setter. - */ - type SpiedSetter = JestMock.SpiedSetter; - } - - export function spyOn( - obj: T, - methodOrPropertyValue: K, - ): Mock any ? T[K] : never>; - - interface FunctionLike { - readonly name: string; - } - - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export interface Describe { - (fn: () => void): void; - - (label: number | string | Function | FunctionLike, fn: () => void): void; - /** - * Skips all other tests, except this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - only(label: string, fn: () => void): void; - /** - * Skips this group of tests. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - skip(label: string, fn: () => void): void; - /** - * Marks this group of tests as to be written or to be fixed. - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - todo(label: string, fn?: () => void): void; - /** - * Runs this group of tests, only if `condition` is true. - * - * This is the opposite of `describe.skipIf()`. - * - * @param condition if these tests should run - */ - if(condition: boolean): (label: string, fn: () => void) => void; - /** - * Skips this group of tests, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - skipIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Marks this group of tests as to be written or to be fixed, if `condition` is true. - * - * @param condition if these tests should be skipped - */ - todoIf(condition: boolean): (label: string, fn: () => void) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; - each( - table: readonly T[], - ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; - each( - table: T[], - ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; - } - /** - * Describes a group of related tests. - * - * @example - * function sum(a, b) { - * return a + b; - * } - * describe("sum()", () => { - * test("can sum two values", () => { - * expect(sum(1, 1)).toBe(2); - * }); - * }); - * - * @param label the label for the tests - * @param fn the function that defines the tests - */ - export const describe: Describe; - /** - * Runs a function, once, before all the tests. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, tests will not run in this file. - * - * @example - * let database; - * beforeAll(async () => { - * database = await connect("localhost"); - * }); - * - * @param fn the function to run - */ - export function beforeAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function before each test. - * - * This is useful for running set up tasks, like initializing - * a global variable or connecting to a database. - * - * If this function throws, the test will not run. - * - * @param fn the function to run - */ - export function beforeEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function, once, after all the tests. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @example - * let database; - * afterAll(async () => { - * if (database) { - * await database.close(); - * } - * }); - * - * @param fn the function to run - */ - export function afterAll(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs a function after each test. - * - * This is useful for running clean up tasks, like closing - * a socket or deleting temporary files. - * - * @param fn the function to run - */ - export function afterEach(fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Sets the default timeout for all tests in the current file. If a test specifies a timeout, it will - * override this value. The default timeout is 5000ms (5 seconds). - * - * @param milliseconds the number of milliseconds for the default timeout - */ - export function setDefaultTimeout(milliseconds: number): void; - export interface TestOptions { - /** - * Sets the timeout for the test in milliseconds. - * - * If the test does not complete within this time, the test will fail with: - * ```ts - * 'Timeout: test {name} timed out after 5000ms' - * ``` - * - * @default 5000 // 5 seconds - */ - timeout?: number; - /** - * Sets the number of times to retry the test if it fails. - * - * @default 0 - */ - retry?: number; - /** - * Sets the number of times to repeat the test, regardless of whether it passed or failed. - * - * @default 0 - */ - repeats?: number; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * test("can set a timeout", async () => { - * await Bun.sleep(100); - * }, 50); // or { timeout: 50 } - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - export interface Test { - ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - /** - * - If a `number`, sets the timeout for the test in milliseconds. - * - If an `object`, sets the options for the test. - * - `timeout` sets the timeout for the test in milliseconds. - * - `retry` sets the number of times to retry the test if it fails. - * - `repeats` sets the number of times to repeat the test, regardless of whether it passed or failed. - */ - options?: number | TestOptions, - ): void; - /** - * Skips all other tests, except this test when run with the `--only` option. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - only( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Skips this test. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - skip( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as to be written or to be fixed. - * - * These tests will not be executed unless the `--todo` flag is passed. With the flag, - * if the test passes, the test will be marked as `fail` in the results; you will have to - * remove the `.todo` or check that your test - * is implemented correctly. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - todo( - label: string, - fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ): void; - /** - * Marks this test as failing. - * - * Use `test.failing` when you are writing a test and expecting it to fail. - * These tests will behave the other way normal tests do. If failing test - * will throw any errors then it will pass. If it does not throw it will - * fail. - * - * `test.failing` is very similar to {@link test.todo} except that it always - * runs, regardless of the `--todo` flag. - * - * @param label the label for the test - * @param fn the test function - * @param options the test timeout or options - */ - failing(label: string, fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; - /** - * Runs this test, if `condition` is true. - * - * This is the opposite of `test.skipIf()`. - * - * @param condition if the test should run - */ - if( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Skips this test, if `condition` is true. - * - * @param condition if the test should be skipped - */ - skipIf( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Marks this test as to be written or to be fixed, if `condition` is true. - * - * @param condition if the test should be marked TODO - */ - todoIf( - condition: boolean, - ): ( - label: string, - fn: (() => void | Promise) | ((done: (err?: unknown) => void) => void), - options?: number | TestOptions, - ) => void; - /** - * Returns a function that runs for each item in `table`. - * - * @param table Array of Arrays with the arguments that are passed into the test fn for each row. - */ - each>( - table: readonly T[], - ): (label: string, fn: (...args: [...T]) => void | Promise, options?: number | TestOptions) => void; - each( - table: readonly T[], - ): (label: string, fn: (...args: Readonly) => void | Promise, options?: number | TestOptions) => void; - each( - table: T[], - ): (label: string, fn: (...args: T[]) => void | Promise, options?: number | TestOptions) => void; - } - /** - * Runs a test. - * - * @example - * test("can check if using Bun", () => { - * expect(Bun).toBeDefined(); - * }); - * - * test("can make a fetch() request", async () => { - * const response = await fetch("https://example.com/"); - * expect(response.ok).toBe(true); - * }); - * - * @param label the label for the test - * @param fn the test function - */ - export const test: Test; - export { test as it }; - - /** - * Asserts that a value matches some criteria. - * - * @link https://jestjs.io/docs/expect#reference - * @example - * expect(1 + 1).toBe(2); - * expect([1,2,3]).toContain(2); - * expect(null).toBeNull(); - * - * @param actual The actual (received) value - */ - export const expect: Expect; - - type ExpectNot = Omit & AsymmetricMatchersBuiltinNegated; - - export interface Expect extends AsymmetricMatchers { - // the `expect()` callable signature - /** - * @param actual the actual value - * @param customFailMessage an optional custom message to display if the test fails. - * */ - - (actual?: T, customFailMessage?: string): Matchers; - - /** - * Access to negated asymmetric matchers. - * - * @example - * expect("abc").toEqual(expect.stringContaining("abc")); // will pass - * expect("abc").toEqual(expect.not.stringContaining("abc")); // will fail - */ - not: ExpectNot; - - /** - * Create an asymmetric matcher for a promise resolved value. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will pass - * expect(Promise.reject("value")).toEqual(expect.resolvesTo.stringContaining("value")); // will fail - * expect("value").toEqual(expect.resolvesTo.stringContaining("value")); // will fail - */ - resolvesTo: AsymmetricMatchers; - - /** - * Create an asymmetric matcher for a promise rejected value. - * - * @example - * expect(Promise.reject("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will pass - * expect(Promise.resolve("error")).toEqual(expect.rejectsTo.stringContaining("error")); // will fail - * expect("error").toEqual(expect.rejectsTo.stringContaining("error")); // will fail - */ - rejectsTo: AsymmetricMatchers; - - /** - * Register new custom matchers. - * @param matchers An object containing the matchers to register, where each key is the matcher name, and its value the implementation function. - * The function must satisfy: `(actualValue, ...matcherInstantiationArguments) => { pass: true|false, message: () => string }` - * - * @example - * expect.extend({ - * toBeWithinRange(actual, min, max) { - * if (typeof actual !== 'number' || typeof min !== 'number' || typeof max !== 'number') - * throw new Error('Invalid usage'); - * const pass = actual >= min && actual <= max; - * return { - * pass: pass, - * message: () => `expected ${this.utils.printReceived(actual)} ` + - * (pass ? `not to be`: `to be`) + ` within range ${this.utils.printExpected(`${min} .. ${max}`)}`, - * }; - * }, - * }); - * - * test('some test', () => { - * expect(50).toBeWithinRange(0, 100); // will pass - * expect(50).toBeWithinRange(100, 200); // will fail - * expect(50).toBe(expect.toBeWithinRange(0, 100)); // will pass - * expect(50).toBe(expect.not.toBeWithinRange(100, 200)); // will pass - * }); - */ - extend(matchers: ExpectExtendMatchers): void; - - /** - * Throw an error if this function is called. - * - * @param msg Optional message to display if the test fails - * @returns never - * - * @example - * ## Example - * - * ```ts - * import { expect, test } from "bun:test"; - * - * test("!!abc!! is not a module", () => { - * try { - * require("!!abc!!"); - * expect.unreachable(); - * } catch(e) { - * expect(e.name).not.toBe("UnreachableError"); - * } - * }); - * ``` - */ - unreachable(msg?: string | Error): never; - - /** - * Ensures that an assertion is made - */ - hasAssertions(): void; - - /** - * Ensures that a specific number of assertions are made - */ - assertions(neededAssertions: number): void; - } - - /** - * You can extend this interface with declaration merging, in order to add type support for custom matchers. - * @template T Type of the actual value - * - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface Matchers extends MatchersBuiltin {} - - /** - * You can extend this interface with declaration merging, in order to add type support for custom asymmetric matchers. - * @example - * // my_modules.d.ts - * interface MyCustomMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * declare module "bun:test" { - * interface Matchers extends MyCustomMatchers {} - * interface AsymmetricMatchers extends MyCustomMatchers {} - * } - * - * @example - * // my_modules.d.ts (alternatively) - * declare module "bun:test" { - * interface Matchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * interface AsymmetricMatchers { - * toBeWithinRange(floor: number, ceiling: number): any; - * } - * } - */ - export interface AsymmetricMatchers extends AsymmetricMatchersBuiltin {} - - export interface AsymmetricMatchersBuiltin { - /** - * Matches anything that was created with the given constructor. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * @example - * - * function randocall(fn) { - * return fn(Math.floor(Math.random() * 6 + 1)); - * } - * - * test('randocall calls its callback with a number', () => { - * const mock = jest.fn(); - * randocall(mock); - * expect(mock).toBeCalledWith(expect.any(Number)); - * }); - */ - any(constructor: ((...args: any[]) => any) | { new (...args: any[]): any }): AsymmetricMatcher; - /** - * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead - * of a literal value. For example, if you want to check that a mock function is called with a - * non-null argument: - * - * @example - * - * test('map calls its argument with a non-null argument', () => { - * const mock = jest.fn(); - * [1].map(x => mock(x)); - * expect(mock).toBeCalledWith(expect.anything()); - * }); - */ - anything(): AsymmetricMatcher; - /** - * Matches any array made up entirely of elements in the provided array. - * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - /** - * Matches any object that recursively matches the provided keys. - * This is often handy in conjunction with other asymmetric matchers. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - /** - * Matches any received string that contains the exact expected string - */ - stringContaining(str: string | String): AsymmetricMatcher; - /** - * Matches any string that contains the exact provided string - */ - stringMatching(regex: string | String | RegExp): AsymmetricMatcher; - /** - * Useful when comparing floating point numbers in object properties or array item. - * If you need to compare a number, use `.toBeCloseTo` instead. - * - * The optional `numDigits` argument limits the number of digits to check after the decimal point. - * For the default value 2, the test criterion is `Math.abs(expected - received) < 0.005` (that is, `10 ** -2 / 2`). - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - interface AsymmetricMatchersBuiltinNegated { - /** - * Create an asymmetric matcher that will fail on a promise resolved value that matches the chained matcher. - * - * @example - * expect(Promise.resolve("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will fail - * expect(Promise.reject("value")).toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.resolvesTo.stringContaining("value")); // will pass - */ - resolvesTo: ExpectNot; - - /** - * Create an asymmetric matcher that will fail on a promise rejected value that matches the chained matcher. - * - * @example - * expect(Promise.reject("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will fail - * expect(Promise.resolve("value")).toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - * expect("value").toEqual(expect.not.rejectsTo.stringContaining("value")); // will pass - */ - rejectsTo: ExpectNot; - - /** - * `expect.not.arrayContaining(array)` matches a received array which - * does not contain all of the elements in the expected array. That is, - * the expected array is not a subset of the received array. It is the - * inverse of `expect.arrayContaining`. - * - * Optionally, you can provide a type for the elements via a generic. - */ - arrayContaining(arr: readonly E[]): AsymmetricMatcher; - - /** - * `expect.not.objectContaining(object)` matches any received object - * that does not recursively match the expected properties. That is, the - * expected object is not a subset of the received object. Therefore, - * it matches a received object which contains properties that are not - * in the expected object. It is the inverse of `expect.objectContaining`. - * - * Optionally, you can provide a type for the object via a generic. - * This ensures that the object contains the desired structure. - */ - objectContaining(obj: object): AsymmetricMatcher; - - /** - * `expect.not.stringContaining(string)` matches the received string - * that does not contain the exact expected string. It is the inverse of - * `expect.stringContaining`. - */ - stringContaining(str: string | String): AsymmetricMatcher; - - /** - * `expect.not.stringMatching(string | regexp)` matches the received - * string that does not match the expected regexp. It is the inverse of - * `expect.stringMatching`. - */ - stringMatching(str: string | String | RegExp): AsymmetricMatcher; - - /** - * `expect.not.closeTo` matches a number not close to the provided value. - * Useful when comparing floating point numbers in object properties or array item. - * It is the inverse of `expect.closeTo`. - */ - closeTo(num: number, numDigits?: number): AsymmetricMatcher; - } - - export interface MatchersBuiltin { - /** - * Negates the result of a subsequent assertion. - * If you know how to test something, `.not` lets you test its opposite. - * - * @example - * expect(1).not.toBe(0); - * expect(null).not.toBeNull(); - * - * @example - * expect(42).toEqual(42); // will pass - * expect(42).not.toEqual(42); // will fail - */ - not: Matchers; - - /** - * Expects the value to be a promise that resolves. - * - * @example - * expect(Promise.resolve(1)).resolves.toBe(1); - */ - resolves: Matchers>; - - /** - * Expects the value to be a promise that rejects. - * - * @example - * expect(Promise.reject("error")).rejects.toBe("error"); - */ - rejects: Matchers; - - /** - * Assertion which passes. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass - * @example - * expect().pass(); - * expect().pass("message is optional"); - * expect().not.pass(); - * expect().not.pass("hi"); - * - * @param message the message to display if the test fails (optional) - */ - pass: (message?: string) => void; - /** - * Assertion which fails. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail - * @example - * expect().fail(); - * expect().fail("message is optional"); - * expect().not.fail(); - * expect().not.fail("hi"); - */ - fail: (message?: string) => void; - /** - * Asserts that a value equals what is expected. - * - * - For non-primitive values, like objects and arrays, - * use `toEqual()` instead. - * - For floating-point numbers, use `toBeCloseTo()` instead. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([123]).toBe([123]); // fail, use toEqual() - * expect(3 + 0.14).toBe(3.14); // fail, use toBeCloseTo() - * - * @param expected the expected value - */ - toBe(expected: T): void; - /** - * Asserts that a number is odd. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd - * @example - * expect(1).toBeOdd(); - * expect(2).not.toBeOdd(); - */ - toBeOdd(): void; - /** - * Asserts that a number is even. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven - * @example - * expect(2).toBeEven(); - * expect(1).not.toBeEven(); - */ - toBeEven(): void; - /** - * Asserts that value is close to the expected by floating point precision. - * - * For example, the following fails because arithmetic on decimal (base 10) - * values often have rounding errors in limited precision binary (base 2) representation. - * - * @example - * expect(0.2 + 0.1).toBe(0.3); // fails - * - * Use `toBeCloseTo` to compare floating point numbers for approximate equality. - * - * @example - * expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // passes - * - * @param expected the expected value - * @param numDigits the number of digits to check after the decimal point. Default is `2` - */ - toBeCloseTo(expected: number, numDigits?: number): void; - /** - * Asserts that a value is deeply equal to what is expected. - * - * @example - * expect(100 + 23).toBe(123); - * expect("d" + "og").toBe("dog"); - * expect([456]).toEqual([456]); - * expect({ value: 1 }).toEqual({ value: 1 }); - * - * @param expected the expected value - */ - toEqual(expected: T): void; - /** - * Asserts that a value is deeply and strictly equal to - * what is expected. - * - * There are two key differences from `toEqual()`: - * 1. It checks that the class is the same. - * 2. It checks that `undefined` values match as well. - * - * @example - * class Dog { - * type = "dog"; - * } - * const actual = new Dog(); - * expect(actual).toStrictEqual(new Dog()); - * expect(actual).toStrictEqual({ type: "dog" }); // fail - * - * @example - * const actual = { value: 1, name: undefined }; - * expect(actual).toEqual({ value: 1 }); - * expect(actual).toStrictEqual({ value: 1 }); // fail - * - * @param expected the expected value - */ - toStrictEqual(expected: T): void; - /** - * Asserts that the value is deep equal to an element in the expected array. - * - * The value must be an array or iterable, which includes strings. - * - * @example - * expect(1).toBeOneOf([1,2,3]); - * expect("foo").toBeOneOf(["foo", "bar"]); - * expect(true).toBeOneOf(new Set([true])); - * - * @param expected the expected value - */ - toBeOneOf(expected: Array | Iterable): void; - /** - * Asserts that a value contains what is expected. - * - * The value must be an array or iterable, which - * includes strings. - * - * @example - * expect([1, 2, 3]).toContain(1); - * expect(new Set([true])).toContain(true); - * expect("hello").toContain("o"); - * - * @param expected the expected value - */ - toContain(expected: unknown): void; - /** - * Asserts that an `object` contains a key. - * - * The value must be an object - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('a'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('b'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKey('c'); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKey('d'); - * - * @param expected the expected value - */ - toContainKey(expected: unknown): void; - /** - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['a','b']); - * expect({ a: 'hello', b: 'world' }).toContainAllKeys(['b','a']); - * expect({ 1: 'hello', b: 'world' }).toContainAllKeys([1,'b']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAllKeys(['a']); - * - * @param expected the expected value - */ - toContainAllKeys(expected: unknown): void; - /** - * Asserts that an `object` contains at least one of the provided keys. - * Asserts that an `object` contains all the provided keys. - * - * The value must be an object - * - * @example - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']); - * expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']); - * expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']); - * - * @param expected the expected value - */ - toContainAnyKeys(expected: unknown): void; - - /** - * Asserts that an `object` contain the provided value. - * - * The value must be an object - * - * @example - * const shallow = { hello: "world" }; - * const deep = { message: shallow }; - * const deepArray = { message: [shallow] }; - * const o = { a: "foo", b: [1, "hello", true], c: "baz" }; - - * expect(shallow).toContainValue("world"); - * expect({ foo: false }).toContainValue(false); - * expect(deep).toContainValue({ hello: "world" }); - * expect(deepArray).toContainValue([{ hello: "world" }]); - - * expect(o).toContainValue("foo", "barr"); - * expect(o).toContainValue([1, "hello", true]); - * expect(o).not.toContainValue("qux"); - - // NOT - * expect(shallow).not.toContainValue("foo"); - * expect(deep).not.toContainValue({ foo: "bar" }); - * expect(deepArray).not.toContainValue([{ foo: "bar" }]); - * - * @param expected the expected value - */ - toContainValue(expected: unknown): void; - - /** - * Asserts that an `object` contain the provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainValues(['foo']); - * expect(o).toContainValues(['baz', 'bar']); - * expect(o).not.toContainValues(['qux', 'foo']); - * @param expected the expected value - */ - toContainValues(expected: unknown): void; - - /** - * Asserts that an `object` contain all the provided values. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAllValues(['foo', 'bar', 'baz']); - * expect(o).toContainAllValues(['baz', 'bar', 'foo']); - * expect(o).not.toContainAllValues(['bar', 'foo']); - * @param expected the expected value - */ - toContainAllValues(expected: unknown): void; - - /** - * Asserts that an `object` contain any provided value. - * - * The value must be an object - * - * @example - * const o = { a: 'foo', b: 'bar', c: 'baz' }; - * expect(o).toContainAnyValues(['qux', 'foo']); - * expect(o).toContainAnyValues(['qux', 'bar']); - * expect(o).toContainAnyValues(['qux', 'baz']); - * expect(o).not.toContainAnyValues(['qux']); - * @param expected the expected value - */ - toContainAnyValues(expected: unknown): void; - - /** - * Asserts that an `object` contains all the provided keys. - * - * @example - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']); - * expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']); - * - * @param expected the expected value - */ - toContainKeys(expected: unknown): void; - /** - * Asserts that a value contains and equals what is expected. - * - * This matcher will perform a deep equality check for members - * of arrays, rather than checking for object identity. - * - * @example - * expect([{ a: 1 }]).toContainEqual({ a: 1 }); - * expect([{ a: 1 }]).not.toContainEqual({ a: 2 }); - * - * @param expected the expected value - */ - toContainEqual(expected: unknown): void; - /** - * Asserts that a value has a `.length` property - * that is equal to the expected length. - * - * @example - * expect([]).toHaveLength(0); - * expect("hello").toHaveLength(4); - * - * @param length the expected length - */ - toHaveLength(length: number): void; - /** - * Asserts that a value has a property with the - * expected name, and value if provided. - * - * @example - * expect(new Set()).toHaveProperty("size"); - * expect(new Uint8Array()).toHaveProperty("byteLength", 0); - * expect({ kitchen: { area: 20 }}).toHaveProperty("kitchen.area", 20); - * expect({ kitchen: { area: 20 }}).toHaveProperty(["kitchen", "area"], 20); - * - * @param keyPath the expected property name or path, or an index - * @param value the expected property value, if provided - */ - toHaveProperty(keyPath: string | number | Array, value?: unknown): void; - /** - * Asserts that a value is "truthy". - * - * To assert that a value equals `true`, use `toBe(true)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Truthy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeTruthy(): void; - /** - * Asserts that a value is "falsy". - * - * To assert that a value equals `false`, use `toBe(false)` instead. - * - * @link https://developer.mozilla.org/en-US/docs/Glossary/Falsy - * @example - * expect(true).toBeTruthy(); - * expect(1).toBeTruthy(); - * expect({}).toBeTruthy(); - */ - toBeFalsy(): void; - /** - * Asserts that a value is defined. (e.g. is not `undefined`) - * - * @example - * expect(true).toBeDefined(); - * expect(undefined).toBeDefined(); // fail - */ - toBeDefined(): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that the expected value is an instance of value - * - * @example - * expect([]).toBeInstanceOf(Array); - * expect(null).toBeInstanceOf(Array); // fail - */ - toBeInstanceOf(value: unknown): void; - /** - * Asserts that a value is `undefined`. - * - * @example - * expect(undefined).toBeUndefined(); - * expect(null).toBeUndefined(); // fail - */ - toBeUndefined(): void; - /** - * Asserts that a value is `null`. - * - * @example - * expect(null).toBeNull(); - * expect(undefined).toBeNull(); // fail - */ - toBeNull(): void; - /** - * Asserts that a value is `NaN`. - * - * Same as using `Number.isNaN()`. - * - * @example - * expect(NaN).toBeNaN(); - * expect(Infinity).toBeNaN(); // fail - * expect("notanumber").toBeNaN(); // fail - */ - toBeNaN(): void; - /** - * Asserts that a value is a `number` and is greater than the expected value. - * - * @example - * expect(1).toBeGreaterThan(0); - * expect(3.14).toBeGreaterThan(3); - * expect(9).toBeGreaterThan(9); // fail - * - * @param expected the expected number - */ - toBeGreaterThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is greater than or equal to the expected value. - * - * @example - * expect(1).toBeGreaterThanOrEqual(0); - * expect(3.14).toBeGreaterThanOrEqual(3); - * expect(9).toBeGreaterThanOrEqual(9); - * - * @param expected the expected number - */ - toBeGreaterThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than the expected value. - * - * @example - * expect(-1).toBeLessThan(0); - * expect(3).toBeLessThan(3.14); - * expect(9).toBeLessThan(9); // fail - * - * @param expected the expected number - */ - toBeLessThan(expected: number | bigint): void; - /** - * Asserts that a value is a `number` and is less than or equal to the expected value. - * - * @example - * expect(-1).toBeLessThanOrEqual(0); - * expect(3).toBeLessThanOrEqual(3.14); - * expect(9).toBeLessThanOrEqual(9); - * - * @param expected the expected number - */ - toBeLessThanOrEqual(expected: number | bigint): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrow("Oops!"); - * expect(fail).toThrow(/oops/i); - * expect(fail).toThrow(Error); - * expect(fail).toThrow(); - * - * @param expected the expected error, error message, or error pattern - */ - toThrow(expected?: unknown): void; - /** - * Asserts that a function throws an error. - * - * - If expected is a `string` or `RegExp`, it will check the `message` property. - * - If expected is an `Error` object, it will check the `name` and `message` properties. - * - If expected is an `Error` constructor, it will check the class of the `Error`. - * - If expected is not provided, it will check if anything has thrown. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowError("Oops!"); - * expect(fail).toThrowError(/oops/i); - * expect(fail).toThrowError(Error); - * expect(fail).toThrowError(); - * - * @param expected the expected error, error message, or error pattern - * @alias toThrow - */ - toThrowError(expected?: unknown): void; - /** - * Asserts that a value matches a regular expression or includes a substring. - * - * @example - * expect("dog").toMatch(/dog/); - * expect("dog").toMatch("og"); - * - * @param expected the expected substring or pattern. - */ - toMatch(expected: string | RegExp): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot('hint message'); - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(hint?: string): void; - /** - * Asserts that a value matches the most recent snapshot. - * - * @example - * expect([1, 2, 3]).toMatchSnapshot(); - * expect({ a: 1, b: 2 }).toMatchSnapshot({ a: 1 }); - * expect({ c: new Date() }).toMatchSnapshot({ c: expect.any(Date) }); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param hint Hint used to identify the snapshot in the snapshot file. - */ - toMatchSnapshot(propertyMatchers?: object, hint?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect("Hello").toMatchInlineSnapshot(); - * expect("Hello").toMatchInlineSnapshot(`"Hello"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(value?: string): void; - /** - * Asserts that a value matches the most recent inline snapshot. - * - * @example - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }); - * expect({ c: new Date() }).toMatchInlineSnapshot({ c: expect.any(Date) }, ` - * { - * "v": Any, - * } - * `); - * - * @param propertyMatchers Object containing properties to match against the value. - * @param value The latest automatically-updated snapshot value. - */ - toMatchInlineSnapshot(propertyMatchers?: object, value?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingSnapshot(); - * expect(fail).toThrowErrorMatchingSnapshot("This one should say Oops!"); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingSnapshot(hint?: string): void; - /** - * Asserts that a function throws an error matching the most recent snapshot. - * - * @example - * function fail() { - * throw new Error("Oops!"); - * } - * expect(fail).toThrowErrorMatchingInlineSnapshot(); - * expect(fail).toThrowErrorMatchingInlineSnapshot(`"Oops!"`); - * - * @param value The latest automatically-updated snapshot value. - */ - toThrowErrorMatchingInlineSnapshot(value?: string): void; - /** - * Asserts that an object matches a subset of properties. - * - * @example - * expect({ a: 1, b: 2 }).toMatchObject({ b: 2 }); - * expect({ c: new Date(), d: 2 }).toMatchObject({ d: 2 }); - * - * @param subset Subset of properties to match with. - */ - toMatchObject(subset: object): void; - /** - * Asserts that a value is empty. - * - * @example - * expect("").toBeEmpty(); - * expect([]).toBeEmpty(); - * expect({}).toBeEmpty(); - * expect(new Set()).toBeEmpty(); - */ - toBeEmpty(): void; - /** - * Asserts that a value is an empty `object`. - * - * @example - * expect({}).toBeEmptyObject(); - * expect({ a: 'hello' }).not.toBeEmptyObject(); - */ - toBeEmptyObject(): void; - /** - * Asserts that a value is `null` or `undefined`. - * - * @example - * expect(null).toBeNil(); - * expect(undefined).toBeNil(); - */ - toBeNil(): void; - /** - * Asserts that a value is a `array`. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray - * @example - * expect([1]).toBeArray(); - * expect(new Array(1)).toBeArray(); - * expect({}).not.toBeArray(); - */ - toBeArray(): void; - /** - * Asserts that a value is a `array` of a certain length. - * - * @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize - * @example - * expect([]).toBeArrayOfSize(0); - * expect([1]).toBeArrayOfSize(1); - * expect(new Array(1)).toBeArrayOfSize(1); - * expect({}).not.toBeArrayOfSize(0); - */ - toBeArrayOfSize(size: number): void; - /** - * Asserts that a value is a `boolean`. - * - * @example - * expect(true).toBeBoolean(); - * expect(false).toBeBoolean(); - * expect(null).not.toBeBoolean(); - * expect(0).not.toBeBoolean(); - */ - toBeBoolean(): void; - /** - * Asserts that a value is `true`. - * - * @example - * expect(true).toBeTrue(); - * expect(false).not.toBeTrue(); - * expect(1).not.toBeTrue(); - */ - toBeTrue(): void; - /** - * Asserts that a value matches a specific type. - * - * @link https://vitest.dev/api/expect.html#tobetypeof - * @example - * expect(1).toBeTypeOf("number"); - * expect("hello").toBeTypeOf("string"); - * expect([]).not.toBeTypeOf("boolean"); - */ - toBeTypeOf(type: "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"): void; - /** - * Asserts that a value is `false`. - * - * @example - * expect(false).toBeFalse(); - * expect(true).not.toBeFalse(); - * expect(0).not.toBeFalse(); - */ - toBeFalse(): void; - /** - * Asserts that a value is a `number`. - * - * @example - * expect(1).toBeNumber(); - * expect(3.14).toBeNumber(); - * expect(NaN).toBeNumber(); - * expect(BigInt(1)).not.toBeNumber(); - */ - toBeNumber(): void; - /** - * Asserts that a value is a `number`, and is an integer. - * - * @example - * expect(1).toBeInteger(); - * expect(3.14).not.toBeInteger(); - * expect(NaN).not.toBeInteger(); - */ - toBeInteger(): void; - /** - * Asserts that a value is an `object`. - * - * @example - * expect({}).toBeObject(); - * expect("notAnObject").not.toBeObject(); - * expect(NaN).not.toBeObject(); - */ - toBeObject(): void; - /** - * Asserts that a value is a `number`, and is not `NaN` or `Infinity`. - * - * @example - * expect(1).toBeFinite(); - * expect(3.14).toBeFinite(); - * expect(NaN).not.toBeFinite(); - * expect(Infinity).not.toBeFinite(); - */ - toBeFinite(): void; - /** - * Asserts that a value is a positive `number`. - * - * @example - * expect(1).toBePositive(); - * expect(-3.14).not.toBePositive(); - * expect(NaN).not.toBePositive(); - */ - toBePositive(): void; - /** - * Asserts that a value is a negative `number`. - * - * @example - * expect(-3.14).toBeNegative(); - * expect(1).not.toBeNegative(); - * expect(NaN).not.toBeNegative(); - */ - toBeNegative(): void; - /** - * Asserts that a value is a number between a start and end value. - * - * @param start the start number (inclusive) - * @param end the end number (exclusive) - */ - toBeWithin(start: number, end: number): void; - /** - * Asserts that a value is equal to the expected string, ignoring any whitespace. - * - * @example - * expect(" foo ").toEqualIgnoringWhitespace("foo"); - * expect("bar").toEqualIgnoringWhitespace(" bar "); - * - * @param expected the expected string - */ - toEqualIgnoringWhitespace(expected: string): void; - /** - * Asserts that a value is a `symbol`. - * - * @example - * expect(Symbol("foo")).toBeSymbol(); - * expect("foo").not.toBeSymbol(); - */ - toBeSymbol(): void; - /** - * Asserts that a value is a `function`. - * - * @example - * expect(() => {}).toBeFunction(); - */ - toBeFunction(): void; - /** - * Asserts that a value is a `Date` object. - * - * To check if a date is valid, use `toBeValidDate()` instead. - * - * @example - * expect(new Date()).toBeDate(); - * expect(new Date(null)).toBeDate(); - * expect("2020-03-01").not.toBeDate(); - */ - toBeDate(): void; - /** - * Asserts that a value is a valid `Date` object. - * - * @example - * expect(new Date()).toBeValidDate(); - * expect(new Date(null)).not.toBeValidDate(); - * expect("2020-03-01").not.toBeValidDate(); - */ - toBeValidDate(): void; - /** - * Asserts that a value is a `string`. - * - * @example - * expect("foo").toBeString(); - * expect(new String("bar")).toBeString(); - * expect(123).not.toBeString(); - */ - toBeString(): void; - /** - * Asserts that a value includes a `string`. - * - * For non-string values, use `toContain()` instead. - * - * @param expected the expected substring - */ - toInclude(expected: string): void; - /** - * Asserts that a value includes a `string` {times} times. - * @param expected the expected substring - * @param times the number of times the substring should occur - */ - toIncludeRepeated(expected: string, times: number): void; - /** - * Checks whether a value satisfies a custom condition. - * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean. - * @example - * expect(1).toSatisfy((val) => val > 0); - * expect("foo").toSatisfy((val) => val === "foo"); - * expect("bar").not.toSatisfy((val) => val === "bun"); - * @link https://vitest.dev/api/expect.html#tosatisfy - * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy - */ - toSatisfy(predicate: (value: T) => boolean): void; - /** - * Asserts that a value starts with a `string`. - * - * @param expected the string to start with - */ - toStartWith(expected: string): void; - /** - * Asserts that a value ends with a `string`. - * - * @param expected the string to end with - */ - toEndWith(expected: string): void; - /** - * Ensures that a mock function has returned successfully at least once. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturned(): void; - - /** - * Ensures that a mock function has returned successfully at `times` times. - * - * A promise that is unfulfilled will be considered a failure. If the - * function threw an error, it will be considered a failure. - */ - toHaveReturnedTimes(times: number): void; - - /** - * Ensures that a mock function is called. - */ - toHaveBeenCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - * @alias toHaveBeenCalled - */ - toBeCalled(): void; - /** - * Ensures that a mock function is called an exact number of times. - */ - toHaveBeenCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledTimes - */ - toBeCalledTimes(expected: number): void; - /** - * Ensure that a mock function is called with specific arguments. - */ - toHaveBeenCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments. - * @alias toHaveBeenCalledWith - */ - toBeCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the last call. - */ - toHaveBeenLastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - lastCalledWith(...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - */ - toHaveBeenNthCalledWith(n: number, ...expected: unknown[]): void; - /** - * Ensure that a mock function is called with specific arguments for the nth call. - * @alias toHaveBeenCalledWith - */ - nthCalledWith(n: number, ...expected: unknown[]): void; - } - - /** - * Object representing an asymmetric matcher obtained by an static call to expect like `expect.anything()`, `expect.stringContaining("...")`, etc. - */ - // Defined as an alias of `any` so that it does not trigger any type mismatch - export type AsymmetricMatcher = any; - - export interface MatcherResult { - pass: boolean; - message?: string | (() => string); - } - - export type CustomMatcher = ( - this: MatcherContext, - expected: E, - ...matcherArguments: P - ) => MatcherResult | Promise; - - /** All non-builtin matchers and asymmetric matchers that have been type-registered through declaration merging */ - export type CustomMatchersDetected = Omit, keyof MatchersBuiltin> & - Omit; - - /** - * If the types has been defined through declaration merging, enforce it. - * Otherwise enforce the generic custom matcher signature. - */ - export type ExpectExtendMatchers = { - [k in keyof M]: k extends keyof CustomMatchersDetected - ? CustomMatcher> - : CustomMatcher; - }; - - /** Custom equality tester */ - export type Tester = (this: TesterContext, a: any, b: any, customTesters: Tester[]) => boolean | undefined; - - export type EqualsFunction = ( - a: unknown, - b: unknown, - //customTesters?: Array, - //strictCheck?: boolean, - ) => boolean; - - export interface TesterContext { - equals: EqualsFunction; - } - - interface MatcherState { - //assertionCalls: number; - //currentConcurrentTestName?: () => string | undefined; - //currentTestName?: string; - //error?: Error; - //expand: boolean; - //expectedAssertionsNumber: number | null; - //expectedAssertionsNumberError?: Error; - //isExpectingAssertions: boolean; - //isExpectingAssertionsError?: Error; - isNot: boolean; - //numPassingAsserts: number; - promise: string; - //suppressedErrors: Array; - //testPath?: string; - } - - type MatcherHintColor = (arg: string) => string; // subset of Chalk type - - interface MatcherUtils { - //customTesters: Array; - //dontThrow(): void; // (internally used by jest snapshot) - equals: EqualsFunction; - utils: Readonly<{ - stringify(value: unknown): string; - printReceived(value: unknown): string; - printExpected(value: unknown): string; - matcherHint( - matcherName: string, - received?: unknown, - expected?: unknown, - options?: { - isNot?: boolean; - promise?: string; - isDirectExpectCall?: boolean; // (internal) - comment?: string; - expectedColor?: MatcherHintColor; - receivedColor?: MatcherHintColor; - secondArgument?: string; - secondArgumentColor?: MatcherHintColor; - }, - ): string; - //iterableEquality: Tester; - //subsetEquality: Tester; - // ... - }>; - } - - type MatcherContext = MatcherUtils & MatcherState; -} - -declare module "test" { - export type * from "bun:test"; -} - -declare namespace JestMock { - /** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - export interface ClassLike { - new (...args: any): any; - } - - export type ConstructorLikeKeys = keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - }; - - // export const fn: ( - // implementation?: T | undefined, - // ) => Mock; - - export type FunctionLike = (...args: any) => any; - - export type MethodLikeKeys = keyof { - [K in keyof T as Required[K] extends FunctionLike ? K : never]: T[K]; - }; - - export interface Mock any> extends MockInstance { - (...args: Parameters): ReturnType; - } - - /** - * All what the internal typings need is to be sure that we have any-function. - * `FunctionLike` type ensures that and helps to constrain the type as well. - * The default of `UnknownFunction` makes sure that `any`s do not leak to the - * user side. For instance, calling `fn()` without implementation will return - * a mock of `(...args: Array) => unknown` type. If implementation - * is provided, its typings are inferred correctly. - */ - // export interface Mock - // extends Function, - // MockInstance { - // new (...args: Parameters): ReturnType; - // (...args: Parameters): ReturnType; - // } - - // export type Mocked = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunction - // : T extends object - // ? MockedObject - // : T; - - // export const mocked: { - // ( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // ( - // source: T_1, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // }; - - // export type MockedClass = MockInstance< - // (...args: ConstructorParameters) => Mocked> - // > & - // MockedObject; - - // export type MockedFunction = MockInstance & - // MockedObject; - - // type MockedFunctionShallow = MockInstance & T; - - // export type MockedObject = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunction - // : T[K] extends object - // ? MockedObject - // : T[K]; - // } & T; - - // type MockedObjectShallow = { - // [K in keyof T]: T[K] extends ClassLike - // ? MockedClass - // : T[K] extends FunctionLike - // ? MockedFunctionShallow - // : T[K]; - // } & T; - - // export type MockedShallow = T extends ClassLike - // ? MockedClass - // : T extends FunctionLike - // ? MockedFunctionShallow - // : T extends object - // ? MockedObjectShallow - // : T; - - // export type MockFunctionMetadata< - // T = unknown, - // MetadataType = MockMetadataType, - // > = MockMetadata; - - // export type MockFunctionMetadataType = MockMetadataType; - - type MockFunctionResult = - | MockFunctionResultIncomplete - | MockFunctionResultReturn - | MockFunctionResultThrow; - - interface MockFunctionResultIncomplete { - type: "incomplete"; - /** - * Result of a single call to a mock function that has not yet completed. - * This occurs if you test the result from within the mock function itself, - * or from within a function that was called by the mock. - */ - value: undefined; - } - - interface MockFunctionResultReturn { - type: "return"; - /** - * Result of a single call to a mock function that returned. - */ - value: ReturnType; - } - - interface MockFunctionResultThrow { - type: "throw"; - /** - * Result of a single call to a mock function that threw. - */ - value: unknown; - } - - interface MockFunctionState { - /** - * List of the call arguments of all calls that have been made to the mock. - */ - calls: Array>; - /** - * List of all the object instances that have been instantiated from the mock. - */ - instances: Array>; - /** - * List of all the function contexts that have been applied to calls to the mock. - */ - contexts: Array>; - /** - * List of the call order indexes of the mock. Jest is indexing the order of - * invocations of all mocks in a test file. The index is starting with `1`. - */ - invocationCallOrder: number[]; - /** - * List of the call arguments of the last call that was made to the mock. - * If the function was not called, it will return `undefined`. - */ - lastCall?: Parameters; - /** - * List of the results of all calls that have been made to the mock. - */ - results: Array>; - } - - export interface MockInstance { - _isMockFunction: true; - _protoImpl: Function; - getMockImplementation(): T | undefined; - getMockName(): string; - mock: MockFunctionState; - mockClear(): this; - mockReset(): this; - mockRestore(): void; - mockImplementation(fn: T): this; - mockImplementationOnce(fn: T): this; - withImplementation(fn: T, callback: () => Promise): Promise; - withImplementation(fn: T, callback: () => void): void; - mockName(name: string): this; - mockReturnThis(): this; - mockReturnValue(value: ReturnType): this; - mockReturnValueOnce(value: ReturnType): this; - mockResolvedValue(value: ResolveType): this; - mockResolvedValueOnce(value: ResolveType): this; - mockRejectedValue(value: RejectType): this; - mockRejectedValueOnce(value: RejectType): this; - } - - // export type MockMetadata = { - // ref?: number; - // members?: Record>; - // mockImpl?: T; - // name?: string; - // refID?: number; - // type?: MetadataType; - // value?: T; - // length?: number; - // }; - - // export type MockMetadataType = - // | "object" - // | "array" - // | "regexp" - // | "function" - // | "constant" - // | "collection" - // | "null" - // | "undefined"; - - // export class ModuleMocker { - // private readonly _environmentGlobal; - // private _mockState; - // private _mockConfigRegistry; - // private _spyState; - // private _invocationCallCounter; - // /** - // * @see README.md - // * @param global Global object of the test environment, used to create - // * mocks - // */ - // constructor(global: typeof globalThis); - // private _getSlots; - // private _ensureMockConfig; - // private _ensureMockState; - // private _defaultMockConfig; - // private _defaultMockState; - // private _makeComponent; - // private _createMockFunction; - // private _generateMock; - // /** - // * Check whether the given property of an object has been already replaced. - // */ - // private _findReplacedProperty; - // /** - // * @see README.md - // * @param metadata Metadata for the mock in the schema returned by the - // * getMetadata method of this module. - // */ - // generateFromMetadata(metadata: MockMetadata): Mocked; - // /** - // * @see README.md - // * @param component The component for which to retrieve metadata. - // */ - // getMetadata( - // component: T, - // _refs?: Map, - // ): MockMetadata | null; - // isMockFunction( - // fn: MockInstance, - // ): fn is MockInstance; - // isMockFunction

, R>( - // fn: (...args: P) => R, - // ): fn is Mock<(...args: P) => R>; - // isMockFunction(fn: unknown): fn is Mock; - // fn(implementation?: T): Mock; - // private _attachMockImplementation; - // spyOn< - // T extends object, - // K extends PropertyLikeKeys, - // A extends "get" | "set", - // >( - // object: T, - // methodKey: K, - // accessType: A, - // ): A extends "get" - // ? SpiedGetter - // : A extends "set" - // ? SpiedSetter - // : never; - // spyOn< - // T extends object, - // K extends ConstructorLikeKeys | MethodLikeKeys, - // V extends Required[K], - // >( - // object: T, - // methodKey: K, - // ): V extends ClassLike | FunctionLike ? Spied : never; - // private _spyOnProperty; - // replaceProperty< - // T extends object, - // K extends PropertyLikeKeys, - // V extends T[K], - // >(object: T, propertyKey: K, value: V): Replaced; - // clearAllMocks(): void; - // resetAllMocks(): void; - // restoreAllMocks(): void; - // private _typeOf; - // mocked( - // source: T, - // options?: { - // shallow: false; - // }, - // ): Mocked; - // mocked( - // source: T, - // options: { - // shallow: true; - // }, - // ): MockedShallow; - // } - - export type PropertyLikeKeys = Exclude | MethodLikeKeys>; - - export type RejectType = ReturnType extends PromiseLike ? unknown : never; - - export interface Replaced { - /** - * Restore property to its original value known at the time of mocking. - */ - restore(): void; - /** - * Change the value of the property. - */ - replaceValue(value: T): this; - } - - export function replaceProperty< - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; - } - >, - V extends T[K_2], - >(object: T, propertyKey: K_2, value: V): Replaced; - - export type ResolveType = ReturnType extends PromiseLike ? U : never; - - export type Spied = T extends ClassLike - ? SpiedClass - : T extends FunctionLike - ? SpiedFunction - : never; - - export type SpiedClass = MockInstance< - (...args: ConstructorParameters) => InstanceType - >; - - export type SpiedFunction = MockInstance< - (...args: Parameters) => ReturnType - >; - - export type SpiedGetter = MockInstance<() => T>; - - export type SpiedSetter = MockInstance<(arg: T) => void>; - - export interface SpyInstance extends MockInstance {} - - export const spyOn: { - < - T extends object, - K_2 extends Exclude< - keyof T, - | keyof { - [K in keyof T as Required[K] extends ClassLike ? K : never]: T[K]; - } - | keyof { - [K_1 in keyof T as Required[K_1] extends FunctionLike ? K_1 : never]: T[K_1]; - } - >, - V extends Required[K_2], - A extends "set" | "get", - >( - object: T, - methodKey: K_2, - accessType: A, - ): A extends "get" ? SpiedGetter : A extends "set" ? SpiedSetter : never; - < - T_1 extends object, - K_5 extends - | keyof { - [K_3 in keyof T_1 as Required[K_3] extends ClassLike ? K_3 : never]: T_1[K_3]; - } - | keyof { - [K_4 in keyof T_1 as Required[K_4] extends FunctionLike ? K_4 : never]: T_1[K_4]; - }, - V_1 extends Required[K_5], - >( - object: T_1, - methodKey: K_5, - ): V_1 extends ClassLike | FunctionLike ? Spied : never; - }; - - export interface UnknownClass { - new (...args: unknown[]): unknown; - } - - export type UnknownFunction = (...args: unknown[]) => unknown; -} diff --git a/packages/bun-types/new/wasm.d.ts b/packages/bun-types/new/wasm.d.ts deleted file mode 100644 index 84c1a8fe4fba9f..00000000000000 --- a/packages/bun-types/new/wasm.d.ts +++ /dev/null @@ -1,193 +0,0 @@ -declare module "bun" { - namespace WebAssembly { - type ImportExportKind = "function" | "global" | "memory" | "table"; - type TableKind = "anyfunc" | "externref"; - type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table; - type Exports = Record; - type ImportValue = ExportValue | number; - type Imports = Record; - type ModuleImports = Record; - - interface ValueTypeMap { - anyfunc: Function; - externref: any; - f32: number; - f64: number; - i32: number; - i64: bigint; - v128: never; - } - - type ValueType = keyof ValueTypeMap; - - interface GlobalDescriptor { - mutable?: boolean; - value: T; - } - - interface Global { - // { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ - value: ValueTypeMap[T]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ - valueOf(): ValueTypeMap[T]; - } - - interface CompileError extends Error {} - - interface LinkError extends Error {} - - interface RuntimeError extends Error {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ - interface Instance { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ - readonly exports: Exports; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ - interface Memory { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ - readonly buffer: ArrayBuffer; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ - grow(delta: number): number; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ - interface Module {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ - interface Table { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ - readonly length: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ - get(index: number): any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ - grow(delta: number, value?: any): number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ - set(index: number, value?: any): void; - } - - interface MemoryDescriptor { - initial: number; - maximum?: number; - shared?: boolean; - } - - interface ModuleExportDescriptor { - kind: ImportExportKind; - name: string; - } - - interface ModuleImportDescriptor { - kind: ImportExportKind; - module: string; - name: string; - } - - interface TableDescriptor { - element: TableKind; - initial: number; - maximum?: number; - } - - interface WebAssemblyInstantiatedSource { - instance: Instance; - module: Module; - } - } -} - -declare namespace WebAssembly { - interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} - interface GlobalDescriptor - extends Bun.WebAssembly.GlobalDescriptor {} - interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} - interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} - interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} - interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} - interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} - - interface LinkError extends Bun.WebAssembly.LinkError {} - var LinkError: { - prototype: LinkError; - new (message?: string): LinkError; - (message?: string): LinkError; - }; - - interface CompileError extends Bun.WebAssembly.CompileError {} - var CompileError: { - prototype: CompileError; - new (message?: string): CompileError; - (message?: string): CompileError; - }; - - interface RuntimeError extends Bun.WebAssembly.RuntimeError {} - var RuntimeError: { - prototype: RuntimeError; - new (message?: string): RuntimeError; - (message?: string): RuntimeError; - }; - - interface Global extends Bun.WebAssembly.Global {} - var Global: { - prototype: Global; - new ( - descriptor: GlobalDescriptor, - v?: ValueTypeMap[T], - ): Global; - }; - - interface Instance extends Bun.WebAssembly.Instance {} - var Instance: { - prototype: Instance; - new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; - }; - - interface Memory extends Bun.WebAssembly.Memory {} - var Memory: { - prototype: Memory; - new (descriptor: MemoryDescriptor): Memory; - }; - - interface Module extends Bun.WebAssembly.Module {} - var Module: Bun.__internal.UseLibDomIfAvailable< - "WebAssembly", - { - Module: { - prototype: Module; - new (bytes: Bun.BufferSource): Module; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ - customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ - exports(moduleObject: Module): ModuleExportDescriptor[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ - imports(moduleObject: Module): ModuleImportDescriptor[]; - }; - } - >["Module"]; - - interface Table extends Bun.WebAssembly.Table {} - var Table: { - prototype: Table; - new (descriptor: TableDescriptor, value?: any): Table; - }; - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ - function compile(bytes: Bun.BufferSource): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ - function compileStreaming(source: Response | PromiseLike): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ - function instantiate( - bytes: Bun.BufferSource, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ - function instantiateStreaming( - source: Response | PromiseLike, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ - function validate(bytes: Bun.BufferSource): boolean; -} diff --git a/packages/bun-types/overrides.d.ts b/packages/bun-types/overrides.d.ts index 2c9563224342e2..03ad7b0bf2cff4 100644 --- a/packages/bun-types/overrides.d.ts +++ b/packages/bun-types/overrides.d.ts @@ -1,18 +1,33 @@ export {}; -import type { BunFile, Env, PathLike } from "bun"; - declare global { namespace NodeJS { + interface Process { + readonly version: string; + browser: boolean; + + /** + * Whether you are using Bun + */ + isBun: true; + + /** + * The current git sha of Bun + */ + revision: string; + + reallyExit(code?: number): never; + dlopen(module: { exports: any }, filename: string, flags?: number): void; + } + interface ProcessVersions extends Dict { bun: string; } - interface ProcessEnv extends Env {} } } declare module "fs/promises" { - function exists(path: PathLike): Promise; + function exists(path: Bun.PathLike): Promise; } declare module "tls" { @@ -22,7 +37,7 @@ declare module "tls" { * the well-known CAs curated by Mozilla. Mozilla's CAs are completely * replaced when CAs are explicitly specified using this option. */ - ca?: string | Buffer | NodeJS.TypedArray | BunFile | Array | undefined; + ca?: string | Buffer | NodeJS.TypedArray | Bun.BunFile | Array | undefined; /** * Cert chains in PEM format. One cert chain should be provided per * private key. Each cert chain should consist of the PEM formatted @@ -38,8 +53,8 @@ declare module "tls" { | string | Buffer | NodeJS.TypedArray - | BunFile - | Array + | Bun.BunFile + | Array | undefined; /** * Private keys in PEM format. PEM allows the option of private keys @@ -54,9 +69,9 @@ declare module "tls" { key?: | string | Buffer - | BunFile + | Bun.BunFile | NodeJS.TypedArray - | Array + | Array | undefined; } diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index f3db479d424c03..c3adf8474ebad8 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -2,7 +2,7 @@ "version": "1.2.5", "name": "bun-types", "license": "MIT", - "types": "./new/index.d.ts", + "types": "./index.d.ts", "description": "Type definitions and documentation for Bun, an incredibly fast JavaScript runtime", "repository": { "type": "git", @@ -10,7 +10,7 @@ "directory": "packages/bun-types" }, "files": [ - "new/**/*.d.ts", + "./*.d.ts", "docs/**/*.md", "docs/*.md" ], diff --git a/packages/bun-types/new/s3.d.ts b/packages/bun-types/s3.d.ts similarity index 100% rename from packages/bun-types/new/s3.d.ts rename to packages/bun-types/s3.d.ts diff --git a/packages/bun-types/new/sink.d.ts b/packages/bun-types/sink.d.ts similarity index 100% rename from packages/bun-types/new/sink.d.ts rename to packages/bun-types/sink.d.ts diff --git a/packages/bun-types/test.d.ts b/packages/bun-types/test.d.ts index acd28c72153ef7..8448317743fc6e 100644 --- a/packages/bun-types/test.d.ts +++ b/packages/bun-types/test.d.ts @@ -149,6 +149,10 @@ declare module "bun:test" { methodOrPropertyValue: K, ): Mock any ? T[K] : never>; + interface FunctionLike { + readonly name: string; + } + /** * Describes a group of related tests. * @@ -165,10 +169,6 @@ declare module "bun:test" { * @param label the label for the tests * @param fn the function that defines the tests */ - - interface FunctionLike { - readonly name: string; - } export interface Describe { (fn: () => void): void; diff --git a/packages/bun-types/wasm.d.ts b/packages/bun-types/wasm.d.ts index e0681ff8aba209..84c1a8fe4fba9f 100644 --- a/packages/bun-types/wasm.d.ts +++ b/packages/bun-types/wasm.d.ts @@ -1,269 +1,193 @@ -export {}; - -type _Global = typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; -} - ? T - : Bun.WebAssembly.Global; - -type _CompileError = typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; -} - ? T - : Bun.WebAssembly.CompileError; - -type _LinkError = typeof globalThis extends { - onerror: any; - WebAssembly: { LinkError: infer T }; -} - ? T - : Bun.WebAssembly.LinkError; - -type _RuntimeError = typeof globalThis extends { - onerror: any; - WebAssembly: { RuntimeError: infer T }; -} - ? T - : Bun.WebAssembly.RuntimeError; - -type _Memory = typeof globalThis extends { - onerror: any; - WebAssembly: { Memory: infer T }; -} - ? T - : Bun.WebAssembly.Memory; - -type _Instance = typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; -} - ? T - : Bun.WebAssembly.Instance; - -type _Module = typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; -} - ? T - : Bun.WebAssembly.Module; - -type _Table = typeof globalThis extends { - onerror: any; - WebAssembly: { Table: infer T }; -} - ? T - : Bun.WebAssembly.Table; - -declare global { - namespace Bun { - namespace WebAssembly { - type ImportExportKind = "function" | "global" | "memory" | "table"; - type TableKind = "anyfunc" | "externref"; - - type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table; - type Exports = Record; - type ImportValue = ExportValue | number; - type Imports = Record; - type ModuleImports = Record; - - interface ValueTypeMap { - anyfunc: Function; - externref: any; - f32: number; - f64: number; - i32: number; - i64: bigint; - v128: never; - } - - type ValueType = keyof ValueTypeMap; - - interface GlobalDescriptor { - mutable?: boolean; - value: T; - } - - interface Global { - // { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ - value: ValueTypeMap[T]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ - valueOf(): ValueTypeMap[T]; - } - - interface CompileError extends Error {} - - interface LinkError extends Error {} - - interface RuntimeError extends Error {} - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ - interface Instance { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ - readonly exports: Exports; - } - - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ - interface Memory { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ - readonly buffer: ArrayBuffer; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ - grow(delta: number): number; - } +declare module "bun" { + namespace WebAssembly { + type ImportExportKind = "function" | "global" | "memory" | "table"; + type TableKind = "anyfunc" | "externref"; + type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table; + type Exports = Record; + type ImportValue = ExportValue | number; + type Imports = Record; + type ModuleImports = Record; + + interface ValueTypeMap { + anyfunc: Function; + externref: any; + f32: number; + f64: number; + i32: number; + i64: bigint; + v128: never; + } - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ - interface Module {} + type ValueType = keyof ValueTypeMap; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ - interface Table { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ - readonly length: number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ - get(index: number): any; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ - grow(delta: number, value?: any): number; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ - set(index: number, value?: any): void; - } + interface GlobalDescriptor { + mutable?: boolean; + value: T; + } - interface MemoryDescriptor { - initial: number; - maximum?: number; - shared?: boolean; - } + interface Global { + // { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/value) */ + value: ValueTypeMap[T]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global/valueOf) */ + valueOf(): ValueTypeMap[T]; + } - interface ModuleExportDescriptor { - kind: ImportExportKind; - name: string; - } + interface CompileError extends Error {} - interface ModuleImportDescriptor { - kind: ImportExportKind; - module: string; - name: string; - } + interface LinkError extends Error {} - interface TableDescriptor { - element: TableKind; - initial: number; - maximum?: number; - } + interface RuntimeError extends Error {} - interface WebAssemblyInstantiatedSource { - instance: Instance; - module: Module; - } + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */ + interface Instance { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */ + readonly exports: Exports; } - } - namespace WebAssembly { - interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} - interface GlobalDescriptor - extends Bun.WebAssembly.GlobalDescriptor {} - interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} - interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} - interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} - interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} - interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} - - interface LinkError extends _LinkError {} - var LinkError: { - prototype: LinkError; - new (message?: string): LinkError; - (message?: string): LinkError; - }; - - interface CompileError extends _CompileError {} - var CompileError: typeof globalThis extends { - onerror: any; - WebAssembly: { CompileError: infer T }; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */ + interface Memory { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */ + readonly buffer: ArrayBuffer; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */ + grow(delta: number): number; } - ? T - : { - prototype: CompileError; - new (message?: string): CompileError; - (message?: string): CompileError; - }; - interface RuntimeError extends _RuntimeError {} - var RuntimeError: { - prototype: RuntimeError; - new (message?: string): RuntimeError; - (message?: string): RuntimeError; - }; - - interface Global extends _Global {} - var Global: typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */ + interface Module {} + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */ + interface Table { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */ + readonly length: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */ + get(index: number): any; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */ + grow(delta: number, value?: any): number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */ + set(index: number, value?: any): void; } - ? T - : { - prototype: Global; - new ( - descriptor: GlobalDescriptor, - v?: ValueTypeMap[T], - ): Global; - }; - interface Instance extends _Instance {} - var Instance: typeof globalThis extends { - onerror: any; - WebAssembly: { Instance: infer T }; + interface MemoryDescriptor { + initial: number; + maximum?: number; + shared?: boolean; } - ? T - : { - prototype: Instance; - new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; - }; - interface Memory extends _Memory {} - var Memory: { - prototype: Memory; - new (descriptor: MemoryDescriptor): Memory; - }; + interface ModuleExportDescriptor { + kind: ImportExportKind; + name: string; + } - interface Module extends _Module {} - var Module: typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; + interface ModuleImportDescriptor { + kind: ImportExportKind; + module: string; + name: string; } - ? T - : { - prototype: Module; - new (bytes: Bun.BufferSource): Module; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ - customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ - exports(moduleObject: Module): ModuleExportDescriptor[]; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ - imports(moduleObject: Module): ModuleImportDescriptor[]; - }; - interface Table extends _Table {} - var Table: { - prototype: Table; - new (descriptor: TableDescriptor, value?: any): Table; - }; + interface TableDescriptor { + element: TableKind; + initial: number; + maximum?: number; + } - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ - function compile(bytes: Bun.BufferSource): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ - function compileStreaming(source: Response | PromiseLike): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ - function instantiate( - bytes: Bun.BufferSource, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ - function instantiateStreaming( - source: Response | PromiseLike, - importObject?: Bun.WebAssembly.Imports, - ): Promise; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ - function validate(bytes: Bun.BufferSource): boolean; + interface WebAssemblyInstantiatedSource { + instance: Instance; + module: Module; + } } } + +declare namespace WebAssembly { + interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {} + interface GlobalDescriptor + extends Bun.WebAssembly.GlobalDescriptor {} + interface MemoryDescriptor extends Bun.WebAssembly.MemoryDescriptor {} + interface ModuleExportDescriptor extends Bun.WebAssembly.ModuleExportDescriptor {} + interface ModuleImportDescriptor extends Bun.WebAssembly.ModuleImportDescriptor {} + interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {} + interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {} + + interface LinkError extends Bun.WebAssembly.LinkError {} + var LinkError: { + prototype: LinkError; + new (message?: string): LinkError; + (message?: string): LinkError; + }; + + interface CompileError extends Bun.WebAssembly.CompileError {} + var CompileError: { + prototype: CompileError; + new (message?: string): CompileError; + (message?: string): CompileError; + }; + + interface RuntimeError extends Bun.WebAssembly.RuntimeError {} + var RuntimeError: { + prototype: RuntimeError; + new (message?: string): RuntimeError; + (message?: string): RuntimeError; + }; + + interface Global extends Bun.WebAssembly.Global {} + var Global: { + prototype: Global; + new ( + descriptor: GlobalDescriptor, + v?: ValueTypeMap[T], + ): Global; + }; + + interface Instance extends Bun.WebAssembly.Instance {} + var Instance: { + prototype: Instance; + new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; + }; + + interface Memory extends Bun.WebAssembly.Memory {} + var Memory: { + prototype: Memory; + new (descriptor: MemoryDescriptor): Memory; + }; + + interface Module extends Bun.WebAssembly.Module {} + var Module: Bun.__internal.UseLibDomIfAvailable< + "WebAssembly", + { + Module: { + prototype: Module; + new (bytes: Bun.BufferSource): Module; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */ + customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */ + exports(moduleObject: Module): ModuleExportDescriptor[]; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */ + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + } + >["Module"]; + + interface Table extends Bun.WebAssembly.Table {} + var Table: { + prototype: Table; + new (descriptor: TableDescriptor, value?: any): Table; + }; + + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile) */ + function compile(bytes: Bun.BufferSource): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming) */ + function compileStreaming(source: Response | PromiseLike): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) */ + function instantiate( + bytes: Bun.BufferSource, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + function instantiate(moduleObject: Module, importObject?: Bun.WebAssembly.Imports): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) */ + function instantiateStreaming( + source: Response | PromiseLike, + importObject?: Bun.WebAssembly.Imports, + ): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */ + function validate(bytes: Bun.BufferSource): boolean; +} From a5d11b99eff5a35ad773e224e602465fcde3f4da Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 15:00:50 +0000 Subject: [PATCH 43/72] change svg decl in extensions.d.ts --- packages/bun-types/extensions.d.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/bun-types/extensions.d.ts b/packages/bun-types/extensions.d.ts index e70c5245ea4d23..fb0a2ee0653f4f 100644 --- a/packages/bun-types/extensions.d.ts +++ b/packages/bun-types/extensions.d.ts @@ -1,8 +1,3 @@ -declare module "*.svg" { - const content: `${string}.svg`; - export = content; -} - declare module "*.txt" { var text: string; export = text; @@ -24,7 +19,13 @@ declare module "*/bun.lock" { } declare module "*.html" { - // In Bun v1.2, we might change this to Bun.HTMLBundle + // In Bun v1.2, this might change to Bun.HTMLBundle var contents: any; export = contents; } + +declare module "*.svg" { + // Bun 1.2.3 added support for frontend dev server + var content: `${string}.svg`; + export = content; +} From 70660c612acf8bcf57f29cd10fa0e586e2b4d496 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 15:07:10 +0000 Subject: [PATCH 44/72] make devserver.d.ts non-module to fix namespace clash --- packages/bun-types/devserver.d.ts | 342 +++++++++---------- test/integration/bun-types/fixture/test.d.ts | 1 - 2 files changed, 169 insertions(+), 174 deletions(-) delete mode 100644 test/integration/bun-types/fixture/test.d.ts diff --git a/packages/bun-types/devserver.d.ts b/packages/bun-types/devserver.d.ts index cfb0ebe9eb5108..76e4e4eeae2f8a 100644 --- a/packages/bun-types/devserver.d.ts +++ b/packages/bun-types/devserver.d.ts @@ -1,193 +1,189 @@ -export {}; +declare module "bun" { + type HMREventNames = + | "bun:beforeUpdate" + | "bun:afterUpdate" + | "bun:beforeFullReload" + | "bun:beforePrune" + | "bun:invalidate" + | "bun:error" + | "bun:ws:disconnect" + | "bun:ws:connect"; -declare global { - namespace Bun { - type HMREventNames = - | "bun:beforeUpdate" - | "bun:afterUpdate" - | "bun:beforeFullReload" - | "bun:beforePrune" - | "bun:invalidate" - | "bun:error" - | "bun:ws:disconnect" - | "bun:ws:connect"; + /** + * The event names for the dev server + */ + type HMREvent = `bun:${HMREventNames}` | (string & {}); +} +interface ImportMeta { + /** + * Hot module replacement APIs. This value is `undefined` in production and + * can be used in an `if` statement to check if HMR APIs are available + * + * ```ts + * if (import.meta.hot) { + * // HMR APIs are available + * } + * ``` + * + * However, this check is usually not needed as Bun will dead-code-eliminate + * calls to all of the HMR APIs in production builds. + * + * https://bun.sh/docs/bundler/hmr + */ + hot: { /** - * The event names for the dev server + * `import.meta.hot.data` maintains state between module instances during + * hot replacement, enabling data transfer from previous to new versions. + * When `import.meta.hot.data` is written to, Bun will mark this module as + * capable of self-accepting (equivalent of calling `accept()`). + * + * @example + * ```ts + * const root = import.meta.hot.data.root ??= createRoot(elem); + * root.render(); // re-use an existing root + * ``` + * + * In production, `data` is inlined to be `{}`. This is handy because Bun + * knows it can minify `{}.prop ??= value` into `value` in production. + * + * */ - type HMREvent = `bun:${HMREventNames}` | (string & {}); - } + data: any; - interface ImportMeta { /** - * Hot module replacement APIs. This value is `undefined` in production and - * can be used in an `if` statement to check if HMR APIs are available + * Indicate that this module can be replaced simply by re-evaluating the + * file. After a hot update, importers of this module will be + * automatically patched. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. * + * @example * ```ts - * if (import.meta.hot) { - * // HMR APIs are available - * } - * ``` + * import { getCount } from "./foo"; * - * However, this check is usually not needed as Bun will dead-code-eliminate - * calls to all of the HMR APIs in production builds. + * console.log("count is ", getCount()); * - * https://bun.sh/docs/bundler/hmr + * import.meta.hot.accept(); + * ``` */ - hot: { - /** - * `import.meta.hot.data` maintains state between module instances during - * hot replacement, enabling data transfer from previous to new versions. - * When `import.meta.hot.data` is written to, Bun will mark this module as - * capable of self-accepting (equivalent of calling `accept()`). - * - * @example - * ```ts - * const root = import.meta.hot.data.root ??= createRoot(elem); - * root.render(); // re-use an existing root - * ``` - * - * In production, `data` is inlined to be `{}`. This is handy because Bun - * knows it can minify `{}.prop ??= value` into `value` in production. - * - * - */ - data: any; - - /** - * Indicate that this module can be replaced simply by re-evaluating the - * file. After a hot update, importers of this module will be - * automatically patched. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * import { getCount } from "./foo"; - * - * console.log("count is ", getCount()); - * - * import.meta.hot.accept(); - * ``` - */ - accept(): void; + accept(): void; - /** - * Indicate that this module can be replaced by evaluating the new module, - * and then calling the callback with the new module. In this mode, the - * importers do not get patched. This is to match Vite, which is unable - * to patch their import statements. Prefer using `import.meta.hot.accept()` - * without an argument as it usually makes your code easier to understand. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * export const count = 0; - * - * import.meta.hot.accept((newModule) => { - * if (newModule) { - * // newModule is undefined when SyntaxError happened - * console.log('updated: count is now ', newModule.count) - * } - * }); - * ``` - * - * In production, calls to this are dead-code-eliminated. - */ - accept(cb: (newModule: any | undefined) => void): void; + /** + * Indicate that this module can be replaced by evaluating the new module, + * and then calling the callback with the new module. In this mode, the + * importers do not get patched. This is to match Vite, which is unable + * to patch their import statements. Prefer using `import.meta.hot.accept()` + * without an argument as it usually makes your code easier to understand. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + * + * @example + * ```ts + * export const count = 0; + * + * import.meta.hot.accept((newModule) => { + * if (newModule) { + * // newModule is undefined when SyntaxError happened + * console.log('updated: count is now ', newModule.count) + * } + * }); + * ``` + * + * In production, calls to this are dead-code-eliminated. + */ + accept(cb: (newModule: any | undefined) => void): void; - /** - * Indicate that a dependency's module can be accepted. When the dependency - * is updated, the callback will be called with the new module. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - * - * @example - * ```ts - * import.meta.hot.accept('./foo', (newModule) => { - * if (newModule) { - * // newModule is undefined when SyntaxError happened - * console.log('updated: count is now ', newModule.count) - * } - * }); - * ``` - */ - accept(specifier: string, callback: (newModule: any) => void): void; + /** + * Indicate that a dependency's module can be accepted. When the dependency + * is updated, the callback will be called with the new module. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + * + * @example + * ```ts + * import.meta.hot.accept('./foo', (newModule) => { + * if (newModule) { + * // newModule is undefined when SyntaxError happened + * console.log('updated: count is now ', newModule.count) + * } + * }); + * ``` + */ + accept(specifier: string, callback: (newModule: any) => void): void; - /** - * Indicate that a dependency's module can be accepted. This variant - * accepts an array of dependencies, where the callback will receive - * the one updated module, and `undefined` for the rest. - * - * When `import.meta.hot.accept` is not used, the page will reload when - * the file updates, and a console message shows which files were checked. - */ - accept(specifiers: string[], callback: (newModules: (any | undefined)[]) => void): void; + /** + * Indicate that a dependency's module can be accepted. This variant + * accepts an array of dependencies, where the callback will receive + * the one updated module, and `undefined` for the rest. + * + * When `import.meta.hot.accept` is not used, the page will reload when + * the file updates, and a console message shows which files were checked. + */ + accept(specifiers: string[], callback: (newModules: (any | undefined)[]) => void): void; - /** - * Attach an on-dispose callback. This is called: - * - Just before the module is replaced with another copy (before the next is loaded) - * - After the module is detached (removing all imports to this module) - * - * This callback is not called on route navigation or when the browser tab closes. - * - * Returning a promise will delay module replacement until the module is - * disposed. All dispose callbacks are called in parallel. - */ - dispose(cb: (data: any) => void | Promise): void; + /** + * Attach an on-dispose callback. This is called: + * - Just before the module is replaced with another copy (before the next is loaded) + * - After the module is detached (removing all imports to this module) + * + * This callback is not called on route navigation or when the browser tab closes. + * + * Returning a promise will delay module replacement until the module is + * disposed. All dispose callbacks are called in parallel. + */ + dispose(cb: (data: any) => void | Promise): void; - /** - * No-op - * @deprecated - */ - decline(): void; + /** + * No-op + * @deprecated + */ + decline(): void; - // NOTE TO CONTRIBUTORS //////////////////////////////////////// - // Callback is currently never called for `.prune()` // - // so the types are commented out until we support it. // - //////////////////////////////////////////////////////////////// - // /** - // * Attach a callback that is called when the module is removed from the module graph. - // * - // * This can be used to clean up resources that were created when the module was loaded. - // * Unlike `import.meta.hot.dispose()`, this pairs much better with `accept` and `data` to manage stateful resources. - // * - // * @example - // * ```ts - // * export const ws = (import.meta.hot.data.ws ??= new WebSocket(location.origin)); - // * - // * import.meta.hot.prune(() => { - // * ws.close(); - // * }); - // * ``` - // */ - // prune(callback: () => void): void; + // NOTE TO CONTRIBUTORS //////////////////////////////////////// + // Callback is currently never called for `.prune()` // + // so the types are commented out until we support it. // + //////////////////////////////////////////////////////////////// + // /** + // * Attach a callback that is called when the module is removed from the module graph. + // * + // * This can be used to clean up resources that were created when the module was loaded. + // * Unlike `import.meta.hot.dispose()`, this pairs much better with `accept` and `data` to manage stateful resources. + // * + // * @example + // * ```ts + // * export const ws = (import.meta.hot.data.ws ??= new WebSocket(location.origin)); + // * + // * import.meta.hot.prune(() => { + // * ws.close(); + // * }); + // * ``` + // */ + // prune(callback: () => void): void; - /** - * Listen for an event from the dev server - * - * For compatibility with Vite, event names are also available via vite:* prefix instead of bun:*. - * - * https://bun.sh/docs/bundler/hmr#import-meta-hot-on-and-off - * @param event The event to listen to - * @param callback The callback to call when the event is emitted - */ - on(event: Bun.HMREvent, callback: () => void): void; + /** + * Listen for an event from the dev server + * + * For compatibility with Vite, event names are also available via vite:* prefix instead of bun:*. + * + * https://bun.sh/docs/bundler/hmr#import-meta-hot-on-and-off + * @param event The event to listen to + * @param callback The callback to call when the event is emitted + */ + on(event: Bun.HMREvent, callback: () => void): void; - /** - * Stop listening for an event from the dev server - * - * For compatibility with Vite, event names are also available via vite:* prefix instead of bun:*. - * - * https://bun.sh/docs/bundler/hmr#import-meta-hot-on-and-off - * @param event The event to stop listening to - * @param callback The callback to stop listening to - */ - off(event: Bun.HMREvent, callback: () => void): void; - }; - } + /** + * Stop listening for an event from the dev server + * + * For compatibility with Vite, event names are also available via vite:* prefix instead of bun:*. + * + * https://bun.sh/docs/bundler/hmr#import-meta-hot-on-and-off + * @param event The event to stop listening to + * @param callback The callback to stop listening to + */ + off(event: Bun.HMREvent, callback: () => void): void; + }; } diff --git a/test/integration/bun-types/fixture/test.d.ts b/test/integration/bun-types/fixture/test.d.ts deleted file mode 100644 index cb0ff5c3b541f6..00000000000000 --- a/test/integration/bun-types/fixture/test.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; From 4a192812f2ea6a24c5ad1955f6a0c552facfc8a1 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 15:28:40 +0000 Subject: [PATCH 45/72] authoring --- packages/bun-types/authoring.md | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 packages/bun-types/authoring.md diff --git a/packages/bun-types/authoring.md b/packages/bun-types/authoring.md new file mode 100644 index 00000000000000..e2b54ed36e254a --- /dev/null +++ b/packages/bun-types/authoring.md @@ -0,0 +1,89 @@ +# Authoring @types/bun + +### Module Declaration + +The `Bun` global variable and the `'bun'` module are now declared in one place. It supports declaring types/interfaces and also runtime values. + +```typescript +declare module "bun" { + // Your types go here + interface MyInterface { + // ... + } + + type MyType = string | number; + + function myFunction(): void; +} +``` + +The above can now be used like this + +```ts +import { type MyInterface, type MyType, myFunction } from "bun"; +const myInterface: MyInterface = {}; +const myType: MyType = "cool"; +myFunction(); +// OR +const myInterface: Bun.MyInterface = {}; +const myType: Bun.MyType = "cool"; +Bun.myFunction(); +``` + +### File structure + +Types are organized across multiple `.d.ts` files in the `packages/bun-types` directory: + +- `bun.d.ts` - Core Bun APIs and types +- `globals.d.ts` - Global type declarations +- `test.d.ts` - Testing-related types +- `sqlite.d.ts` - SQLite-related types +- etc. + +All these files are referenced in `index.d.ts` using `/// `. + +Make sure to leave the `bun.ns.d.ts` reference last. + +### Best Practices + +1. **Type Safety** + + - Please use strict types instead of `any` where possible + - Leverage TypeScript's type system features (generics, unions, etc.) + - Document complex types with JSDoc comments + +2. **Compatibility** + + - Use `Bun.__internal.UseLibDomIfAvailable` for types that might conflict with lib.dom.d.ts + - `@types/node` often expects variables to always be defined (this was the biggest cause of most of the conflicts in the past!), so we use the `UseLibDomIfAvailable` type to make sure we don't overwrite `lib.dom.d.ts` but still provide Bun types while simultaneously declaring the variable exists (for Node to work) in the cases that we can. + +3. **Documentation** + - Add JSDoc comments for public APIs + - Include examples in documentation when helpful + - Document default values and important behaviors + +### Internal Types + +For internal types that shouldn't be exposed to users, use the `__internal` namespace: + +```typescript +declare module "bun" { + namespace __internal { + interface MyInternalType { + // ... + } + } +} +``` + +The internal namespace is mostly used for declaring things that shouldn't be globally accessible on the `bun` namespace, but are still used in public apis. You can see a pretty good example of that in the [`./fetch.d.ts`](./fetch.d.ts) file. + +## Testing Types + +There is a `fixture/index.ts` file which doesn't actually ever get ran, but does get type-checked in two environments - with lib.dom.d.ts, and without. + +Your types should pass in both environments! + +## Questions + +Feel free to open an issue or speak to any of the more TypeScript-focused team members if you need help authoring types or fixing type tests. From 3c292cea958086ec21b24957637847a384b7ecbc Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 15:50:57 +0000 Subject: [PATCH 46/72] make clarifications in authoring.md --- packages/bun-types/authoring.md | 41 ++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/packages/bun-types/authoring.md b/packages/bun-types/authoring.md index e2b54ed36e254a..8f98892e9eac78 100644 --- a/packages/bun-types/authoring.md +++ b/packages/bun-types/authoring.md @@ -1,8 +1,10 @@ # Authoring @types/bun -### Module Declaration +These declarations define the `'bun'` module, the `Bun` global variable, and lots of other global declarations like extending the `fetch` interface. -The `Bun` global variable and the `'bun'` module are now declared in one place. It supports declaring types/interfaces and also runtime values. +## The `'bun'` Module + +The `Bun` global variable and the `'bun'` module types are defined with one syntax. It supports declaring both types/interfaces and runtime values: ```typescript declare module "bun" { @@ -17,32 +19,38 @@ declare module "bun" { } ``` -The above can now be used like this +You can use these declarations in two ways: + +1. Importing it from `'bun'`: -```ts +```typescript import { type MyInterface, type MyType, myFunction } from "bun"; + const myInterface: MyInterface = {}; const myType: MyType = "cool"; myFunction(); -// OR +``` + +2. Using the global `Bun` object: + +```typescript const myInterface: Bun.MyInterface = {}; const myType: Bun.MyType = "cool"; Bun.myFunction(); ``` -### File structure +## File Structure Types are organized across multiple `.d.ts` files in the `packages/bun-types` directory: +- `index.d.ts` - The main entry point that references all other type files - `bun.d.ts` - Core Bun APIs and types - `globals.d.ts` - Global type declarations - `test.d.ts` - Testing-related types - `sqlite.d.ts` - SQLite-related types -- etc. - -All these files are referenced in `index.d.ts` using `/// `. +- ...etc. You can make more files -Make sure to leave the `bun.ns.d.ts` reference last. +Note: The order of references in `index.d.ts` is important - `bun.ns.d.ts` must be referenced last to ensure the `Bun` global gets defined properly. ### Best Practices @@ -54,7 +62,7 @@ Make sure to leave the `bun.ns.d.ts` reference last. 2. **Compatibility** - - Use `Bun.__internal.UseLibDomIfAvailable` for types that might conflict with lib.dom.d.ts + - Use `Bun.__internal.UseLibDomIfAvailable` for types that might conflict with lib.dom.d.ts (see [`./fetch.d.ts`](./fetch.d.ts) for a real example) - `@types/node` often expects variables to always be defined (this was the biggest cause of most of the conflicts in the past!), so we use the `UseLibDomIfAvailable` type to make sure we don't overwrite `lib.dom.d.ts` but still provide Bun types while simultaneously declaring the variable exists (for Node to work) in the cases that we can. 3. **Documentation** @@ -80,9 +88,16 @@ The internal namespace is mostly used for declaring things that shouldn't be glo ## Testing Types -There is a `fixture/index.ts` file which doesn't actually ever get ran, but does get type-checked in two environments - with lib.dom.d.ts, and without. +We test our type definitions using a special test file at `fixture/index.ts`. This file contains TypeScript code that exercises our type definitions, but is never actually executed - it's only used to verify that the types work correctly. + +The test file is type-checked in two different environments: + +1. With `lib.dom.d.ts` included - This simulates usage in a browser environment where DOM types are available +2. Without `lib.dom.d.ts` - This simulates usage in a Node.js-like environment without DOM types + +Your type definitions must work properly in both environments. This ensures that Bun's types are compatible regardless of whether DOM types are present or not. -Your types should pass in both environments! +For example, if you're adding types for a new API, you should just add code to `fixture/index.ts` that uses your new API. Doesn't need to work at runtime (e.g. you can fake api keys for example), it's just checking that the types are correct. ## Questions From 7e9cd478e1c639756e002a9abc4860368ebc2795 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 16:10:38 +0000 Subject: [PATCH 47/72] update --- packages/bun-types/authoring.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bun-types/authoring.md b/packages/bun-types/authoring.md index 8f98892e9eac78..bb3017d5deb58f 100644 --- a/packages/bun-types/authoring.md +++ b/packages/bun-types/authoring.md @@ -93,7 +93,7 @@ We test our type definitions using a special test file at `fixture/index.ts`. Th The test file is type-checked in two different environments: 1. With `lib.dom.d.ts` included - This simulates usage in a browser environment where DOM types are available -2. Without `lib.dom.d.ts` - This simulates usage in a Node.js-like environment without DOM types +2. Without `lib.dom.d.ts` - This simulates usage in a server-like environment without DOM types Your type definitions must work properly in both environments. This ensures that Bun's types are compatible regardless of whether DOM types are present or not. From 1cba7d6a77214ef6eb47f2d343c4e8d68c56bdd5 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 13 Mar 2025 16:13:25 +0000 Subject: [PATCH 48/72] update authoring.md --- packages/bun-types/authoring.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/bun-types/authoring.md b/packages/bun-types/authoring.md index bb3017d5deb58f..6b3dd9f0ab4e33 100644 --- a/packages/bun-types/authoring.md +++ b/packages/bun-types/authoring.md @@ -19,7 +19,9 @@ declare module "bun" { } ``` -You can use these declarations in two ways: +You can write as many `declare module "bun"` declarations as you need. Symbols will be accessible from other files inside of the declaration, and they will all be merged when the types are evaluated. + +You can consume these declarations in two ways: 1. Importing it from `'bun'`: @@ -39,6 +41,14 @@ const myType: Bun.MyType = "cool"; Bun.myFunction(); ``` +Consuming them inside the ambient declarations is also easy: + +```ts +// These are equivalent +type A = import("bun").MyType; +type A = Bun.MyType; +``` + ## File Structure Types are organized across multiple `.d.ts` files in the `packages/bun-types` directory: From df459eac5b0d172bf97453bb2399eab0a009d87f Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 14 Mar 2025 02:14:58 +0000 Subject: [PATCH 49/72] fix: globally define RequestInit and ResponseInit --- bun.lock | 7 +-- packages/bun-types/bun.d.ts | 11 +--- packages/bun-types/fetch.d.ts | 52 +++++++++++++++---- packages/bun-types/package.json | 3 +- test/integration/bun-types/fixture/bun.lock | 8 ++- test/integration/bun-types/fixture/index.ts | 12 ++++- .../bun-types/fixture/package.json | 2 +- 7 files changed, 59 insertions(+), 36 deletions(-) diff --git a/bun.lock b/bun.lock index bd862d199df4e5..98862ac558c74e 100644 --- a/bun.lock +++ b/bun.lock @@ -31,8 +31,7 @@ "dependencies": { "@types/node": "*", "@types/ws": "*", - "@typescript/lib-dom": "github:alii/lib-dom-bun-testing", - "@oven/typescript-bun-lib-dom": "https://github.com/alii/lib-dom-bun-testing", + "@typescript/lib-dom": "github:alii/lib-dom-bun-testing#156f65536ab9431abae2db4f9489e3d85cfb9f41", }, "devDependencies": { "@biomejs/biome": "^1.5.3", @@ -152,8 +151,6 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], - "@qiwi/npm-registry-client": ["@qiwi/npm-registry-client@8.9.1", "", { "dependencies": { "concat-stream": "^2.0.0", "graceful-fs": "^4.2.4", "normalize-package-data": "~1.0.1 || ^2.0.0 || ^3.0.0", "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^8.0.0", "once": "^1.4.0", "request": "^2.88.2", "retry": "^0.12.0", "safe-buffer": "^5.2.1", "semver": "2 >=2.2.1 || 3.x || 4 || 5 || 7", "slide": "^1.1.6", "ssri": "^8.0.0" }, "optionalDependencies": { "npmlog": "2 || ^3.1.0 || ^4.0.0" } }, "sha512-rZF+mG+NfijR0SHphhTLHRr4aM4gtfdwoAMY6we2VGQam8vkN1cxGG1Lg/Llrj8Dd0Mu6VjdFQRyMMRZxtZR2A=="], "@types/bun": ["@types/bun@1.2.2", "", { "dependencies": { "bun-types": "1.2.2" } }, "sha512-tr74gdku+AEDN5ergNiBnplr7hpDp3V1h7fqI2GcR/rsUaM39jpSeKH0TFibRvU0KwniRx5POgaYnaXbk0hU+w=="], @@ -188,7 +185,7 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" } }, "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg=="], - "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], + "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#156f655", {}, "alii-lib-dom-bun-testing-156f655"], "@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="], diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 4dbe674852b08c..3d3382448d0759 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -152,15 +152,6 @@ declare module "bun" { value: T[]; } - interface ResponseInit { - headers?: Bun.__internal.BunHeadersInit; - /** @default 200 */ - status?: number; - - /** @default "OK" */ - statusText?: string; - } - interface EventSourceEventMap { error: Event; message: MessageEvent; @@ -4064,7 +4055,7 @@ declare module "bun" { /** * Send any additional headers while upgrading, like cookies */ - headers?: Bun.__internal.BunHeadersInit; + headers?: HeadersInit; /** * This value is passed to the {@link ServerWebSocket.data} property */ diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index bdee6570700e7a..22028b2b1f447b 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,17 +1,17 @@ -declare module "bun" { - namespace __internal { - type BunBodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; +interface BunGlobalSymbolRegistry { + BodyInit: ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; + HeadersInit: Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; +} - type BunHeadersInit = - | Headers - | Record - | Array<[string, string]> - | IterableIterator<[string, string]>; +declare module "bun" { + type BodyInit = BunGlobalSymbolRegistry["BodyInit"]; + type HeadersInit = BunGlobalSymbolRegistry["HeadersInit"]; + namespace __internal { /** * @internal */ - type LibOrUndiciHeaders = LibDomIsLoaded extends true ? typeof globalThis.Headers : import("undici-types").Headers; + type LibOrUndiciHeaders = LibDomIsLoaded extends true ? {} : import("undici-types").Headers; /** * @internal @@ -23,6 +23,30 @@ declare module "bun" { */ type LibOrUndiciResponse = LibDomIsLoaded extends true ? {} : import("undici-types").Response; + /** + * @internal + */ + type LibOrUndiciRequestInit = LibDomIsLoaded extends true + ? {} + : Omit & { + body?: BodyInit | null | undefined; + }; + + /** + * @internal + */ + type LibOrUndiciResponseInit = LibDomIsLoaded extends true + ? { + headers?: HeadersInit; + + /** @default 200 */ + status?: number; + + /** @default "OK" */ + statusText?: string; + } + : import("undici-types").ResponseInit; + interface BunHeadersOverride extends LibOrUndiciHeaders { /** * Convert {@link Headers} to a plain JavaScript object. @@ -66,14 +90,20 @@ declare module "bun" { headers: BunHeadersOverride; } } + + interface RequestInit extends Bun.__internal.LibOrUndiciRequestInit {} + interface ResponseInit extends Bun.__internal.LibOrUndiciResponseInit {} } +interface RequestInit extends Bun.RequestInit {} +interface ResponseInit extends Bun.ResponseInit {} + interface Headers extends Bun.__internal.BunHeadersOverride {} declare var Headers: Bun.__internal.UseLibDomIfAvailable< "Headers", { prototype: Headers; - new (init?: Bun.__internal.BunHeadersInit): Headers; + new (init?: Bun.HeadersInit): Headers; } >; @@ -92,7 +122,7 @@ declare var Request: Bun.__internal.UseLibDomIfAvailable< interface Response extends Bun.__internal.BunResponseOverride {} interface ResponseConstructor { - new (body?: Bun.__internal.BunBodyInit | null | undefined, init?: ResponseInit | undefined): Response; + new (body?: Bun.BodyInit | null | undefined, init?: ResponseInit | undefined): Response; /** * Create a new {@link Response} with a JSON body * diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index c3adf8474ebad8..c907625ba0495c 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -16,10 +16,9 @@ ], "homepage": "https://bun.sh", "dependencies": { - "@oven/typescript-bun-lib-dom": "https://github.com/alii/lib-dom-bun-testing", "@types/node": "*", "@types/ws": "*", - "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" + "@typescript/lib-dom": "github:alii/lib-dom-bun-testing#156f65536ab9431abae2db4f9489e3d85cfb9f41" }, "devDependencies": { "@biomejs/biome": "^1.5.3", diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index b62f6b5a663bcf..673f191ac585da 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -5,7 +5,7 @@ "name": "fixture", "dependencies": { "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing#f34eacab7b78435ee18f0227974bc0a6756ccb0f", - "@types/bun": "types-bun-1.2.6.tgz", + "@types/bun": "types-bun-1.2.5.tgz", }, "peerDependencies": { "typescript": "^5.8.2", @@ -15,18 +15,16 @@ "packages": { "@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], - "@types/bun": ["@types/bun@types-bun-1.2.6.tgz", { "dependencies": { "@oven/typescript-bun-lib-dom": "https://github.com/alii/lib-dom-bun-testing", "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing" } }], + "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing#156f65536ab9431abae2db4f9489e3d85cfb9f41" } }], "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], "@types/ws": ["@types/ws@8.18.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw=="], - "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], + "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#156f655", {}, "alii-lib-dom-bun-testing-156f655"], "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/bun/@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], } } diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index e99270b25a09f9..5b0bf8b9e23144 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -255,8 +255,8 @@ URL.canParse; URL.createObjectURL; URL.revokeObjectURL; -declare const myBodyInit: BodyInit; -declare const myHeadersInit: HeadersInit; +declare const myBodyInit: Bun.BodyInit; +declare const myHeadersInit: Bun.HeadersInit; new MessagePort(); @@ -284,6 +284,14 @@ Bun.fetch("", { const myRequest: Request = new Request(""); +const myRequestInit: RequestInit = { + body: "", + method: "GET", +}; + +declare const requestInitKeys: `evaluate-${keyof RequestInit}`; +requestInitKeys satisfies string; + Bun.serve({ fetch(req) { req.headers; diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index aad9eef9faaddf..23b71c528dd4d7 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -10,6 +10,6 @@ "type": "module", "dependencies": { "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing#f34eacab7b78435ee18f0227974bc0a6756ccb0f", - "@types/bun": "types-bun-1.2.6.tgz" + "@types/bun": "types-bun-1.2.5.tgz" } } From e2f825d7f5d80d2476ab2fc74a9428d9899725de Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 14 Mar 2025 15:57:51 +0000 Subject: [PATCH 50/72] fetch changes + some doc + test fixture work --- packages/bun-types/bun.d.ts | 4 +- packages/bun-types/fetch.d.ts | 53 ++++++++++++------- test/integration/bun-types/bun-types.test.ts | 2 +- test/integration/bun-types/fixture/bun.lock | 4 +- .../bun-types/fixture/package.json | 4 +- 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 3d3382448d0759..0e9cd864e8f01c 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -82,9 +82,11 @@ declare module "bun" { | "win32" | "cygwin" | "netbsd"; + type Architecture = "arm" | "arm64" | "ia32" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x" | "x64"; 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. @@ -93,8 +95,6 @@ declare module "bun" { type MultipleResolveListener = (type: MultipleResolveType, promise: Promise, value: unknown) => void; - type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; - interface ErrorEventInit extends EventInit { colno?: number; error?: any; diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 22028b2b1f447b..5b73174a5d3c3f 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,3 +1,22 @@ +/** + * Bun uses a customised version of `lib.dom.d.ts` that allows us to declare + * certain types from within bun-types instead of the original DOM definitions. + * + * Our `lib.dom.d.ts` declares BunGlobalSymbolRegistry as an empty interface, + * which we can then extend in `bun-types` with our own Bun-specific overrides. + * + * For example, the type `BodyInit` is implemented like this in Bun's lib.dom.d.ts: + * ```ts + * interface BunGlobalSymbolRegistry {}; + * // ... elsewhere ... + * type BodyInit = BunGlobalSymbolRegistry extends {BodyInit: infer T} ? T : never; + * ``` + * + * While this solution works well, the ideal approach would be to define these types + * entirely within bun-types without any declarations in lib.dom.d.ts. This isn't + * done yet as as we need to determine how to make the TypeScript lib-dom + * generator emit types for not-yet-existing definitions. + */ interface BunGlobalSymbolRegistry { BodyInit: ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; HeadersInit: Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; @@ -7,26 +26,28 @@ declare module "bun" { type BodyInit = BunGlobalSymbolRegistry["BodyInit"]; type HeadersInit = BunGlobalSymbolRegistry["HeadersInit"]; + type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; + namespace __internal { /** * @internal */ - type LibOrUndiciHeaders = LibDomIsLoaded extends true ? {} : import("undici-types").Headers; + type LibOrFallbackHeaders = LibDomIsLoaded extends true ? {} : import("undici-types").Headers; /** * @internal */ - type LibOrUndiciRequest = LibDomIsLoaded extends true ? {} : import("undici-types").Request; + type LibOrFallbackRequest = LibDomIsLoaded extends true ? {} : import("undici-types").Request; /** * @internal */ - type LibOrUndiciResponse = LibDomIsLoaded extends true ? {} : import("undici-types").Response; + type LibOrFallbackResponse = LibDomIsLoaded extends true ? {} : import("undici-types").Response; /** * @internal */ - type LibOrUndiciRequestInit = LibDomIsLoaded extends true + type LibOrFallbackRequestInit = LibDomIsLoaded extends true ? {} : Omit & { body?: BodyInit | null | undefined; @@ -35,19 +56,9 @@ declare module "bun" { /** * @internal */ - type LibOrUndiciResponseInit = LibDomIsLoaded extends true - ? { - headers?: HeadersInit; - - /** @default 200 */ - status?: number; - - /** @default "OK" */ - statusText?: string; - } - : import("undici-types").ResponseInit; + type LibOrFallbackResponseInit = LibDomIsLoaded extends true ? {} : import("undici-types").ResponseInit; - interface BunHeadersOverride extends LibOrUndiciHeaders { + interface BunHeadersOverride extends LibOrFallbackHeaders { /** * Convert {@link Headers} to a plain JavaScript object. * @@ -82,19 +93,21 @@ declare module "bun" { getAll(name: "set-cookie" | "Set-Cookie"): string[]; } - interface BunResponseOverride extends LibOrUndiciResponse { + interface BunRequestOverride extends LibOrFallbackRequest { headers: BunHeadersOverride; } - interface BunRequestOverride extends LibOrUndiciRequest { + interface BunResponseOverride extends LibOrFallbackResponse { headers: BunHeadersOverride; } } - interface RequestInit extends Bun.__internal.LibOrUndiciRequestInit {} - interface ResponseInit extends Bun.__internal.LibOrUndiciResponseInit {} + // Required so that you can do `Bun.RequestInit` & `Bun.ResponseInit`... + interface RequestInit extends Bun.__internal.LibOrFallbackRequestInit {} + interface ResponseInit extends Bun.__internal.LibOrFallbackResponseInit {} } +// ...but also exist here, so they get declared globally interface RequestInit extends Bun.RequestInit {} interface ResponseInit extends Bun.ResponseInit {} diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index b37b8c186247d3..d1b9afb6055788 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -7,7 +7,7 @@ const BUN_TYPES_PACKAGE_ROOT = join(BUN_REPO_ROOT, "packages", "bun-types"); const FIXTURE_DIR = fileURLToPath(import.meta.resolve("./fixture")); const TSCONFIG_SOURCE_PATH = join(BUN_REPO_ROOT, "src/cli/init/tsconfig.default.json"); const BUN_TYPES_PACKAGE_JSON_PATH = join(BUN_TYPES_PACKAGE_ROOT, "package.json"); -const BUN_VERSION = (process.env.BUN_VERSION || Bun.version || process.versions.bun).replace(/^.*v/, ""); +const BUN_VERSION = (process.env.BUN_VERSION ?? Bun.version ?? process.versions.bun).replace(/^.*v/, ""); const BUN_TYPES_TARBALL_NAME = `types-bun-${BUN_VERSION}.tgz`; const $ = Shell.cwd(BUN_REPO_ROOT).nothrow(); diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index 673f191ac585da..3f2bf0d563c2a2 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -5,7 +5,7 @@ "name": "fixture", "dependencies": { "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing#f34eacab7b78435ee18f0227974bc0a6756ccb0f", - "@types/bun": "types-bun-1.2.5.tgz", + "@types/bun": "types-bun-1.2.6.tgz", }, "peerDependencies": { "typescript": "^5.8.2", @@ -15,7 +15,7 @@ "packages": { "@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], - "@types/bun": ["@types/bun@types-bun-1.2.5.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing#156f65536ab9431abae2db4f9489e3d85cfb9f41" } }], + "@types/bun": ["@types/bun@types-bun-1.2.6.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing#156f65536ab9431abae2db4f9489e3d85cfb9f41" } }], "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index 23b71c528dd4d7..6270f484373358 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -5,11 +5,11 @@ "typescript": "^5.8.2" }, "scripts": { - "check": "tsc --noEmit" + "check": "tsc --noEmit -p ./tsconfig.json" }, "type": "module", "dependencies": { "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing#f34eacab7b78435ee18f0227974bc0a6756ccb0f", - "@types/bun": "types-bun-1.2.5.tgz" + "@types/bun": "types-bun-1.2.6.tgz" } } From 7a98828227ce5bba0744a58f16d578809d5b9d84 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 14 Mar 2025 23:11:14 +0000 Subject: [PATCH 51/72] deps --- test/integration/bun-types/fixture/bun.lock | 2 -- test/integration/bun-types/fixture/package.json | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index 3f2bf0d563c2a2..4cd1e4b11aba89 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -6,8 +6,6 @@ "dependencies": { "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing#f34eacab7b78435ee18f0227974bc0a6756ccb0f", "@types/bun": "types-bun-1.2.6.tgz", - }, - "peerDependencies": { "typescript": "^5.8.2", }, }, diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index 6270f484373358..056a64cf2d3d7c 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -1,15 +1,13 @@ { "name": "fixture", "module": "index.ts", - "peerDependencies": { - "typescript": "^5.8.2" - }, "scripts": { "check": "tsc --noEmit -p ./tsconfig.json" }, "type": "module", "dependencies": { "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing#f34eacab7b78435ee18f0227974bc0a6756ccb0f", - "@types/bun": "types-bun-1.2.6.tgz" + "@types/bun": "types-bun-1.2.6.tgz", + "typescript": "^5.8.2" } } From a829ae855739eb5a7bb3c2b67d50b14e19a5070c Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 13:17:11 +0000 Subject: [PATCH 52/72] isolate test fixture, remove BunGlobalSymbolRegistry for fetch declarations --- bun.lock | 3 - packages/bun-types/fetch.d.ts | 162 +++++++----------- packages/bun-types/package.json | 3 +- test/integration/bun-types/bun-types.test.ts | 41 +++-- test/integration/bun-types/fixture/bun.lock | 7 +- test/integration/bun-types/fixture/index.ts | 7 +- .../bun-types/fixture/package.json | 1 - tsconfig.json | 38 ++-- 8 files changed, 121 insertions(+), 141 deletions(-) diff --git a/bun.lock b/bun.lock index 98862ac558c74e..2f08f1d900c29c 100644 --- a/bun.lock +++ b/bun.lock @@ -31,7 +31,6 @@ "dependencies": { "@types/node": "*", "@types/ws": "*", - "@typescript/lib-dom": "github:alii/lib-dom-bun-testing#156f65536ab9431abae2db4f9489e3d85cfb9f41", }, "devDependencies": { "@biomejs/biome": "^1.5.3", @@ -185,8 +184,6 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" } }, "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg=="], - "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#156f655", {}, "alii-lib-dom-bun-testing-156f655"], - "@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="], "@vscode/debugadapter": ["@vscode/debugadapter@1.66.0", "", { "dependencies": { "@vscode/debugprotocol": "1.66.0" } }, "sha512-U/m5l6igHtQ8rSMSKW9oWeco9ySPqGYjqW9NECGPGWZ/xnoYicpqUoXhGx3xUNsafrinzWvUWrSUL/Cdgj2V+w=="], diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 5b73174a5d3c3f..b42f4ca1c3a339 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,62 +1,20 @@ -/** - * Bun uses a customised version of `lib.dom.d.ts` that allows us to declare - * certain types from within bun-types instead of the original DOM definitions. - * - * Our `lib.dom.d.ts` declares BunGlobalSymbolRegistry as an empty interface, - * which we can then extend in `bun-types` with our own Bun-specific overrides. - * - * For example, the type `BodyInit` is implemented like this in Bun's lib.dom.d.ts: - * ```ts - * interface BunGlobalSymbolRegistry {}; - * // ... elsewhere ... - * type BodyInit = BunGlobalSymbolRegistry extends {BodyInit: infer T} ? T : never; - * ``` - * - * While this solution works well, the ideal approach would be to define these types - * entirely within bun-types without any declarations in lib.dom.d.ts. This isn't - * done yet as as we need to determine how to make the TypeScript lib-dom - * generator emit types for not-yet-existing definitions. - */ -interface BunGlobalSymbolRegistry { - BodyInit: ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; - HeadersInit: Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; -} - declare module "bun" { - type BodyInit = BunGlobalSymbolRegistry["BodyInit"]; - type HeadersInit = BunGlobalSymbolRegistry["HeadersInit"]; - + type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; + type HeadersInit = Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; + // Required to expose `Bun.RequestInit` & `Bun.ResponseInit` + interface ResponseInit extends Bun.__internal.LibOrFallbackResponseInit {} + interface RequestInit extends Bun.__internal.LibOrFallbackRequestInit {} + namespace __internal { - /** - * @internal - */ type LibOrFallbackHeaders = LibDomIsLoaded extends true ? {} : import("undici-types").Headers; - - /** - * @internal - */ type LibOrFallbackRequest = LibDomIsLoaded extends true ? {} : import("undici-types").Request; - - /** - * @internal - */ type LibOrFallbackResponse = LibDomIsLoaded extends true ? {} : import("undici-types").Response; - - /** - * @internal - */ + type LibOrFallbackResponseInit = LibDomIsLoaded extends true ? {} : import("undici-types").ResponseInit; type LibOrFallbackRequestInit = LibDomIsLoaded extends true ? {} - : Omit & { - body?: BodyInit | null | undefined; - }; - - /** - * @internal - */ - type LibOrFallbackResponseInit = LibDomIsLoaded extends true ? {} : import("undici-types").ResponseInit; + : Omit & { body?: BodyInit | null | undefined }; interface BunHeadersOverride extends LibOrFallbackHeaders { /** @@ -69,10 +27,12 @@ declare module "bun" { * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is. */ toJSON(): Record; + /** * Get the total number of headers */ readonly count: number; + /** * Get all headers matching the name * @@ -101,13 +61,8 @@ declare module "bun" { headers: BunHeadersOverride; } } - - // Required so that you can do `Bun.RequestInit` & `Bun.ResponseInit`... - interface RequestInit extends Bun.__internal.LibOrFallbackRequestInit {} - interface ResponseInit extends Bun.__internal.LibOrFallbackResponseInit {} } -// ...but also exist here, so they get declared globally interface RequestInit extends Bun.RequestInit {} interface ResponseInit extends Bun.ResponseInit {} @@ -121,7 +76,6 @@ declare var Headers: Bun.__internal.UseLibDomIfAvailable< >; interface Request extends Bun.__internal.BunRequestOverride {} - declare var Request: Bun.__internal.UseLibDomIfAvailable< "Request", { @@ -133,57 +87,57 @@ declare var Request: Bun.__internal.UseLibDomIfAvailable< >; interface Response extends Bun.__internal.BunResponseOverride {} +declare var Response: Bun.__internal.UseLibDomIfAvailable< + "Response", + { + new (body?: Bun.BodyInit | null | undefined, init?: ResponseInit | undefined): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, init?: ResponseInit | number): Response; -interface ResponseConstructor { - new (body?: Bun.BodyInit | null | undefined, init?: ResponseInit | undefined): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, options?: ResponseInit | number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - redirect(url: string, status?: number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - redirect(url: string, options?: Bun.ResponseInit): Response; + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + redirect(url: string, status?: number): Response; - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; -} + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + redirect(url: string, init?: ResponseInit): Response; -declare var Response: ResponseConstructor; + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; + } +>; interface BunFetchRequestInitTLS extends Bun.TLSOptions { /** diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index c907625ba0495c..018b4de6b12768 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -17,8 +17,7 @@ "homepage": "https://bun.sh", "dependencies": { "@types/node": "*", - "@types/ws": "*", - "@typescript/lib-dom": "github:alii/lib-dom-bun-testing#156f65536ab9431abae2db4f9489e3d85cfb9f41" + "@types/ws": "*" }, "devDependencies": { "@biomejs/biome": "^1.5.3", diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index d1b9afb6055788..b8b17ea51d0b51 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -1,10 +1,12 @@ import { fileURLToPath, $ as Shell } from "bun"; -import { beforeAll, beforeEach, describe, expect, setDefaultTimeout, test } from "bun:test"; +import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test"; +import { cp, mkdtemp, rm } from "node:fs/promises"; +import { tmpdir } from "node:os"; import { join } from "node:path"; const BUN_REPO_ROOT = fileURLToPath(import.meta.resolve("../../../")); const BUN_TYPES_PACKAGE_ROOT = join(BUN_REPO_ROOT, "packages", "bun-types"); -const FIXTURE_DIR = fileURLToPath(import.meta.resolve("./fixture")); +const FIXTURE_SOURCE_DIR = fileURLToPath(import.meta.resolve("./fixture")); const TSCONFIG_SOURCE_PATH = join(BUN_REPO_ROOT, "src/cli/init/tsconfig.default.json"); const BUN_TYPES_PACKAGE_JSON_PATH = join(BUN_TYPES_PACKAGE_ROOT, "package.json"); const BUN_VERSION = (process.env.BUN_VERSION ?? Bun.version ?? process.versions.bun).replace(/^.*v/, ""); @@ -12,8 +14,18 @@ const BUN_TYPES_TARBALL_NAME = `types-bun-${BUN_VERSION}.tgz`; const $ = Shell.cwd(BUN_REPO_ROOT).nothrow(); -beforeEach(async () => { +let TEMP_DIR: string; +let FIXTURE_DIR: string; + +beforeAll(async () => { + TEMP_DIR = await mkdtemp(join(tmpdir(), "bun-types-test-")); + FIXTURE_DIR = join(TEMP_DIR, "fixture"); + try { + await $`mkdir -p ${FIXTURE_DIR}`; + + await cp(FIXTURE_SOURCE_DIR, FIXTURE_DIR, { recursive: true }); + await $` cd ${BUN_TYPES_PACKAGE_ROOT} bun install @@ -38,7 +50,7 @@ beforeEach(async () => { cd ${FIXTURE_DIR} cp ${TSCONFIG_SOURCE_PATH} tsconfig.json - bun uninstall @types/bun + bun uninstall @types/bun || true bun add @types/bun@${BUN_TYPES_TARBALL_NAME} rm ${BUN_TYPES_TARBALL_NAME} `; @@ -51,23 +63,32 @@ beforeEach(async () => { } }); -beforeAll(() => { - setDefaultTimeout(1000 * 60 * 5); +beforeEach(async () => { + await $` + cd ${FIXTURE_DIR} + cp ${TSCONFIG_SOURCE_PATH} tsconfig.json + `; +}); + +afterAll(async () => { + if (TEMP_DIR) { + await rm(TEMP_DIR, { recursive: true, force: true }); + } }); describe("@types/bun integration test", () => { - test("it typechecks successfully without DOM lib", async () => { + test("checks without lib.dom.d.ts", async () => { const p = await $` cd ${FIXTURE_DIR} - # modify tsconfig.json to remove dom lib - sed -i 's/"lib": \["ESNext", "DOM"\]/"lib": \["ESNext"\]/' tsconfig.json + # remove DOM from tsconfig.json + sed -i '' 's/"lib": \["ESNext", "DOM"\]/"lib": \["ESNext"\]/' tsconfig.json bun run check `; expect(p.exitCode).toBe(0); }); - test("it typechecks successfully with DOM lib", async () => { + test("checks with default settings", async () => { const p = await $` cd ${FIXTURE_DIR} bun run check diff --git a/test/integration/bun-types/fixture/bun.lock b/test/integration/bun-types/fixture/bun.lock index 4cd1e4b11aba89..d5b22f1f209b23 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -4,23 +4,18 @@ "": { "name": "fixture", "dependencies": { - "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing#f34eacab7b78435ee18f0227974bc0a6756ccb0f", "@types/bun": "types-bun-1.2.6.tgz", "typescript": "^5.8.2", }, }, }, "packages": { - "@oven/typescript-bun-lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#f34eaca", {}, "alii-lib-dom-bun-testing-f34eaca"], - - "@types/bun": ["@types/bun@types-bun-1.2.6.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*", "@typescript/lib-dom": "github:alii/lib-dom-bun-testing#156f65536ab9431abae2db4f9489e3d85cfb9f41" } }], + "@types/bun": ["@types/bun@types-bun-1.2.6.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }], "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], "@types/ws": ["@types/ws@8.18.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw=="], - "@typescript/lib-dom": ["@oven/typescript-bun-lib-dom@github:alii/lib-dom-bun-testing#156f655", {}, "alii-lib-dom-bun-testing-156f655"], - "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 5b0bf8b9e23144..382a97f75d9475 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -265,13 +265,18 @@ new File(["code"], "name.ts"); Response.json(""); Response.redirect("bun.sh", 300); Response.error(); +Response.redirect("bun.sh", 302); Response.redirect("bun.sh", { headers: { "x-bun": "is cool", }, }); -Bun.fetch.preconnect; +Bun.inspect.custom; +Bun.inspect; + +fetch.preconnect("bun.sh"); +Bun.fetch.preconnect("bun.sh"); new Uint8Array().toBase64(); diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index 056a64cf2d3d7c..94dc7050d43609 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -6,7 +6,6 @@ }, "type": "module", "dependencies": { - "@oven/typescript-bun-lib-dom": "github:alii/lib-dom-bun-testing#f34eacab7b78435ee18f0227974bc0a6756ccb0f", "@types/bun": "types-bun-1.2.6.tgz", "typescript": "^5.8.2" } diff --git a/tsconfig.json b/tsconfig.json index c3ec51e2a1cb7a..0c416efad6e0d3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,28 @@ { - "files": [], - "include": [], "compilerOptions": { + // Environment setup & latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, "noEmit": true, - "skipLibCheck": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true - }, - "references": [ - // - { "path": "./src" }, - { "path": "./src/bake" }, - { "path": "./src/js" }, - { "path": "./test" }, - { "path": "./packages/bun-types" } - ] + + // Best practices + "strict": true, + "skipLibCheck": false, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } } From 9301f78be73395193b91338f52746ec3ad2ea79f Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 13:28:48 +0000 Subject: [PATCH 53/72] fix testing to check for Response.redirect failure when DOM is loaded --- test/integration/bun-types/bun-types.test.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index b8b17ea51d0b51..7447862cc35918 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -91,9 +91,16 @@ describe("@types/bun integration test", () => { test("checks with default settings", async () => { const p = await $` cd ${FIXTURE_DIR} + # Ensure DOM is in tsconfig.json + sed -i '' 's/"lib": \["ESNext"\]/"lib": \["ESNext", "DOM"\]/' tsconfig.json bun run check `; - expect(p.exitCode).toBe(0); + const expectedOutput = [ + "index.ts(269,29): error TS2345: Argument of type '{ headers: { \"x-bun\": string; }; }' is not assignable to parameter of type 'number'.\n$ tsc --noEmit -p ./tsconfig.json\n", + ].join("\n"); + + expect(p.stdout.toString() + p.stderr.toString()).toEqual(expectedOutput); + expect(p.exitCode).not.toBe(0); }); }); From 85c970c9b7d916c46fe5c46702f18db11eda4fa7 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 13:42:56 +0000 Subject: [PATCH 54/72] use latest ts version --- test/integration/bun-types/fixture/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index 94dc7050d43609..e455fad98c04f5 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -7,6 +7,6 @@ "type": "module", "dependencies": { "@types/bun": "types-bun-1.2.6.tgz", - "typescript": "^5.8.2" + "typescript": "latest" } } From c159b6da300bb9f8b82eee668fdeb5d73ded3118 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 14:01:05 +0000 Subject: [PATCH 55/72] fix test to work cross-platform --- test/integration/bun-types/bun-types.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 7447862cc35918..859f61d720ddbc 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -89,10 +89,11 @@ describe("@types/bun integration test", () => { }); test("checks with default settings", async () => { - const p = await $` + const tsconfig = Bun.file(join(FIXTURE_DIR, "tsconfig.json")); + await tsconfig.write((await tsconfig.text()).replace(/"lib": \["ESNext"\]/, '"lib": ["ESNext", "DOM"]')); + + const p = await $` cd ${FIXTURE_DIR} - # Ensure DOM is in tsconfig.json - sed -i '' 's/"lib": \["ESNext"\]/"lib": \["ESNext", "DOM"\]/' tsconfig.json bun run check `; From 347047bcc28691c2857c5bf41e0e17b4cac42316 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 14:20:27 +0000 Subject: [PATCH 56/72] test cases to check for issue described in #13167 --- test/integration/bun-types/fixture/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 382a97f75d9475..1d6502ab6563dd 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -181,6 +181,9 @@ const r = new Request("", { await fetch(r); await fetch("", { tls: { + key: Bun.file("key.pem"), + cert: Bun.file("cert.pem"), + ca: [Bun.file("ca.pem")], rejectUnauthorized: false, }, }); From db5adf49141b531fa9832d8da4526c406ebdf899 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 14:39:00 +0000 Subject: [PATCH 57/72] higher tolerance for failing test error message --- test/integration/bun-types/bun-types.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 859f61d720ddbc..e5d0c9fd729335 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -98,7 +98,7 @@ describe("@types/bun integration test", () => { `; const expectedOutput = [ - "index.ts(269,29): error TS2345: Argument of type '{ headers: { \"x-bun\": string; }; }' is not assignable to parameter of type 'number'.\n$ tsc --noEmit -p ./tsconfig.json\n", + "error TS2345: Argument of type '{ headers: { \"x-bun\": string; }; }' is not assignable to parameter of type 'number'.\n$ tsc --noEmit -p ./tsconfig.json\n", ].join("\n"); expect(p.stdout.toString() + p.stderr.toString()).toEqual(expectedOutput); From e387f8114e09143eb66bde9dc82bf2d953896631 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 14:44:41 +0000 Subject: [PATCH 58/72] update tsconfigs + test --- bench/express/tsconfig.json | 2 +- bench/postgres/tsconfig.json | 2 +- docs/quickstart.md | 2 +- docs/typescript.md | 2 +- packages/bun-vscode/example/tsconfig.json | 2 +- src/cli/init/tsconfig.default.json | 2 +- test/integration/bun-types/bun-types.test.ts | 10 ++++------ test/integration/bun-types/fixture/.gitignore | 3 --- .../bun-types/fixture/.vscode/settings.json | 3 --- tsconfig.json | 2 +- 10 files changed, 11 insertions(+), 19 deletions(-) delete mode 100644 test/integration/bun-types/fixture/.gitignore delete mode 100644 test/integration/bun-types/fixture/.vscode/settings.json diff --git a/bench/express/tsconfig.json b/bench/express/tsconfig.json index 238655f2ce24cd..0fef23a368018b 100644 --- a/bench/express/tsconfig.json +++ b/bench/express/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/bench/postgres/tsconfig.json b/bench/postgres/tsconfig.json index 238655f2ce24cd..0fef23a368018b 100644 --- a/bench/postgres/tsconfig.json +++ b/bench/postgres/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/docs/quickstart.md b/docs/quickstart.md index e93450f8c83c1b..6e151b3fefd088 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -56,7 +56,7 @@ Then add the following to your `compilerOptions` in `tsconfig.json`: ```json#tsconfig.json { "compilerOptions": { - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/docs/typescript.md b/docs/typescript.md index 210f1bb19e076c..600b145ffa3982 100644 --- a/docs/typescript.md +++ b/docs/typescript.md @@ -18,7 +18,7 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh { "compilerOptions": { // Enable latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/packages/bun-vscode/example/tsconfig.json b/packages/bun-vscode/example/tsconfig.json index fd276eb0ffe3c5..7eff589c7420ff 100644 --- a/packages/bun-vscode/example/tsconfig.json +++ b/packages/bun-vscode/example/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "module": "esnext", "target": "esnext", "moduleResolution": "bundler", diff --git a/src/cli/init/tsconfig.default.json b/src/cli/init/tsconfig.default.json index 0c416efad6e0d3..a13c2d36626846 100644 --- a/src/cli/init/tsconfig.default.json +++ b/src/cli/init/tsconfig.default.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Environment setup & latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index e5d0c9fd729335..79a07ff05a8f82 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -80,15 +80,13 @@ describe("@types/bun integration test", () => { test("checks without lib.dom.d.ts", async () => { const p = await $` cd ${FIXTURE_DIR} - # remove DOM from tsconfig.json - sed -i '' 's/"lib": \["ESNext", "DOM"\]/"lib": \["ESNext"\]/' tsconfig.json bun run check `; expect(p.exitCode).toBe(0); }); - test("checks with default settings", async () => { + test("checks with lib.dom.d.ts", async () => { const tsconfig = Bun.file(join(FIXTURE_DIR, "tsconfig.json")); await tsconfig.write((await tsconfig.text()).replace(/"lib": \["ESNext"\]/, '"lib": ["ESNext", "DOM"]')); @@ -98,10 +96,10 @@ describe("@types/bun integration test", () => { `; const expectedOutput = [ - "error TS2345: Argument of type '{ headers: { \"x-bun\": string; }; }' is not assignable to parameter of type 'number'.\n$ tsc --noEmit -p ./tsconfig.json\n", + "error TS2345: Argument of type '{ headers: { \"x-bun\": string; }; }' is not assignable to parameter of type 'number'.", ].join("\n"); - expect(p.stdout.toString() + p.stderr.toString()).toEqual(expectedOutput); - expect(p.exitCode).not.toBe(0); + expect(p.stdout.toString() + p.stderr.toString()).toContain(expectedOutput); + expect(p.exitCode).toBe(2); }); }); diff --git a/test/integration/bun-types/fixture/.gitignore b/test/integration/bun-types/fixture/.gitignore deleted file mode 100644 index c183f93ee33b1f..00000000000000 --- a/test/integration/bun-types/fixture/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules -# generated by test -tsconfig.json diff --git a/test/integration/bun-types/fixture/.vscode/settings.json b/test/integration/bun-types/fixture/.vscode/settings.json deleted file mode 100644 index 25fa6215fdd332..00000000000000 --- a/test/integration/bun-types/fixture/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "typescript.tsdk": "node_modules/typescript/lib" -} diff --git a/tsconfig.json b/tsconfig.json index 0c416efad6e0d3..a13c2d36626846 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Environment setup & latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", From e736c36a50371c710a5793e1252ad2c205a4217f Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 15:11:28 +0000 Subject: [PATCH 59/72] support URL.parse, Error.isError, add some more test cases --- packages/bun-types/globals.d.ts | 11 +++++++++++ test/integration/bun-types/bun-types.test.ts | 5 +++-- test/integration/bun-types/fixture/index.ts | 17 +++++++++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index c1938c233f472c..374442da3e5ac4 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1325,6 +1325,13 @@ declare var URL: Bun.__internal.UseLibDomIfAvailable< * @param url - The URL to revoke. */ revokeObjectURL(url: string): void; + /** + * Parse a URL. + * + * @param url - The URL to parse. + * @param base - The base URL to use. + */ + parse(url: string, base?: string): URL | null; } >; @@ -1448,3 +1455,7 @@ declare var MessagePort: Bun.__internal.UseLibDomIfAvailable< new (): MessagePort; } >; + +interface ErrorConstructor { + isError(value: unknown): value is Error; +} diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 79a07ff05a8f82..011bc9258571a8 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -1,6 +1,6 @@ import { fileURLToPath, $ as Shell } from "bun"; import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test"; -import { cp, mkdtemp, rm } from "node:fs/promises"; +import { cp, mkdtemp } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -72,7 +72,8 @@ beforeEach(async () => { afterAll(async () => { if (TEMP_DIR) { - await rm(TEMP_DIR, { recursive: true, force: true }); + console.log("TEMP_DIR", TEMP_DIR); + // await rm(TEMP_DIR, { recursive: true, force: true }); } }); diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 1d6502ab6563dd..8de1849f30f518 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -243,15 +243,20 @@ Bun.serve({ port: 3000, fetch: () => new Response("ok"), - key: Bun.file(""), - cert: Bun.file(""), + // don't do this, use the `tls: {}` options instead + key: Bun.file(""), // dont do it! + cert: Bun.file(""), // dont do it! tls: { - key: Bun.file(""), - cert: Bun.file(""), + key: Bun.file(""), // do this! + cert: Bun.file(""), // do this! }, }); +import type { BinaryLike } from "node:crypto"; +declare function asIs(value: BinaryLike): BinaryLike; +asIs(Buffer.from("Hey", "utf-8")); + new URL("", ""); const myUrl: URL = new URL(""); URL.canParse; @@ -265,6 +270,10 @@ new MessagePort(); new File(["code"], "name.ts"); +URL.parse("bun.sh"); +URL.parse("bun.sh", "bun.sh"); +Error.isError(new Error()); + Response.json(""); Response.redirect("bun.sh", 300); Response.error(); From e9f1a93aac1635b59551bb19a337e1ef77fb21b7 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 15:11:40 +0000 Subject: [PATCH 60/72] do the cleanup --- test/integration/bun-types/bun-types.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 011bc9258571a8..79a07ff05a8f82 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -1,6 +1,6 @@ import { fileURLToPath, $ as Shell } from "bun"; import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test"; -import { cp, mkdtemp } from "node:fs/promises"; +import { cp, mkdtemp, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -72,8 +72,7 @@ beforeEach(async () => { afterAll(async () => { if (TEMP_DIR) { - console.log("TEMP_DIR", TEMP_DIR); - // await rm(TEMP_DIR, { recursive: true, force: true }); + await rm(TEMP_DIR, { recursive: true, force: true }); } }); From d57f61c1f89dbe35b93d2dc13f794325568a37b0 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 15:59:03 +0000 Subject: [PATCH 61/72] types: more test cases --- packages/bun-types/fetch.d.ts | 16 +++++----- test/integration/bun-types/fixture/index.ts | 33 ++++++++++++++++++++- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index b42f4ca1c3a339..57794904274f9b 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,11 +1,6 @@ declare module "bun" { + type HeadersInit = string[][] | Record> | Headers; type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams; - type HeadersInit = Headers | Record | Array<[string, string]> | IterableIterator<[string, string]>; - type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"; - - // Required to expose `Bun.RequestInit` & `Bun.ResponseInit` - interface ResponseInit extends Bun.__internal.LibOrFallbackResponseInit {} - interface RequestInit extends Bun.__internal.LibOrFallbackRequestInit {} namespace __internal { type LibOrFallbackHeaders = LibDomIsLoaded extends true ? {} : import("undici-types").Headers; @@ -14,7 +9,10 @@ declare module "bun" { type LibOrFallbackResponseInit = LibDomIsLoaded extends true ? {} : import("undici-types").ResponseInit; type LibOrFallbackRequestInit = LibDomIsLoaded extends true ? {} - : Omit & { body?: BodyInit | null | undefined }; + : Omit & { + body?: Bun.BodyInit | null | undefined; + headers?: Bun.HeadersInit; + }; interface BunHeadersOverride extends LibOrFallbackHeaders { /** @@ -63,8 +61,8 @@ declare module "bun" { } } -interface RequestInit extends Bun.RequestInit {} -interface ResponseInit extends Bun.ResponseInit {} +interface RequestInit extends Bun.__internal.LibOrFallbackRequestInit {} +interface ResponseInit extends Bun.__internal.LibOrFallbackResponseInit {} interface Headers extends Bun.__internal.BunHeadersOverride {} declare var Headers: Bun.__internal.UseLibDomIfAvailable< diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 8de1849f30f518..e0766ba03c3a25 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -299,7 +299,38 @@ Bun.fetch("", { }, }); -const myRequest: Request = new Request(""); +const myHeaders: Headers = new Headers(); +myHeaders.append("x-bun", "is cool"); +myHeaders.get("x-bun"); +myHeaders.has("x-bun"); +myHeaders.set("x-bun", "is cool"); +myHeaders.delete("x-bun"); +myHeaders.getSetCookie(); +myHeaders.toJSON(); +myHeaders.count; +myHeaders.getAll("set-cookie"); +myHeaders.getAll("Set-Cookie"); + +// @ts-expect-error +myHeaders.getAll("Should fail"); + +const myRequest: Request = new Request("", { + headers: new Headers(myHeaders), + body: "", + method: "GET", + redirect: "follow", + credentials: "include", + mode: "cors", + referrer: "about:client", + referrerPolicy: "no-referrer", + window: null, +}); + +const myResponse: Response = new Response("", { + headers: new Headers([]), + status: 200, + statusText: "OK", +}); const myRequestInit: RequestInit = { body: "", From 3aa3ea644e04afe93da6606bf34c044c9e9ad90b Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 16:36:51 +0000 Subject: [PATCH 62/72] docs supported tsconfig --- packages/bun-types/index.d.ts | 3 +++ packages/bun-types/tsconfig.docs.json | 12 ++++++++++++ packages/bun-types/tsconfig.json | 20 ++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 packages/bun-types/tsconfig.docs.json diff --git a/packages/bun-types/index.d.ts b/packages/bun-types/index.d.ts index 0060cdd11a22b9..012e5e3f871a4f 100644 --- a/packages/bun-types/index.d.ts +++ b/packages/bun-types/index.d.ts @@ -24,4 +24,7 @@ // @ts-ignore Must disable this so it doesn't conflict with the DOM onmessage type, but still // allows us to declare our own globals that Node's types can "see" and not conflict with +/** + * @private + */ declare var onmessage: never; diff --git a/packages/bun-types/tsconfig.docs.json b/packages/bun-types/tsconfig.docs.json new file mode 100644 index 00000000000000..609904458a3179 --- /dev/null +++ b/packages/bun-types/tsconfig.docs.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "skipLibCheck": true, + "declaration": true, + "emitDeclarationOnly": true, + "noEmit": false, + "declarationDir": "out" + }, + "include": ["./*.d.ts"], + "exclude": ["dist", "node_modules"] +} diff --git a/packages/bun-types/tsconfig.json b/packages/bun-types/tsconfig.json index 0c33ffe9c4245d..e5006c96e06b2b 100644 --- a/packages/bun-types/tsconfig.json +++ b/packages/bun-types/tsconfig.json @@ -1,12 +1,12 @@ { - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "skipLibCheck": true, - "declaration": true, - "emitDeclarationOnly": true, - "noEmit": false, - "declarationDir": "out" - }, - "include": ["**/*.ts"], - "exclude": ["dist", "node_modules"] + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "skipLibCheck": true, + "declaration": true, + "emitDeclarationOnly": true, + "noEmit": false, + "declarationDir": "out" + }, + "include": ["**/*.ts"], + "exclude": ["dist", "node_modules"] } From 5db7eb6b38cc7b1a9e68d994be7d246b4620530b Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 16:49:26 +0000 Subject: [PATCH 63/72] remove talk of bundle.ts (doesnt exist) --- packages/bun-types/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/bun-types/README.md b/packages/bun-types/README.md index c51b1b22faabf2..45c74a24d1efa2 100644 --- a/packages/bun-types/README.md +++ b/packages/bun-types/README.md @@ -20,7 +20,7 @@ That's it! VS Code and TypeScript automatically load `@types/*` packages into yo # Contributing -The `@types/bun` package is a shim that loads `bun-types`. The `bun-types` package lives in the Bun repo under `packages/bun-types`. It is generated via [./scripts/bundle.ts](./scripts/bundle.ts). +The `@types/bun` package is a shim that loads `bun-types`. The `bun-types` package lives in the Bun repo under `packages/bun-types`. To add a new file, add it under `packages/bun-types`. Then add a [triple-slash directive](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html) pointing to it inside [./index.d.ts](./index.d.ts). @@ -28,8 +28,6 @@ To add a new file, add it under `packages/bun-types`. Then add a [triple-slash d + /// ``` -[`./bundle.ts`](./bundle.ts) merges the types in this folder into a single file. To run it: - ```bash bun build ``` From b64cd17cfcbdac560e7876c48239402a51f006b8 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 18:00:26 +0000 Subject: [PATCH 64/72] add jsdocs --- packages/bun-types/bun.d.ts | 46 +++++++++++++++++++++++++++++------ packages/bun-types/fetch.d.ts | 3 +++ packages/bun-types/test.d.ts | 1 - 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 835ee280a13056..7fee02fd448d5f 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -3330,7 +3330,7 @@ declare module "bun" { * * @param ws The websocket that was closed * @param code The close code - * @param message The close message + * @param reason The close reason */ close?(ws: ServerWebSocket, code: number, reason: string): void | Promise; @@ -3731,6 +3731,9 @@ declare module "bun" { syscall?: string; } + /** + * Options for TLS connections + */ interface TLSOptions { /** * Passphrase for the TLS key @@ -4198,6 +4201,9 @@ declare module "bun" { readonly id: string; } + /** + * The type of options that can be passed to {@link serve} + */ type Serve = | ServeOptions | TLSServeOptions @@ -4208,6 +4214,9 @@ declare module "bun" { | UnixWebSocketServeOptions | UnixTLSWebSocketServeOptions; + /** + * The type of options that can be passed to {@link serve}, with support for `routes` and a safer requirement for `fetch` + */ type ServeFunctionOptions }> = | (DistributedOmit, WebSocketServeOptions>, "fetch"> & { routes: R; @@ -4240,7 +4249,6 @@ declare module "bun" { * parameters and method-specific handling. * * @param options - Server configuration options - * @param options.routes - Route definitions mapping paths to handlers * * @example Basic Usage * ```ts @@ -4456,7 +4464,6 @@ declare module "bun" { * * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} */ - function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; /** @@ -4473,7 +4480,6 @@ declare module "bun" { * * @param fileDescriptor The file descriptor of the file */ - function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; /** @@ -4483,10 +4489,25 @@ declare module "bun" { */ function allocUnsafe(size: number): Uint8Array; + /** + * Options for `Bun.inspect` + */ interface BunInspectOptions { + /** + * Whether to colorize the output + */ colors?: boolean; + /** + * The depth of the inspection + */ depth?: number; + /** + * Whether to sort the properties of the object + */ sorted?: boolean; + /** + * Whether to compact the output + */ compact?: boolean; } @@ -4495,7 +4516,8 @@ declare module "bun" { * * Supports JSX * - * @param args + * @param arg The value to inspect + * @param options Options for the inspection */ function inspect(arg: any, options?: BunInspectOptions): string; namespace inspect { @@ -4930,14 +4952,25 @@ declare module "bun" { */ digest(encoding: DigestEncoding): string; + /** + * Finalize the hash and return a `Buffer` + */ + digest(): Buffer; + /** * Finalize the hash * * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time */ - digest(): Buffer; digest(hashInto: NodeJS.TypedArray): NodeJS.TypedArray; + /** + * Run the hash over the given data + * + * @param input `string`, `Uint8Array`, or `ArrayBuffer` to hash. `Uint8Array` or `ArrayBuffer` is faster. + */ + static hash(algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer): Buffer; + /** * Run the hash over the given data * @@ -4945,7 +4978,6 @@ declare module "bun" { * * @param hashInto `TypedArray` to write the hash into. Faster than creating a new one each time */ - static hash(algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer): Buffer; static hash( algorithm: SupportedCryptoAlgorithms, input: Bun.BlobOrStringOrBuffer, diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 57794904274f9b..304b4ee977b97b 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -137,6 +137,9 @@ declare var Response: Bun.__internal.UseLibDomIfAvailable< } >; +/** + * Extends Bun.TLSOptions with extra properties that are only supported in `fetch(url, {tls: ...})` + */ interface BunFetchRequestInitTLS extends Bun.TLSOptions { /** * Custom function to check the server identity diff --git a/packages/bun-types/test.d.ts b/packages/bun-types/test.d.ts index 8448317743fc6e..a3c013f000e7b3 100644 --- a/packages/bun-types/test.d.ts +++ b/packages/bun-types/test.d.ts @@ -420,7 +420,6 @@ declare module "bun:test" { * * @param label the label for the test * @param fn the test function - * @param options the test timeout or options */ failing(label: string, fn?: (() => void | Promise) | ((done: (err?: unknown) => void) => void)): void; /** From bdaf9d1a8813ce1d7b90ddd760c6801e8916f2b3 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 18:17:51 +0000 Subject: [PATCH 65/72] Support more documentation --- packages/bun-types/bun.d.ts | 81 ++++++++++++++++++++---------------- packages/bun-types/test.d.ts | 4 -- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 7fee02fd448d5f..6233feb8c3005f 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -45,6 +45,9 @@ declare module "bun" { type EventListenerOrEventListenerObject = EventListener | EventListenerObject; type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob; + /** + * @private + */ namespace __internal { type LibDomIsLoaded = typeof globalThis extends { onabort: any } ? true : false; @@ -4592,6 +4595,11 @@ declare module "bun" { | number | { toString(): string }; + /** + * Converts formats of colors + * @param input A value that could possibly be a color + * @param outputFormat An optional output format + */ function color( input: ColorInput, outputFormat?: /** @@ -4645,53 +4653,52 @@ declare module "bun" { | "rgba", ): string | null; - function color( - input: ColorInput, - /** - * An array of numbers representing the RGB color - * @example [100, 200, 200] - */ - outputFormat: "[rgb]", - ): [number, number, number] | null; - function color( - input: ColorInput, - /** - * An array of numbers representing the RGBA color - * @example [100, 200, 200, 255] - */ - outputFormat: "[rgba]", - ): [number, number, number, number] | null; - function color( - input: ColorInput, - /** - * An object representing the RGB color - * @example { r: 100, g: 200, b: 200 } - */ - outputFormat: "{rgb}", - ): { r: number; g: number; b: number } | null; - function color( - input: ColorInput, - /** - * An object representing the RGBA color - * @example { r: 100, g: 200, b: 200, a: 0.5 } - */ - outputFormat: "{rgba}", - ): { r: number; g: number; b: number; a: number } | null; + /** + * Convert any color input to rgb + * @param input Any color input + * @param outputFormat Specify `[rgb]` to output as an array with `r`, `g`, and `b` properties + */ + function color(input: ColorInput, outputFormat: "[rgb]"): [number, number, number] | null; + /** + * Convert any color input to rgba + * @param input Any color input + * @param outputFormat Specify `[rgba]` to output as an array with `r`, `g`, `b`, and `a` properties + */ + function color(input: ColorInput, outputFormat: "[rgba]"): [number, number, number, number] | null; + /** + * Convert any color input to a number + * @param input Any color input + * @param outputFormat Specify `{rgb}` to output as an object with `r`, `g`, and `b` properties + */ + function color(input: ColorInput, outputFormat: "{rgb}"): { r: number; g: number; b: number } | null; + /** + * Convert any color input to rgba + * @param input Any color input + * @param outputFormat Specify {rgba} to output as an object with `r`, `g`, `b`, and `a` properties + */ + function color(input: ColorInput, outputFormat: "{rgba}"): { r: number; g: number; b: number; a: number } | null; + /** + * Convert any color input to a number + * @param input Any color input + * @param outputFormat Specify `number` to output as a number + */ function color(input: ColorInput, outputFormat: "number"): number | null; - interface Semver { + /** + * Bun.semver provides a fast way to parse and compare version numbers. + */ + var semver: { /** * Test if the version satisfies the range. Stringifies both arguments. Returns `true` or `false`. */ - satisfies(version: StringLike, range: StringLike): boolean; + satisfies: (version: StringLike, range: StringLike) => boolean; /** * Returns 0 if the versions are equal, 1 if `v1` is greater, or -1 if `v2` is greater. * Throws an error if either version is invalid. */ - order(this: void, v1: StringLike, v2: StringLike): -1 | 0 | 1; - } - var semver: Semver; + order: (v1: StringLike, v2: StringLike) => -1 | 0 | 1; + }; interface Unsafe { /** diff --git a/packages/bun-types/test.d.ts b/packages/bun-types/test.d.ts index a3c013f000e7b3..e908c6318d0ee7 100644 --- a/packages/bun-types/test.d.ts +++ b/packages/bun-types/test.d.ts @@ -1777,10 +1777,6 @@ declare module "bun:test" { type MatcherContext = MatcherUtils & MatcherState; } -declare module "test" { - export type * from "bun:test"; -} - declare namespace JestMock { /** * Copyright (c) Meta Platforms, Inc. and affiliates. From 1b240be880358c410beaab88b6e2a5572048d798 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 19:04:18 +0000 Subject: [PATCH 66/72] remove tsconfig --- packages/bun-types/tsconfig.docs.json | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 packages/bun-types/tsconfig.docs.json diff --git a/packages/bun-types/tsconfig.docs.json b/packages/bun-types/tsconfig.docs.json deleted file mode 100644 index 609904458a3179..00000000000000 --- a/packages/bun-types/tsconfig.docs.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "skipLibCheck": true, - "declaration": true, - "emitDeclarationOnly": true, - "noEmit": false, - "declarationDir": "out" - }, - "include": ["./*.d.ts"], - "exclude": ["dist", "node_modules"] -} From 8b070ca759dda36a39285e4f6e64f4bd7dff55fe Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 19:13:39 +0000 Subject: [PATCH 67/72] Blob#text --- packages/bun-types/globals.d.ts | 10 ++++++++++ test/integration/bun-types/fixture/index.ts | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 374442da3e5ac4..340e56bf33701a 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1236,6 +1236,7 @@ interface Blob { */ // eslint-disable-next-line @definitelytyped/no-unnecessary-generics json(): Promise; + /** * Read the data from the blob as a {@link FormData} object. * @@ -1249,6 +1250,15 @@ interface Blob { * closely to the `BodyMixin` API. */ formData(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as a string + */ + text(): Promise; + + /** + * Returns a promise that resolves to the contents of the blob as an ArrayBuffer + */ arrayBuffer(): Promise; /** * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index e0766ba03c3a25..bfede972c3ebe0 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -266,6 +266,12 @@ URL.revokeObjectURL; declare const myBodyInit: Bun.BodyInit; declare const myHeadersInit: Bun.HeadersInit; +new Blob().text(); +new Blob().json(); +new Blob().arrayBuffer(); +new Blob().bytes(); +new Blob().formData(); + new MessagePort(); new File(["code"], "name.ts"); From b3fd8c7a0d8b921baebe63a408a77425639821e8 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 22:29:10 +0000 Subject: [PATCH 68/72] fix HMREventNames --- packages/bun-types/devserver.d.ts | 16 ++++++++-------- packages/bun-types/package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/bun-types/devserver.d.ts b/packages/bun-types/devserver.d.ts index 76e4e4eeae2f8a..24879853f2e7d6 100644 --- a/packages/bun-types/devserver.d.ts +++ b/packages/bun-types/devserver.d.ts @@ -1,13 +1,13 @@ declare module "bun" { type HMREventNames = - | "bun:beforeUpdate" - | "bun:afterUpdate" - | "bun:beforeFullReload" - | "bun:beforePrune" - | "bun:invalidate" - | "bun:error" - | "bun:ws:disconnect" - | "bun:ws:connect"; + | "beforeUpdate" + | "afterUpdate" + | "beforeFullReload" + | "beforePrune" + | "invalidate" + | "error" + | "ws:disconnect" + | "ws:connect"; /** * The event names for the dev server diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index 018b4de6b12768..32c4e9b58060ed 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -37,4 +37,4 @@ "bun.js", "types" ] -} +} \ No newline at end of file From eae873681856bca8352796876a90618bf92c3d8a Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 23:05:52 +0000 Subject: [PATCH 69/72] Others --- test/integration/bun-types/fixture/index.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index bfede972c3ebe0..0ff288d4565bd7 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -266,11 +266,17 @@ URL.revokeObjectURL; declare const myBodyInit: Bun.BodyInit; declare const myHeadersInit: Bun.HeadersInit; -new Blob().text(); -new Blob().json(); -new Blob().arrayBuffer(); -new Blob().bytes(); -new Blob().formData(); +await new Blob().text(); +await new Blob().json(); +await new Blob().arrayBuffer(); +await new Blob().bytes(); +await new Blob().formData(); + +await Bun.file("test").text(); +await Bun.file("test").json(); +await Bun.file("test").arrayBuffer(); +await Bun.file("test").bytes(); +await Bun.file("test").formData(); new MessagePort(); From adb9e05d81357634f7a665f87027fd6e00f7222b Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 23:27:58 +0000 Subject: [PATCH 70/72] test direct readablestream --- packages/bun-types/index.d.ts | 3 -- test/integration/bun-types/bun-types.test.ts | 8 ++++-- test/integration/bun-types/fixture/index.ts | 6 ++++ .../bun-types/fixture/tsconfig.json | 28 +++++++++++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 test/integration/bun-types/fixture/tsconfig.json diff --git a/packages/bun-types/index.d.ts b/packages/bun-types/index.d.ts index 012e5e3f871a4f..0060cdd11a22b9 100644 --- a/packages/bun-types/index.d.ts +++ b/packages/bun-types/index.d.ts @@ -24,7 +24,4 @@ // @ts-ignore Must disable this so it doesn't conflict with the DOM onmessage type, but still // allows us to declare our own globals that Node's types can "see" and not conflict with -/** - * @private - */ declare var onmessage: never; diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 79a07ff05a8f82..850707df6b87ba 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -97,9 +97,13 @@ describe("@types/bun integration test", () => { const expectedOutput = [ "error TS2345: Argument of type '{ headers: { \"x-bun\": string; }; }' is not assignable to parameter of type 'number'.", - ].join("\n"); + "error TS2339: Property 'write' does not exist on type 'ReadableByteStreamController'.", + ]; + + for (const expected of expectedOutput) { + expect(p.stdout.toString() + p.stderr.toString()).toContain(expected); + } - expect(p.stdout.toString() + p.stderr.toString()).toContain(expectedOutput); expect(p.exitCode).toBe(2); }); }); diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 0ff288d4565bd7..48b93e9babf8a1 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -227,6 +227,12 @@ req1.headers; req1.headers.toJSON(); new ReadableStream({}); +new ReadableStream({ + type: "direct", + async pull(controller) { + controller.write(new TextEncoder().encode("Hello, world!")); + }, +}); const body = await fetch(req1); diff --git a/test/integration/bun-types/fixture/tsconfig.json b/test/integration/bun-types/fixture/tsconfig.json new file mode 100644 index 00000000000000..a13c2d36626846 --- /dev/null +++ b/test/integration/bun-types/fixture/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + // Environment setup & latest features + "lib": ["ESNext"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": false, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} From 11d4a885ed887a6a5e7afbcfc1808ea11fdf9533 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Mon, 17 Mar 2025 23:57:32 +0000 Subject: [PATCH 71/72] move fetch declarations to globals.d.ts for doc gen purposes --- packages/bun-types/fetch.d.ts | 164 ------------------------------- packages/bun-types/globals.d.ts | 166 ++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 164 deletions(-) diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 304b4ee977b97b..e2f5fce86db11f 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -60,167 +60,3 @@ declare module "bun" { } } } - -interface RequestInit extends Bun.__internal.LibOrFallbackRequestInit {} -interface ResponseInit extends Bun.__internal.LibOrFallbackResponseInit {} - -interface Headers extends Bun.__internal.BunHeadersOverride {} -declare var Headers: Bun.__internal.UseLibDomIfAvailable< - "Headers", - { - prototype: Headers; - new (init?: Bun.HeadersInit): Headers; - } ->; - -interface Request extends Bun.__internal.BunRequestOverride {} -declare var Request: Bun.__internal.UseLibDomIfAvailable< - "Request", - { - prototype: Request; - new (requestInfo: string, init?: RequestInit): Request; - new (requestInfo: RequestInit & { url: string }): Request; - new (requestInfo: Request, init?: RequestInit): Request; - } ->; - -interface Response extends Bun.__internal.BunResponseOverride {} -declare var Response: Bun.__internal.UseLibDomIfAvailable< - "Response", - { - new (body?: Bun.BodyInit | null | undefined, init?: ResponseInit | undefined): Response; - /** - * Create a new {@link Response} with a JSON body - * - * @param body - The body of the response - * @param options - options to pass to the response - * - * @example - * - * ```ts - * const response = Response.json({hi: "there"}); - * console.assert( - * await response.text(), - * `{"hi":"there"}` - * ); - * ``` - * ------- - * - * This is syntactic sugar for: - * ```js - * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) - * ``` - * @link https://github.com/whatwg/fetch/issues/1389 - */ - json(body?: any, init?: ResponseInit | number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param status - the HTTP status code to use for the redirect - */ - redirect(url: string, status?: number): Response; - - /** - * Create a new {@link Response} that redirects to url - * - * @param url - the URL to redirect to - * @param options - options to pass to the response - */ - redirect(url: string, init?: ResponseInit): Response; - - /** - * Create a new {@link Response} that has a network error - */ - error(): Response; - } ->; - -/** - * Extends Bun.TLSOptions with extra properties that are only supported in `fetch(url, {tls: ...})` - */ -interface BunFetchRequestInitTLS extends Bun.TLSOptions { - /** - * Custom function to check the server identity - * @param hostname - The hostname of the server - * @param cert - The certificate of the server - * @returns An error if the server is unauthorized, otherwise undefined - */ - checkServerIdentity?: NonNullable; -} - -/** - * BunFetchRequestInit represents additional options that Bun supports in `fetch()` only. - * - * Bun extends the `fetch` API with some additional options, except - * this interface is not quite a `RequestInit`, because they won't work - * if passed to `new Request()`. This is why it's a separate type. - */ -interface BunFetchRequestInit extends RequestInit { - /** - * Override the default TLS options - */ - tls?: BunFetchRequestInitTLS; - - /** - * Log the raw HTTP request & response to stdout. This API may be - * removed in a future version of Bun without notice. - * This is a custom property that is not part of the Fetch API specification. - * It exists mostly as a debugging tool - */ - verbose?: boolean; - - /** - * Override http_proxy or HTTPS_PROXY - * This is a custom property that is not part of the Fetch API specification. - */ - proxy?: string; - - /** - * Override the default S3 options - */ - s3?: Bun.S3Options; -} - -/** - * Send a HTTP(s) request - * - * @param request Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(request: Request, init?: BunFetchRequestInit): Promise; - -/** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; - -/** - * Send a HTTP(s) request - * - * @param input URL string or Request object - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - */ -declare function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; - -declare namespace fetch { - export function preconnect( - url: string | URL, - options?: { - dns?: boolean; - tcp?: boolean; - http?: boolean; - https?: boolean; - }, - ): void; -} diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 340e56bf33701a..9bcb671e68160c 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1469,3 +1469,169 @@ declare var MessagePort: Bun.__internal.UseLibDomIfAvailable< interface ErrorConstructor { isError(value: unknown): value is Error; } + +//#region Fetch +interface RequestInit extends Bun.__internal.LibOrFallbackRequestInit {} +interface ResponseInit extends Bun.__internal.LibOrFallbackResponseInit {} + +interface Headers extends Bun.__internal.BunHeadersOverride {} +declare var Headers: Bun.__internal.UseLibDomIfAvailable< + "Headers", + { + prototype: Headers; + new (init?: Bun.HeadersInit): Headers; + } +>; + +interface Request extends Bun.__internal.BunRequestOverride {} +declare var Request: Bun.__internal.UseLibDomIfAvailable< + "Request", + { + prototype: Request; + new (requestInfo: string, init?: RequestInit): Request; + new (requestInfo: RequestInit & { url: string }): Request; + new (requestInfo: Request, init?: RequestInit): Request; + } +>; + +interface Response extends Bun.__internal.BunResponseOverride {} +declare var Response: Bun.__internal.UseLibDomIfAvailable< + "Response", + { + new (body?: Bun.BodyInit | null | undefined, init?: ResponseInit | undefined): Response; + /** + * Create a new {@link Response} with a JSON body + * + * @param body - The body of the response + * @param options - options to pass to the response + * + * @example + * + * ```ts + * const response = Response.json({hi: "there"}); + * console.assert( + * await response.text(), + * `{"hi":"there"}` + * ); + * ``` + * ------- + * + * This is syntactic sugar for: + * ```js + * new Response(JSON.stringify(body), {headers: { "Content-Type": "application/json" }}) + * ``` + * @link https://github.com/whatwg/fetch/issues/1389 + */ + json(body?: any, init?: ResponseInit | number): Response; + + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param status - the HTTP status code to use for the redirect + */ + redirect(url: string, status?: number): Response; + + /** + * Create a new {@link Response} that redirects to url + * + * @param url - the URL to redirect to + * @param options - options to pass to the response + */ + redirect(url: string, init?: ResponseInit): Response; + + /** + * Create a new {@link Response} that has a network error + */ + error(): Response; + } +>; + +/** + * Extends Bun.TLSOptions with extra properties that are only supported in `fetch(url, {tls: ...})` + */ +interface BunFetchRequestInitTLS extends Bun.TLSOptions { + /** + * Custom function to check the server identity + * @param hostname - The hostname of the server + * @param cert - The certificate of the server + * @returns An error if the server is unauthorized, otherwise undefined + */ + checkServerIdentity?: NonNullable; +} + +/** + * BunFetchRequestInit represents additional options that Bun supports in `fetch()` only. + * + * Bun extends the `fetch` API with some additional options, except + * this interface is not quite a `RequestInit`, because they won't work + * if passed to `new Request()`. This is why it's a separate type. + */ +interface BunFetchRequestInit extends RequestInit { + /** + * Override the default TLS options + */ + tls?: BunFetchRequestInitTLS; + + /** + * Log the raw HTTP request & response to stdout. This API may be + * removed in a future version of Bun without notice. + * This is a custom property that is not part of the Fetch API specification. + * It exists mostly as a debugging tool + */ + verbose?: boolean; + + /** + * Override http_proxy or HTTPS_PROXY + * This is a custom property that is not part of the Fetch API specification. + */ + proxy?: string; + + /** + * Override the default S3 options + */ + s3?: Bun.S3Options; +} + +/** + * Send a HTTP(s) request + * + * @param request Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(request: Request, init?: BunFetchRequestInit): Promise; + +/** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise; + +/** + * Send a HTTP(s) request + * + * @param input URL string or Request object + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + */ +declare function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; + +declare namespace fetch { + export function preconnect( + url: string | URL, + options?: { + dns?: boolean; + tcp?: boolean; + http?: boolean; + https?: boolean; + }, + ): void; +} +//#endregion From 5b36ee6f50fdcc806bb2ba3d161de99f34a6f82a Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 18 Mar 2025 00:02:09 +0000 Subject: [PATCH 72/72] jsdoc for fetch() --- packages/bun-types/globals.d.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 9bcb671e68160c..dee5739cf583b8 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1623,13 +1623,30 @@ declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): */ declare function fetch(input: string | URL | Request, init?: BunFetchRequestInit): Promise; +/** + * Bun's extensions of the `fetch` API + * + * @see {@link fetch} The `fetch` function itself + */ declare namespace fetch { + /** + * Preconnect to a URL. This can be used to improve performance by pre-resolving the DNS and establishing a TCP connection before the request is made. + * + * This is a custom property that is not part of the Fetch API specification. + * + * @param url - The URL to preconnect to + * @param options - Options for the preconnect + */ export function preconnect( url: string | URL, options?: { + /** Preconnect to the DNS of the URL */ dns?: boolean; + /** Preconnect to the TCP connection of the URL */ tcp?: boolean; + /** Preconnect to the HTTP connection of the URL */ http?: boolean; + /** Preconnect to the HTTPS connection of the URL */ https?: boolean; }, ): void;