diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index e6ee3dd8f8..ecfda0192f 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -6393,11 +6393,7 @@ declare module "bun" { | Response | Request; - interface OptionsObject< - In extends Writable = Writable, - Out extends Readable = Readable, - Err extends Readable = Readable, - > { + interface OptionsObject { /** * The current working directory of the process * @@ -6624,22 +6620,6 @@ declare module "bun" { maxBuffer?: number; } - type OptionsToSubprocess = - Opts extends OptionsObject - ? Subprocess< - // "Writable extends In" means "if In === Writable", - // aka if true that means the user didn't specify anything - Writable extends In ? "ignore" : In, - Readable extends Out ? "pipe" : Out, - Readable extends Err ? "inherit" : Err - > - : Subprocess; - - type OptionsToSyncSubprocess = - Opts extends OptionsObject - ? SyncSubprocess - : SyncSubprocess; - type ReadableIO = ReadableStream | number | undefined; type ReadableToIO = X extends "pipe" | undefined @@ -6746,9 +6726,9 @@ declare module "bun" { * - {@link NullSubprocess} (ignore, ignore, ignore) */ interface Subprocess< - In extends SpawnOptions.Writable = SpawnOptions.Writable, - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, + In extends SpawnOptions.Writable, + Out extends SpawnOptions.Readable, + Err extends SpawnOptions.Readable, > extends AsyncDisposable { readonly stdin: SpawnOptions.WritableToIO; readonly stdout: SpawnOptions.ReadableToIO; @@ -6853,10 +6833,7 @@ declare module "bun" { * - {@link ReadableSyncSubprocess} (pipe, pipe) * - {@link NullSyncSubprocess} (ignore, ignore) */ - interface SyncSubprocess< - Out extends SpawnOptions.Readable = SpawnOptions.Readable, - Err extends SpawnOptions.Readable = SpawnOptions.Readable, - > { + interface SyncSubprocess { stdout: SpawnOptions.ReadableToSyncIO; stderr: SpawnOptions.ReadableToSyncIO; exitCode: number; @@ -6888,8 +6865,12 @@ declare module "bun" { * * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) */ - function spawn( - options: Opts & { + function spawn< + const In extends SpawnOptions.Writable = "ignore", + const Out extends SpawnOptions.Readable = "pipe", + const Err extends SpawnOptions.Readable = "inherit", + >( + options: SpawnOptions.OptionsObject & { /** * The command to run * @@ -6906,7 +6887,7 @@ declare module "bun" { */ cmd: string[]; // to support dynamically constructed commands }, - ): SpawnOptions.OptionsToSubprocess; + ): Subprocess; /** * Spawn a new process @@ -6919,7 +6900,11 @@ declare module "bun" { * * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) */ - function spawn( + function spawn< + const In extends SpawnOptions.Writable = "ignore", + const Out extends SpawnOptions.Readable = "pipe", + const Err extends SpawnOptions.Readable = "inherit", + >( /** * The command to run * @@ -6935,8 +6920,8 @@ declare module "bun" { * ``` */ cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSubprocess; + options?: SpawnOptions.OptionsObject, + ): Subprocess; /** * Spawn a new process @@ -6952,8 +6937,11 @@ declare module "bun" { * * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) */ - function spawnSync( - options: Opts & { + function spawnSync< + const Out extends SpawnOptions.Readable = "pipe", + const Err extends SpawnOptions.Readable = "inherit", + >( + options: SpawnOptions.OptionsObject<"ignore", Out, Err> & { /** * The command to run * @@ -6972,7 +6960,7 @@ declare module "bun" { onExit?: never; }, - ): SpawnOptions.OptionsToSyncSubprocess; + ): SyncSubprocess; /** * Synchronously spawn a new process @@ -6984,7 +6972,10 @@ declare module "bun" { * * Internally, this uses [posix_spawn(2)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/posix_spawn.2.html) */ - function spawnSync( + function spawnSync< + const Out extends SpawnOptions.Readable = "pipe", + const Err extends SpawnOptions.Readable = "inherit", + >( /** * The command to run * @@ -7000,8 +6991,8 @@ declare module "bun" { * ``` */ cmds: string[], - options?: Opts, - ): SpawnOptions.OptionsToSyncSubprocess; + options?: SpawnOptions.OptionsObject<"ignore", Out, Err>, + ): SyncSubprocess; /** Utility type for any process from {@link Bun.spawn()} with both stdout and stderr set to `"pipe"` */ type ReadableSubprocess = Subprocess; diff --git a/packages/bun-types/shell.d.ts b/packages/bun-types/shell.d.ts index 2f1170018a..5a91c7f4ab 100644 --- a/packages/bun-types/shell.d.ts +++ b/packages/bun-types/shell.d.ts @@ -6,7 +6,7 @@ declare module "bun" { | Array | string | { raw: string } - | Subprocess + | Subprocess | SpawnOptions.Readable | SpawnOptions.Writable | ReadableStream; diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index e4a7358147..4564d0051b 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -73,7 +73,11 @@ beforeEach(async () => { afterAll(async () => { if (TEMP_DIR) { - await rm(TEMP_DIR, { recursive: true, force: true }); + if (Bun.env.TYPES_INTEGRATION_TEST_KEEP_TEMP_DIR === "true") { + console.log(`Keeping temp dir ${TEMP_DIR} for debugging`); + } else { + await rm(TEMP_DIR, { recursive: true, force: true }); + } } }); diff --git a/test/integration/bun-types/fixture/spawn.ts b/test/integration/bun-types/fixture/spawn.ts index c2eac5bb92..0fc0fff81e 100644 --- a/test/integration/bun-types/fixture/spawn.ts +++ b/test/integration/bun-types/fixture/spawn.ts @@ -14,6 +14,30 @@ function depromise(_promise: Promise): T { return "asdf" as any as T; } +{ + // Test cases for https://github.com/oven-sh/bun/issues/17274 + + { + const proc = Bun.spawn(["cat"], { + stdin: "pipe", + }); + + proc.stdin.write("hello"); + } + + { + const proc = Bun.spawn(["cat"], { + stdin: "pipe", + onExit(proc, exitCode, signalCode, error) { + tsd.expectType(proc).is>(); + console.log(`Process exited: ${exitCode}`); + }, + }); + + proc.stdin.write("hello"); + } +} + { const proc = Bun.spawn(["echo", "hello"], { cwd: "./path/to/subdir", // specify a working direcory @@ -23,11 +47,11 @@ function depromise(_promise: Promise): T { }, }); - proc.pid; // process ID of subprocess + tsd.expectType(proc.pid).is(); - tsd.expectType>(proc.stdout); - tsd.expectType(proc.stderr); - tsd.expectType(proc.stdin); + tsd.expectType(proc.stdout).is>>(); + tsd.expectType(proc.stderr).is(); + tsd.expectType(proc.stdin).is(); } { @@ -115,14 +139,16 @@ function depromise(_promise: Promise): T { const proc = Bun.spawn(["echo", "hello"], { stdio: [null, null, null], }); - tsd.expectType(proc.stdin); - tsd.expectType(proc.stdout); - tsd.expectType(proc.stderr); + + tsd.expectType(proc.stdin).is(); + tsd.expectType(proc.stdout).is(); + tsd.expectType(proc.stderr).is(); } { const proc = Bun.spawn(["echo", "hello"], { stdio: [new Request("1"), null, null], }); + tsd.expectType(proc.stdin); } { @@ -150,5 +176,4 @@ tsd.expectAssignable(Bun.spawn([], { stdio: [null, null, null] } tsd.expectNotAssignable(Bun.spawn([], {})); tsd.expectNotAssignable(Bun.spawn([], {})); -tsd.expectAssignable(Bun.spawnSync([], {})); -tsd.expectAssignable(Bun.spawnSync([], {})); +tsd.expectAssignable>(Bun.spawnSync([], {}));