From d191ea77f9d80338e1edfc2226e742ce53b885d7 Mon Sep 17 00:00:00 2001 From: Douglas Duteil Date: Mon, 5 Jun 2017 18:45:14 +0200 Subject: [PATCH] feat(execa): add typings for `execa` (#16960) --- types/execa/execa-tests.ts | 124 +++++++++++++++++++++++++++++++++++++ types/execa/index.d.ts | 51 +++++++++++++++ types/execa/tsconfig.json | 22 +++++++ types/execa/tslint.json | 1 + 4 files changed, 198 insertions(+) create mode 100644 types/execa/execa-tests.ts create mode 100644 types/execa/index.d.ts create mode 100644 types/execa/tsconfig.json create mode 100644 types/execa/tslint.json diff --git a/types/execa/execa-tests.ts b/types/execa/execa-tests.ts new file mode 100644 index 0000000000..7d5e21e4b4 --- /dev/null +++ b/types/execa/execa-tests.ts @@ -0,0 +1,124 @@ +import * as assert from 'assert'; +import * as execa from 'execa'; +import { PassThrough } from "stream"; + +execa('unicorns') + .then(result => { + assert(result.cmd === 'unicorns'); + assert(result.code === 0); + assert(result.failed === false); + assert(result.killed === false); + assert(result.signal === null); + assert(result.stderr === 'bad unicorns'); + assert(result.stdout === 'good unicorns'); + assert(result.timedOut === false); + }); + +execa('foo') + .catch(error => { + assert(error.cmd === 'foo'); + assert(error.code === 128); + assert(error.failed === true); + assert(error.killed === false); + assert(error.signal === 'SIGINT'); + assert(error.stderr === 'stderr'); + assert(error.stdout === 'stdout'); + assert(error.timedOut === false); + }); + +execa('noop', ['foo']) + .then(result => result.stderr.toLocaleLowerCase()); + +execa.stdout('unicorns') + .then(stdout => stdout.toLocaleLowerCase()); +execa.stdout('echo', ['unicorns']) + .then(stdout => stdout.toLocaleLowerCase()); + +execa.stderr('unicorns') + .then(stderr => stderr.toLocaleLowerCase()); +execa.stderr('echo', ['unicorns']) + .then(stderr => stderr.toLocaleLowerCase()); + +execa.shell('echo unicorns') + .then(result => result.stdout.toLocaleLowerCase()); + +{ + let result: string; + result = execa.shellSync('foo').stderr; + result = execa.shellSync('noop', ['foo']).stdout; + + result = execa.shellSync('foo').stderr; + result = execa.shellSync('noop foo').stdout; +} + +execa('echo', ['unicorns']).stdout.pipe(process.stdout); +execa('echo', ['unicorns']).stderr.pipe(process.stderr); + +async () => { + const { stdout } = await execa('noop', ['foo'], { stripEof: false }); + assert(stdout === 'foo\n'); +}; + +async () => { + const { stdout } = await execa('foo', { preferLocal: false }); + assert(stdout === 'global foo'); +}; + +async () => { + const { stdout } = await execa('stdin', { input: 'foobar' }); + assert(stdout === 'foobar'); +}; + +async () => { + const { stdout } = await execa('stdin', { input: new Buffer('foobar') }); + assert(stdout === 'foobar'); +}; + +async () => { + const s = new PassThrough(); + s.write('howdy'); + s.end(); + const { stdout } = await execa('stdin', { input: s }); + assert(stdout === 'foobar'); +}; + +async () => { + const child = execa('stdin'); + child.stdin.end('unicorns'); + const { stdout } = await child; + assert(stdout === 'unicorns'); +}; + +async () => { + const { stdout } = await execa('stdin', { + input: 'hello', + stdio: [null, 'ignore', null] + }); + assert(stdout === null); +}; + +{ + const child = execa('stdin', { + input: 'hello', + stdio: [null, 'ignore', null] + }); + + child.stdout.setEncoding('utf8'); + + assert(child.pid === 0); + child.kill(); +} + +async () => { + const { timedOut, code } = await execa('delay', ['3000', '22'], { timeout: 9000 }); + assert(timedOut === true); + assert(code === 22); +}; + +async () => { + const { stdout } = await execa.shell('noop foo', { + shell: process.platform === 'win32' ? 'cmd.exe' : '/bin/bash' + }); + + assert(stdout === 'foo'); +}; diff --git a/types/execa/index.d.ts b/types/execa/index.d.ts new file mode 100644 index 0000000000..df868e4d15 --- /dev/null +++ b/types/execa/index.d.ts @@ -0,0 +1,51 @@ +// Type definitions for execa 0.6 +// Project: https://github.com/sindresorhus/execa#readme +// Definitions by: Douglas Duteil +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.3 + +/// + +import { ExecOptions, SpawnOptions, SpawnSyncOptions, SpawnSyncReturns, ChildProcess } from "child_process"; +import { Stream } from 'stream'; + +interface ExecaOptions { + input: string | Buffer | Stream; + preferLocal: boolean; + stripEof: boolean; +} + +type Options = SpawnOptions & ExecaOptions & ExecOptions; + +interface ExecaReturns { + cmd: string; + code: number; + failed: boolean; + killed: boolean; + signal: string | null; + stderr: string; + stdout: string; + timedOut: boolean; +} + +type ExecaError = Error & ExecaReturns; + +interface ExecaChildPromise { + catch(onrejected?: ((reason: ExecaError) => TResult | PromiseLike) | undefined | null): Promise; +} +type ExecaChildProcess = ChildProcess & ExecaChildPromise & Promise; + +declare function execa(file: string, options?: Partial): ExecaChildProcess; +declare function execa(file: string, args?: string[], options?: Partial): ExecaChildProcess; +declare namespace execa { + function stdout(file: string, options?: Partial): Promise; + function stdout(file: string, args?: string[], options?: Partial): Promise; + function stderr(file: string, options?: Partial): Promise; + function stderr(file: string, args?: string[], options?: Partial): Promise; + function shell(command: string, options?: SpawnOptions): ExecaChildProcess; + function sync(file: string, options?: SpawnSyncOptions): ExecaReturns; + function sync(file: string, args?: string[], options?: SpawnSyncOptions): ExecaReturns; + function shellSync(command: string, options?: SpawnOptions): ExecaReturns; +} + +export = execa; diff --git a/types/execa/tsconfig.json b/types/execa/tsconfig.json new file mode 100644 index 0000000000..276a55194a --- /dev/null +++ b/types/execa/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "execa-tests.ts" + ] +} diff --git a/types/execa/tslint.json b/types/execa/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/execa/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }