From 57381d43ed3150df8df87d250c2d5127af021b6a Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 25 Mar 2025 21:33:30 +0000 Subject: [PATCH] types: Rewrite to avoid conflicts and allow for doc generation (#18024) Co-authored-by: Jarred Sumner --- bench/express/tsconfig.json | 2 +- bench/postgres/tsconfig.json | 2 +- bun.lock | 3 +- docs/guides/runtime/typescript.md | 13 +- docs/typescript.md | 13 +- packages/bun-types/README.md | 4 +- packages/bun-types/authoring.md | 114 + packages/bun-types/bun.d.ts | 2058 +++++----- packages/bun-types/bun.ns.d.ts | 7 + packages/bun-types/deprecated.d.ts | 30 +- packages/bun-types/devserver.d.ts | 343 +- .../{ambient.d.ts => extensions.d.ts} | 6 +- packages/bun-types/fetch.d.ts | 223 +- packages/bun-types/ffi.d.ts | 8 - packages/bun-types/globals.d.ts | 3434 ++++++++--------- packages/bun-types/index.d.ts | 24 +- packages/bun-types/overrides.d.ts | 71 +- packages/bun-types/package.json | 9 +- packages/bun-types/s3.d.ts | 825 ++++ packages/bun-types/test.d.ts | 13 +- packages/bun-types/tsconfig.json | 20 +- packages/bun-types/wasm.d.ts | 433 +-- src/cli/init/tsconfig.default.json | 2 +- src/js/builtins/shell.ts | 1 + test/integration/bun-types/bun-types.test.ts | 81 +- test/integration/bun-types/fixture/.gitignore | 3 - test/integration/bun-types/fixture/bun.lock | 10 +- test/integration/bun-types/fixture/index.ts | 308 +- .../bun-types/fixture/package.json | 8 +- tsconfig.json | 1 - 30 files changed, 4405 insertions(+), 3664 deletions(-) create mode 100644 packages/bun-types/authoring.md create mode 100644 packages/bun-types/bun.ns.d.ts rename packages/bun-types/{ambient.d.ts => extensions.d.ts} (80%) create mode 100644 packages/bun-types/s3.d.ts delete mode 100644 test/integration/bun-types/fixture/.gitignore diff --git a/bench/express/tsconfig.json b/bench/express/tsconfig.json index 238655f2ce..0fef23a368 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 238655f2ce..0fef23a368 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/bun.lock b/bun.lock index ee4803a290..2f08f1d900 100644 --- a/bun.lock +++ b/bun.lock @@ -27,9 +27,10 @@ }, "packages/bun-types": { "name": "bun-types", + "version": "1.2.5", "dependencies": { "@types/node": "*", - "@types/ws": "~8.5.10", + "@types/ws": "*", }, "devDependencies": { "@biomejs/biome": "^1.5.3", diff --git a/docs/guides/runtime/typescript.md b/docs/guides/runtime/typescript.md index 67edcb83ce..c6ce400981 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", "DOM"], + // Environment setup & latest features + "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", @@ -33,11 +33,12 @@ Below is the full set of recommended `compilerOptions` for a Bun project. With t "strict": true, "skipLibCheck": true, "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, }, } ``` diff --git a/docs/typescript.md b/docs/typescript.md index 0790ceccf9..71b38ea601 100644 --- a/docs/typescript.md +++ b/docs/typescript.md @@ -17,7 +17,7 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh ```jsonc { "compilerOptions": { - // Enable latest features + // Environment setup & latest features "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", @@ -35,12 +35,13 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh "strict": true, "skipLibCheck": true, "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, + }, } ``` diff --git a/packages/bun-types/README.md b/packages/bun-types/README.md index c51b1b22fa..45c74a24d1 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 ``` diff --git a/packages/bun-types/authoring.md b/packages/bun-types/authoring.md new file mode 100644 index 0000000000..6b3dd9f0ab --- /dev/null +++ b/packages/bun-types/authoring.md @@ -0,0 +1,114 @@ +# Authoring @types/bun + +These declarations define the `'bun'` module, the `Bun` global variable, and lots of other global declarations like extending the `fetch` interface. + +## 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" { + // Your types go here + interface MyInterface { + // ... + } + + type MyType = string | number; + + function myFunction(): void; +} +``` + +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'`: + +```typescript +import { type MyInterface, type MyType, myFunction } from "bun"; + +const myInterface: MyInterface = {}; +const myType: MyType = "cool"; +myFunction(); +``` + +2. Using the global `Bun` object: + +```typescript +const myInterface: Bun.MyInterface = {}; +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: + +- `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. You can make more files + +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 + +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 (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** + - 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 + +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 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. + +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 + +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. diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 5434cf5687..1c890efa3f 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -14,14 +14,502 @@ * 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; + + /** + * @private + */ + 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 + LibDomIsLoaded extends true + ? typeof globalThis extends { [K in GlobalThisKeyName]: infer T } // if it is loaded, infer it from `globalThis` and use that value + ? T + : Otherwise // Not defined in lib dom (or anywhere else), so no conflict. We can safely use our own definition + : Otherwise; // Lib dom not loaded anyway, so no conflict. We can safely use our own definition + } + + 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; + + 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 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 +590,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 +602,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 +721,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 +781,88 @@ 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; + + /** + * 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; @@ -446,7 +944,7 @@ declare module "bun" { blob(): Blob; } - export const $: Shell; + const $: Shell; interface TOML { /** @@ -465,7 +963,6 @@ declare module "bun" { * * On failure, throws a `ResolveMessage` */ - // tslint:disable-next-line:unified-signatures function resolveSync(moduleId: string, parent: string): string; /** @@ -475,7 +972,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 +983,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 +1035,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 +1068,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 +1102,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?: { /** @@ -1020,65 +1513,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. @@ -1104,7 +1538,7 @@ declare module "bun" { * ``` */ 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. @@ -1198,767 +1632,9 @@ declare module "bun" { /** * 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; + 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 @@ -2093,12 +1769,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(); @@ -2108,13 +1784,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. @@ -2368,6 +2044,7 @@ declare module "bun" { var SQL: SQL; var CSRF: CSRF; + /** * This lets you use macros as regular imports * @example @@ -2721,7 +2398,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" * @@ -3357,7 +3034,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. @@ -3379,7 +3056,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. @@ -3411,14 +3088,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. @@ -3431,7 +3108,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. @@ -3455,7 +3132,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. @@ -3656,7 +3333,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; @@ -3749,13 +3426,26 @@ declare module "bun" { type RouteHandler = (req: BunRequest, server: Server) => Response | Promise; + type RouteHandlerWithWebSocketUpgrade = ( + req: BunRequest, + server: Server, + ) => Response | undefined | void | Promise; + type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; type RouteHandlerObject = { [K in HTTPMethod]?: RouteHandler; }; + type RouteHandlerWithWebSocketUpgradeObject = { + [K in HTTPMethod]?: RouteHandlerWithWebSocketUpgrade; + }; + type RouteValue = Response | false | RouteHandler | RouteHandlerObject; + type RouteValueWithWebSocketUpgrade = + | RouteValue + | RouteHandlerWithWebSocketUpgrade + | RouteHandlerWithWebSocketUpgradeObject; } interface BunRequest extends Request { @@ -3807,7 +3497,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 @@ -4057,6 +3747,9 @@ declare module "bun" { syscall?: string; } + /** + * Options for TLS connections + */ interface TLSOptions { /** * Passphrase for the TLS key @@ -4381,7 +4074,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 */ @@ -4524,6 +4217,9 @@ declare module "bun" { readonly id: string; } + /** + * The type of options that can be passed to {@link serve} + */ type Serve = | ServeOptions | TLSServeOptions @@ -4534,179 +4230,10 @@ 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 }> = + /** + * 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; fetch?: (this: Server, request: Request, server: Server) => Response | Promise; @@ -4715,15 +4242,17 @@ declare module "bun" { routes?: never; fetch: (this: Server, request: Request, server: Server) => Response | Promise; }) - | (WebSocketServeOptions & { - routes: R; + | (Omit, "fetch"> & { + routes: { + [K in keyof R]: RouterTypes.RouteValueWithWebSocketUpgrade>; + }; fetch?: ( this: Server, request: Request, server: Server, ) => Response | Promise | void | undefined; }) - | (WebSocketServeOptions & { + | (Omit, "fetch"> & { routes?: never; fetch: ( this: Server, @@ -4732,6 +4261,178 @@ 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 + * + * @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. * @@ -4756,7 +4457,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; /** @@ -4782,7 +4482,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} */ - // tslint:disable-next-line:unified-signatures function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; /** @@ -4799,7 +4498,6 @@ declare module "bun" { * * @param fileDescriptor The file descriptor of the file */ - // tslint:disable-next-line:unified-signatures function file(fileDescriptor: number, options?: BlobPropertyBag): BunFile; /** @@ -4809,10 +4507,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; } @@ -4821,7 +4534,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 { @@ -4869,7 +4583,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; @@ -4896,6 +4610,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?: /** @@ -4949,53 +4668,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 { /** @@ -5014,11 +4732,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, @@ -5036,6 +4751,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; @@ -5049,7 +4769,7 @@ declare module "bun" { const enableANSIColors: boolean; /** - * What script launched bun? + * What script launched Bun? * * Absolute file path * @@ -5139,9 +4859,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"; @@ -5242,7 +4960,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 @@ -5256,14 +4974,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 * @@ -5271,7 +5000,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, @@ -5738,7 +5466,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 { @@ -5967,7 +5695,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. @@ -5979,7 +5707,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 @@ -6120,8 +5848,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. @@ -6137,7 +5865,7 @@ declare module "bun" { * ``` * */ - getCipher(): CipherNameAndProtocol; + getCipher(): import("tls").CipherNameAndProtocol; /** * Returns an object representing the type, name, and size of parameter of @@ -6148,7 +5876,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 @@ -6159,8 +5887,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/bun.ns.d.ts b/packages/bun-types/bun.ns.d.ts new file mode 100644 index 0000000000..d55c3f5352 --- /dev/null +++ b/packages/bun-types/bun.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/deprecated.d.ts b/packages/bun-types/deprecated.d.ts index 5a90164689..2fb502e4ad 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/devserver.d.ts b/packages/bun-types/devserver.d.ts index 53df578834..24879853f2 100644 --- a/packages/bun-types/devserver.d.ts +++ b/packages/bun-types/devserver.d.ts @@ -1,192 +1,189 @@ -export {}; +declare module "bun" { + type HMREventNames = + | "beforeUpdate" + | "afterUpdate" + | "beforeFullReload" + | "beforePrune" + | "invalidate" + | "error" + | "ws:disconnect" + | "ws:connect"; -declare global { - namespace Bun { - type HMREventNames = - | "bun:ready" - | "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 - */ - 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 + * `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 - * if (import.meta.hot) { - * // HMR APIs are available - * } + * const root = import.meta.hot.data.root ??= createRoot(elem); + * root.render(); // re-use an existing root * ``` * - * However, this check is usually not needed as Bun will dead-code-eliminate - * calls to all of the HMR APIs in production builds. + * In production, `data` is inlined to be `{}`. This is handy because Bun + * knows it can minify `{}.prop ??= value` into `value` in production. + * * - * 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; + 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; - // 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/packages/bun-types/ambient.d.ts b/packages/bun-types/extensions.d.ts similarity index 80% rename from packages/bun-types/ambient.d.ts rename to packages/bun-types/extensions.d.ts index 05d9085577..fb0a2ee065 100644 --- a/packages/bun-types/ambient.d.ts +++ b/packages/bun-types/extensions.d.ts @@ -19,13 +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 contents: `${string}.svg`; - export = contents; + var content: `${string}.svg`; + export = content; } diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index 58e138bbad..b144f48451 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,161 +1,72 @@ -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[]; -} +/* -var Headers: { - prototype: Headers; - new (init?: Bun.HeadersInit): Headers; -}; + This file does not declare any global types. -interface Request { - headers: Headers; -} + That should only happen in [./globals.d.ts](./globals.d.ts) + so that our documentation generator can pick it up, as it + expects all globals to be declared in one file. -var 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; - - /** - * 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; -} - -/** - * 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; + +declare module "bun" { + type HeadersInit = string[][] | Record> | Headers; + type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams | AsyncGenerator; + + namespace __internal { + type LibOrFallbackHeaders = LibDomIsLoaded extends true ? {} : import("undici-types").Headers; + type LibOrFallbackRequest = LibDomIsLoaded extends true ? {} : import("undici-types").Request; + type LibOrFallbackResponse = LibDomIsLoaded extends true ? {} : import("undici-types").Response; + type LibOrFallbackResponseInit = LibDomIsLoaded extends true ? {} : import("undici-types").ResponseInit; + type LibOrFallbackRequestInit = LibDomIsLoaded extends true + ? {} + : Omit & { + body?: Bun.BodyInit | null | undefined; + headers?: Bun.HeadersInit; + }; + + interface BunHeadersOverride extends LibOrFallbackHeaders { + /** + * 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 BunRequestOverride extends LibOrFallbackRequest { + headers: BunHeadersOverride; + } + + interface BunResponseOverride extends LibOrFallbackResponse { + headers: BunHeadersOverride; + } + } } - -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 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; - - /** - * 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 650dec2063..e1e2270086 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/globals.d.ts b/packages/bun-types/globals.d.ts index 3daeb5b682..ee61fef7e6 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1,43 +1,175 @@ -export {}; +declare module "bun" { + namespace __internal { + type NodeWorkerThreadsWorker = import("worker_threads").Worker; + type LibWorkerOrNodeWorkerThreadsWorker = Bun.__internal.UseLibDomIfAvailable<"Worker", NodeWorkerThreadsWorker>; -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 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; + + type LibEmptyOrNodeReadableStream = LibDomIsLoaded extends true + ? {} + : import("stream/web").ReadableStream; + + type LibEmptyOrNodeWritableStream = LibDomIsLoaded extends true + ? {} + : import("stream/web").WritableStream; + + type LibEmptyOrNodeTransformStream = LibDomIsLoaded extends true + ? {} + : import("stream/web").TransformStream; + } +} + +interface ReadableStream extends Bun.__internal.LibEmptyOrNodeReadableStream {} +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 extends Bun.__internal.LibEmptyOrNodeWritableStream {} +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; }; -type _EventTarget = { +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. * @@ -60,650 +192,79 @@ type _EventTarget = { listener: EventListener | EventListenerObject, options?: Bun.EventListenerOptions | boolean, ): void; +} +declare var EventTarget: { + prototype: EventTarget; + new (): EventTarget; }; -declare global { - var Bun: typeof import("bun"); +interface File extends Blob { + readonly lastModified: number; + readonly name: string; +} - 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; - _exiting: boolean; - noDeprecation: boolean; - - binding(m: string): object; - binding(m: "constants"): { - os: typeof import("node:os").constants; - fs: typeof import("node:fs").constants; - crypto: typeof import("node:crypto").constants; - zlib: typeof import("node:zlib").constants; - trace: typeof import("node:trace").constants; - }; - } - } - - 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; +declare var File: typeof globalThis extends { onabort: any } + ? typeof globalThis extends { File: infer T } + ? T + : never + : { + prototype: File; /** - * 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. + * Create a new [File](https://developer.mozilla.org/en-US/docs/Web/API/File) * - * ```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. + * @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) */ - 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; + 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 { /** - * 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). + * Creates a new [ShadowRealm](https://github.com/tc39/proposal-shadowrealm/blob/main/explainer.md#introduction) * * @example * @@ -739,1108 +300,1427 @@ 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; - } - - 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; - - 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, - ): { - /** - * The number of bytes read from the base64 string - */ - read: number; - /** - * The number of bytes written to the Uint8Array - * Will never be greater than the `.byteLength` of this Uint8Array - */ - written: number; - }; - - /** - * Convert the Uint8Array to a hex encoded string - * @returns The hex encoded string representation of the Uint8Array - */ - toHex(): string; - - /** - * Set the contents of the Uint8Array from a hex encoded string - * @param hex The hex encoded string to decode into the array. The string must have - * an even number of characters, be valid hexadecimal characters and contain no whitespace. - */ - setFromHex(hex: string): { - /** - * The number of bytes read from the hex string - */ - read: number; - /** - * The number of bytes written to the Uint8Array - * Will never be greater than the `.byteLength` of this Uint8Array - */ - written: number; - }; - } - - 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, - options?: { - alphabet?: "base64" | "base64url"; - lastChunkHandling?: "loose" | "strict" | "stop-before-partial"; - }, - ): Uint8Array; - } + 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"; +} + +interface ErrorConstructor { + isError(value: unknown): value is Error; + + /** + * 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; + + /** + * The maximum number of stack frames to capture. + */ + 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; + }; + + /** + * Try to run a function and return the result. + * If the function throws, return the result of the `catch` function. + * + * @param fn - The function to run + * @param args - The arguments to pass to the function. This is similar to `setTimeout` and avoids the extra closure. + * @returns The result of the function or the result of the `catch` function + */ + try(fn: (...args: A) => T | PromiseLike, ...args: A): Promise; +} + +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; + + /** + * 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())` + */ + bytes(): Promise; + + /** + * Returns a readable stream of the blob's contents + */ + stream(): ReadableStream; +} + +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, + ): { + /** + * The number of bytes read from the base64 string + */ + read: number; + /** + * The number of bytes written to the Uint8Array + * Will never be greater than the `.byteLength` of this Uint8Array + */ + written: number; + }; + + /** + * Convert the Uint8Array to a hex encoded string + * @returns The hex encoded string representation of the Uint8Array + */ + toHex(): string; + + /** + * Set the contents of the Uint8Array from a hex encoded string + * @param hex The hex encoded string to decode into the array. The string must have + * an even number of characters, be valid hexadecimal characters and contain no whitespace. + */ + setFromHex(hex: string): { + /** + * The number of bytes read from the hex string + */ + read: number; + /** + * The number of bytes written to the Uint8Array + * Will never be greater than the `.byteLength` of this Uint8Array + */ + written: number; + }; +} + +interface Uint8ArrayConstructor { + /** + * Create a new Uint8Array from a base64 encoded string + * @param base64 The base64 encoded string to convert to a Uint8Array + * @param options Optional options for decoding the base64 string + * @returns A new Uint8Array containing the decoded data + */ + fromBase64( + base64: string, + options?: { + alphabet?: "base64" | "base64url"; + lastChunkHandling?: "loose" | "strict" | "stop-before-partial"; + }, + ): Uint8Array; + + /** + * Create a new Uint8Array from a hex encoded string + * @param hex The hex encoded string to convert to a Uint8Array + * @returns A new Uint8Array containing the decoded data + */ + fromHex(hex: 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; + /** + * Parse a URL. + * + * @param url - The URL to parse. + * @param base - The base URL to use. + */ + parse(url: string, base?: string): URL | null; + } +>; + +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; + } +>; + +//#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; + +/** + * 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; +} +//#endregion diff --git a/packages/bun-types/index.d.ts b/packages/bun-types/index.d.ts index 7198791e33..ee29d26f77 100644 --- a/packages/bun-types/index.d.ts +++ b/packages/bun-types/index.d.ts @@ -1,24 +1,26 @@ // 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/overrides.d.ts b/packages/bun-types/overrides.d.ts index 2c95632243..a85cd3d73b 100644 --- a/packages/bun-types/overrides.d.ts +++ b/packages/bun-types/overrides.d.ts @@ -1,18 +1,71 @@ 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; + _exiting: boolean; + noDeprecation: boolean; + + binding(m: "constants"): { + os: typeof import("node:os").constants; + fs: typeof import("node:fs").constants; + crypto: typeof import("node:crypto").constants; + zlib: typeof import("node:zlib").constants; + trace: { + TRACE_EVENT_PHASE_BEGIN: number; + TRACE_EVENT_PHASE_END: number; + TRACE_EVENT_PHASE_COMPLETE: number; + TRACE_EVENT_PHASE_INSTANT: number; + TRACE_EVENT_PHASE_ASYNC_BEGIN: number; + TRACE_EVENT_PHASE_ASYNC_STEP_INTO: number; + TRACE_EVENT_PHASE_ASYNC_STEP_PAST: number; + TRACE_EVENT_PHASE_ASYNC_END: number; + TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN: number; + TRACE_EVENT_PHASE_NESTABLE_ASYNC_END: number; + TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT: number; + TRACE_EVENT_PHASE_FLOW_BEGIN: number; + TRACE_EVENT_PHASE_FLOW_STEP: number; + TRACE_EVENT_PHASE_FLOW_END: number; + TRACE_EVENT_PHASE_METADATA: number; + TRACE_EVENT_PHASE_COUNTER: number; + TRACE_EVENT_PHASE_SAMPLE: number; + TRACE_EVENT_PHASE_CREATE_OBJECT: number; + TRACE_EVENT_PHASE_SNAPSHOT_OBJECT: number; + TRACE_EVENT_PHASE_DELETE_OBJECT: number; + TRACE_EVENT_PHASE_MEMORY_DUMP: number; + TRACE_EVENT_PHASE_MARK: number; + TRACE_EVENT_PHASE_CLOCK_SYNC: number; + TRACE_EVENT_PHASE_ENTER_CONTEXT: number; + TRACE_EVENT_PHASE_LEAVE_CONTEXT: number; + TRACE_EVENT_PHASE_LINK_IDS: number; + }; + }; + binding(m: string): object; + } + 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 +75,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 +91,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 +107,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 1f7ffd8665..32c4e9b580 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -1,4 +1,5 @@ { + "version": "1.2.5", "name": "bun-types", "license": "MIT", "types": "./index.d.ts", @@ -9,14 +10,14 @@ "directory": "packages/bun-types" }, "files": [ - "*.d.ts", + "./*.d.ts", "docs/**/*.md", "docs/*.md" ], "homepage": "https://bun.sh", "dependencies": { "@types/node": "*", - "@types/ws": "~8.5.10" + "@types/ws": "*" }, "devDependencies": { "@biomejs/biome": "^1.5.3", @@ -27,7 +28,7 @@ "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", + "build": "bun run copy-docs && bun scripts/build.ts", "test": "tsc", "fmt": "echo $(which biome) && biome format --write ." }, @@ -36,4 +37,4 @@ "bun.js", "types" ] -} +} \ No newline at end of file diff --git a/packages/bun-types/s3.d.ts b/packages/bun-types/s3.d.ts new file mode 100644 index 0000000000..0c54149232 --- /dev/null +++ b/packages/bun-types/s3.d.ts @@ -0,0 +1,825 @@ +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; + } + + /** + * 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/test.d.ts b/packages/bun-types/test.d.ts index acd28c7215..e908c6318d 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; @@ -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; /** @@ -1778,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. diff --git a/packages/bun-types/tsconfig.json b/packages/bun-types/tsconfig.json index 0c33ffe9c4..e5006c96e0 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"] } diff --git a/packages/bun-types/wasm.d.ts b/packages/bun-types/wasm.d.ts index b4975f140a..84c1a8fe4f 100644 --- a/packages/bun-types/wasm.d.ts +++ b/packages/bun-types/wasm.d.ts @@ -1,270 +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"; - // 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; - } - } - } - +declare module "bun" { 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 {} + 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 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 }; + interface ValueTypeMap { + anyfunc: Function; + externref: any; + f32: number; + f64: number; + i32: number; + i64: bigint; + v128: never; } - ? 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; - }; + type ValueType = keyof ValueTypeMap; - interface Global extends _Global {} - var Global: typeof globalThis extends { - onerror: any; - WebAssembly: { Global: infer T }; + interface GlobalDescriptor { + mutable?: boolean; + value: 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 }; + 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]; } - ? T - : { - prototype: Instance; - new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance; - }; - interface Memory extends _Memory {} - var Memory: { - prototype: Memory; - new (descriptor: MemoryDescriptor): Memory; - }; + interface CompileError extends Error {} - interface Module extends _Module {} - var Module: typeof globalThis extends { - onerror: any; - WebAssembly: { Module: infer T }; + 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; } - ? 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/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/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; + /** [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/src/cli/init/tsconfig.default.json b/src/cli/init/tsconfig.default.json index ab0f0b0964..9c62f74b91 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"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", diff --git a/src/js/builtins/shell.ts b/src/js/builtins/shell.ts index 8567a2cced..a88f4a6fec 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/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 69952f3394..29978387ea 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -1,18 +1,31 @@ -import { fileURLToPath, $ as Shell, ShellError } from "bun"; -import { beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test"; +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 { 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/, ""); +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(); + +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 @@ -36,13 +49,12 @@ beforeAll(async () => { mv package.json.backup package.json 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} `; } catch (e) { - if (e instanceof ShellError) { + if (e instanceof Bun.$.ShellError) { console.log(e.stderr.toString()); } @@ -50,12 +62,23 @@ beforeAll(async () => { } }); -beforeAll(() => { - setDefaultTimeout(1000 * 60 * 5); +beforeEach(async () => { + await $` + cd ${FIXTURE_DIR} + cp ${TSCONFIG_SOURCE_PATH} tsconfig.json + sed -i 's/"skipLibCheck": true/"skipLibCheck": false/' tsconfig.json + cat tsconfig.json + `; +}); + +afterAll(async () => { + if (TEMP_DIR) { + await rm(TEMP_DIR, { recursive: true, force: true }); + } }); describe("@types/bun integration test", () => { - test("it typechecks successfully", async () => { + test("checks without lib.dom.d.ts", async () => { const p = await $` cd ${FIXTURE_DIR} bun run check @@ -63,4 +86,40 @@ describe("@types/bun integration test", () => { expect(p.exitCode).toBe(0); }); + + 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", "DOM.Iterable", "DOM.AsyncIterable"]', + ), + ); + + const p = await $` + cd ${FIXTURE_DIR} + bun run check + `; + + const importantLines = [ + `error TS2345: Argument of type 'AsyncGenerator, void, unknown>' is not assignable to parameter of type 'BodyInit | null | undefined'.`, + "error TS2769: No overload matches this call.", + "Overload 1 of 3, '(underlyingSource: UnderlyingByteSource, strategy?: { highWaterMark?: number | undefined; } | undefined): ReadableStream>', gave the following error.", + `Type '"direct"' is not assignable to type '"bytes"'`, + "error TS2345: Argument of type '{ headers: { \"x-bun\": string; }; }' is not assignable to parameter of type 'number'.", + "error TS2339: Property 'write' does not exist on type 'ReadableByteStreamController'.", + ]; + + const fullOutput = p.stdout.toString() + p.stderr.toString(); + + const expectedErrorCount = importantLines.filter(e => e.includes("error")).length; + const actualErrorCount = fullOutput.match(/error/g)?.length ?? 0; + expect(actualErrorCount).toBe(expectedErrorCount); + + for (const line of importantLines) { + expect(fullOutput).toContain(line); + } + + 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 c183f93ee3..0000000000 --- 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/bun.lock b/test/integration/bun-types/fixture/bun.lock index 035166f8a5..d5b22f1f20 100644 --- a/test/integration/bun-types/fixture/bun.lock +++ b/test/integration/bun-types/fixture/bun.lock @@ -5,20 +5,18 @@ "name": "fixture", "dependencies": { "@types/bun": "types-bun-1.2.6.tgz", - }, - "peerDependencies": { - "typescript": "^5.0.0", + "typescript": "^5.8.2", }, }, }, "packages": { - "@types/bun": ["@types/bun@types-bun-1.2.6.tgz", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }], + "@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.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": ["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 30338bbfd7..d464151f17 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -1,6 +1,70 @@ import svgpath from "cool.svg"; svgpath satisfies `${string}.svg`; +import * as test from "bun:test"; +test.describe; +test.it; + +const options: Bun.TLSOptions = { + keyFile: "", +}; + +process.assert; + +new SubtleCrypto(); +declare const mySubtleCrypto: SubtleCrypto; + +new CryptoKey(); +declare const myCryptoKey: CryptoKey; + +import * as sqlite from "bun:sqlite"; +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; + +type c = import("bun").S3Client; + +Bun.s3.file("").name; + +const client = new Bun.S3Client({ + secretAccessKey: "", +}); + +new TextEncoder(); + +client.file(""); + +Bun.fetch; + // just some APIs new Request("url"); new Response(); @@ -15,7 +79,24 @@ new TransformStream(); new AbortSignal(); new AbortController(); -fetch("url"); +new TextDecoder(); +new TextEncoder(); + +fetch("url", { + proxy: "", +}); + +fetch(new URL("url"), { + proxy: "", +}); + +Bun.fetch(new URL("url"), { + proxy: "", +}); + +Bun.S3Client; + +Bun.$.ShellPromise; new Bun.$.ShellError(); @@ -56,13 +137,13 @@ Bun.serve({ }, fetch: (req, server) => { - return new Response("upgraded"); + return new Response("cool"); }, }); Bun.serve({ fetch: (req, server) => { - return new Response("upgraded"); + return new Response("cool"); }, }); @@ -83,6 +164,38 @@ Bun.serve({ }, }); +Bun.serve({ + websocket: { + message: () => { + // + }, + }, + fetch: (req, server) => { + if (server.upgrade(req)) { + return; + } + + return new Response("not upgraded"); + }, +}); + +Bun.serve({ + websocket: { + message: () => { + // + }, + }, + routes: { + "/ws": (req, server) => { + if (server.upgrade(req)) { + return; + } + + return new Response("not upgraded"); + }, + }, +}); + new Map(); new Set(); new WeakMap(); @@ -91,6 +204,37 @@ new Map(); new Set(); new WeakMap(); +Promise.try(() => { + return 1; +}); + +Promise.try(() => { + throw new Error("test"); +}); + +Promise.try((message: string) => { + throw new Error(message); +}, "Bun"); + +declare const myReadableStream: ReadableStream; +for await (const chunk of myReadableStream) { + console.log(chunk); +} + +for await (const chunk of Bun.stdin.stream()) { + // chunk is Uint8Array + // this converts it to text (assumes ASCII encoding) + const chunkText = Buffer.from(chunk).toString(); + console.log(`Chunk: ${chunkText}`); +} + +const myAsyncGenerator = async function* () { + yield new Uint8Array([1, 2, 3]); + yield new Uint8Array([4, 5, 6]); +}; + +new Response(myAsyncGenerator()); + const statuses = [200, 400, 401, 403, 404, 500, 501, 502, 503, 504]; const r = new Request("", { @@ -100,6 +244,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, }, }); @@ -108,6 +255,7 @@ r.method; r.body; r.headers.get("content-type"); +new Request("", {}); new Bun.$.ShellError() instanceof Bun.$.ShellError; await r.json(); @@ -120,6 +268,10 @@ const req1 = new Request("", { body: "", }); +for (const header of new Headers()) { + console.log(header); +} + fetch("", { tls: { rejectUnauthorized: false, @@ -142,52 +294,153 @@ 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); +Bun.fetch satisfies typeof fetch; +Bun.fetch.preconnect satisfies typeof fetch.preconnect; + await body.text(); +fetch; + fetch.preconnect(new URL("")); 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; URL.createObjectURL; URL.revokeObjectURL; -Response.json(); +declare const myBodyInit: Bun.BodyInit; +declare const myHeadersInit: Bun.HeadersInit; + +await new Blob().text(); +await new Blob().json(); +await new Blob().arrayBuffer(); +await new Blob().bytes(); +await new Blob().formData(); + +await new File(["code"], "name.ts").text(); +await new File(["code"], "name.ts").json(); +await new File(["code"], "name.ts").arrayBuffer(); +await new File(["code"], "name.ts").bytes(); +await new File(["code"], "name.ts").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(); + +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(); +Response.redirect("bun.sh", 302); 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; +Bun.inspect.custom; +Bun.inspect; + +fetch.preconnect("bun.sh"); +Bun.fetch.preconnect("bun.sh"); + +new Uint8Array().toBase64(); Bun.fetch("", { proxy: "", - s3: {}, + s3: { + acl: "public-read", + }, }); +new HTMLRewriter() + .on("script", { + element(element) { + console.log(element.getAttribute("src")); + }, + }) + .transform(new Blob([''])); + +Buffer.from("foo").equals(Buffer.from("bar")); + +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: "", + method: "GET", +}; + +declare const requestInitKeys: `evaluate-${keyof RequestInit}`; +requestInitKeys satisfies string; + Bun.serve({ fetch(req) { req.headers; @@ -202,15 +455,22 @@ Bun.serve({ }, }); +import.meta.hot.accept(); import.meta.hot.data; -import { serve } from "bun"; - -new Worker("").on("message", (e: MessageEvent) => { - e; - e.data satisfies string; +fetch("", { + tls: { + rejectUnauthorized: false, + }, }); +new AbortController(); +const myAbortController: AbortController = new AbortController(); +new AbortSignal(); +const myAbortSignal: AbortSignal = new AbortSignal(); + +import { serve } from "bun"; + new Worker("", { type: "module", preload: ["preload.ts"], diff --git a/test/integration/bun-types/fixture/package.json b/test/integration/bun-types/fixture/package.json index 4911bcb89f..e455fad98c 100644 --- a/test/integration/bun-types/fixture/package.json +++ b/test/integration/bun-types/fixture/package.json @@ -1,14 +1,12 @@ { "name": "fixture", "module": "index.ts", - "peerDependencies": { - "typescript": "^5.0.0" - }, "scripts": { - "check": "tsc --noEmit" + "check": "tsc --noEmit -p ./tsconfig.json" }, "type": "module", "dependencies": { - "@types/bun": "types-bun-1.2.6.tgz" + "@types/bun": "types-bun-1.2.6.tgz", + "typescript": "latest" } } diff --git a/tsconfig.json b/tsconfig.json index c3ec51e2a1..6d7eece9e7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,6 @@ "emitDecoratorMetadata": true }, "references": [ - // { "path": "./src" }, { "path": "./src/bake" }, { "path": "./src/js" },