mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
types: Rewrite to avoid conflicts and allow for doc generation (#18024)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// Enable latest features
|
// Enable latest features
|
||||||
"lib": ["ESNext", "DOM"],
|
"lib": ["ESNext"],
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// Enable latest features
|
// Enable latest features
|
||||||
"lib": ["ESNext", "DOM"],
|
"lib": ["ESNext"],
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
|
|||||||
3
bun.lock
3
bun.lock
@@ -27,9 +27,10 @@
|
|||||||
},
|
},
|
||||||
"packages/bun-types": {
|
"packages/bun-types": {
|
||||||
"name": "bun-types",
|
"name": "bun-types",
|
||||||
|
"version": "1.2.5",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/ws": "~8.5.10",
|
"@types/ws": "*",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.5.3",
|
"@biomejs/biome": "^1.5.3",
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ Below is the full set of recommended `compilerOptions` for a Bun project. With t
|
|||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// Enable latest features
|
// Environment setup & latest features
|
||||||
"lib": ["ESNext", "DOM"],
|
"lib": ["ESNext"],
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
@@ -33,11 +33,12 @@ Below is the full set of recommended `compilerOptions` for a Bun project. With t
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
|
||||||
// Some stricter flags
|
// Some stricter flags (disabled by default)
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": false,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": false,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh
|
|||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// Enable latest features
|
// Environment setup & latest features
|
||||||
"lib": ["ESNext"],
|
"lib": ["ESNext"],
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
@@ -35,12 +35,13 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
|
||||||
// Some stricter flags
|
// Some stricter flags (disabled by default)
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": false,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": false,
|
||||||
"noPropertyAccessFromIndexSignature": true
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ That's it! VS Code and TypeScript automatically load `@types/*` packages into yo
|
|||||||
|
|
||||||
# Contributing
|
# 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).
|
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
|
|||||||
+ /// <reference path="./newfile.d.ts" />
|
+ /// <reference path="./newfile.d.ts" />
|
||||||
```
|
```
|
||||||
|
|
||||||
[`./bundle.ts`](./bundle.ts) merges the types in this folder into a single file. To run it:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun build
|
bun build
|
||||||
```
|
```
|
||||||
|
|||||||
114
packages/bun-types/authoring.md
Normal file
114
packages/bun-types/authoring.md
Normal file
@@ -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<LibDomName extends string, OurType>` 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.
|
||||||
2058
packages/bun-types/bun.d.ts
vendored
2058
packages/bun-types/bun.d.ts
vendored
File diff suppressed because it is too large
Load Diff
7
packages/bun-types/bun.ns.d.ts
vendored
Normal file
7
packages/bun-types/bun.ns.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import * as BunModule from "bun";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
export import Bun = BunModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
30
packages/bun-types/deprecated.d.ts
vendored
30
packages/bun-types/deprecated.d.ts
vendored
@@ -1,4 +1,19 @@
|
|||||||
declare module "bun" {
|
declare module "bun" {
|
||||||
|
interface BunMessageEvent<T> {
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
initMessageEvent(
|
||||||
|
type: string,
|
||||||
|
bubbles?: boolean,
|
||||||
|
cancelable?: boolean,
|
||||||
|
data?: any,
|
||||||
|
origin?: string,
|
||||||
|
lastEventId?: string,
|
||||||
|
source?: null,
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Renamed to `ErrorLike`
|
* @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<T = any> {
|
interface CustomEvent<T = any> {
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void;
|
initCustomEvent(type: string, bubbles?: boolean, cancelable?: boolean, detail?: T): void;
|
||||||
|
|||||||
25
packages/bun-types/devserver.d.ts
vendored
25
packages/bun-types/devserver.d.ts
vendored
@@ -1,17 +1,13 @@
|
|||||||
export {};
|
declare module "bun" {
|
||||||
|
|
||||||
declare global {
|
|
||||||
namespace Bun {
|
|
||||||
type HMREventNames =
|
type HMREventNames =
|
||||||
| "bun:ready"
|
| "beforeUpdate"
|
||||||
| "bun:beforeUpdate"
|
| "afterUpdate"
|
||||||
| "bun:afterUpdate"
|
| "beforeFullReload"
|
||||||
| "bun:beforeFullReload"
|
| "beforePrune"
|
||||||
| "bun:beforePrune"
|
| "invalidate"
|
||||||
| "bun:invalidate"
|
| "error"
|
||||||
| "bun:error"
|
| "ws:disconnect"
|
||||||
| "bun:ws:disconnect"
|
| "ws:connect";
|
||||||
| "bun:ws:connect";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event names for the dev server
|
* The event names for the dev server
|
||||||
@@ -50,6 +46,8 @@ declare global {
|
|||||||
*
|
*
|
||||||
* In production, `data` is inlined to be `{}`. This is handy because Bun
|
* In production, `data` is inlined to be `{}`. This is handy because Bun
|
||||||
* knows it can minify `{}.prop ??= value` into `value` in production.
|
* knows it can minify `{}.prop ??= value` into `value` in production.
|
||||||
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
data: any;
|
data: any;
|
||||||
|
|
||||||
@@ -189,4 +187,3 @@ declare global {
|
|||||||
off(event: Bun.HMREvent, callback: () => void): void;
|
off(event: Bun.HMREvent, callback: () => void): void;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ declare module "*/bun.lock" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare module "*.html" {
|
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;
|
var contents: any;
|
||||||
export = contents;
|
export = contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "*.svg" {
|
declare module "*.svg" {
|
||||||
// Bun 1.2.3 added support for frontend dev server
|
// Bun 1.2.3 added support for frontend dev server
|
||||||
var contents: `${string}.svg`;
|
var content: `${string}.svg`;
|
||||||
export = contents;
|
export = content;
|
||||||
}
|
}
|
||||||
157
packages/bun-types/fetch.d.ts
vendored
157
packages/bun-types/fetch.d.ts
vendored
@@ -1,4 +1,30 @@
|
|||||||
interface Headers {
|
/*
|
||||||
|
|
||||||
|
This file does not declare any global types.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare module "bun" {
|
||||||
|
type HeadersInit = string[][] | Record<string, string | ReadonlyArray<string>> | Headers;
|
||||||
|
type BodyInit = ReadableStream | Bun.XMLHttpRequestBodyInit | URLSearchParams | AsyncGenerator<Uint8Array>;
|
||||||
|
|
||||||
|
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<import("undici-types").RequestInit, "body" | "headers"> & {
|
||||||
|
body?: Bun.BodyInit | null | undefined;
|
||||||
|
headers?: Bun.HeadersInit;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface BunHeadersOverride extends LibOrFallbackHeaders {
|
||||||
/**
|
/**
|
||||||
* Convert {@link Headers} to a plain JavaScript object.
|
* Convert {@link Headers} to a plain JavaScript object.
|
||||||
*
|
*
|
||||||
@@ -9,10 +35,12 @@ interface Headers {
|
|||||||
* Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is.
|
* Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is.
|
||||||
*/
|
*/
|
||||||
toJSON(): Record<string, string>;
|
toJSON(): Record<string, string>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of headers
|
* Get the total number of headers
|
||||||
*/
|
*/
|
||||||
readonly count: number;
|
readonly count: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all headers matching the name
|
* Get all headers matching the name
|
||||||
*
|
*
|
||||||
@@ -33,129 +61,12 @@ interface Headers {
|
|||||||
getAll(name: "set-cookie" | "Set-Cookie"): string[];
|
getAll(name: "set-cookie" | "Set-Cookie"): string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
var Headers: {
|
interface BunRequestOverride extends LibOrFallbackRequest {
|
||||||
prototype: Headers;
|
headers: BunHeadersOverride;
|
||||||
new (init?: Bun.HeadersInit): Headers;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Request {
|
|
||||||
headers: Headers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var Request: {
|
interface BunResponseOverride extends LibOrFallbackResponse {
|
||||||
prototype: Request;
|
headers: BunHeadersOverride;
|
||||||
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<import("node:tls").ConnectionOptions["checkServerIdentity"]>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* BunFetchRequestInit represents additional options that Bun supports in `fetch()` only.
|
|
||||||
*
|
|
||||||
* Bun extends the `fetch` API with some additional options, except
|
|
||||||
* this interface is not quite a `RequestInit`, because they won't work
|
|
||||||
* if passed to `new Request()`. This is why it's a separate type.
|
|
||||||
*/
|
|
||||||
interface BunFetchRequestInit extends RequestInit {
|
|
||||||
/**
|
|
||||||
* Override the default TLS options
|
|
||||||
*/
|
|
||||||
tls?: BunFetchRequestInitTLS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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<Response>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<Response>;
|
|
||||||
|
|
||||||
(input: string | URL | globalThis.Request, init?: BunFetchRequestInit): Promise<Response>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|||||||
8
packages/bun-types/ffi.d.ts
vendored
8
packages/bun-types/ffi.d.ts
vendored
@@ -543,14 +543,6 @@ declare module "bun:ffi" {
|
|||||||
|
|
||||||
type Symbols = Readonly<Record<string, FFIFunction>>;
|
type Symbols = Readonly<Record<string, FFIFunction>>;
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Compile a callback function
|
|
||||||
// *
|
|
||||||
// * Returns a function pointer
|
|
||||||
// *
|
|
||||||
// */
|
|
||||||
// export function callback(ffi: FFIFunction, cb: Function): number;
|
|
||||||
|
|
||||||
interface Library<Fns extends Symbols> {
|
interface Library<Fns extends Symbols> {
|
||||||
symbols: ConvertFns<Fns>;
|
symbols: ConvertFns<Fns>;
|
||||||
|
|
||||||
|
|||||||
1382
packages/bun-types/globals.d.ts
vendored
1382
packages/bun-types/globals.d.ts
vendored
File diff suppressed because it is too large
Load Diff
24
packages/bun-types/index.d.ts
vendored
24
packages/bun-types/index.d.ts
vendored
@@ -1,24 +1,26 @@
|
|||||||
// Project: https://github.com/oven-sh/bun
|
// Project: https://github.com/oven-sh/bun
|
||||||
// Definitions by: Jarred Sumner <https://github.com/Jarred-Sumner>
|
// Definitions by: Bun Contributors <https://github.com/oven-sh/bun/graphs/contributors>
|
||||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||||
|
|
||||||
/// <reference lib="esnext" />
|
|
||||||
/// <reference types="ws" />
|
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
|
|
||||||
// contributors: uncomment this to detect conflicts with lib.dom.d.ts
|
|
||||||
// /// <reference lib="dom" />
|
|
||||||
|
|
||||||
/// <reference path="./bun.d.ts" />
|
|
||||||
/// <reference path="./globals.d.ts" />
|
/// <reference path="./globals.d.ts" />
|
||||||
|
/// <reference path="./s3.d.ts" />
|
||||||
/// <reference path="./fetch.d.ts" />
|
/// <reference path="./fetch.d.ts" />
|
||||||
/// <reference path="./overrides.d.ts" />
|
/// <reference path="./bun.d.ts" />
|
||||||
|
/// <reference path="./extensions.d.ts" />
|
||||||
|
/// <reference path="./devserver.d.ts" />
|
||||||
/// <reference path="./ffi.d.ts" />
|
/// <reference path="./ffi.d.ts" />
|
||||||
/// <reference path="./test.d.ts" />
|
|
||||||
/// <reference path="./html-rewriter.d.ts" />
|
/// <reference path="./html-rewriter.d.ts" />
|
||||||
/// <reference path="./jsc.d.ts" />
|
/// <reference path="./jsc.d.ts" />
|
||||||
/// <reference path="./sqlite.d.ts" />
|
/// <reference path="./sqlite.d.ts" />
|
||||||
|
/// <reference path="./test.d.ts" />
|
||||||
/// <reference path="./wasm.d.ts" />
|
/// <reference path="./wasm.d.ts" />
|
||||||
|
/// <reference path="./overrides.d.ts" />
|
||||||
/// <reference path="./deprecated.d.ts" />
|
/// <reference path="./deprecated.d.ts" />
|
||||||
/// <reference path="./ambient.d.ts" />
|
|
||||||
/// <reference path="./devserver.d.ts" />
|
/// <reference path="./bun.ns.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;
|
||||||
|
|||||||
71
packages/bun-types/overrides.d.ts
vendored
71
packages/bun-types/overrides.d.ts
vendored
@@ -1,18 +1,71 @@
|
|||||||
export {};
|
export {};
|
||||||
|
|
||||||
import type { BunFile, Env, PathLike } from "bun";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace NodeJS {
|
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<string> {
|
interface ProcessVersions extends Dict<string> {
|
||||||
bun: string;
|
bun: string;
|
||||||
}
|
}
|
||||||
interface ProcessEnv extends Env {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "fs/promises" {
|
declare module "fs/promises" {
|
||||||
function exists(path: PathLike): Promise<boolean>;
|
function exists(path: Bun.PathLike): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "tls" {
|
declare module "tls" {
|
||||||
@@ -22,7 +75,7 @@ declare module "tls" {
|
|||||||
* the well-known CAs curated by Mozilla. Mozilla's CAs are completely
|
* the well-known CAs curated by Mozilla. Mozilla's CAs are completely
|
||||||
* replaced when CAs are explicitly specified using this option.
|
* replaced when CAs are explicitly specified using this option.
|
||||||
*/
|
*/
|
||||||
ca?: string | Buffer | NodeJS.TypedArray | BunFile | Array<string | Buffer | BunFile> | undefined;
|
ca?: string | Buffer | NodeJS.TypedArray | Bun.BunFile | Array<string | Buffer | Bun.BunFile> | undefined;
|
||||||
/**
|
/**
|
||||||
* Cert chains in PEM format. One cert chain should be provided per
|
* Cert chains in PEM format. One cert chain should be provided per
|
||||||
* private key. Each cert chain should consist of the PEM formatted
|
* private key. Each cert chain should consist of the PEM formatted
|
||||||
@@ -38,8 +91,8 @@ declare module "tls" {
|
|||||||
| string
|
| string
|
||||||
| Buffer
|
| Buffer
|
||||||
| NodeJS.TypedArray
|
| NodeJS.TypedArray
|
||||||
| BunFile
|
| Bun.BunFile
|
||||||
| Array<string | Buffer | NodeJS.TypedArray | BunFile>
|
| Array<string | Buffer | NodeJS.TypedArray | Bun.BunFile>
|
||||||
| undefined;
|
| undefined;
|
||||||
/**
|
/**
|
||||||
* Private keys in PEM format. PEM allows the option of private keys
|
* Private keys in PEM format. PEM allows the option of private keys
|
||||||
@@ -54,9 +107,9 @@ declare module "tls" {
|
|||||||
key?:
|
key?:
|
||||||
| string
|
| string
|
||||||
| Buffer
|
| Buffer
|
||||||
| BunFile
|
| Bun.BunFile
|
||||||
| NodeJS.TypedArray
|
| NodeJS.TypedArray
|
||||||
| Array<string | Buffer | BunFile | NodeJS.TypedArray | KeyObject>
|
| Array<string | Buffer | Bun.BunFile | NodeJS.TypedArray | KeyObject>
|
||||||
| undefined;
|
| undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"version": "1.2.5",
|
||||||
"name": "bun-types",
|
"name": "bun-types",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"types": "./index.d.ts",
|
"types": "./index.d.ts",
|
||||||
@@ -9,14 +10,14 @@
|
|||||||
"directory": "packages/bun-types"
|
"directory": "packages/bun-types"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"*.d.ts",
|
"./*.d.ts",
|
||||||
"docs/**/*.md",
|
"docs/**/*.md",
|
||||||
"docs/*.md"
|
"docs/*.md"
|
||||||
],
|
],
|
||||||
"homepage": "https://bun.sh",
|
"homepage": "https://bun.sh",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/ws": "~8.5.10"
|
"@types/ws": "*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.5.3",
|
"@biomejs/biome": "^1.5.3",
|
||||||
@@ -27,7 +28,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "echo $(pwd)",
|
"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' {} +",
|
"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",
|
"test": "tsc",
|
||||||
"fmt": "echo $(which biome) && biome format --write ."
|
"fmt": "echo $(which biome) && biome format --write ."
|
||||||
},
|
},
|
||||||
|
|||||||
825
packages/bun-types/s3.d.ts
vendored
Normal file
825
packages/bun-types/s3.d.ts
vendored
Normal file
@@ -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<number>;
|
||||||
|
/**
|
||||||
|
* Close the file descriptor. This also flushes the internal buffer.
|
||||||
|
*/
|
||||||
|
end(error?: Error): number | Promise<number>;
|
||||||
|
|
||||||
|
start(options?: {
|
||||||
|
/**
|
||||||
|
* Preallocate an internal buffer of this size
|
||||||
|
* This can significantly improve performance when the chunk size is small
|
||||||
|
*/
|
||||||
|
highWaterMark?: number;
|
||||||
|
}): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For FIFOs & pipes, this lets you decide whether Bun's process should
|
||||||
|
* remain alive until the pipe is closed.
|
||||||
|
*
|
||||||
|
* By default, it is automatically managed. While the stream is open, the
|
||||||
|
* process remains alive and once the other end hangs up or the stream
|
||||||
|
* closes, the process exits.
|
||||||
|
*
|
||||||
|
* If you previously called {@link unref}, you can call this again to re-enable automatic management.
|
||||||
|
*
|
||||||
|
* Internally, it will reference count the number of times this is called. By default, that number is 1
|
||||||
|
*
|
||||||
|
* If the file is not a FIFO or pipe, {@link ref} and {@link unref} do
|
||||||
|
* nothing. If the pipe is already closed, this does nothing.
|
||||||
|
*/
|
||||||
|
ref(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For FIFOs & pipes, this lets you decide whether Bun's process should
|
||||||
|
* remain alive until the pipe is closed.
|
||||||
|
*
|
||||||
|
* If you want to allow Bun's process to terminate while the stream is open,
|
||||||
|
* call this.
|
||||||
|
*
|
||||||
|
* If the file is not a FIFO or pipe, {@link ref} and {@link unref} do
|
||||||
|
* nothing. If the pipe is already closed, this does nothing.
|
||||||
|
*/
|
||||||
|
unref(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface 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<number>;
|
||||||
|
/**
|
||||||
|
* Finish the upload. This also flushes the internal buffer.
|
||||||
|
*/
|
||||||
|
end(error?: Error): number | Promise<number>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the stat of the file.
|
||||||
|
*/
|
||||||
|
stat(): Promise<import("node:fs").Stats>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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://<account-id>.r2.cloudflarestorage.com"
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // DigitalOcean Spaces
|
||||||
|
* const file = s3("my-file.txt", {
|
||||||
|
* endpoint: "https://<region>.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<number>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<number>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<S3Stats>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<number>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<void>;
|
||||||
|
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<number>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<boolean>;
|
||||||
|
/**
|
||||||
|
* 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<S3Stats>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A default instance of S3Client
|
||||||
|
*
|
||||||
|
* Pulls credentials from environment variables. Use `new Bun.S3Client()` if you need to explicitly set credentials.
|
||||||
|
*/
|
||||||
|
var s3: S3Client;
|
||||||
|
}
|
||||||
13
packages/bun-types/test.d.ts
vendored
13
packages/bun-types/test.d.ts
vendored
@@ -149,6 +149,10 @@ declare module "bun:test" {
|
|||||||
methodOrPropertyValue: K,
|
methodOrPropertyValue: K,
|
||||||
): Mock<T[K] extends (...args: any[]) => any ? T[K] : never>;
|
): Mock<T[K] extends (...args: any[]) => any ? T[K] : never>;
|
||||||
|
|
||||||
|
interface FunctionLike {
|
||||||
|
readonly name: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a group of related tests.
|
* Describes a group of related tests.
|
||||||
*
|
*
|
||||||
@@ -165,10 +169,6 @@ declare module "bun:test" {
|
|||||||
* @param label the label for the tests
|
* @param label the label for the tests
|
||||||
* @param fn the function that defines the tests
|
* @param fn the function that defines the tests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface FunctionLike {
|
|
||||||
readonly name: string;
|
|
||||||
}
|
|
||||||
export interface Describe {
|
export interface Describe {
|
||||||
(fn: () => void): void;
|
(fn: () => void): void;
|
||||||
|
|
||||||
@@ -420,7 +420,6 @@ declare module "bun:test" {
|
|||||||
*
|
*
|
||||||
* @param label the label for the test
|
* @param label the label for the test
|
||||||
* @param fn the test function
|
* @param fn the test function
|
||||||
* @param options the test timeout or options
|
|
||||||
*/
|
*/
|
||||||
failing(label: string, fn?: (() => void | Promise<unknown>) | ((done: (err?: unknown) => void) => void)): void;
|
failing(label: string, fn?: (() => void | Promise<unknown>) | ((done: (err?: unknown) => void) => void)): void;
|
||||||
/**
|
/**
|
||||||
@@ -1778,10 +1777,6 @@ declare module "bun:test" {
|
|||||||
type MatcherContext = MatcherUtils & MatcherState;
|
type MatcherContext = MatcherUtils & MatcherState;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "test" {
|
|
||||||
export type * from "bun:test";
|
|
||||||
}
|
|
||||||
|
|
||||||
declare namespace JestMock {
|
declare namespace JestMock {
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
|||||||
115
packages/bun-types/wasm.d.ts
vendored
115
packages/bun-types/wasm.d.ts
vendored
@@ -1,67 +1,7 @@
|
|||||||
export {};
|
declare module "bun" {
|
||||||
|
|
||||||
type _Global<T extends Bun.WebAssembly.ValueType = Bun.WebAssembly.ValueType> = typeof globalThis extends {
|
|
||||||
onerror: any;
|
|
||||||
WebAssembly: { Global: infer T };
|
|
||||||
}
|
|
||||||
? T
|
|
||||||
: Bun.WebAssembly.Global<T>;
|
|
||||||
|
|
||||||
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 {
|
namespace WebAssembly {
|
||||||
type ImportExportKind = "function" | "global" | "memory" | "table";
|
type ImportExportKind = "function" | "global" | "memory" | "table";
|
||||||
type TableKind = "anyfunc" | "externref";
|
type TableKind = "anyfunc" | "externref";
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
||||||
type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table;
|
type ExportValue = Function | Global | WebAssembly.Memory | WebAssembly.Table;
|
||||||
type Exports = Record<string, ExportValue>;
|
type Exports = Record<string, ExportValue>;
|
||||||
type ImportValue = ExportValue | number;
|
type ImportValue = ExportValue | number;
|
||||||
@@ -69,7 +9,6 @@ declare global {
|
|||||||
type ModuleImports = Record<string, ImportValue>;
|
type ModuleImports = Record<string, ImportValue>;
|
||||||
|
|
||||||
interface ValueTypeMap {
|
interface ValueTypeMap {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
||||||
anyfunc: Function;
|
anyfunc: Function;
|
||||||
externref: any;
|
externref: any;
|
||||||
f32: number;
|
f32: number;
|
||||||
@@ -159,7 +98,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace WebAssembly {
|
declare namespace WebAssembly {
|
||||||
interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {}
|
interface ValueTypeMap extends Bun.WebAssembly.ValueTypeMap {}
|
||||||
interface GlobalDescriptor<T extends keyof ValueTypeMap = keyof ValueTypeMap>
|
interface GlobalDescriptor<T extends keyof ValueTypeMap = keyof ValueTypeMap>
|
||||||
extends Bun.WebAssembly.GlobalDescriptor<T> {}
|
extends Bun.WebAssembly.GlobalDescriptor<T> {}
|
||||||
@@ -169,39 +108,29 @@ declare global {
|
|||||||
interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {}
|
interface TableDescriptor extends Bun.WebAssembly.TableDescriptor {}
|
||||||
interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {}
|
interface WebAssemblyInstantiatedSource extends Bun.WebAssembly.WebAssemblyInstantiatedSource {}
|
||||||
|
|
||||||
interface LinkError extends _LinkError {}
|
interface LinkError extends Bun.WebAssembly.LinkError {}
|
||||||
var LinkError: {
|
var LinkError: {
|
||||||
prototype: LinkError;
|
prototype: LinkError;
|
||||||
new (message?: string): LinkError;
|
new (message?: string): LinkError;
|
||||||
(message?: string): LinkError;
|
(message?: string): LinkError;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CompileError extends _CompileError {}
|
interface CompileError extends Bun.WebAssembly.CompileError {}
|
||||||
var CompileError: typeof globalThis extends {
|
var CompileError: {
|
||||||
onerror: any;
|
|
||||||
WebAssembly: { CompileError: infer T };
|
|
||||||
}
|
|
||||||
? T
|
|
||||||
: {
|
|
||||||
prototype: CompileError;
|
prototype: CompileError;
|
||||||
new (message?: string): CompileError;
|
new (message?: string): CompileError;
|
||||||
(message?: string): CompileError;
|
(message?: string): CompileError;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface RuntimeError extends _RuntimeError {}
|
interface RuntimeError extends Bun.WebAssembly.RuntimeError {}
|
||||||
var RuntimeError: {
|
var RuntimeError: {
|
||||||
prototype: RuntimeError;
|
prototype: RuntimeError;
|
||||||
new (message?: string): RuntimeError;
|
new (message?: string): RuntimeError;
|
||||||
(message?: string): RuntimeError;
|
(message?: string): RuntimeError;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Global<T extends keyof ValueTypeMap = keyof ValueTypeMap> extends _Global<T> {}
|
interface Global<T extends keyof ValueTypeMap = keyof ValueTypeMap> extends Bun.WebAssembly.Global<T> {}
|
||||||
var Global: typeof globalThis extends {
|
var Global: {
|
||||||
onerror: any;
|
|
||||||
WebAssembly: { Global: infer T };
|
|
||||||
}
|
|
||||||
? T
|
|
||||||
: {
|
|
||||||
prototype: Global;
|
prototype: Global;
|
||||||
new <T extends Bun.WebAssembly.ValueType = Bun.WebAssembly.ValueType>(
|
new <T extends Bun.WebAssembly.ValueType = Bun.WebAssembly.ValueType>(
|
||||||
descriptor: GlobalDescriptor<T>,
|
descriptor: GlobalDescriptor<T>,
|
||||||
@@ -209,30 +138,23 @@ declare global {
|
|||||||
): Global<T>;
|
): Global<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Instance extends _Instance {}
|
interface Instance extends Bun.WebAssembly.Instance {}
|
||||||
var Instance: typeof globalThis extends {
|
var Instance: {
|
||||||
onerror: any;
|
|
||||||
WebAssembly: { Instance: infer T };
|
|
||||||
}
|
|
||||||
? T
|
|
||||||
: {
|
|
||||||
prototype: Instance;
|
prototype: Instance;
|
||||||
new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance;
|
new (module: Module, importObject?: Bun.WebAssembly.Imports): Instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Memory extends _Memory {}
|
interface Memory extends Bun.WebAssembly.Memory {}
|
||||||
var Memory: {
|
var Memory: {
|
||||||
prototype: Memory;
|
prototype: Memory;
|
||||||
new (descriptor: MemoryDescriptor): Memory;
|
new (descriptor: MemoryDescriptor): Memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Module extends _Module {}
|
interface Module extends Bun.WebAssembly.Module {}
|
||||||
var Module: typeof globalThis extends {
|
var Module: Bun.__internal.UseLibDomIfAvailable<
|
||||||
onerror: any;
|
"WebAssembly",
|
||||||
WebAssembly: { Module: infer T };
|
{
|
||||||
}
|
Module: {
|
||||||
? T
|
|
||||||
: {
|
|
||||||
prototype: Module;
|
prototype: Module;
|
||||||
new (bytes: Bun.BufferSource): Module;
|
new (bytes: Bun.BufferSource): Module;
|
||||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */
|
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */
|
||||||
@@ -242,8 +164,10 @@ declare global {
|
|||||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */
|
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */
|
||||||
imports(moduleObject: Module): ModuleImportDescriptor[];
|
imports(moduleObject: Module): ModuleImportDescriptor[];
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
>["Module"];
|
||||||
|
|
||||||
interface Table extends _Table {}
|
interface Table extends Bun.WebAssembly.Table {}
|
||||||
var Table: {
|
var Table: {
|
||||||
prototype: Table;
|
prototype: Table;
|
||||||
new (descriptor: TableDescriptor, value?: any): Table;
|
new (descriptor: TableDescriptor, value?: any): Table;
|
||||||
@@ -267,4 +191,3 @@ declare global {
|
|||||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */
|
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate) */
|
||||||
function validate(bytes: Bun.BufferSource): boolean;
|
function validate(bytes: Bun.BufferSource): boolean;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// Environment setup & latest features
|
// Environment setup & latest features
|
||||||
"lib": ["esnext"],
|
"lib": ["ESNext"],
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export function createBunShellTemplateFunction(createShellInterpreter, createPar
|
|||||||
stdout: Buffer;
|
stdout: Buffer;
|
||||||
stderr: Buffer;
|
stderr: Buffer;
|
||||||
exitCode: number;
|
exitCode: number;
|
||||||
|
|
||||||
constructor(stdout: Buffer, stderr: Buffer, exitCode: number) {
|
constructor(stdout: Buffer, stderr: Buffer, exitCode: number) {
|
||||||
this.stdout = stdout;
|
this.stdout = stdout;
|
||||||
this.stderr = stderr;
|
this.stderr = stderr;
|
||||||
|
|||||||
@@ -1,18 +1,31 @@
|
|||||||
import { fileURLToPath, $ as Shell, ShellError } from "bun";
|
import { fileURLToPath, $ as Shell } from "bun";
|
||||||
import { beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test";
|
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
||||||
|
import { cp, mkdtemp, rm } from "node:fs/promises";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
const BUN_REPO_ROOT = fileURLToPath(import.meta.resolve("../../../"));
|
const BUN_REPO_ROOT = fileURLToPath(import.meta.resolve("../../../"));
|
||||||
const BUN_TYPES_PACKAGE_ROOT = join(BUN_REPO_ROOT, "packages", "bun-types");
|
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 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_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 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 () => {
|
beforeAll(async () => {
|
||||||
|
TEMP_DIR = await mkdtemp(join(tmpdir(), "bun-types-test-"));
|
||||||
|
FIXTURE_DIR = join(TEMP_DIR, "fixture");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await $`mkdir -p ${FIXTURE_DIR}`;
|
||||||
|
|
||||||
|
await cp(FIXTURE_SOURCE_DIR, FIXTURE_DIR, { recursive: true });
|
||||||
|
|
||||||
await $`
|
await $`
|
||||||
cd ${BUN_TYPES_PACKAGE_ROOT}
|
cd ${BUN_TYPES_PACKAGE_ROOT}
|
||||||
bun install
|
bun install
|
||||||
@@ -36,13 +49,12 @@ beforeAll(async () => {
|
|||||||
mv package.json.backup package.json
|
mv package.json.backup package.json
|
||||||
|
|
||||||
cd ${FIXTURE_DIR}
|
cd ${FIXTURE_DIR}
|
||||||
cp ${TSCONFIG_SOURCE_PATH} tsconfig.json
|
bun uninstall @types/bun || true
|
||||||
bun uninstall @types/bun
|
|
||||||
bun add @types/bun@${BUN_TYPES_TARBALL_NAME}
|
bun add @types/bun@${BUN_TYPES_TARBALL_NAME}
|
||||||
rm ${BUN_TYPES_TARBALL_NAME}
|
rm ${BUN_TYPES_TARBALL_NAME}
|
||||||
`;
|
`;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ShellError) {
|
if (e instanceof Bun.$.ShellError) {
|
||||||
console.log(e.stderr.toString());
|
console.log(e.stderr.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,12 +62,23 @@ beforeAll(async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeEach(async () => {
|
||||||
setDefaultTimeout(1000 * 60 * 5);
|
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", () => {
|
describe("@types/bun integration test", () => {
|
||||||
test("it typechecks successfully", async () => {
|
test("checks without lib.dom.d.ts", async () => {
|
||||||
const p = await $`
|
const p = await $`
|
||||||
cd ${FIXTURE_DIR}
|
cd ${FIXTURE_DIR}
|
||||||
bun run check
|
bun run check
|
||||||
@@ -63,4 +86,40 @@ describe("@types/bun integration test", () => {
|
|||||||
|
|
||||||
expect(p.exitCode).toBe(0);
|
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<Uint8Array<ArrayBuffer>, 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<Uint8Array<ArrayBufferLike>>', 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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
node_modules
|
|
||||||
# generated by test
|
|
||||||
tsconfig.json
|
|
||||||
@@ -5,20 +5,18 @@
|
|||||||
"name": "fixture",
|
"name": "fixture",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/bun": "types-bun-1.2.6.tgz",
|
"@types/bun": "types-bun-1.2.6.tgz",
|
||||||
},
|
"typescript": "^5.8.2",
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5.0.0",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages": {
|
"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/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=="],
|
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,70 @@
|
|||||||
import svgpath from "cool.svg";
|
import svgpath from "cool.svg";
|
||||||
svgpath satisfies `${string}.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<T> = 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<Bun.WebAssembly.Global>;
|
||||||
|
WebAssembly.Memory satisfies ConstructorOf<Bun.WebAssembly.Memory>;
|
||||||
|
|
||||||
|
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
|
// just some APIs
|
||||||
new Request("url");
|
new Request("url");
|
||||||
new Response();
|
new Response();
|
||||||
@@ -15,7 +79,24 @@ new TransformStream();
|
|||||||
new AbortSignal();
|
new AbortSignal();
|
||||||
new AbortController();
|
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();
|
new Bun.$.ShellError();
|
||||||
|
|
||||||
@@ -56,13 +137,13 @@ Bun.serve({
|
|||||||
},
|
},
|
||||||
|
|
||||||
fetch: (req, server) => {
|
fetch: (req, server) => {
|
||||||
return new Response("upgraded");
|
return new Response("cool");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Bun.serve({
|
Bun.serve({
|
||||||
fetch: (req, server) => {
|
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 Map();
|
||||||
new Set();
|
new Set();
|
||||||
new WeakMap();
|
new WeakMap();
|
||||||
@@ -91,6 +204,37 @@ new Map();
|
|||||||
new Set();
|
new Set();
|
||||||
new WeakMap();
|
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<string>;
|
||||||
|
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 statuses = [200, 400, 401, 403, 404, 500, 501, 502, 503, 504];
|
||||||
|
|
||||||
const r = new Request("", {
|
const r = new Request("", {
|
||||||
@@ -100,6 +244,9 @@ const r = new Request("", {
|
|||||||
await fetch(r);
|
await fetch(r);
|
||||||
await fetch("", {
|
await fetch("", {
|
||||||
tls: {
|
tls: {
|
||||||
|
key: Bun.file("key.pem"),
|
||||||
|
cert: Bun.file("cert.pem"),
|
||||||
|
ca: [Bun.file("ca.pem")],
|
||||||
rejectUnauthorized: false,
|
rejectUnauthorized: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -108,6 +255,7 @@ r.method;
|
|||||||
r.body;
|
r.body;
|
||||||
r.headers.get("content-type");
|
r.headers.get("content-type");
|
||||||
|
|
||||||
|
new Request("", {});
|
||||||
new Bun.$.ShellError() instanceof Bun.$.ShellError;
|
new Bun.$.ShellError() instanceof Bun.$.ShellError;
|
||||||
|
|
||||||
await r.json();
|
await r.json();
|
||||||
@@ -120,6 +268,10 @@ const req1 = new Request("", {
|
|||||||
body: "",
|
body: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const header of new Headers()) {
|
||||||
|
console.log(header);
|
||||||
|
}
|
||||||
|
|
||||||
fetch("", {
|
fetch("", {
|
||||||
tls: {
|
tls: {
|
||||||
rejectUnauthorized: false,
|
rejectUnauthorized: false,
|
||||||
@@ -142,52 +294,153 @@ req1.headers;
|
|||||||
req1.headers.toJSON();
|
req1.headers.toJSON();
|
||||||
|
|
||||||
new ReadableStream({});
|
new ReadableStream({});
|
||||||
|
new ReadableStream({
|
||||||
|
type: "direct",
|
||||||
|
async pull(controller) {
|
||||||
|
controller.write(new TextEncoder().encode("Hello, world!"));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const body = await fetch(req1);
|
const body = await fetch(req1);
|
||||||
|
|
||||||
|
Bun.fetch satisfies typeof fetch;
|
||||||
|
Bun.fetch.preconnect satisfies typeof fetch.preconnect;
|
||||||
|
|
||||||
await body.text();
|
await body.text();
|
||||||
|
|
||||||
|
fetch;
|
||||||
|
|
||||||
fetch.preconnect(new URL(""));
|
fetch.preconnect(new URL(""));
|
||||||
|
|
||||||
Bun.serve({
|
Bun.serve({
|
||||||
port: 3000,
|
port: 3000,
|
||||||
fetch: () => new Response("ok"),
|
fetch: () => new Response("ok"),
|
||||||
|
|
||||||
key: Bun.file(""),
|
// don't do this, use the `tls: {}` options instead
|
||||||
cert: Bun.file(""),
|
key: Bun.file(""), // dont do it!
|
||||||
|
cert: Bun.file(""), // dont do it!
|
||||||
|
|
||||||
tls: {
|
tls: {
|
||||||
key: Bun.file(""),
|
key: Bun.file(""), // do this!
|
||||||
cert: Bun.file(""),
|
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.canParse;
|
||||||
URL.createObjectURL;
|
URL.createObjectURL;
|
||||||
URL.revokeObjectURL;
|
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.redirect("bun.sh", 300);
|
||||||
Response.error();
|
Response.error();
|
||||||
|
Response.redirect("bun.sh", 302);
|
||||||
Response.redirect("bun.sh", {
|
Response.redirect("bun.sh", {
|
||||||
status: 200,
|
headers: {
|
||||||
headers: new Headers(
|
"x-bun": "is cool",
|
||||||
(() => {
|
},
|
||||||
const h = new Headers();
|
|
||||||
h.set("key", "value");
|
|
||||||
h.toJSON();
|
|
||||||
return h;
|
|
||||||
})(),
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Bun.fetch.preconnect;
|
Bun.inspect.custom;
|
||||||
|
Bun.inspect;
|
||||||
|
|
||||||
|
fetch.preconnect("bun.sh");
|
||||||
|
Bun.fetch.preconnect("bun.sh");
|
||||||
|
|
||||||
|
new Uint8Array().toBase64();
|
||||||
|
|
||||||
Bun.fetch("", {
|
Bun.fetch("", {
|
||||||
proxy: "",
|
proxy: "",
|
||||||
s3: {},
|
s3: {
|
||||||
|
acl: "public-read",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
new HTMLRewriter()
|
||||||
|
.on("script", {
|
||||||
|
element(element) {
|
||||||
|
console.log(element.getAttribute("src"));
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.transform(new Blob(['<script src="/main.js"></script>']));
|
||||||
|
|
||||||
|
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({
|
Bun.serve({
|
||||||
fetch(req) {
|
fetch(req) {
|
||||||
req.headers;
|
req.headers;
|
||||||
@@ -202,15 +455,22 @@ Bun.serve({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
import.meta.hot.accept();
|
||||||
import.meta.hot.data;
|
import.meta.hot.data;
|
||||||
|
|
||||||
import { serve } from "bun";
|
fetch("", {
|
||||||
|
tls: {
|
||||||
new Worker("").on("message", (e: MessageEvent<string>) => {
|
rejectUnauthorized: false,
|
||||||
e;
|
},
|
||||||
e.data satisfies string;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
new AbortController();
|
||||||
|
const myAbortController: AbortController = new AbortController();
|
||||||
|
new AbortSignal();
|
||||||
|
const myAbortSignal: AbortSignal = new AbortSignal();
|
||||||
|
|
||||||
|
import { serve } from "bun";
|
||||||
|
|
||||||
new Worker("", {
|
new Worker("", {
|
||||||
type: "module",
|
type: "module",
|
||||||
preload: ["preload.ts"],
|
preload: ["preload.ts"],
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "fixture",
|
"name": "fixture",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5.0.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"check": "tsc --noEmit"
|
"check": "tsc --noEmit -p ./tsconfig.json"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/bun": "types-bun-1.2.6.tgz"
|
"@types/bun": "types-bun-1.2.6.tgz",
|
||||||
|
"typescript": "latest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
"emitDecoratorMetadata": true
|
"emitDecoratorMetadata": true
|
||||||
},
|
},
|
||||||
"references": [
|
"references": [
|
||||||
//
|
|
||||||
{ "path": "./src" },
|
{ "path": "./src" },
|
||||||
{ "path": "./src/bake" },
|
{ "path": "./src/bake" },
|
||||||
{ "path": "./src/js" },
|
{ "path": "./src/js" },
|
||||||
|
|||||||
Reference in New Issue
Block a user