diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/js/lib.deno.ns.d.ts | 10 | ||||
-rw-r--r-- | cli/js/process.ts | 45 | ||||
-rw-r--r-- | cli/tests/unit/process_test.ts | 18 |
3 files changed, 38 insertions, 35 deletions
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts index 63e9b342e..c79007ebd 100644 --- a/cli/js/lib.deno.ns.d.ts +++ b/cli/js/lib.deno.ns.d.ts @@ -1741,12 +1741,12 @@ declare namespace Deno { options?: { recursive: boolean } ): AsyncIterableIterator<FsEvent>; - export class Process { + export class Process<T extends RunOptions = RunOptions> { readonly rid: number; readonly pid: number; - readonly stdin?: Writer & Closer; - readonly stdout?: Reader & Closer; - readonly stderr?: Reader & Closer; + readonly stdin: T["stdin"] extends "piped" ? Writer & Closer : null; + readonly stdout: T["stdout"] extends "piped" ? Reader & Closer : null; + readonly stderr: T["stderr"] extends "piped" ? Reader & Closer : null; /** Resolves to the current status of the process. */ status(): Promise<ProcessStatus>; /** Buffer the stdout until EOF and return it as `Uint8Array`. @@ -1829,7 +1829,7 @@ declare namespace Deno { * Details of the spawned process are returned. * * Requires `allow-run` permission. */ - export function run(opt: RunOptions): Process; + export function run<T extends RunOptions = RunOptions>(opt: T): Process<T>; interface InspectOptions { depth?: number; diff --git a/cli/js/process.ts b/cli/js/process.ts index c8627f86d..cfae7fe56 100644 --- a/cli/js/process.ts +++ b/cli/js/process.ts @@ -5,17 +5,15 @@ import { Closer, Reader, Writer } from "./io.ts"; import { readAll } from "./buffer.ts"; import { kill, runStatus as runStatusOp, run as runOp } from "./ops/process.ts"; -export type ProcessStdio = "inherit" | "piped" | "null"; - // TODO Maybe extend VSCode's 'CommandOptions'? // See https://code.visualstudio.com/docs/editor/tasks-appendix#_schema-for-tasksjson export interface RunOptions { cmd: string[]; cwd?: string; env?: { [key: string]: string }; - stdout?: ProcessStdio | number; - stderr?: ProcessStdio | number; - stdin?: ProcessStdio | number; + stdout?: "inherit" | "piped" | "null" | number; + stderr?: "inherit" | "piped" | "null" | number; + stdin?: "inherit" | "piped" | "null" | number; } async function runStatus(rid: number): Promise<ProcessStatus> { @@ -30,12 +28,12 @@ async function runStatus(rid: number): Promise<ProcessStatus> { } } -export class Process { +export class Process<T extends RunOptions = RunOptions> { readonly rid: number; readonly pid: number; - readonly stdin?: Writer & Closer; - readonly stdout?: Reader & Closer; - readonly stderr?: Reader & Closer; + readonly stdin!: T["stdin"] extends "piped" ? Writer & Closer : null; + readonly stdout!: T["stdout"] extends "piped" ? Reader & Closer : null; + readonly stderr!: T["stderr"] extends "piped" ? Reader & Closer : null; // @internal constructor(res: RunResponse) { @@ -43,15 +41,19 @@ export class Process { this.pid = res.pid; if (res.stdinRid && res.stdinRid > 0) { - this.stdin = new File(res.stdinRid); + this.stdin = (new File(res.stdinRid) as unknown) as Process<T>["stdin"]; } if (res.stdoutRid && res.stdoutRid > 0) { - this.stdout = new File(res.stdoutRid); + this.stdout = (new File(res.stdoutRid) as unknown) as Process< + T + >["stdout"]; } if (res.stderrRid && res.stderrRid > 0) { - this.stderr = new File(res.stderrRid); + this.stderr = (new File(res.stderrRid) as unknown) as Process< + T + >["stderr"]; } } @@ -61,23 +63,23 @@ export class Process { async output(): Promise<Uint8Array> { if (!this.stdout) { - throw new Error("Process.output: stdout is undefined"); + throw new TypeError("stdout was not piped"); } try { - return await readAll(this.stdout); + return await readAll(this.stdout as Reader & Closer); } finally { - this.stdout.close(); + (this.stdout as Reader & Closer).close(); } } async stderrOutput(): Promise<Uint8Array> { if (!this.stderr) { - throw new Error("Process.stderrOutput: stderr is undefined"); + throw new TypeError("stderr was not piped"); } try { - return await readAll(this.stderr); + return await readAll(this.stderr as Reader & Closer); } finally { - this.stderr.close(); + (this.stderr as Reader & Closer).close(); } } @@ -107,14 +109,15 @@ interface RunResponse { stdoutRid: number | null; stderrRid: number | null; } -export function run({ + +export function run<T extends RunOptions = RunOptions>({ cmd, cwd = undefined, env = {}, stdout = "inherit", stderr = "inherit", stdin = "inherit", -}: RunOptions): Process { +}: T): Process<T> { const res = runOp({ cmd: cmd.map(String), cwd, @@ -126,5 +129,5 @@ export function run({ stdoutRid: isRid(stdout) ? stdout : 0, stderrRid: isRid(stderr) ? stderr : 0, }) as RunResponse; - return new Process(res); + return new Process<T>(res); } diff --git a/cli/tests/unit/process_test.ts b/cli/tests/unit/process_test.ts index abd845041..79e36dc4b 100644 --- a/cli/tests/unit/process_test.ts +++ b/cli/tests/unit/process_test.ts @@ -36,7 +36,7 @@ unitTest({ perms: { run: true } }, async function runSuccess(): Promise<void> { assertEquals(status.success, true); assertEquals(status.code, 0); assertEquals(status.signal, undefined); - p.stdout!.close(); + p.stdout.close(); p.close(); }); @@ -141,7 +141,7 @@ unitTest({ perms: { run: true } }, async function runStdinPiped(): Promise< const n = await p.stdin.write(msg); assertEquals(n, msg.byteLength); - p.stdin!.close(); + p.stdin.close(); const status = await p.status(); assertEquals(status.success, true); @@ -161,16 +161,16 @@ unitTest({ perms: { run: true } }, async function runStdoutPiped(): Promise< assert(!p.stderr); const data = new Uint8Array(10); - let r = await p.stdout!.read(data); + let r = await p.stdout.read(data); if (r === null) { throw new Error("p.stdout.read(...) should not be null"); } assertEquals(r, 5); const s = new TextDecoder().decode(data.subarray(0, r)); assertEquals(s, "hello"); - r = await p.stdout!.read(data); + r = await p.stdout.read(data); assertEquals(r, null); - p.stdout!.close(); + p.stdout.close(); const status = await p.status(); assertEquals(status.success, true); @@ -190,14 +190,14 @@ unitTest({ perms: { run: true } }, async function runStderrPiped(): Promise< assert(!p.stdout); const data = new Uint8Array(10); - let r = await p.stderr!.read(data); + let r = await p.stderr.read(data); if (r === null) { throw new Error("p.stderr.read should not return null here"); } assertEquals(r, 5); const s = new TextDecoder().decode(data.subarray(0, r)); assertEquals(s, "hello"); - r = await p.stderr!.read(data); + r = await p.stderr.read(data); assertEquals(r, null); p.stderr!.close(); @@ -320,9 +320,9 @@ unitTest({ perms: { run: true } }, async function runClose(): Promise<void> { p.close(); const data = new Uint8Array(10); - const r = await p.stderr!.read(data); + const r = await p.stderr.read(data); assertEquals(r, null); - p.stderr!.close(); + p.stderr.close(); }); unitTest(function signalNumbers(): void { |