diff options
author | 2023-02-22 17:45:22 -0800 | |
---|---|---|
committer | 2023-02-22 17:45:22 -0800 | |
commit | 9f53a2210cac920c34c858d1fb408dbf9b8d8f94 (patch) | |
tree | baabceb3cb4db1d261746ecdba80cb040640fc05 | |
parent | 575291a301eb14f8452958d49b74148b97b89106 (diff) | |
download | bun-9f53a2210cac920c34c858d1fb408dbf9b8d8f94.tar.gz bun-9f53a2210cac920c34c858d1fb408dbf9b8d8f94.tar.zst bun-9f53a2210cac920c34c858d1fb408dbf9b8d8f94.zip |
Various type fixes (#2135)
* Simplify serve() types
* Remove baseURI
* Add Bun.serve type tests
* Number env vars
* Make loader optional
* FSRouter doesn't support URL
* Update sqlite types
* Bench
---------
Co-authored-by: Colin McDonnell <colinmcd@alum.mit.edu>
-rw-r--r-- | bench/ffi/bun.js | 3 | ||||
-rw-r--r-- | packages/bun-types/bun.d.ts | 106 | ||||
-rw-r--r-- | packages/bun-types/sqlite.d.ts | 37 | ||||
-rw-r--r-- | packages/bun-types/tests/serve.test-d.ts | 81 | ||||
-rw-r--r-- | packages/bun-types/tests/spawn.test-d.ts | 70 | ||||
-rw-r--r-- | packages/bun-types/tests/sqlite.test-d.ts | 28 | ||||
-rw-r--r-- | packages/bun-types/tests/tcp.test-d.ts | 4 |
7 files changed, 272 insertions, 57 deletions
diff --git a/bench/ffi/bun.js b/bench/ffi/bun.js index 593473929..6e83702ee 100644 --- a/bench/ffi/bun.js +++ b/bench/ffi/bun.js @@ -1,8 +1,7 @@ import { ptr, dlopen, CString, toBuffer } from "bun:ffi"; import { run, bench, group } from "mitata"; -const { napiNoop, napiHash, napiString } = require(import.meta.dir + - "/src/ffi_napi_bench.node"); +const { napiNoop, napiHash, napiString } = require(import.meta.dir + "/src/ffi_napi_bench.node"); const { symbols: { diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index a04ec91a0..8f020dcfc 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -52,6 +52,12 @@ declare module "bun" { options?: { PATH?: string; cwd?: string }, ): string; + export type Serve<WebSocketDataType = undefined> = + | ServeOptions + | TLSServeOptions + | WebSocketServeOptions<WebSocketDataType> + | TLSWebSocketServeOptions<WebSocketDataType>; + /** * Start a fast HTTP server. * @@ -88,8 +94,12 @@ declare module "bun" { * }); * ``` */ - export function serve<WebSocketDataType>( - options: Serve<WebSocketDataType>, + export function serve<T>( + options: + | ServeOptions + | TLSServeOptions + | WebSocketServeOptions<T> + | TLSWebSocketServeOptions<T>, ): Server; /** @@ -821,8 +831,9 @@ declare module "bun" { * ``` * */ + export class Transpiler { - constructor(options: TranspilerOptions); + constructor(options?: TranspilerOptions); /** * Transpile code from TypeScript or JSX into valid JavaScript. @@ -856,7 +867,7 @@ declare module "bun" { * @param code The code to transpile * */ - transformSync(code: StringOrBuffer, loader: JavaScriptLoader): string; + transformSync(code: StringOrBuffer, loader?: JavaScriptLoader): string; /** * Get a list of import paths and paths from a TypeScript, JSX, TSX, or JavaScript file. @@ -1439,7 +1450,7 @@ declare module "bun" { * "http://localhost:3000" * */ - baseURI?: string; + // baseURI?: string; /** * What is the maximum size of a request body? (in bytes) @@ -1527,6 +1538,9 @@ declare module "bun" { ): Response | undefined | Promise<Response | undefined>; } + export interface TLSWebSocketServeOptions<WebSocketDataType = undefined> + extends WebSocketServeOptions<WebSocketDataType>, + TLSOptions {} export interface Errorlike extends Error { code?: string; errno?: number; @@ -1547,8 +1561,18 @@ declare module "bun" { */ certFile: string; + /** + * Passphrase for the TLS key + */ passphrase?: string; + /** + * File path to a .pem file for a custom root CA + */ caFile?: string; + + /** + * File path to a .pem file custom Diffie Helman parameters + */ dhParamsFile?: string; /** @@ -1564,17 +1588,13 @@ declare module "bun" { lowMemoryMode?: boolean; } - export type TLSServeOptions<WebSocketDataType = undefined> = ( - | WebSocketServeOptions<WebSocketDataType> - | ServerWebSocket - ) & - TLSOptions & { - /** - * The keys are [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication) hostnames. - * The values are SSL options objects. - */ - serverNames: Record<string, TLSOptions>; - }; + export interface TLSServeOptions extends ServeOptions, TLSOptions { + /** + * The keys are [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication) hostnames. + * The values are SSL options objects. + */ + serverNames?: Record<string, TLSOptions>; + } /** * HTTP & HTTPS Server @@ -1754,11 +1774,6 @@ declare module "bun" { readonly development: boolean; } - export type Serve<WebSocketDataType = undefined> = - | TLSServeOptions<WebSocketDataType> - | WebSocketServeOptions<WebSocketDataType> - | ServeOptions; - /** * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. * @@ -2775,20 +2790,18 @@ declare module "bun" { readonly localPort: number; } - interface SocketListener<Options extends SocketOptions = SocketOptions> { + interface SocketListener<Data = undefined> { stop(closeActiveConnections?: boolean): void; ref(): void; unref(): void; - reload(options: Pick<Partial<Options>, "socket">): void; - data: Options["data"]; + reload(options: Pick<Partial<SocketOptions>, "socket">): void; + data: Data; } - interface TCPSocketListener<Options extends TCPSocketOptions<unknown>> - extends SocketListener<Options> { + interface TCPSocketListener<Data> extends SocketListener<Data> { readonly port: number; readonly hostname: string; } - interface UnixSocketListener<Options extends UnixSocketOptions<unknown>> - extends SocketListener<Options> { + interface UnixSocketListener<Data> extends SocketListener<Data> { readonly unix: string; } @@ -2808,7 +2821,7 @@ declare module "bun" { Data = unknown, DataBinaryType extends BinaryType = "buffer", > { - open(socket: Socket<Data>): void | Promise<void>; + open?(socket: Socket<Data>): void | Promise<void>; close?(socket: Socket<Data>): void | Promise<void>; error?(socket: Socket<Data>, error: Error): void | Promise<void>; data?( @@ -2839,6 +2852,10 @@ declare module "bun" { connectError?(socket: Socket<Data>, error: Error): void | Promise<void>; /** + * Called when a message times out. + */ + timeout?(socket: Socket<Data>): void | Promise<void>; + /** * Choose what `ArrayBufferView` is returned in the {@link SocketHandler.data} callback. * * @default "buffer" @@ -2858,12 +2875,25 @@ declare module "bun" { interface SocketOptions<Data = unknown> { socket: SocketHandler<Data>; - tls?: boolean | TLSOptions; data?: Data; } - interface TCPSocketOptions<Data = undefined> extends SocketOptions<Data> { + // interface TCPSocketOptions<Data = undefined> extends SocketOptions<Data> { + // hostname: string; + // port: number; + // } + + interface TCPSocketListenOptions<Data = undefined> + extends SocketOptions<Data> { hostname: string; port: number; + tls?: TLSOptions; + } + + interface TCPSocketConnectOptions<Data = undefined> + extends SocketOptions<Data> { + hostname: string; + port: number; + tls?: boolean; } interface UnixSocketOptions<Data = undefined> extends SocketOptions<Data> { @@ -2884,7 +2914,7 @@ declare module "bun" { * */ export function connect<Data = undefined>( - options: TCPSocketOptions<Data>, + options: TCPSocketConnectOptions<Data>, ): Promise<TCPSocketListener<typeof options>>; export function connect<Data = undefined>( options: UnixSocketOptions<Data>, @@ -2904,11 +2934,11 @@ declare module "bun" { * */ export function listen<Data = undefined>( - options: TCPSocketOptions<Data>, - ): TCPSocketListener<typeof options>; + options: TCPSocketListenOptions<Data>, + ): TCPSocketListener<Data>; export function listen<Data = undefined>( options: UnixSocketOptions<Data>, - ): UnixSocketListener<typeof options>; + ): UnixSocketListener<Data>; namespace SpawnOptions { type Readable = @@ -2951,7 +2981,7 @@ declare module "bun" { * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. * */ - env?: Record<string, string>; + env?: Record<string, string | number>; /** * The standard file descriptors of the process @@ -3117,11 +3147,11 @@ declare module "bun" { /** The base path to use when routing */ assetPrefix?: string; - origin?: string; }); - match(input: string | Request | Response | URL): MatchedRoute | null; + // todo: URL + match(input: string | Request | Response): MatchedRoute | null; readonly assetPrefix: string; readonly origin: string; diff --git a/packages/bun-types/sqlite.d.ts b/packages/bun-types/sqlite.d.ts index e908f0281..92acce170 100644 --- a/packages/bun-types/sqlite.d.ts +++ b/packages/bun-types/sqlite.d.ts @@ -165,14 +165,14 @@ declare module "bun:sqlite" { * | `bigint` | `INTEGER` | * | `null` | `NULL` | */ - run<ParamsType = SQLQueryBindings>( + run<ParamsType extends SQLQueryBindings[]>( sqlQuery: string, ...bindings: ParamsType[] ): void; /** This is an alias of {@link Database.prototype.run} */ - exec<ParamsType = SQLQueryBindings>( + exec<ParamsType extends SQLQueryBindings[]>( sqlQuery: string, ...bindings: ParamsType[] ): void; @@ -202,9 +202,12 @@ declare module "bun:sqlite" { * Under the hood, this calls `sqlite3_prepare_v3`. * */ - query<ParamsType = SQLQueryBindings, ReturnType = any>( + query<ReturnType, ParamsType extends SQLQueryBindings | SQLQueryBindings[]>( sqlQuery: string, - ): Statement<ParamsType, ReturnType>; + ): Statement< + ReturnType, + ParamsType extends Array<any> ? ParamsType : [ParamsType] + >; /** * Compile a SQL query and return a {@link Statement} object. @@ -227,10 +230,15 @@ declare module "bun:sqlite" { * Under the hood, this calls `sqlite3_prepare_v3`. * */ - prepare<ParamsType = SQLQueryBindings, ReturnType = any>( - sql: string, - ...params: ParamsType[] - ): Statement<ParamsType, ReturnType>; + prepare< + ReturnType, + ParamsType extends SQLQueryBindings | SQLQueryBindings[], + >( + sqlQuery: string, + ): Statement< + ReturnType, + ParamsType extends Array<any> ? ParamsType : [ParamsType] + >; /** * Is the database in a transaction? @@ -383,7 +391,10 @@ declare module "bun:sqlite" { * // => undefined * ``` */ - export class Statement<ParamsType = SQLQueryBindings, ReturnType = any> { + export class Statement< + ReturnType = unknown, + ParamsType extends SQLQueryBindings[] = any[], + > { /** * Creates a new prepared statement from native code. * @@ -410,7 +421,7 @@ declare module "bun:sqlite" { * // => [{bar: "foo"}] * ``` */ - all(...params: ParamsType[]): ReturnType[]; + all(...params: ParamsType): ReturnType[]; /** * Execute the prepared statement and return **the first** result. @@ -446,7 +457,7 @@ declare module "bun:sqlite" { * | `null` | `NULL` | * */ - get(...params: ParamsType[]): ReturnType | null; + get(...params: ParamsType): ReturnType | null; /** * Execute the prepared statement. This returns `undefined`. @@ -479,7 +490,7 @@ declare module "bun:sqlite" { * | `null` | `NULL` | * */ - run(...params: ParamsType[]): void; + run(...params: ParamsType): void; /** * Execute the prepared statement and return the results as an array of arrays. @@ -516,7 +527,7 @@ declare module "bun:sqlite" { * */ values( - ...params: ParamsType[] + ...params: ParamsType ): Array<Array<string | bigint | number | boolean | Uint8Array>>; /** diff --git a/packages/bun-types/tests/serve.test-d.ts b/packages/bun-types/tests/serve.test-d.ts new file mode 100644 index 000000000..67a450f7e --- /dev/null +++ b/packages/bun-types/tests/serve.test-d.ts @@ -0,0 +1,81 @@ +Bun.serve({ + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, +}); + +Bun.serve({ + fetch(req) { + console.log(req.url); // => http://localhost:3000/ + return new Response("Hello World"); + }, + keyFile: "ca.pem", + certFile: "cert.pem", +}); + +Bun.serve({ + websocket: { + message(ws, message) { + ws.send(message); + }, + }, + + fetch(req, server) { + // Upgrade to a ServerWebSocket if we can + // This automatically checks for the `Sec-WebSocket-Key` header + // meaning you don't have to check headers, you can just call `upgrade()` + if (server.upgrade(req)) + // When upgrading, we return undefined since we don't want to send a Response + return; + + return new Response("Regular HTTP response"); + }, +}); + +type User = { + name: string; +}; + +Bun.serve<User>({ + fetch(req, server) { + if (req.url === "/chat") { + if ( + server.upgrade(req, { + data: { + name: new URL(req.url).searchParams.get("name") || "Friend", + }, + headers: { + "Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"), + }, + }) + ) + return; + } + + return new Response("Expected a websocket connection", { status: 400 }); + }, + + websocket: { + open(ws) { + console.log("WebSocket opened"); + ws.subscribe("the-group-chat"); + }, + + message(ws, message) { + ws.publish("the-group-chat", `${ws.data.name}: ${message}`); + }, + + close(ws, code, reason) { + ws.publish("the-group-chat", `${ws.data.name} left the chat`); + }, + + drain(ws) { + console.log("Please send me data. I am ready to receive it."); + }, + + perMessageDeflate: true, + }, +}); + +export {}; diff --git a/packages/bun-types/tests/spawn.test-d.ts b/packages/bun-types/tests/spawn.test-d.ts new file mode 100644 index 000000000..cd776e43f --- /dev/null +++ b/packages/bun-types/tests/spawn.test-d.ts @@ -0,0 +1,70 @@ +Bun.spawn(["echo", "hello"]); +{ + const proc = Bun.spawn(["echo", "hello"], { + cwd: "./path/to/subdir", // specify a working direcory + env: { ...process.env, FOO: "bar" }, // specify environment variables + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + proc.pid; // process ID of subprocess +} + +{ + const proc = Bun.spawn(["cat"], { + stdin: await fetch( + "https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js", + ), + }); + + const text = await new Response(proc.stdout).text(); + console.log(text); // "const input = "hello world".repeat(400); ..." +} + +{ + const proc = Bun.spawn(["cat"], { + stdin: "pipe", // return a FileSink for writing + }); + + // enqueue string data + proc.stdin!.write("hello"); + + // enqueue binary data + const enc = new TextEncoder(); + proc.stdin!.write(enc.encode(" world!")); + + // send buffered data + proc.stdin!.flush(); + + // close the input stream + proc.stdin!.end(); +} + +{ + const proc = Bun.spawn(["echo", "hello"]); + const text = await new Response(proc.stdout).text(); + console.log(text); // => "hello" +} + +{ + const proc = Bun.spawn(["echo", "hello"], { + onExit(proc, exitCode, signalCode, error) { + // exit handler + }, + }); + + await proc.exited; // resolves when process exit + proc.killed; // boolean — was the process killed? + proc.exitCode; // null | number + proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... + proc.kill(); + proc.killed; // true + + proc.kill(); // specify an exit code + proc.unref(); +} + +{ +} +export {}; diff --git a/packages/bun-types/tests/sqlite.test-d.ts b/packages/bun-types/tests/sqlite.test-d.ts new file mode 100644 index 000000000..b1c2e3ddb --- /dev/null +++ b/packages/bun-types/tests/sqlite.test-d.ts @@ -0,0 +1,28 @@ +import { Database } from "bun:sqlite"; +import { expectType } from "tsd"; + +const db = new Database(":memory:"); +const query1 = db.query< + { name: string; dob: number }, // return type first + { $id: string } +>("select name, dob from users where id = $id"); +query1.all({ $id: "asdf" }); // => {name: string; dob:string}[] + +const query2 = db.query< + { name: string; dob: number }, + [string, number] // pass tuple for positional params +>("select ?1 as name, ?2 as dob"); +const allResults = query2.all("Shaq", 50); // => {name: string; dob:string}[] +const getResults = query2.get("Shaq", 50); // => {name: string; dob:string}[] +const runResults = query2.run("Shaq", 50); // => {name: string; dob:string}[] + +expectType<{ name: string; dob: number }[]>(allResults); +expectType<{ name: string; dob: number } | null>(getResults); +expectType<void>(runResults); + +const query3 = db.prepare< + { name: string; dob: number }, // return type first + [{ $id: string }] +>("select name, dob from users where id = $id"); +const allResults3 = query3.all({ $id: "asdf" }); +expectType<{ name: string; dob: number }[]>(allResults3); diff --git a/packages/bun-types/tests/tcp.test-d.ts b/packages/bun-types/tests/tcp.test-d.ts index 2d5f66f52..f951163d6 100644 --- a/packages/bun-types/tests/tcp.test-d.ts +++ b/packages/bun-types/tests/tcp.test-d.ts @@ -26,10 +26,6 @@ await Bun.connect({ }, hostname: "adsf", port: 324, - tls: { - certFile: "asdf", - keyFile: "adsf", - }, }); await Bun.connect({ |