@types/bun: fix URLSearchParams, bring back old types test suite (#18598)

This commit is contained in:
Alistair Smith
2025-03-29 00:51:52 +00:00
committed by GitHub
parent ee89130991
commit e83b5fb720
45 changed files with 350 additions and 293 deletions

View File

@@ -40,7 +40,6 @@ declare module "bun" {
type SignalsListener = (signal: NodeJS.Signals) => void;
type BlobPart = string | Blob | BufferSource;
type TimerHandler = (...args: any[]) => void;
type DOMHighResTimeStamp = number;
type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob;
@@ -3813,6 +3812,14 @@ declare module "bun" {
tls?: TLSOptions | TLSOptions[];
}
interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated {
tls?: TLSOptions | TLSOptions[];
}
interface UnixTLSServeOptions extends UnixServeOptions, TLSOptionsAsDeprecated {
tls?: TLSOptions | TLSOptions[];
}
interface ErrorLike extends Error {
code?: string;
errno?: number;
@@ -4013,14 +4020,6 @@ declare module "bun" {
secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options
}
interface TLSServeOptions extends ServeOptions, TLSOptionsAsDeprecated {
tls?: TLSOptions | TLSOptions[];
}
interface UnixTLSServeOptions extends UnixServeOptions, TLSOptionsAsDeprecated {
tls?: TLSOptions | TLSOptions[];
}
interface SocketAddress {
/**
* The IP address of the client.

View File

@@ -1,7 +1,7 @@
declare module "bun" {
namespace __internal {
type NodeWorkerThreadsWorker = import("worker_threads").Worker;
type LibWorkerOrNodeWorkerThreadsWorker = Bun.__internal.UseLibDomIfAvailable<"Worker", NodeWorkerThreadsWorker>;
type LibWorkerOrBunWorker = Bun.__internal.UseLibDomIfAvailable<"Worker", Bun.Worker>;
type NodePerfHooksPerformance = import("perf_hooks").Performance;
type LibPerformanceOrNodePerfHooksPerformance = Bun.__internal.UseLibDomIfAvailable<
@@ -11,8 +11,10 @@ declare module "bun" {
type NodeCryptoWebcryptoSubtleCrypto = import("crypto").webcrypto.SubtleCrypto;
type NodeCryptoWebcryptoCryptoKey = import("crypto").webcrypto.CryptoKey;
type NodeUtilTextEncoder = import("util").TextEncoder;
type NodeUtilTextDecoder = import("util").TextDecoder;
type LibEmptyOrNodeUtilTextEncoder = LibDomIsLoaded extends true ? {} : import("util").TextEncoder;
type LibEmptyOrNodeUtilTextDecoder = LibDomIsLoaded extends true ? {} : import("util").TextDecoder;
type LibEmptyOrNodeReadableStream<T = any> = LibDomIsLoaded extends true
? {}
@@ -25,6 +27,8 @@ declare module "bun" {
type LibEmptyOrNodeTransformStream<I = any, O = any> = LibDomIsLoaded extends true
? {}
: import("stream/web").TransformStream<I, O>;
type LibEmptyOrNodeMessagePort = LibDomIsLoaded extends true ? {} : import("worker_threads").MessagePort;
}
}
@@ -47,7 +51,7 @@ declare var WritableStream: Bun.__internal.UseLibDomIfAvailable<
}
>;
interface Worker extends Bun.__internal.LibWorkerOrNodeWorkerThreadsWorker {}
interface Worker extends Bun.__internal.LibWorkerOrBunWorker {}
declare var Worker: Bun.__internal.UseLibDomIfAvailable<
"Worker",
{
@@ -62,6 +66,13 @@ declare var Worker: Bun.__internal.UseLibDomIfAvailable<
}
>;
/**
* A WebSocket client implementation
*
* If `DOM` is included in tsconfig `lib`, this falls back to the default DOM global `WebSocket`.
* Otherwise (when outside of a browser environment), this will be the `WebSocket`
* implementation from the `ws` package, which Bun implements.
*/
declare var WebSocket: Bun.__internal.UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>;
interface Crypto {}
@@ -81,7 +92,7 @@ declare var crypto: Crypto;
* const uint8array = encoder.encode('this is some data');
* ```
*/
interface TextEncoder extends Bun.__internal.NodeUtilTextEncoder {
interface TextEncoder extends Bun.__internal.LibEmptyOrNodeUtilTextEncoder {
/**
* UTF-8 encodes the `src` string to the `dest` Uint8Array and returns an object
* containing the read Unicode code units and written UTF-8 bytes.
@@ -113,53 +124,51 @@ declare var TextEncoder: Bun.__internal.UseLibDomIfAvailable<
* const decoder = new TextDecoder();
* const uint8array = decoder.decode('this is some data');
*/
interface TextDecoder extends Bun.__internal.LibEmptyOrNodeUtilTextDecoder {}
declare var TextDecoder: Bun.__internal.UseLibDomIfAvailable<
"TextDecoder",
{
prototype: Bun.__internal.NodeUtilTextDecoder;
new (
encoding?: Bun.Encoding,
options?: { fatal?: boolean; ignoreBOM?: boolean },
): Bun.__internal.NodeUtilTextDecoder;
prototype: TextDecoder;
new (encoding?: Bun.Encoding, options?: { fatal?: boolean; ignoreBOM?: boolean }): TextDecoder;
}
>;
// interface Event {
// /** This is not used in Node.js and is provided purely for completeness. */
// readonly bubbles: boolean;
// /** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */
// cancelBubble: () => void;
// /** True if the event was created with the cancelable option */
// readonly cancelable: boolean;
// /** This is not used in Node.js and is provided purely for completeness. */
// readonly composed: boolean;
// /** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */
// composedPath(): [EventTarget?];
// /** Alias for event.target. */
// readonly currentTarget: EventTarget | null;
// /** Is true if cancelable is true and event.preventDefault() has been called. */
// readonly defaultPrevented: boolean;
// /** This is not used in Node.js and is provided purely for completeness. */
// readonly eventPhase: typeof globalThis extends { Event: infer T extends {eventPhase: number} } ? T['eventPhase'] : 0 | 2;
// /** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */
// readonly isTrusted: boolean;
// /** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */
// preventDefault(): void;
// /** This is not used in Node.js and is provided purely for completeness. */
// returnValue: boolean;
// /** Alias for event.target. */
// readonly srcElement: EventTarget | null;
// /** Stops the invocation of event listeners after the current one completes. */
// stopImmediatePropagation(): void;
// /** This is not used in Node.js and is provided purely for completeness. */
// stopPropagation(): void;
// /** The `EventTarget` dispatching the event */
// readonly target: EventTarget | null;
// /** The millisecond timestamp when the Event object was created. */
// readonly timeStamp: number;
// /** Returns the type of event, e.g. "click", "hashchange", or "submit". */
// readonly type: string;
// }
interface Event {
/** This is not used in Node.js and is provided purely for completeness. */
readonly bubbles: boolean;
/** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */
cancelBubble: boolean;
/** True if the event was created with the cancelable option */
readonly cancelable: boolean;
/** This is not used in Node.js and is provided purely for completeness. */
readonly composed: boolean;
/** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */
composedPath(): [EventTarget?];
/** Alias for event.target. */
readonly currentTarget: EventTarget | null;
/** Is true if cancelable is true and event.preventDefault() has been called. */
readonly defaultPrevented: boolean;
/** This is not used in Node.js and is provided purely for completeness. */
readonly eventPhase: number;
/** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */
readonly isTrusted: boolean;
/** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */
preventDefault(): void;
/** This is not used in Node.js and is provided purely for completeness. */
returnValue: boolean;
/** Alias for event.target. */
readonly srcElement: EventTarget | null;
/** Stops the invocation of event listeners after the current one completes. */
stopImmediatePropagation(): void;
/** This is not used in Node.js and is provided purely for completeness. */
stopPropagation(): void;
/** The `EventTarget` dispatching the event */
readonly target: EventTarget | null;
/** The millisecond timestamp when the Event object was created. */
readonly timeStamp: number;
/** Returns the type of event, e.g. "click", "hashchange", or "submit". */
readonly type: string;
}
declare var Event: {
prototype: Event;
readonly NONE: 0;
@@ -411,7 +420,13 @@ declare var CloseEvent: {
};
interface MessageEvent<T = any> extends Bun.MessageEvent<T> {}
declare var MessageEvent: Bun.__internal.UseLibDomIfAvailable<"MessageEvent", MessageEvent>;
declare var MessageEvent: Bun.__internal.UseLibDomIfAvailable<
"MessageEvent",
{
prototype: MessageEvent;
new <T>(type: string, eventInitDict?: Bun.MessageEventInit<T>): MessageEvent<any>;
}
>;
interface CustomEvent<T = any> extends Event {
/** Returns any custom data event was created with. Typically used for synthetic events. */
@@ -1119,7 +1134,7 @@ interface ImportMeta {
* import.meta.env === process.env
* ```
*/
readonly env: NodeJS.ProcessEnv;
readonly env: Bun.Env;
/**
* @deprecated Use `require.resolve` or `Bun.resolveSync(moduleId, path.dirname(parent))` instead
@@ -1256,6 +1271,16 @@ interface BlobPropertyBag {
interface WorkerOptions extends Bun.WorkerOptions {}
interface Blob {
/**
* The size of this Blob in bytes
*/
readonly size: number;
/**
* The MIME type of this Blob
*/
readonly type: string;
/**
* Read the data from the blob as a JSON object.
*
@@ -1461,7 +1486,28 @@ declare var DOMException: Bun.__internal.UseLibDomIfAvailable<
{ prototype: DOMException; new (): DOMException }
>;
interface FormData {}
interface FormData {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FormData/append) */
append(name: string, value: string | Blob): void;
append(name: string, value: string): void;
append(name: string, blobValue: Blob, filename?: string): void;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FormData/delete) */
delete(name: string): void;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FormData/get) */
get(name: string): Bun.FormDataEntryValue | null;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FormData/getAll) */
getAll(name: string): Bun.FormDataEntryValue[];
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FormData/has) */
has(name: string): boolean;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FormData/set) */
set(name: string, value: string | Blob): void;
set(name: string, value: string): void;
set(name: string, blobValue: Blob, filename?: string): void;
forEach(callbackfn: (value: Bun.FormDataEntryValue, key: string, parent: FormData) => void, thisArg?: any): void;
keys(): IterableIterator<string>;
values(): IterableIterator<string>;
entries(): IterableIterator<[string, string]>;
}
declare var FormData: Bun.__internal.UseLibDomIfAvailable<"FormData", { prototype: FormData; new (): FormData }>;
interface EventSource {}
@@ -1542,16 +1588,39 @@ declare var TextEncoderStream: Bun.__internal.UseLibDomIfAvailable<
interface URLSearchParams {}
declare var URLSearchParams: Bun.__internal.UseLibDomIfAvailable<
"URLSearchParams",
{ prototype: URLSearchParams; new (): URLSearchParams }
{
prototype: URLSearchParams;
new (
init?:
| URLSearchParams
| string
| Record<string, string | readonly string[]>
| Iterable<[string, string]>
| ReadonlyArray<[string, string]>,
): URLSearchParams;
}
>;
interface MessageChannel {}
interface MessageChannel {
/**
* Returns the first MessagePort object.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageChannel/port1)
*/
readonly port1: MessagePort;
/**
* Returns the second MessagePort object.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageChannel/port2)
*/
readonly port2: MessagePort;
}
declare var MessageChannel: Bun.__internal.UseLibDomIfAvailable<
"MessageChannel",
{ prototype: MessageChannel; new (): MessageChannel }
>;
interface MessagePort {}
interface MessagePort extends Bun.__internal.LibEmptyOrNodeMessagePort {}
declare var MessagePort: Bun.__internal.UseLibDomIfAvailable<
"MessagePort",
{
@@ -1683,26 +1752,6 @@ interface BunFetchRequestInit extends RequestInit {
s3?: Bun.S3Options;
}
/**
* Send a HTTP(s) request
*
* @param request Request object
* @param init A structured value that contains settings for the fetch() request.
*
* @returns A promise that resolves to {@link Response} object.
*/
declare function fetch(request: Request, init?: BunFetchRequestInit): Promise<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.
*/
declare function fetch(url: string | URL | Request, init?: BunFetchRequestInit): Promise<Response>;
/**
* Send a HTTP(s) request
*

View File

@@ -1,2 +0,0 @@
Bun.spawn(["echo", '"hi"']);
performance;

View File

@@ -1,23 +0,0 @@
new ReadableStream({
start(controller) {
controller.enqueue("hello");
controller.enqueue("world");
controller.close();
},
});
// this will have type errors when lib.dom.d.ts is present
// afaik this isn't fixable
new ReadableStream({
type: "direct",
pull(controller) {
// eslint-disable-next-line
controller.write("hello");
// eslint-disable-next-line
controller.write("world");
controller.close();
},
cancel() {
// called if stream.cancel() is called
},
});

View File

@@ -102,6 +102,7 @@ describe("@types/bun integration test", () => {
`;
const importantLines = [
`error TS2353: Object literal may only specify known properties, and 'headers' does not exist in type 'string[]'.`,
`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", // This line ends early because we've seen TypeScript emit differing messages in different environments
@@ -109,6 +110,9 @@ describe("@types/bun integration test", () => {
`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'.",
"error TS2339: Property 'ref' does not exist on type 'Worker'.",
"error TS2339: Property 'unref' does not exist on type 'Worker'.",
"error TS2339: Property 'threadId' does not exist on type 'Worker'.",
];
const fullOutput = p.stdout.toString() + p.stderr.toString();

View File

@@ -1,4 +1,4 @@
import { expectType } from "./utilities.test";
import { expectType } from "./utilities";
async function* listReleases() {
for (let page = 1; ; page++) {

View File

@@ -2,8 +2,7 @@ const channel = new BroadcastChannel("my-channel");
const message = { hello: "world" };
channel.onmessage = event => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
console.log((event as any).data); // { hello: "world" }
console.log(event);
};
channel.postMessage(message);

View File

@@ -1,5 +1,5 @@
import { BunFile, BunPlugin, FileBlob } from "bun";
import * as tsd from "./utilities.test";
import type { BunFile, BunPlugin, FileBlob } from "bun";
import * as tsd from "./utilities";
{
const _plugin: BunPlugin = {
name: "asdf",
@@ -7,6 +7,7 @@ import * as tsd from "./utilities.test";
};
_plugin;
}
{
// tslint:disable-next-line:no-void-expression
const arg = Bun.plugin({

View File

@@ -1,4 +1,4 @@
import { expectType } from "./utilities.test";
import { expectType } from "./utilities";
declare module "bun" {
interface Env {

View File

@@ -1,5 +1,5 @@
import { EventEmitter } from "events";
import { expectType } from "./utilities.test";
import { expectType } from "./utilities";
// eslint-disable-next-line @definitelytyped/no-single-element-tuple-type
// EventEmitter<

View File

@@ -1,5 +1,5 @@
import { CString, dlopen, FFIType, JSCallback, Pointer, read, suffix } from "bun:ffi";
import * as tsd from "./utilities.test";
import { dlopen, FFIType, JSCallback, read, suffix, type CString, type Pointer } from "bun:ffi";
import * as tsd from "./utilities";
// `suffix` is either "dylib", "so", or "dll" depending on the platform
// you don't have to use "suffix", it's just there for convenience

View File

@@ -4,7 +4,7 @@ constants.O_APPEND;
import * as fs from "fs";
import { exists } from "fs/promises";
import * as tsd from "./utilities.test";
import * as tsd from "./utilities";
tsd.expectType<Promise<boolean>>(exists("/etc/passwd"));
tsd.expectType<Promise<boolean>>(fs.promises.exists("/etc/passwd"));

View File

@@ -1,5 +1,5 @@
import { FileSystemRouter } from "bun";
import { expectType } from "./utilities.test";
import { expectType } from "./utilities";
const router = new FileSystemRouter({
dir: "/pages",

View File

@@ -1,7 +1,6 @@
import { ZlibCompressionOptions } from "bun";
import * as fs from "fs";
import * as fsPromises from "fs/promises";
import { expectAssignable, expectType } from "./utilities.test";
import { expectAssignable, expectType } from "./utilities";
// FileBlob
expectType<ReadableStream<Uint8Array>>(Bun.file("index.test-d.ts").stream());
@@ -36,7 +35,7 @@ expectType<Uint8Array>(
expectType<Uint8Array>(Bun.gzipSync(new Uint8Array(128), { level: 9, memLevel: 6, windowBits: 27 }));
expectType<Uint8Array>(Bun.inflateSync(new Uint8Array(64))); // Pretend this is DEFLATE compressed data
expectType<Uint8Array>(Bun.gunzipSync(new Uint8Array(64))); // Pretend this is GZIP compressed data
expectAssignable<ZlibCompressionOptions>({ windowBits: -11 });
expectAssignable<Bun.ZlibCompressionOptions>({ windowBits: -11 });
// Other
expectType<Promise<number>>(Bun.write("test.json", "lol"));
@@ -47,14 +46,8 @@ expectType<string>(Bun.fileURLToPath(new URL("file:///foo/bar.txt")));
// Testing ../fs.d.ts
expectType<string>(fs.readFileSync("./index.d.ts", { encoding: "utf-8" }).toString());
expectType<boolean>(fs.existsSync("./index.d.ts"));
// tslint:disable-next-line:no-void-expression
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
expectType<void>(fs.accessSync("./index.d.ts"));
// tslint:disable-next-line:no-void-expression
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
expectType<void>(fs.appendFileSync("./index.d.ts", "test"));
// tslint:disable-next-line:no-void-expression
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
expectType<void>(fs.mkdirSync("./index.d.ts"));
// Testing ^promises.d.ts
@@ -112,38 +105,36 @@ CountQueuingStrategy;
TextEncoder;
TextDecoder;
ReadableStreamDefaultReader;
// ReadableStreamBYOBReader;
ReadableStreamBYOBReader;
ReadableStreamDefaultController;
// ReadableByteStreamController;
ReadableByteStreamController;
WritableStreamDefaultWriter;
function stuff(arg: Blob): any;
function stuff(arg: WebSocket): any;
function stuff(arg: Request): any;
function stuff(arg: Response): any;
function stuff(arg: Headers): any;
function stuff(arg: FormData): any;
function stuff(arg: URL): any;
function stuff(arg: URLSearchParams): any;
function stuff(arg: ReadableStream): any;
function stuff(arg: WritableStream): any;
function stuff(arg: TransformStream): any;
function stuff(arg: ByteLengthQueuingStrategy): any;
function stuff(arg: CountQueuingStrategy): any;
function stuff(arg: TextEncoder): any;
function stuff(arg: TextDecoder): any;
function stuff(arg: ReadableStreamDefaultReader): any;
function stuff(arg: ReadableStreamDefaultController): any;
function stuff(arg: WritableStreamDefaultWriter): any;
function stuff(arg: any) {
return "asfd";
}
declare function stuff(arg: Blob): any;
declare function stuff(arg: WebSocket): any;
declare function stuff(arg: Request): any;
declare function stuff(arg: Response): any;
declare function stuff(arg: Headers): any;
declare function stuff(arg: FormData): any;
declare function stuff(arg: URL): any;
declare function stuff(arg: URLSearchParams): any;
declare function stuff(arg: ReadableStream): any;
declare function stuff(arg: WritableStream): any;
declare function stuff(arg: TransformStream): any;
declare function stuff(arg: ByteLengthQueuingStrategy): any;
declare function stuff(arg: CountQueuingStrategy): any;
declare function stuff(arg: TextEncoder): any;
declare function stuff(arg: TextDecoder): any;
declare function stuff(arg: ReadableStreamDefaultReader): any;
declare function stuff(arg: ReadableStreamDefaultController): any;
declare function stuff(arg: WritableStreamDefaultWriter): any;
stuff("asdf" as any as Blob);
new ReadableStream();
new WritableStream();
new Worker("asdfasdf");
new Worker("asdfasdf").onmessage;
new File([{} as Blob], "asdf");
new Crypto();
new ShadowRealm();
@@ -229,6 +220,19 @@ const writableStream = new WritableStream();
{
const a = new FormData();
a.delete("asdf");
a.get("asdf");
a.append("asdf", "asdf");
a.set("asdf", "asdf");
a.forEach((value, key) => {
console.log(value, key);
});
a.entries();
a.get("asdf");
a.getAll("asdf");
a.has("asdf");
a.keys();
a.values();
a.toString();
}
{
const a = new Headers();
@@ -260,8 +264,9 @@ const writableStream = new WritableStream();
a.href;
}
{
const a = new URLSearchParams();
a;
new URLSearchParams();
new URLSearchParams("");
new URLSearchParams([]);
}
{
const a = new TextDecoder();
@@ -278,6 +283,7 @@ const writableStream = new WritableStream();
{
const a = new MessageChannel();
a.port1;
new MessageChannel().port1.addEventListener("message", console.log);
}
{
const a = new MessagePort();
@@ -296,6 +302,10 @@ const writableStream = new WritableStream();
{
const ws = new WebSocket("ws://www.host.com/path");
ws.send("asdf");
new WebSocket("url", {
headers: { "Authorization": "my key" },
});
}
atob("asf");

View File

@@ -32,4 +32,10 @@ for (const q of sp) {
console.log(q);
}
fetch;
fetch("https://example.com", {
s3: {
accessKeyId: "123",
secretAccessKey: "456",
},
proxy: "cool",
});

View File

@@ -11,15 +11,6 @@ const options: Bun.TLSOptions = {
process.assert;
const channel = new BroadcastChannel("my-channel");
const message = { hello: "world" };
channel.onmessage = event => {
console.log(event);
};
channel.postMessage(message);
const error = new Error("hello world");
const clone = structuredClone(error);
console.log(clone.message); // "hello world"
@@ -83,7 +74,7 @@ new Request("url");
new Response();
new Headers();
new URL("");
new URLSearchParams();
new URLSearchParams([["cool", "stuff"]]);
new File([], "filename", { type: "text/plain" });
new Blob([], { type: "text/plain" });
new ReadableStream();
@@ -120,98 +111,10 @@ new Promise(resolve => {
resolve(1);
});
Bun.serve({
routes: {
"/:test": req => {
return new Response(req.params.test);
},
},
fetch: (req, server) => {
if (!server.upgrade(req)) {
return new Response("not upgraded");
}
},
websocket: {
message: ws => {
ws.data;
ws.send(" ");
},
},
});
import.meta.hot.on("bun:bun:beforeFullReloadBut also allows anything", () => {
//
});
Bun.serve({
routes: {
"/:test": req => {
return new Response(req.params.test);
},
},
fetch: (req, server) => {
return new Response("cool");
},
});
Bun.serve({
fetch: (req, server) => {
return new Response("cool");
},
});
Bun.serve({
routes: {
"/:test": req => {
return new Response(req.params.test);
},
},
});
Bun.serve({
fetch: () => new Response("ok"),
websocket: {
message: ws => {
//
},
},
});
Bun.serve({
websocket: {
message: () => {
//
},
},
fetch: (req, server) => {
if (server.upgrade(req)) {
return;
}
return new Response("not upgraded");
},
});
Bun.serve({
websocket: {
message: () => {
//
},
},
routes: {
"/ws": (req, server) => {
if (server.upgrade(req)) {
return;
}
return new Response("not upgraded");
},
},
});
new Map();
new Set();
new WeakMap();
@@ -310,12 +213,6 @@ req1.headers;
req1.headers.toJSON();
new ReadableStream({});
new ReadableStream({
type: "direct",
async pull(controller) {
controller.write(new TextEncoder().encode("Hello, world!"));
},
});
const body = await fetch(req1);

View File

@@ -1,5 +1,5 @@
import { jest, mock } from "bun:test";
import { expectType } from "./utilities.test";
import { expectType } from "./utilities";
const mock1 = mock((arg: string) => {
return arg.length;

View File

@@ -5,6 +5,7 @@ const rl = readline.createInterface({
output: process.stdout,
terminal: true,
});
await rl.question("What is your age?\n").then(answer => {
console.log("Your age is: " + answer);
});

View File

@@ -10,8 +10,10 @@ Bun.serve({
console.log(req.url); // => http://localhost:3000/
return new Response("Hello World");
},
keyFile: "ca.pem",
certFile: "cert.pem",
tls: {
key: "ca.pem",
cert: "cert.pem",
},
});
Bun.serve({
@@ -34,9 +36,7 @@ Bun.serve({
},
});
Bun.serve<{
name: string;
}>({
Bun.serve({
fetch(req, server) {
const url = new URL(req.url);
if (url.pathname === "/chat") {
@@ -58,7 +58,7 @@ Bun.serve<{
},
websocket: {
open(ws) {
open(ws: Bun.ServerWebSocket<{ name: string }>) {
console.log("WebSocket opened");
ws.subscribe("the-group-chat");
},
@@ -111,33 +111,113 @@ Bun.serve({
},
});
// Bun.serve({
// unix: "/tmp/bun.sock",
// fetch(req, server) {
// server.upgrade(req);
// if (Math.random() > 0.5) return undefined;
// return new Response();
// },
// websocket: { message() {} },
// });
// Bun.serve({
// unix: "/tmp/bun.sock",
// fetch(req, server) {
// server.upgrade(req);
// if (Math.random() > 0.5) return undefined;
// return new Response();
// },
// websocket: { message() {} },
// tls: {},
// });
Bun.serve({
unix: "/tmp/bun.sock",
fetch(req, server) {
server.upgrade(req);
if (Math.random() > 0.5) return undefined;
return new Response();
routes: {
"/:test": req => {
return new Response(req.params.test);
},
},
fetch: (req, server) => {
if (!server.upgrade(req)) {
return new Response("not upgraded");
}
},
websocket: {
message: ws => {
ws.data;
ws.send(" ");
},
},
websocket: { message() {} },
});
Bun.serve({
unix: "/tmp/bun.sock",
fetch() {
return new Response();
routes: {
"/:test": req => {
return new Response(req.params.test);
},
},
fetch: (req, server) => {
return new Response("cool");
},
tls: {},
});
Bun.serve({
unix: "/tmp/bun.sock",
fetch(req, server) {
server.upgrade(req);
if (Math.random() > 0.5) return undefined;
return new Response();
fetch: (req, server) => {
return new Response("cool");
},
});
Bun.serve({
routes: {
"/:test": req => {
return new Response(req.params.test);
},
},
});
Bun.serve({
fetch: () => new Response("ok"),
websocket: {
message: ws => {
//
},
},
});
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");
},
},
websocket: { message() {} },
tls: {},
});
Bun.serve({

View File

@@ -1,5 +1,12 @@
import { FileSink, NullSubprocess, PipedSubprocess, ReadableSubprocess, SyncSubprocess, WritableSubprocess } from "bun";
import * as tsd from "./utilities.test";
import type {
FileSink,
NullSubprocess,
PipedSubprocess,
ReadableSubprocess,
SyncSubprocess,
WritableSubprocess,
} from "bun";
import * as tsd from "./utilities";
Bun.spawn(["echo", "hello"]);

View File

@@ -1,5 +1,5 @@
import { Changes, Database } from "bun:sqlite";
import { expectType } from "./utilities.test";
import { type Changes, Database } from "bun:sqlite";
import { expectType } from "./utilities";
const db = new Database(":memory:");
const query1 = db.query<

View File

@@ -0,0 +1,32 @@
new ReadableStream({
start(controller) {
controller.enqueue("hello");
controller.enqueue("world");
controller.close();
},
});
// This will have type errors when lib.dom.d.ts is present
// Not fixable because ReadableStream has no ReadableStreamConstructor interface
// we can merge into. See https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1941
// for details about when/why/how TypeScript might support this.
new ReadableStream({
type: "direct",
async pull(controller) {
controller.write(new TextEncoder().encode("Hello, world!"));
},
});
// new ReadableStream({
// type: "direct",
// pull(controller) {
// // eslint-disable-next-line
// controller.write("hello");
// // eslint-disable-next-line
// controller.write("world");
// controller.close();
// },
// cancel() {
// // called if stream.cancel() is called
// },
// });

View File

@@ -1,5 +1,5 @@
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, spyOn, test } from "bun:test";
import { expectType } from "./utilities.test";
import { expectType } from "./utilities";
const spy = spyOn(console, "log");
expectType<any[][]>(spy.mock.calls);
@@ -93,8 +93,8 @@ const data = [
["a", true, 5],
["b", false, "asdf"],
];
test.each(data)("test.each", (...args) => {
expectType<string | number | boolean>(args[0]);
test.each(data)("test.each", arg => {
expectType<string | number | boolean>(arg);
});
describe.each(data)("test.each", (a, b, c) => {
expectType<string | number | boolean>(a);

View File

@@ -1,4 +1,4 @@
import data from "./bunfig.toml";
import { expectType } from "./utilities.test";
import { expectType } from "./utilities";
expectType<any>(data);

View File

@@ -1,8 +1,4 @@
// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
export declare const expectType: <T>(expression: T) => void;
// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
export declare const expectAssignable: <T>(expression: T) => void;
// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
export declare const expectNotAssignable: <T>(expression: any) => void;
// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
export declare const expectTypeEquals: <T, S>(expression: T extends S ? (S extends T ? true : false) : false) => void;

View File

@@ -1,5 +1,5 @@
import { Worker as NodeWorker } from "node:worker_threads";
import * as tsd from "./utilities.test";
import * as tsd from "./utilities";
const webWorker = new Worker("./worker.js");
@@ -18,6 +18,7 @@ webWorker.postMessage("asdf", []);
webWorker.terminate();
webWorker.addEventListener("close", () => {});
webWorker.removeEventListener("sadf", () => {});
// these methods don't exist if lib.dom.d.ts is present
webWorker.ref();
webWorker.unref();