bun-types 1.1.45-canary.20250119T140626 → 1.1.45-canary.20250121T140608
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.d.ts +53 -14
- package/docs/api/fetch.md +1 -1
- package/docs/api/spawn.md +1 -1
- package/docs/api/sql.md +571 -0
- package/docs/bundler/fullstack.md +48 -1
- package/docs/bundler/index.md +2 -65
- package/docs/cli/publish.md +1 -1
- package/docs/runtime/debugger.md +3 -3
- package/docs/runtime/nodejs-apis.md +4 -5
- package/docs/test/dom.md +1 -1
- package/package.json +2 -2
package/bun.d.ts
CHANGED
|
@@ -2061,7 +2061,7 @@ declare module "bun" {
|
|
|
2061
2061
|
/** Database server port number */
|
|
2062
2062
|
port: number | string;
|
|
2063
2063
|
/** Database user for authentication */
|
|
2064
|
-
|
|
2064
|
+
username: string;
|
|
2065
2065
|
/** Database password for authentication */
|
|
2066
2066
|
password: string;
|
|
2067
2067
|
/** Name of the database to connect to */
|
|
@@ -2082,6 +2082,8 @@ declare module "bun" {
|
|
|
2082
2082
|
onclose: (client: SQL) => void;
|
|
2083
2083
|
/** Maximum number of connections in the pool */
|
|
2084
2084
|
max: number;
|
|
2085
|
+
/** By default values outside i32 range are returned as strings. If this is true, values outside i32 range are returned as BigInts. */
|
|
2086
|
+
bigint: boolean;
|
|
2085
2087
|
};
|
|
2086
2088
|
|
|
2087
2089
|
/**
|
|
@@ -2107,9 +2109,16 @@ declare module "bun" {
|
|
|
2107
2109
|
* Callback function type for transaction contexts
|
|
2108
2110
|
* @param sql Function to execute SQL queries within the transaction
|
|
2109
2111
|
*/
|
|
2110
|
-
type
|
|
2111
|
-
sql:
|
|
2112
|
-
) => Promise<any>;
|
|
2112
|
+
type SQLTransactionContextCallback = (
|
|
2113
|
+
sql: TransactionSQL,
|
|
2114
|
+
) => Promise<any> | Array<SQLQuery>;
|
|
2115
|
+
/**
|
|
2116
|
+
* Callback function type for savepoint contexts
|
|
2117
|
+
* @param sql Function to execute SQL queries within the savepoint
|
|
2118
|
+
*/
|
|
2119
|
+
type SQLSavepointContextCallback = (
|
|
2120
|
+
sql: SavepointSQL,
|
|
2121
|
+
) => Promise<any> | Array<SQLQuery>;
|
|
2113
2122
|
|
|
2114
2123
|
/**
|
|
2115
2124
|
* Main SQL client interface providing connection and transaction management
|
|
@@ -2135,7 +2144,13 @@ declare module "bun" {
|
|
|
2135
2144
|
* @example
|
|
2136
2145
|
* const [user] = await sql`select * from users where id = ${1}`;
|
|
2137
2146
|
*/
|
|
2138
|
-
(strings: string, ...values: any[]): SQLQuery;
|
|
2147
|
+
(strings: string | TemplateStringsArray, ...values: any[]): SQLQuery;
|
|
2148
|
+
/**
|
|
2149
|
+
* Helper function to allow easy use to insert values into a query
|
|
2150
|
+
* @example
|
|
2151
|
+
* const result = await sql`insert into users ${sql(users)} RETURNING *`;
|
|
2152
|
+
*/
|
|
2153
|
+
(obj: any): SQLQuery;
|
|
2139
2154
|
/** Commits a distributed transaction also know as prepared transaction in postgres or XA transaction in MySQL
|
|
2140
2155
|
* @example
|
|
2141
2156
|
* await sql.commitDistributed("my_distributed_transaction");
|
|
@@ -2151,12 +2166,12 @@ declare module "bun" {
|
|
|
2151
2166
|
* await sql.connect();
|
|
2152
2167
|
*/
|
|
2153
2168
|
connect(): Promise<SQL>;
|
|
2154
|
-
/** Closes the database connection with optional timeout in seconds
|
|
2169
|
+
/** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing.
|
|
2155
2170
|
* @example
|
|
2156
2171
|
* await sql.close({ timeout: 1 });
|
|
2157
2172
|
*/
|
|
2158
2173
|
close(options?: { timeout?: number }): Promise<undefined>;
|
|
2159
|
-
/** Closes the database connection with optional timeout in seconds
|
|
2174
|
+
/** Closes the database connection with optional timeout in seconds. If timeout is 0, it will close immediately, if is not provided it will wait for all queries to finish before closing.
|
|
2160
2175
|
* @alias close
|
|
2161
2176
|
* @example
|
|
2162
2177
|
* await sql.end({ timeout: 1 });
|
|
@@ -2210,7 +2225,7 @@ declare module "bun" {
|
|
|
2210
2225
|
* return [user, account]
|
|
2211
2226
|
* })
|
|
2212
2227
|
*/
|
|
2213
|
-
begin(fn:
|
|
2228
|
+
begin(fn: SQLTransactionContextCallback): Promise<any>;
|
|
2214
2229
|
/** Begins a new transaction with options
|
|
2215
2230
|
* Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.begin will resolve with the returned value from the callback function.
|
|
2216
2231
|
* BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue.
|
|
@@ -2235,7 +2250,7 @@ declare module "bun" {
|
|
|
2235
2250
|
* return [user, account]
|
|
2236
2251
|
* })
|
|
2237
2252
|
*/
|
|
2238
|
-
begin(options: string, fn:
|
|
2253
|
+
begin(options: string, fn: SQLTransactionContextCallback): Promise<any>;
|
|
2239
2254
|
/** Alternative method to begin a transaction
|
|
2240
2255
|
* Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function.
|
|
2241
2256
|
* BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue.
|
|
@@ -2261,7 +2276,7 @@ declare module "bun" {
|
|
|
2261
2276
|
* return [user, account]
|
|
2262
2277
|
* })
|
|
2263
2278
|
*/
|
|
2264
|
-
transaction(fn:
|
|
2279
|
+
transaction(fn: SQLTransactionContextCallback): Promise<any>;
|
|
2265
2280
|
/** Alternative method to begin a transaction with options
|
|
2266
2281
|
* Will reserve a connection for the transaction and supply a scoped sql instance for all transaction uses in the callback function. sql.transaction will resolve with the returned value from the callback function.
|
|
2267
2282
|
* BEGIN is automatically sent with the optional options, and if anything fails ROLLBACK will be called so the connection can be released and execution can continue.
|
|
@@ -2287,7 +2302,10 @@ declare module "bun" {
|
|
|
2287
2302
|
* return [user, account]
|
|
2288
2303
|
* })
|
|
2289
2304
|
*/
|
|
2290
|
-
transaction(
|
|
2305
|
+
transaction(
|
|
2306
|
+
options: string,
|
|
2307
|
+
fn: SQLTransactionContextCallback,
|
|
2308
|
+
): Promise<any>;
|
|
2291
2309
|
/** Begins a distributed transaction
|
|
2292
2310
|
* Also know as Two-Phase Commit, in a distributed transaction, Phase 1 involves the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes committing or rolling back based on the coordinator's decision, ensuring durability and releasing locks.
|
|
2293
2311
|
* In PostgreSQL and MySQL distributed transactions persist beyond the original session, allowing privileged users or coordinators to commit/rollback them, ensuring support for distributed transactions, recovery, and administrative tasks.
|
|
@@ -2303,13 +2321,26 @@ declare module "bun" {
|
|
|
2303
2321
|
* await sql.commitDistributed("numbers");
|
|
2304
2322
|
* // or await sql.rollbackDistributed("numbers");
|
|
2305
2323
|
*/
|
|
2306
|
-
beginDistributed(
|
|
2324
|
+
beginDistributed(
|
|
2325
|
+
name: string,
|
|
2326
|
+
fn: SQLTransactionContextCallback,
|
|
2327
|
+
): Promise<any>;
|
|
2307
2328
|
/** Alternative method to begin a distributed transaction
|
|
2308
2329
|
* @alias beginDistributed
|
|
2309
2330
|
*/
|
|
2310
|
-
distributed(name: string, fn:
|
|
2331
|
+
distributed(name: string, fn: SQLTransactionContextCallback): Promise<any>;
|
|
2332
|
+
/**If you know what you're doing, you can use unsafe to pass any string you'd like.
|
|
2333
|
+
* Please note that this can lead to SQL injection if you're not careful.
|
|
2334
|
+
* You can also nest sql.unsafe within a safe sql expression. This is useful if only part of your fraction has unsafe elements.
|
|
2335
|
+
* @example
|
|
2336
|
+
* const result = await sql.unsafe(`select ${danger} from users where id = ${dragons}`)
|
|
2337
|
+
*/
|
|
2338
|
+
unsafe(string: string, values?: any[]): SQLQuery;
|
|
2339
|
+
|
|
2311
2340
|
/** Current client options */
|
|
2312
2341
|
options: SQLOptions;
|
|
2342
|
+
|
|
2343
|
+
[Symbol.asyncDispose](): Promise<any>;
|
|
2313
2344
|
}
|
|
2314
2345
|
|
|
2315
2346
|
/**
|
|
@@ -2319,6 +2350,7 @@ declare module "bun" {
|
|
|
2319
2350
|
interface ReservedSQL extends SQL {
|
|
2320
2351
|
/** Releases the client back to the connection pool */
|
|
2321
2352
|
release(): void;
|
|
2353
|
+
[Symbol.dispose](): void;
|
|
2322
2354
|
}
|
|
2323
2355
|
|
|
2324
2356
|
/**
|
|
@@ -2327,10 +2359,17 @@ declare module "bun" {
|
|
|
2327
2359
|
*/
|
|
2328
2360
|
interface TransactionSQL extends SQL {
|
|
2329
2361
|
/** Creates a savepoint within the current transaction */
|
|
2330
|
-
savepoint(name: string, fn:
|
|
2362
|
+
savepoint(name: string, fn: SQLSavepointContextCallback): Promise<any>;
|
|
2363
|
+
savepoint(fn: SQLSavepointContextCallback): Promise<any>;
|
|
2331
2364
|
}
|
|
2365
|
+
/**
|
|
2366
|
+
* Represents a savepoint within a transaction
|
|
2367
|
+
*/
|
|
2368
|
+
interface SavepointSQL extends SQL {}
|
|
2332
2369
|
|
|
2333
2370
|
var sql: SQL;
|
|
2371
|
+
var postgres: SQL;
|
|
2372
|
+
var SQL: SQL;
|
|
2334
2373
|
|
|
2335
2374
|
/**
|
|
2336
2375
|
* This lets you use macros as regular imports
|
package/docs/api/fetch.md
CHANGED
|
@@ -195,7 +195,7 @@ This will print the request and response headers to your terminal:
|
|
|
195
195
|
```sh
|
|
196
196
|
[fetch] > HTTP/1.1 GET http://example.com/
|
|
197
197
|
[fetch] > Connection: keep-alive
|
|
198
|
-
[fetch] > User-Agent: Bun/1.1.45-canary.
|
|
198
|
+
[fetch] > User-Agent: Bun/1.1.45-canary.20250121T140608
|
|
199
199
|
[fetch] > Accept: */*
|
|
200
200
|
[fetch] > Host: example.com
|
|
201
201
|
[fetch] > Accept-Encoding: gzip, deflate, br
|
package/docs/api/spawn.md
CHANGED
|
@@ -110,7 +110,7 @@ You can read results from the subprocess via the `stdout` and `stderr` propertie
|
|
|
110
110
|
```ts
|
|
111
111
|
const proc = Bun.spawn(["bun", "--version"]);
|
|
112
112
|
const text = await new Response(proc.stdout).text();
|
|
113
|
-
console.log(text); // => "1.1.45-canary.
|
|
113
|
+
console.log(text); // => "1.1.45-canary.20250121T140608"
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
Configure the output stream by passing one of the following values to `stdout/stderr`:
|
package/docs/api/sql.md
ADDED
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
Bun provides native bindings for working with PostgreSQL databases with a modern, Promise-based API. The interface is designed to be simple and performant, using tagged template literals for queries and offering features like connection pooling, transactions, and prepared statements.
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
import { sql } from "bun";
|
|
5
|
+
|
|
6
|
+
const users = await sql`
|
|
7
|
+
SELECT * FROM users
|
|
8
|
+
WHERE active = ${true}
|
|
9
|
+
LIMIT ${10}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
// Select with multiple conditions
|
|
13
|
+
const activeUsers = await sql`
|
|
14
|
+
SELECT *
|
|
15
|
+
FROM users
|
|
16
|
+
WHERE active = ${true}
|
|
17
|
+
AND age >= ${18}
|
|
18
|
+
`;
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
{% features title="Features" %}
|
|
22
|
+
|
|
23
|
+
{% icon size=20 name="Shield" /%} Tagged template literals to protect againt SQL injection
|
|
24
|
+
|
|
25
|
+
{% icon size=20 name="GitMerge" /%} Transactions
|
|
26
|
+
|
|
27
|
+
{% icon size=20 name="Variable" /%} Named & positional parameters
|
|
28
|
+
|
|
29
|
+
{% icon size=20 name="Network" /%} Connection pooling
|
|
30
|
+
|
|
31
|
+
{% icon size=20 name="Binary" /%} `BigInt` support
|
|
32
|
+
|
|
33
|
+
{% icon size=20 name="Key" /%} SASL Auth support (SCRAM-SHA-256), MD5, and Clear Text
|
|
34
|
+
|
|
35
|
+
{% icon size=20 name="Timer" /%} Connection timeouts
|
|
36
|
+
|
|
37
|
+
{% icon size=20 name="Database" /%} Returning rows as data objects, arrays of arrays, or `Buffer`
|
|
38
|
+
|
|
39
|
+
{% icon size=20 name="Code" /%} Binary protocol support makes it faster
|
|
40
|
+
|
|
41
|
+
{% icon size=20 name="Lock" /%} TLS support (and auth mode)
|
|
42
|
+
|
|
43
|
+
{% icon size=20 name="Settings" /%} Automatic configuration with environment variable
|
|
44
|
+
|
|
45
|
+
{% /features %}
|
|
46
|
+
|
|
47
|
+
### Inserting data
|
|
48
|
+
|
|
49
|
+
You can pass JavaScript values directly to the SQL template literal and escaping will be handled for you.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { sql } from "bun";
|
|
53
|
+
|
|
54
|
+
// Basic insert with direct values
|
|
55
|
+
const [user] = await sql`
|
|
56
|
+
INSERT INTO users (name, email)
|
|
57
|
+
VALUES (${name}, ${email})
|
|
58
|
+
RETURNING *
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
// Using object helper for cleaner syntax
|
|
62
|
+
const userData = {
|
|
63
|
+
name: "Alice",
|
|
64
|
+
email: "alice@example.com",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const [newUser] = await sql`
|
|
68
|
+
INSERT INTO users ${sql(userData)}
|
|
69
|
+
RETURNING *
|
|
70
|
+
`;
|
|
71
|
+
// Expands to: INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Bulk Insert
|
|
75
|
+
|
|
76
|
+
You can also pass arrays of objects to the SQL template literal and it will be expanded to a `INSERT INTO ... VALUES ...` statement.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const users = [
|
|
80
|
+
{ name: "Alice", email: "alice@example.com" },
|
|
81
|
+
{ name: "Bob", email: "bob@example.com" },
|
|
82
|
+
{ name: "Charlie", email: "charlie@example.com" },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
await sql`INSERT INTO users ${sql(users)}`;
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Picking columns to insert
|
|
89
|
+
|
|
90
|
+
You can use `sql(object, Array<string>)` to pick which columns to insert. Each of the columns must be defined on the object.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
const user = {
|
|
94
|
+
name: "Alice",
|
|
95
|
+
email: "alice@example.com",
|
|
96
|
+
age: 25,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
await sql`INSERT INTO users ${sql(user, ["name", "email"])}`;
|
|
100
|
+
// Only inserts name and email columns, ignoring other fields
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Query Results
|
|
104
|
+
|
|
105
|
+
By default, Bun's SQL client returns query results as arrays of objects, where each object represents a row with column names as keys. However, there are cases where you might want the data in a different format. The client provides two additional methods for this purpose.
|
|
106
|
+
|
|
107
|
+
### `sql``.values()` format
|
|
108
|
+
|
|
109
|
+
The `sql``.values()` method returns rows as arrays of values rather than objects. Each row becomes an array where the values are in the same order as the columns in your query.
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
const rows = await sql`SELECT * FROM users`.values();
|
|
113
|
+
console.log(rows);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This returns something like:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
[
|
|
120
|
+
["Alice", "alice@example.com"],
|
|
121
|
+
["Bob", "bob@example.com"],
|
|
122
|
+
];
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`sql``.values()` is especially useful if duplicate column names are returned in the query results. When using objects (the default), the last column name is used as the key in the object, which means duplicate column names overwrite each other — but when using `sql``.values()`, each column is present in the array so you can access the values of duplicate columns by index.
|
|
126
|
+
|
|
127
|
+
### `sql``.raw()` format
|
|
128
|
+
|
|
129
|
+
The `.raw()` method returns rows as arrays of `Buffer` objects. This can be useful for working with binary data or for performance reasons.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const rows = await sql`SELECT * FROM users`.raw();
|
|
133
|
+
console.log(rows); // [[Buffer, Buffer], [Buffer, Buffer], [Buffer, Buffer]]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## SQL Fragments
|
|
137
|
+
|
|
138
|
+
A common need in database applications is the ability to construct queries dynamically based on runtime conditions. Bun provides safe ways to do this without risking SQL injection.
|
|
139
|
+
|
|
140
|
+
### Dynamic Table Names
|
|
141
|
+
|
|
142
|
+
When you need to reference tables or schemas dynamically, use the `sql()` helper to ensure proper escaping:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
// Safely reference tables dynamically
|
|
146
|
+
await sql`SELECT * FROM ${sql("users")}`;
|
|
147
|
+
|
|
148
|
+
// With schema qualification
|
|
149
|
+
await sql`SELECT * FROM ${sql("public.users")}`;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Conditional Queries
|
|
153
|
+
|
|
154
|
+
You can use the `sql()` helper to build queries with conditional clauses. This allows you to create flexible queries that adapt to your application's needs:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
// Optional WHERE clauses
|
|
158
|
+
const filterAge = true;
|
|
159
|
+
const minAge = 21;
|
|
160
|
+
const ageFilter = sql`AND age > ${minAge}`;
|
|
161
|
+
await sql`
|
|
162
|
+
SELECT * FROM users
|
|
163
|
+
WHERE active = ${true}
|
|
164
|
+
${filterAge ? ageFilter : sql``}
|
|
165
|
+
`;
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Unsafe Queries
|
|
169
|
+
|
|
170
|
+
You can use the `sql.unsafe` function to execute raw SQL strings. Use this with caution, as it will not escape user input.
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
const result = await sql.unsafe(
|
|
174
|
+
"SELECT " + columns + " FROM users WHERE id = " + id,
|
|
175
|
+
);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### What is SQL Injection?
|
|
179
|
+
|
|
180
|
+
{% image href="https://xkcd.com/327/" src="https://imgs.xkcd.com/comics/exploits_of_a_mom.png" /%}
|
|
181
|
+
|
|
182
|
+
### Execute and Cancelling Queries
|
|
183
|
+
|
|
184
|
+
Bun's SQL is lazy that means its will only start executing when awaited or executed with `.execute()`.
|
|
185
|
+
You can cancel a query that is currently executing by calling the `cancel()` method on the query object.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
const query = await sql`SELECT * FROM users`.execute();
|
|
189
|
+
setTimeout(() => query.cancel(), 100);
|
|
190
|
+
await query;
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Database Environment Variables
|
|
194
|
+
|
|
195
|
+
`sql` connection parameters can be configured using environment variables. The client checks these variables in a specific order of precedence.
|
|
196
|
+
|
|
197
|
+
The following environment variables can be used to define the connection URL:
|
|
198
|
+
|
|
199
|
+
| Environment Variable | Description |
|
|
200
|
+
| --------------------------- | ------------------------------------------ |
|
|
201
|
+
| `POSTGRES_URL` | Primary connection URL for PostgreSQL |
|
|
202
|
+
| `DATABASE_URL` | Alternative connection URL |
|
|
203
|
+
| `PGURL` | Alternative connection URL |
|
|
204
|
+
| `PG_URL` | Alternative connection URL |
|
|
205
|
+
| `TLS_POSTGRES_DATABASE_URL` | SSL/TLS-enabled connection URL |
|
|
206
|
+
| `TLS_DATABASE_URL` | Alternative SSL/TLS-enabled connection URL |
|
|
207
|
+
|
|
208
|
+
If no connection URL is provided, the system checks for the following individual parameters:
|
|
209
|
+
|
|
210
|
+
| Environment Variable | Fallback Variables | Default Value | Description |
|
|
211
|
+
| -------------------- | ---------------------------- | ------------- | ----------------- |
|
|
212
|
+
| `PGHOST` | - | `localhost` | Database host |
|
|
213
|
+
| `PGPORT` | - | `5432` | Database port |
|
|
214
|
+
| `PGUSERNAME` | `PGUSER`, `USER`, `USERNAME` | `postgres` | Database user |
|
|
215
|
+
| `PGPASSWORD` | - | (empty) | Database password |
|
|
216
|
+
| `PGDATABASE` | - | username | Database name |
|
|
217
|
+
|
|
218
|
+
## Connection Options
|
|
219
|
+
|
|
220
|
+
You can configure your database connection manually by passing options to the SQL constructor:
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
import { SQL } from "bun";
|
|
224
|
+
|
|
225
|
+
const db = new SQL({
|
|
226
|
+
// Required
|
|
227
|
+
url: "postgres://user:pass@localhost:5432/dbname",
|
|
228
|
+
|
|
229
|
+
// Optional configuration
|
|
230
|
+
hostname: "localhost",
|
|
231
|
+
port: 5432,
|
|
232
|
+
database: "myapp",
|
|
233
|
+
username: "dbuser",
|
|
234
|
+
password: "secretpass",
|
|
235
|
+
|
|
236
|
+
// Connection pool settings
|
|
237
|
+
max: 20, // Maximum connections in pool
|
|
238
|
+
idleTimeout: 30, // Close idle connections after 30s
|
|
239
|
+
maxLifetime: 0, // Connection lifetime in seconds (0 = forever)
|
|
240
|
+
connectionTimeout: 30, // Timeout when establishing new connections
|
|
241
|
+
|
|
242
|
+
// SSL/TLS options
|
|
243
|
+
tls: true,
|
|
244
|
+
// tls: {
|
|
245
|
+
// rejectUnauthorized: true,
|
|
246
|
+
// requestCert: true,
|
|
247
|
+
// ca: "path/to/ca.pem",
|
|
248
|
+
// key: "path/to/key.pem",
|
|
249
|
+
// cert: "path/to/cert.pem",
|
|
250
|
+
// checkServerIdentity(hostname, cert) {
|
|
251
|
+
// ...
|
|
252
|
+
// },
|
|
253
|
+
// },
|
|
254
|
+
|
|
255
|
+
// Callbacks
|
|
256
|
+
onconnect: client => {
|
|
257
|
+
console.log("Connected to database");
|
|
258
|
+
},
|
|
259
|
+
onclose: client => {
|
|
260
|
+
console.log("Connection closed");
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Transactions
|
|
266
|
+
|
|
267
|
+
To start a new transaction, use `sql.begin`. This method reserves a dedicated connection for the duration of the transaction and provides a scoped `sql` instance to use within the callback function. Once the callback completes, `sql.begin` resolves with the return value of the callback.
|
|
268
|
+
|
|
269
|
+
The `BEGIN` command is sent automatically, including any optional configurations you specify. If an error occurs during the transaction, a `ROLLBACK` is triggered to release the reserved connection and ensure the process continues smoothly.
|
|
270
|
+
|
|
271
|
+
### Basic Transactions
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
await sql.begin(async tx => {
|
|
275
|
+
// All queries in this function run in a transaction
|
|
276
|
+
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
|
|
277
|
+
await tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = 1`;
|
|
278
|
+
|
|
279
|
+
// Transaction automatically commits if no errors are thrown
|
|
280
|
+
// Rolls back if any error occurs
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
It's also possible to pipeline the requests in a transaction if needed by returning an array with queries from the callback function like this:
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
await sql.begin(async tx => {
|
|
288
|
+
return [
|
|
289
|
+
tx`INSERT INTO users (name) VALUES (${"Alice"})`,
|
|
290
|
+
tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = 1`,
|
|
291
|
+
];
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Savepoints
|
|
296
|
+
|
|
297
|
+
Savepoints in SQL create intermediate checkpoints within a transaction, enabling partial rollbacks without affecting the entire operation. They are useful in complex transactions, allowing error recovery and maintaining consistent results.
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
await sql.begin(async tx => {
|
|
301
|
+
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
|
|
302
|
+
|
|
303
|
+
await tx.savepoint(async sp => {
|
|
304
|
+
// This part can be rolled back separately
|
|
305
|
+
await sp`UPDATE users SET status = 'active'`;
|
|
306
|
+
if (someCondition) {
|
|
307
|
+
throw new Error("Rollback to savepoint");
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Continue with transaction even if savepoint rolled back
|
|
312
|
+
await tx`INSERT INTO audit_log (action) VALUES ('user_created')`;
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Distributed Transactions
|
|
317
|
+
|
|
318
|
+
Two-Phase Commit (2PC) is a distributed transaction protocol where Phase 1 has the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes either committing or rolling back based on the coordinator's decision. This process ensures data durability and proper lock management.
|
|
319
|
+
|
|
320
|
+
In PostgreSQL and MySQL, distributed transactions persist beyond their original session, allowing privileged users or coordinators to commit or rollback them later. This supports robust distributed transactions, recovery processes, and administrative operations.
|
|
321
|
+
|
|
322
|
+
Each database system implements distributed transactions differently:
|
|
323
|
+
|
|
324
|
+
PostgreSQL natively supports them through prepared transactions, while MySQL uses XA Transactions.
|
|
325
|
+
|
|
326
|
+
If any exceptions occur during the distributed transaction and aren't caught, the system will automatically rollback all changes. When everything proceeds normally, you maintain the flexibility to either commit or rollback the transaction later.
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
// Begin a distributed transaction
|
|
330
|
+
await sql.beginDistributed("tx1", async tx => {
|
|
331
|
+
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Later, commit or rollback
|
|
335
|
+
await sql.commitDistributed("tx1");
|
|
336
|
+
// or
|
|
337
|
+
await sql.rollbackDistributed("tx1");
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Authentication
|
|
341
|
+
|
|
342
|
+
Bun supports SCRAM-SHA-256 (SASL), MD5, and Clear Text authentication. SASL is recommended for better security. Check [Postgres SASL Authentication](https://www.postgresql.org/docs/current/sasl-authentication.html) for more information.
|
|
343
|
+
|
|
344
|
+
### SSL Modes Overview
|
|
345
|
+
|
|
346
|
+
PostgreSQL supports different SSL/TLS modes to control how secure connections are established. These modes determine the behavior when connecting and the level of certificate verification performed.
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
const sql = new SQL({
|
|
350
|
+
hostname: "localhost",
|
|
351
|
+
username: "user",
|
|
352
|
+
password: "password",
|
|
353
|
+
ssl: "disable", // | "prefer" | "require" | "verify-ca" | "verify-full"
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
| SSL Mode | Description |
|
|
358
|
+
| ------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
359
|
+
| `disable` | No SSL/TLS used. Connections fail if server requires SSL. |
|
|
360
|
+
| `prefer` | Tries SSL first, falls back to non-SSL if SSL fails. Default mode if none specified. |
|
|
361
|
+
| `require` | Requires SSL without certificate verification. Fails if SSL cannot be established. |
|
|
362
|
+
| `verify-ca` | Verifies server certificate is signed by trusted CA. Fails if verification fails. |
|
|
363
|
+
| `verify-full` | Most secure mode. Verifies certificate and hostname match. Protects against untrusted certificates and MITM attacks. |
|
|
364
|
+
|
|
365
|
+
### Using With Connection Strings
|
|
366
|
+
|
|
367
|
+
The SSL mode can also be specified in connection strings:
|
|
368
|
+
|
|
369
|
+
```ts
|
|
370
|
+
// Using prefer mode
|
|
371
|
+
const sql = new SQL("postgres://user:password@localhost/mydb?sslmode=prefer");
|
|
372
|
+
|
|
373
|
+
// Using verify-full mode
|
|
374
|
+
const sql = new SQL(
|
|
375
|
+
"postgres://user:password@localhost/mydb?sslmode=verify-full",
|
|
376
|
+
);
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Connection Pooling
|
|
380
|
+
|
|
381
|
+
Bun's SQL client automatically manages a connection pool, which is a pool of database connections that are reused for multiple queries. This helps to reduce the overhead of establishing and closing connections for each query, and it also helps to manage the number of concurrent connections to the database.
|
|
382
|
+
|
|
383
|
+
```ts
|
|
384
|
+
const db = new SQL({
|
|
385
|
+
// Pool configuration
|
|
386
|
+
max: 20, // Maximum 20 concurrent connections
|
|
387
|
+
idleTimeout: 30, // Close idle connections after 30s
|
|
388
|
+
maxLifetime: 3600, // Max connection lifetime 1 hour
|
|
389
|
+
connectionTimeout: 10, // Connection timeout 10s
|
|
390
|
+
});
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
No connection will be made until a query is made.
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
const sql = Bun.sql(); // no connection are created
|
|
397
|
+
|
|
398
|
+
await sql`...`; // pool is started until max is reached (if possible), first available connection is used
|
|
399
|
+
await sql`...`; // previous connection is reused
|
|
400
|
+
|
|
401
|
+
// two connections are used now at the same time
|
|
402
|
+
await Promise.all([
|
|
403
|
+
sql`INSERT INTO users ${sql({ name: "Alice" })}`,
|
|
404
|
+
sql`UPDATE users SET name = ${user.name} WHERE id = ${user.id}`,
|
|
405
|
+
]);
|
|
406
|
+
|
|
407
|
+
await sql.close(); // await all queries to finish and close all connections from the pool
|
|
408
|
+
await sql.close({ timeout: 5 }); // wait 5 seconds and close all connections from the pool
|
|
409
|
+
await sql.close({ timeout: 0 }); // close all connections from the pool immediately
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Reserved Connections
|
|
413
|
+
|
|
414
|
+
Bun enables you to reserve a connection from the pool, and returns a client that wraps the single connection. This can be used for running queries on an isolated connection.
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
// Get exclusive connection from pool
|
|
418
|
+
const reserved = await sql.reserve();
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
await reserved`INSERT INTO users (name) VALUES (${"Alice"})`;
|
|
422
|
+
} finally {
|
|
423
|
+
// Important: Release connection back to pool
|
|
424
|
+
reserved.release();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Or using Symbol.dispose
|
|
428
|
+
{
|
|
429
|
+
using reserved = await sql.reserve();
|
|
430
|
+
await reserved`SELECT 1`;
|
|
431
|
+
} // Automatically released
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## Error Handling
|
|
435
|
+
|
|
436
|
+
The client provides typed errors for different failure scenarios:
|
|
437
|
+
|
|
438
|
+
### Connection Errors
|
|
439
|
+
|
|
440
|
+
| Connection Errors | Description |
|
|
441
|
+
| --------------------------------- | ---------------------------------------------------- |
|
|
442
|
+
| `ERR_POSTGRES_CONNECTION_CLOSED` | Connection was terminated or never established |
|
|
443
|
+
| `ERR_POSTGRES_CONNECTION_TIMEOUT` | Failed to establish connection within timeout period |
|
|
444
|
+
| `ERR_POSTGRES_IDLE_TIMEOUT` | Connection closed due to inactivity |
|
|
445
|
+
| `ERR_POSTGRES_LIFETIME_TIMEOUT` | Connection exceeded maximum lifetime |
|
|
446
|
+
| `ERR_POSTGRES_TLS_NOT_AVAILABLE` | SSL/TLS connection not available |
|
|
447
|
+
| `ERR_POSTGRES_TLS_UPGRADE_FAILED` | Failed to upgrade connection to SSL/TLS |
|
|
448
|
+
|
|
449
|
+
### Authentication Errors
|
|
450
|
+
|
|
451
|
+
| Authentication Errors | Description |
|
|
452
|
+
| ------------------------------------------------ | ---------------------------------------- |
|
|
453
|
+
| `ERR_POSTGRES_AUTHENTICATION_FAILED_PBKDF2` | Password authentication failed |
|
|
454
|
+
| `ERR_POSTGRES_UNKNOWN_AUTHENTICATION_METHOD` | Server requested unknown auth method |
|
|
455
|
+
| `ERR_POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD` | Server requested unsupported auth method |
|
|
456
|
+
| `ERR_POSTGRES_INVALID_SERVER_KEY` | Invalid server key during authentication |
|
|
457
|
+
| `ERR_POSTGRES_INVALID_SERVER_SIGNATURE` | Invalid server signature |
|
|
458
|
+
| `ERR_POSTGRES_SASL_SIGNATURE_INVALID_BASE64` | Invalid SASL signature encoding |
|
|
459
|
+
| `ERR_POSTGRES_SASL_SIGNATURE_MISMATCH` | SASL signature verification failed |
|
|
460
|
+
|
|
461
|
+
### Query Errors
|
|
462
|
+
|
|
463
|
+
| Query Errors | Description |
|
|
464
|
+
| ------------------------------------ | ------------------------------------------ |
|
|
465
|
+
| `ERR_POSTGRES_SYNTAX_ERROR` | Invalid SQL syntax (extends `SyntaxError`) |
|
|
466
|
+
| `ERR_POSTGRES_SERVER_ERROR` | General error from PostgreSQL server |
|
|
467
|
+
| `ERR_POSTGRES_INVALID_QUERY_BINDING` | Invalid parameter binding |
|
|
468
|
+
| `ERR_POSTGRES_QUERY_CANCELLED` | Query was cancelled |
|
|
469
|
+
|
|
470
|
+
### Data Type Errors
|
|
471
|
+
|
|
472
|
+
| Data Type Errors | Description |
|
|
473
|
+
| ------------------------------------------------------- | ------------------------------------- |
|
|
474
|
+
| `ERR_POSTGRES_INVALID_BINARY_DATA` | Invalid binary data format |
|
|
475
|
+
| `ERR_POSTGRES_INVALID_BYTE_SEQUENCE` | Invalid byte sequence |
|
|
476
|
+
| `ERR_POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING` | Encoding error |
|
|
477
|
+
| `ERR_POSTGRES_INVALID_CHARACTER` | Invalid character in data |
|
|
478
|
+
| `ERR_POSTGRES_OVERFLOW` | Numeric overflow |
|
|
479
|
+
| `ERR_POSTGRES_UNSUPPORTED_BYTEA_FORMAT` | Unsupported binary format |
|
|
480
|
+
| `ERR_POSTGRES_UNSUPPORTED_INTEGER_SIZE` | Integer size not supported |
|
|
481
|
+
| `ERR_POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET` | Multidimensional arrays not supported |
|
|
482
|
+
| `ERR_POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET` | NULL values in arrays not supported |
|
|
483
|
+
|
|
484
|
+
### Protocol Errors
|
|
485
|
+
|
|
486
|
+
| Protocol Errors | Description |
|
|
487
|
+
| --------------------------------------- | --------------------------- |
|
|
488
|
+
| `ERR_POSTGRES_EXPECTED_REQUEST` | Expected client request |
|
|
489
|
+
| `ERR_POSTGRES_EXPECTED_STATEMENT` | Expected prepared statement |
|
|
490
|
+
| `ERR_POSTGRES_INVALID_BACKEND_KEY_DATA` | Invalid backend key data |
|
|
491
|
+
| `ERR_POSTGRES_INVALID_MESSAGE` | Invalid protocol message |
|
|
492
|
+
| `ERR_POSTGRES_INVALID_MESSAGE_LENGTH` | Invalid message length |
|
|
493
|
+
| `ERR_POSTGRES_UNEXPECTED_MESSAGE` | Unexpected message type |
|
|
494
|
+
|
|
495
|
+
### Transaction Errors
|
|
496
|
+
|
|
497
|
+
| Transaction Errors | Description |
|
|
498
|
+
| ---------------------------------------- | ------------------------------------- |
|
|
499
|
+
| `ERR_POSTGRES_UNSAFE_TRANSACTION` | Unsafe transaction operation detected |
|
|
500
|
+
| `ERR_POSTGRES_INVALID_TRANSACTION_STATE` | Invalid transaction state |
|
|
501
|
+
|
|
502
|
+
## Numbers and BigInt
|
|
503
|
+
|
|
504
|
+
Bun's SQL client includes special handling for large numbers that exceed the range of a 53-bit integer. Here’s how it works:
|
|
505
|
+
|
|
506
|
+
```ts
|
|
507
|
+
import { sql } from "bun";
|
|
508
|
+
|
|
509
|
+
const [{ x, y }] = await sql`SELECT 9223372036854777 as x, 12345 as y`;
|
|
510
|
+
|
|
511
|
+
console.log(typeof x, x); // "string" "9223372036854777"
|
|
512
|
+
console.log(typeof y, y); // "number" 12345
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
## BigInt Instead of Strings
|
|
516
|
+
|
|
517
|
+
If you need large numbers as BigInt instead of strings, you can enable this by setting the `bigint` option to `true` when initializing the SQL client:
|
|
518
|
+
|
|
519
|
+
```ts
|
|
520
|
+
const sql = new SQL({
|
|
521
|
+
bigint: true,
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
const [{ x }] = await sql`SELECT 9223372036854777 as x`;
|
|
525
|
+
|
|
526
|
+
console.log(typeof x, x); // "bigint" 9223372036854777n
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## Roadmap
|
|
530
|
+
|
|
531
|
+
There's still some things we haven't finished yet.
|
|
532
|
+
|
|
533
|
+
- Connection preloading via `--db-preconnect` Bun CLI flag
|
|
534
|
+
- MySQL support: [we're working on it](https://github.com/oven-sh/bun/pull/15274)
|
|
535
|
+
- SQLite support: planned, but not started. Ideally, we implement it natively instead of wrapping `bun:sqlite`.
|
|
536
|
+
- Column name transforms (e.g. `snake_case` to `camelCase`). This is mostly blocked on a unicode-aware implementation of changing the case in C++ using WebKit's `WTF::String`.
|
|
537
|
+
- Column type transforms
|
|
538
|
+
|
|
539
|
+
### Postgres-specific features
|
|
540
|
+
|
|
541
|
+
We haven't implemented these yet:
|
|
542
|
+
|
|
543
|
+
- `COPY` support
|
|
544
|
+
- `LISTEN` support
|
|
545
|
+
- `NOTIFY` support
|
|
546
|
+
|
|
547
|
+
We also haven't implemented some of the more uncommon features like:
|
|
548
|
+
|
|
549
|
+
- GSSAPI authentication
|
|
550
|
+
- `SCRAM-SHA-256-PLUS` support
|
|
551
|
+
- Point & PostGIS types
|
|
552
|
+
- All the multi-dimensional integer array types (only a couple of the types are supported)
|
|
553
|
+
|
|
554
|
+
## Frequently Asked Questions
|
|
555
|
+
|
|
556
|
+
> Why is this `Bun.sql` and not `Bun.postgres`?
|
|
557
|
+
|
|
558
|
+
The plan is to add more database drivers in the future.
|
|
559
|
+
|
|
560
|
+
> Why not just use an existing library?
|
|
561
|
+
|
|
562
|
+
npm packages like postgres.js, pg, and node-postgres can be used in Bun too. They're great options.
|
|
563
|
+
|
|
564
|
+
Two reaons why:
|
|
565
|
+
|
|
566
|
+
1. We think it's simpler for developers to have a database driver built into Bun. The time you spend library shopping is time you could be building your app.
|
|
567
|
+
2. We leverage some JavaScriptCore engine internals to make it faster to create objects that would be difficult to implement in a library
|
|
568
|
+
|
|
569
|
+
## Credits
|
|
570
|
+
|
|
571
|
+
Huge thanks to [@porsager](https://github.com/porsager)'s [postgres.js](https://github.com/porsager/postgres) for the inspiration for the API interface.
|
|
@@ -198,6 +198,54 @@ When serving your app in production, set `development: false` in `Bun.serve()`.
|
|
|
198
198
|
- Enables `Cache-Control` headers and `ETag` headers
|
|
199
199
|
- Minifies JavaScript/TypeScript/TSX/JSX files
|
|
200
200
|
|
|
201
|
+
## Plugins
|
|
202
|
+
|
|
203
|
+
Bun's [bundler plugins](https://bun.sh/docs/bundler/plugins) are also supported when bundling static routes.
|
|
204
|
+
|
|
205
|
+
To configure plugins for `Bun.serve`, add a `plugins` array in the `[serve.static]` section of your `bunfig.toml`.
|
|
206
|
+
|
|
207
|
+
### Using TailwindCSS in HTML routes
|
|
208
|
+
|
|
209
|
+
For example, enable TailwindCSS on your routes by adding add the `bun-plugin-tailwind` plugin:
|
|
210
|
+
|
|
211
|
+
```toml
|
|
212
|
+
[serve.static]
|
|
213
|
+
plugins = ["bun-plugin-tailwind"]
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
This will allow you to use TailwindCSS utility classes in your HTML and CSS files. All you need to do is import `tailwindcss` somewhere:
|
|
218
|
+
|
|
219
|
+
```html
|
|
220
|
+
<!-- index.html -->
|
|
221
|
+
<!doctype html>
|
|
222
|
+
<html>
|
|
223
|
+
<head>
|
|
224
|
+
<title>Home</title>
|
|
225
|
+
<link rel="stylesheet" href="tailwindcss" />
|
|
226
|
+
</head>
|
|
227
|
+
<body>
|
|
228
|
+
<!-- the rest of your HTML... -->
|
|
229
|
+
</body>
|
|
230
|
+
</html>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Or in your CSS:
|
|
234
|
+
|
|
235
|
+
```css
|
|
236
|
+
/* style.css */
|
|
237
|
+
@import "tailwindcss";
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Any JS file or module which exports a [valid bundler plugin object](https://bun.sh/docs/bundler/plugins#usage) (essentially an object with a `name` and `setup` field) can be placed inside the `plugins` array:
|
|
241
|
+
|
|
242
|
+
```toml
|
|
243
|
+
[serve.static]
|
|
244
|
+
plugins = ["./my-plugin-implementation.ts"]
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Bun will lazily resolve and load each plugin and use them to bundle your routes.
|
|
248
|
+
|
|
201
249
|
## How this works
|
|
202
250
|
|
|
203
251
|
Bun uses [`HTMLRewriter`](/docs/api/html-rewriter) to scan for `<script>` and `<link>` tags in HTML files, uses them as entrypoints for [Bun's bundler](/docs/bundler), generates an optimized bundle for the JavaScript/TypeScript/TSX/JSX and CSS files, and serves the result.
|
|
@@ -244,4 +292,3 @@ This works similarly to how [`Bun.build` processes HTML files](/docs/bundler/htm
|
|
|
244
292
|
|
|
245
293
|
- Client-side hot reloading isn't wired up yet. It will be in the future.
|
|
246
294
|
- This doesn't support `bun build` yet. It also will in the future.
|
|
247
|
-
- We haven't figured out plugins yet. This probably will live in `bunfig.toml` with the same API as in `Bun.build` otherwise.
|
package/docs/bundler/index.md
CHANGED
|
@@ -1422,7 +1422,8 @@ Refer to [Bundler > Executables](https://bun.sh/docs/bundler/executables) for co
|
|
|
1422
1422
|
## Logs and errors
|
|
1423
1423
|
|
|
1424
1424
|
<!-- 1.2 documentation -->
|
|
1425
|
-
|
|
1425
|
+
|
|
1426
|
+
On failure, `Bun.build` returns a rejected promise with an `AggregateError`. This can be logged to the console for pretty printing of the error list, or programmatically read with a `try`/`catch` block.
|
|
1426
1427
|
|
|
1427
1428
|
```ts
|
|
1428
1429
|
try {
|
|
@@ -1482,70 +1483,6 @@ if (result.logs.length > 0) {
|
|
|
1482
1483
|
console.warn(message);
|
|
1483
1484
|
}
|
|
1484
1485
|
}
|
|
1485
|
-
``` -->
|
|
1486
|
-
|
|
1487
|
-
By default, `Bun.build` only throws if invalid options are provided. Read the `success` property to determine if the build was successful; the `logs` property will contain additional details.
|
|
1488
|
-
|
|
1489
|
-
```ts
|
|
1490
|
-
const result = await Bun.build({
|
|
1491
|
-
entrypoints: ["./index.tsx"],
|
|
1492
|
-
outdir: "./out",
|
|
1493
|
-
});
|
|
1494
|
-
|
|
1495
|
-
if (!result.success) {
|
|
1496
|
-
console.error("Build failed");
|
|
1497
|
-
for (const message of result.logs) {
|
|
1498
|
-
// Bun will pretty print the message object
|
|
1499
|
-
console.error(message);
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
```
|
|
1503
|
-
|
|
1504
|
-
Each message is either a `BuildMessage` or `ResolveMessage` object, which can be used to trace what problems happened in the build.
|
|
1505
|
-
|
|
1506
|
-
```ts
|
|
1507
|
-
class BuildMessage {
|
|
1508
|
-
name: string;
|
|
1509
|
-
position?: Position;
|
|
1510
|
-
message: string;
|
|
1511
|
-
level: "error" | "warning" | "info" | "debug" | "verbose";
|
|
1512
|
-
}
|
|
1513
|
-
|
|
1514
|
-
class ResolveMessage extends BuildMessage {
|
|
1515
|
-
code: string;
|
|
1516
|
-
referrer: string;
|
|
1517
|
-
specifier: string;
|
|
1518
|
-
importKind: ImportKind;
|
|
1519
|
-
}
|
|
1520
|
-
```
|
|
1521
|
-
|
|
1522
|
-
If you want to throw an error from a failed build, consider passing the logs to an `AggregateError`. If uncaught, Bun will pretty-print the contained messages nicely.
|
|
1523
|
-
|
|
1524
|
-
```ts
|
|
1525
|
-
if (!result.success) {
|
|
1526
|
-
throw new AggregateError(result.logs, "Build failed");
|
|
1527
|
-
}
|
|
1528
|
-
```
|
|
1529
|
-
|
|
1530
|
-
In Bun 1.2, throwing an aggregate error like this will become the default beahavior. You can opt-into it early using the `throw: true` option.
|
|
1531
|
-
|
|
1532
|
-
```ts
|
|
1533
|
-
try {
|
|
1534
|
-
const result = await Bun.build({
|
|
1535
|
-
entrypoints: ["./index.tsx"],
|
|
1536
|
-
outdir: "./out",
|
|
1537
|
-
});
|
|
1538
|
-
} catch (e) {
|
|
1539
|
-
// TypeScript does not allow annotations on the catch clause
|
|
1540
|
-
const error = e as AggregateError;
|
|
1541
|
-
console.error("Build Failed");
|
|
1542
|
-
|
|
1543
|
-
// Example: Using the built-in formatter
|
|
1544
|
-
console.error(error);
|
|
1545
|
-
|
|
1546
|
-
// Example: Serializing the failure as a JSON string.
|
|
1547
|
-
console.error(JSON.stringify(error, null, 2));
|
|
1548
|
-
}
|
|
1549
1486
|
```
|
|
1550
1487
|
|
|
1551
1488
|
## Reference
|
package/docs/cli/publish.md
CHANGED
package/docs/runtime/debugger.md
CHANGED
|
@@ -124,11 +124,11 @@ await fetch("https://example.com", {
|
|
|
124
124
|
This prints the `fetch` request as a single-line `curl` command to let you copy-paste into your terminal to replicate the request.
|
|
125
125
|
|
|
126
126
|
```sh
|
|
127
|
-
[fetch] $ curl --http1.1 "https://example.com/" -X POST -H "content-type: application/json" -H "Connection: keep-alive" -H "User-Agent: Bun/1.1.45-canary.
|
|
127
|
+
[fetch] $ curl --http1.1 "https://example.com/" -X POST -H "content-type: application/json" -H "Connection: keep-alive" -H "User-Agent: Bun/1.1.45-canary.20250121T140608" -H "Accept: */*" -H "Host: example.com" -H "Accept-Encoding: gzip, deflate, br" --compressed -H "Content-Length: 13" --data-raw "{\"foo\":\"bar\"}"
|
|
128
128
|
[fetch] > HTTP/1.1 POST https://example.com/
|
|
129
129
|
[fetch] > content-type: application/json
|
|
130
130
|
[fetch] > Connection: keep-alive
|
|
131
|
-
[fetch] > User-Agent: Bun/1.1.45-canary.
|
|
131
|
+
[fetch] > User-Agent: Bun/1.1.45-canary.20250121T140608
|
|
132
132
|
[fetch] > Accept: */*
|
|
133
133
|
[fetch] > Host: example.com
|
|
134
134
|
[fetch] > Accept-Encoding: gzip, deflate, br
|
|
@@ -170,7 +170,7 @@ This prints the following to the console:
|
|
|
170
170
|
[fetch] > HTTP/1.1 POST https://example.com/
|
|
171
171
|
[fetch] > content-type: application/json
|
|
172
172
|
[fetch] > Connection: keep-alive
|
|
173
|
-
[fetch] > User-Agent: Bun/1.1.45-canary.
|
|
173
|
+
[fetch] > User-Agent: Bun/1.1.45-canary.20250121T140608
|
|
174
174
|
[fetch] > Accept: */*
|
|
175
175
|
[fetch] > Host: example.com
|
|
176
176
|
[fetch] > Accept-Encoding: gzip, deflate, br
|
|
@@ -18,6 +18,10 @@ This page is updated regularly to reflect compatibility status of the latest ver
|
|
|
18
18
|
|
|
19
19
|
🟢 Fully implemented.
|
|
20
20
|
|
|
21
|
+
### [`node:dgram`](https://nodejs.org/api/dgram.html)
|
|
22
|
+
|
|
23
|
+
🟢 Fully implemented. > 90% of Node.js's test suite passes.
|
|
24
|
+
|
|
21
25
|
### [`node:diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html)
|
|
22
26
|
|
|
23
27
|
🟢 Fully implemented.
|
|
@@ -100,11 +104,6 @@ This page is updated regularly to reflect compatibility status of the latest ver
|
|
|
100
104
|
|
|
101
105
|
Some methods are not optimized yet.
|
|
102
106
|
|
|
103
|
-
### [`node:dgram`](https://nodejs.org/api/dgram.html)
|
|
104
|
-
|
|
105
|
-
🟡 Missing `setBroadcast` `setTTL` `setMulticastTTL` `setMulticastLoopback` `setMulticastInterface` `addMembership` `dropMembership`
|
|
106
|
-
`addSourceSpecificMembership` `dropSourceSpecificMembership`
|
|
107
|
-
|
|
108
107
|
### [`node:domain`](https://nodejs.org/api/domain.html)
|
|
109
108
|
|
|
110
109
|
🟡 Missing `Domain` `active`
|
package/docs/test/dom.md
CHANGED
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.45-canary.
|
|
2
|
+
"version": "1.1.45-canary.20250121T140608",
|
|
3
3
|
"name": "bun-types",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"files": ["*.d.ts", "docs/**/*.md", "docs/*.md"],
|
|
14
14
|
"homepage": "https://bun.sh",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@types/node": "
|
|
16
|
+
"@types/node": "*",
|
|
17
17
|
"@types/ws": "~8.5.10"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|