Update types (#1581)

* Fix TS types, improve child_process types

* Add prettier

* Add ArrayBuffer types

* Add namespace Bun, improve types for SharedArrayBuffer, add toStrictEqual

* Improve types, add test files for types

* Update type tests

* Fix typo

* Add stdio

* Stdio types

* Use latest setup-bun

* Update action

* Update action

* Update action

Co-authored-by: Colin McDonnell <colinmcd@alum.mit.edu>
Co-authored-by: Ashcon Partovi <ashcon@partovi.net>
This commit is contained in:
Colin McDonnell
2022-12-06 18:48:02 -08:00
committed by GitHub
parent 84b2cc1739
commit 5ea8fe8c90
24 changed files with 237 additions and 84 deletions

View File

@@ -26,9 +26,9 @@ jobs:
node-version: ${{ matrix.node }}
- name: Install bun
uses: xhyrom/setup-bun@v0.1.2
uses: xhyrom/setup-bun@v0.1.8
with:
bun-version: latest
bun-version: canary
- name: Install global dependencies
run: bun install

View File

@@ -14,9 +14,9 @@ jobs:
- uses: actions/checkout@v3
- name: Install bun
uses: xhyrom/setup-bun@v0.1.6
uses: xhyrom/setup-bun@v0.1.8
with:
bun-version: latest
bun-version: canary
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install node
@@ -88,9 +88,9 @@ jobs:
scope: '@oven-sh'
- name: Install bun
uses: xhyrom/setup-bun@v0.1.6
uses: xhyrom/setup-bun@v0.1.8
with:
bun-version: latest
bun-version: canary
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Download all artifacts

View File

@@ -20,9 +20,9 @@ jobs:
uses: actions/checkout@v2
- name: Install bun
uses: xhyrom/setup-bun@v0.1.6
uses: xhyrom/setup-bun@v0.1.8
with:
bun-version: latest
bun-version: canary
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install node

View File

@@ -19,5 +19,6 @@ module.exports = {
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-misused-new": "off",
},
};

View File

@@ -37,6 +37,7 @@ declare module "bun:test" {
toBe(value: any): void;
toContain(value: any): void;
toEqual(value: any): void;
toStrictEqual(value: any): void;
toHaveLength(value: number): void;
toHaveProperty(key: string, value?: any): void;
toBeTruthy(): void;

View File

@@ -1,9 +1,13 @@
import { SignalConstants } from "os";
interface VoidFunction {
(): void;
}
declare namespace Bun {
interface Env extends Dict<string> {
NODE_ENV: string;
}
}
/**
*
* Bun.js runtime APIs
@@ -30,7 +34,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.
*
*/
export const env: Record<string, string>;
export const env: Bun.Env;
export const origin: string;
/**
@@ -2981,7 +2985,4 @@ interface BufferEncodingOption {
encoding?: BufferEncoding;
}
// declare var Bun: typeof import("bun");
declare namespace Bun {
export * from "bun";
}
declare var Bun: typeof import("bun");

Binary file not shown.

View File

@@ -66,14 +66,15 @@
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/child_process.js)
*/
declare module "child_process" {
import { BunSpawnOptions } from "bun";
import { SpawnOptions } from "bun";
import { ObjectEncodingOptions } from "node:fs";
import { EventEmitter, Abortable } from "node:events";
import * as net from "node:net";
import { Writable, Readable, Stream, Pipe } from "node:stream";
import { URL } from "node:url";
type Serializable = string | object | number | boolean | bigint;
type SendHandle = net.Socket | net.Server;
// import * as net from "node:net";
// type SendHandle = net.Socket | net.Server;
/**
* Instances of the `ChildProcess` represent spawned child processes.
*
@@ -84,7 +85,7 @@ declare module "child_process" {
*/
class ChildProcess extends EventEmitter {
spawn(
options: BunSpawnOptions & { cmd: string[] },
options: SpawnOptions.OptionsObject & { args: string[]; file?: string },
): ChildProcessWithoutNullStreams;
/**
@@ -464,17 +465,17 @@ declare module "child_process" {
message: Serializable,
callback?: (error: Error | null) => void,
): boolean;
send(
message: Serializable,
sendHandle?: SendHandle,
callback?: (error: Error | null) => void,
): boolean;
send(
message: Serializable,
sendHandle?: SendHandle,
options?: MessageOptions,
callback?: (error: Error | null) => void,
): boolean;
// send(
// message: Serializable,
// sendHandle?: SendHandle,
// callback?: (error: Error | null) => void,
// ): boolean;
// send(
// message: Serializable,
// sendHandle?: SendHandle,
// options?: MessageOptions,
// callback?: (error: Error | null) => void,
// ): boolean;
/**
* Closes the IPC channel between parent and child, allowing the child to exit
* gracefully once there are no other connections keeping it alive. After calling
@@ -550,10 +551,10 @@ declare module "child_process" {
event: "exit",
listener: (code: number | null, signal: NodeJS.Signals | null) => void,
): this;
addListener(
event: "message",
listener: (message: Serializable, sendHandle: SendHandle) => void,
): this;
// addListener(
// event: "message",
// listener: (message: Serializable, sendHandle: SendHandle) => void,
// ): this;
addListener(event: "spawn", listener: () => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(
@@ -568,11 +569,11 @@ declare module "child_process" {
code: number | null,
signal: NodeJS.Signals | null,
): boolean;
emit(
event: "message",
message: Serializable,
sendHandle: SendHandle,
): boolean;
// emit(
// event: "message",
// message: Serializable,
// sendHandle: SendHandle,
// ): boolean;
emit(event: "spawn", listener: () => void): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(
@@ -585,10 +586,10 @@ declare module "child_process" {
event: "exit",
listener: (code: number | null, signal: NodeJS.Signals | null) => void,
): this;
on(
event: "message",
listener: (message: Serializable, sendHandle: SendHandle) => void,
): this;
// on(
// event: "message",
// listener: (message: Serializable, sendHandle: SendHandle) => void,
// ): this;
on(event: "spawn", listener: () => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(
@@ -601,10 +602,10 @@ declare module "child_process" {
event: "exit",
listener: (code: number | null, signal: NodeJS.Signals | null) => void,
): this;
once(
event: "message",
listener: (message: Serializable, sendHandle: SendHandle) => void,
): this;
// once(
// event: "message",
// listener: (message: Serializable, sendHandle: SendHandle) => void,
// ): this;
once(event: "spawn", listener: () => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(
@@ -617,10 +618,10 @@ declare module "child_process" {
event: "exit",
listener: (code: number | null, signal: NodeJS.Signals | null) => void,
): this;
prependListener(
event: "message",
listener: (message: Serializable, sendHandle: SendHandle) => void,
): this;
// prependListener(
// event: "message",
// listener: (message: Serializable, sendHandle: SendHandle) => void,
// ): this;
prependListener(event: "spawn", listener: () => void): this;
prependOnceListener(
event: string,
@@ -636,10 +637,10 @@ declare module "child_process" {
event: "exit",
listener: (code: number | null, signal: NodeJS.Signals | null) => void,
): this;
prependOnceListener(
event: "message",
listener: (message: Serializable, sendHandle: SendHandle) => void,
): this;
// prependOnceListener(
// event: "message",
// listener: (message: Serializable, sendHandle: SendHandle) => void,
// ): this;
prependOnceListener(event: "spawn", listener: () => void): this;
}
// return this object when stdio option is undefined or not specified
@@ -703,7 +704,7 @@ declare module "child_process" {
uid?: number | undefined;
gid?: number | undefined;
cwd?: string | URL | undefined;
env?: NodeJS.ProcessEnv | undefined;
env?: Partial<Bun.Env> | undefined;
}
interface CommonOptions extends ProcessEnvOptions {
/**
@@ -1172,7 +1173,7 @@ declare module "child_process" {
interface ExecFileOptionsWithOtherEncoding extends ExecFileOptions {
encoding: BufferEncoding;
}
type ExecFileException = ExecException & NodeJS.ErrnoException;
type ExecFileException = ExecException & ErrnoException;
/**
* The `child_process.execFile()` function is similar to {@link exec} except that it does not spawn a shell by default. Rather, the specified
* executable `file` is spawned directly as a new process making it slightly more
@@ -1527,7 +1528,7 @@ declare module "child_process" {
options?: ForkOptions,
): ChildProcess;
interface SpawnSyncOptions extends CommonSpawnOptions {
input?: string | NodeJS.ArrayBufferView | undefined;
input?: string | ArrayBufferView | undefined;
maxBuffer?: number | undefined;
encoding?: BufferEncoding | "buffer" | null | undefined;
}
@@ -1594,7 +1595,7 @@ declare module "child_process" {
options?: SpawnSyncOptions,
): SpawnSyncReturns<string | Buffer>;
interface CommonExecOptions extends CommonOptions {
input?: string | NodeJS.ArrayBufferView | undefined;
input?: string | ArrayBufferView | undefined;
stdio?: StdioOptions | undefined;
killSignal?: NodeJS.Signals | number | undefined;
maxBuffer?: number | undefined;

View File

@@ -65,14 +65,14 @@ type Signals =
| "SIGINFO";
interface ArrayConstructor {
fromAsync(
asyncItems: AsyncIterable | Iterable | ArrayLike,
fromAsync<T>(
asyncItems: AsyncIterable<T> | Iterable<T> | ArrayLike<T>,
mapfn?: (value: any, index: number) => any,
thisArg?: any,
): Array;
): Array<T>;
}
interface console {
interface Console {
/**
* Asynchronously read lines from standard input (fd 0)
*
@@ -172,7 +172,7 @@ interface console {
warn(...data: any[]): void;
}
declare var console: console;
declare var console: Console;
declare namespace NodeJS {
interface RequireResolve {
@@ -184,6 +184,44 @@ declare namespace NodeJS {
(id: string): any;
resolve: RequireResolve;
}
type Signals =
| "SIGABRT"
| "SIGALRM"
| "SIGBUS"
| "SIGCHLD"
| "SIGCONT"
| "SIGFPE"
| "SIGHUP"
| "SIGILL"
| "SIGINT"
| "SIGIO"
| "SIGIOT"
| "SIGKILL"
| "SIGPIPE"
| "SIGPOLL"
| "SIGPROF"
| "SIGPWR"
| "SIGQUIT"
| "SIGSEGV"
| "SIGSTKFLT"
| "SIGSTOP"
| "SIGSYS"
| "SIGTERM"
| "SIGTRAP"
| "SIGTSTP"
| "SIGTTIN"
| "SIGTTOU"
| "SIGUNUSED"
| "SIGURG"
| "SIGUSR1"
| "SIGUSR2"
| "SIGVTALRM"
| "SIGWINCH"
| "SIGXCPU"
| "SIGXFSZ"
| "SIGBREAK"
| "SIGLOST"
| "SIGINFO";
}
interface ImportMeta {
@@ -297,9 +335,7 @@ interface Process {
platform: Platform;
argv: string[];
// execArgv: string[];
env: Record<string, string> & {
NODE_ENV: string;
};
env: Bun.Env;
/** Whether you are using Bun */
isBun: 1; // FIXME: this should actually return a boolean
@@ -315,6 +351,9 @@ interface Process {
getuid(): number;
setuid(id: number | string): void;
dlopen(module: { exports: any }, filename: string, flags?: number): void;
stdin: import("stream").Duplex;
stdout: import("stream").Writable;
stderr: import("stream").Writable;
}
declare var process: Process;
@@ -2637,3 +2676,30 @@ interface CallSite {
*/
isConstructor(): boolean;
}
interface ArrayBufferConstructor {
new (params: { byteLength: number; maxByteLength?: number }): ArrayBuffer;
}
interface ArrayBuffer {
/**
* Read-only. The length of the ArrayBuffer (in bytes).
*/
readonly byteLength: number;
/**
* Resize an ArrayBuffer in-place.
*/
resize(byteLength: number): ArrayBuffer;
/**
* Returns a section of an ArrayBuffer.
*/
slice(begin: number, end?: number): ArrayBuffer;
readonly [Symbol.toStringTag]: string;
}
interface SharedArrayBuffer {
/**
* Grow the SharedArrayBuffer in-place.
*/
grow(size: number): SharedArrayBuffer;
}

View File

@@ -4,13 +4,16 @@
"private": true,
"repository": "https://github.com/oven-sh/bun-types",
"scripts": {
"build": "rm -rf ./dist && bun scripts/bundle.ts ./dist && bun run fmt",
"build": "rm -rf ./dist && bun run bundle && bun run fmt",
"bundle": "bun scripts/bundle.ts ./dist",
"docs": "bun run build && typedoc",
"test": "tsd"
"test": "tsd",
"fmt": "prettier --write './**/*.{ts,tsx,js,jsx}'"
},
"devDependencies": {
"tsd": "^0.22.0",
"typedoc": "^0.23.9"
"typedoc": "^0.23.9",
"prettier": "^2.4.1"
},
"tsd": {
"directory": "tests"

View File

@@ -0,0 +1,12 @@
const buffer = new ArrayBuffer({
byteLength: 1024,
maxByteLength: 2048,
});
console.log(buffer.byteLength); // 1024
buffer.resize(2048);
console.log(buffer.byteLength); // 2048
TextDecoder;
const buf = new SharedArrayBuffer(1024);
buf.grow(2048);

View File

@@ -0,0 +1,19 @@
import { expectType } from "tsd";
async function* listReleases() {
for (let page = 1; ; page++) {
const response = await fetch(
`https://api.github.com/repos/oven-sh/bun/releases?page=${page}`,
);
const releases: { data: string }[] = await response.json();
if (!releases.length) {
break;
}
for (const release of releases) {
yield release;
}
}
}
const releases = await Array.fromAsync(listReleases());
expectType<{ data: string }[]>(releases);

View File

@@ -0,0 +1,5 @@
for await (const line of console) {
console.log("Received:", line);
}
export {};

View File

@@ -0,0 +1,13 @@
import { expectType } from "tsd";
declare global {
namespace Bun {
interface Env {
WHATEVER: "WHATEVER";
}
}
}
expectType<"WHATEVER">(process.env.WHATEVER);
export {};

View File

@@ -0,0 +1,13 @@
import { FileSystemRouter } from "bun";
import { expectType } from "tsd";
const router = new FileSystemRouter({
dir: import.meta.dir + "/pages",
style: "nextjs",
});
const match = router.match("/");
expectType<string>(match?.name!);
expectType<string>(match?.pathname!);
expectType<Record<string, string>>(match?.query!);
expectType<Record<string, string>>(match?.params!);

View File

@@ -1,11 +1,6 @@
import { ZlibCompressionOptions } from "bun";
import { expectAssignable, expectType } from "tsd";
import Bun, { fs, fsPromises } from ".";
// import Bun from "bun";
// import fs from "fs";
// import fsPromises from "fs/promises";
// Testing ../bun.d.ts
import Bun, { fs, fsPromises } from "./exports";
// FileBlob
expectType<ReadableStream<Uint8Array>>(Bun.file("index.test-d.ts").stream());

View File

@@ -0,0 +1,6 @@
const headers = new Headers();
headers.append("Set-Cookie", "a=1");
headers.append("Set-Cookie", "b=1; Secure");
console.log(headers.getAll("Set-Cookie")); // ["a=1", "b=1; Secure"]
console.log(headers.toJSON()); // { "set-cookie": "a=1, b=1; Secure" }

View File

@@ -0,0 +1,3 @@
process.stdin;
process.stdout;
process.stderr;

View File

@@ -116,7 +116,7 @@ const listener = Bun.listen({
unix: "asdf",
});
listener.data.arg = "asdf";
listener.data!.arg = "asdf";
// @ts-expect-error arg is string
listener.data.arg = 234;

View File

@@ -0,0 +1,13 @@
import { test, expect } from "bun:test";
test("new expect() matchers", () => {
expect(1).not.toBe(2);
expect({ a: 1 }).toEqual({ a: 1, b: undefined });
expect({ a: 1 }).toStrictEqual({ a: 1 });
expect(new Set()).toHaveProperty("size");
expect([]).toHaveLength(0);
expect(["bun"]).toContain("bun");
expect(true).toBeTruthy();
expect(Math.PI).toBeGreaterThan(3.14);
expect(null).toBeNull();
});

View File

@@ -3,13 +3,13 @@
"lib": [
"ESNext"
],
"skipLibCheck": true,
"skipLibCheck": false,
"strict": true,
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"disableSolutionSearching": true
"disableSolutionSearching": true,
},
"exclude": [
"dist",

View File

@@ -36,13 +36,13 @@ const it: typeof it_ = (label, fn) => {
} else if (fn.constructor.name === "AsyncFunction") {
return it_(label, async () => {
gcTick();
await fn();
await fn(() => {});
gcTick();
});
} else {
return it_(label, () => {
gcTick();
fn();
fn(() => {});
gcTick();
});
}
@@ -204,7 +204,7 @@ describe("spawn()", () => {
it("should allow explicit setting of argv0", async () => {
var resolve;
const promise = new Promise((resolve1) => {
const promise = new Promise<string>((resolve1) => {
resolve = resolve1;
});
process.env.NO_COLOR = "1";

View File

@@ -4,11 +4,12 @@
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"noEmit": true,
"skipLibCheck": true,
// "skipLibCheck": true,
"allowJs": true
},
"include": [
"."
".",
"**/*.d.ts"
],
"exclude": [
"src/test",