-
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,52 @@ | ||
export type Options = { | ||
readonly timeout: number; | ||
readonly signal: AbortSignal; | ||
// Readonly nativeOptions; | ||
import type {ChildProcess, SpawnOptions} from 'node:child_process'; | ||
|
||
type StdioOption = Readonly<Exclude<SpawnOptions['stdio'], undefined>[number]>; | ||
type StdinOption = StdioOption | {readonly string?: string}; | ||
|
||
export type Options = Omit<SpawnOptions, 'env' | 'stdio'> & Readonly<Partial<{ | ||
stdin: StdinOption; | ||
|
||
stdout: StdioOption; | ||
|
||
stderr: StdioOption; | ||
|
||
stdio: SpawnOptions['stdio'] | readonly [StdinOption, ...readonly StdioOption[]]; | ||
|
||
preferLocal: boolean; | ||
|
||
// Fixes issues with Remix and Next.js | ||
// See https://github.com/sindresorhus/execa/pull/1141 | ||
env: Readonly<Partial<Record<string, string>>>; | ||
}>>; | ||
|
||
export type Result = { | ||
stdout: string; | ||
|
||
stderr: string; | ||
|
||
output: string; | ||
|
||
command: string; | ||
|
||
durationMs: number; | ||
}; | ||
|
||
export type SubprocessError = Error & Result & { | ||
exitCode?: number; | ||
|
||
signalName?: string; | ||
}; | ||
|
||
export type Subprocess = Promise<Result> & AsyncIterable<string> & { | ||
nodeChildProcess: Promise<ChildProcess>; | ||
|
||
stdout: AsyncIterable<string>; | ||
|
||
stderr: AsyncIterable<string>; | ||
|
||
pipe(file: string, arguments?: readonly string[], options?: Options): Subprocess; | ||
pipe(file: string, options?: Options): Subprocess; | ||
}; | ||
|
||
// TODO: Finish this when the API is decided on. | ||
export function nanoSpawn( | ||
command: string, | ||
arguments: readonly string[], | ||
options?: Options | ||
): Promise<void>; | ||
export default function nanoSpawn(file: string, arguments?: readonly string[], options?: Options): Subprocess; | ||
export default function nanoSpawn(file: string, options?: Options): Subprocess; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import type {ChildProcess} from 'node:child_process'; | ||
import { | ||
expectType, | ||
expectAssignable, | ||
expectNotAssignable, | ||
expectError, | ||
} from 'tsd'; | ||
import nanoSpawn, { | ||
type Options, | ||
type Result, | ||
type SubprocessError, | ||
type Subprocess, | ||
} from './index.js'; | ||
|
||
try { | ||
const result = await nanoSpawn('test'); | ||
expectType<Result>(result); | ||
expectType<string>(result.stdout); | ||
expectType<string>(result.stderr); | ||
expectType<string>(result.output); | ||
expectType<string>(result.command); | ||
expectType<number>(result.durationMs); | ||
expectNotAssignable<Error>(result); | ||
expectError(result.exitCode); | ||
expectError(result.signalName); | ||
expectError(result.other); | ||
} catch (error) { | ||
const subprocessError = error as SubprocessError; | ||
expectType<string>(subprocessError.stdout); | ||
expectType<string>(subprocessError.stderr); | ||
expectType<string>(subprocessError.output); | ||
expectType<string>(subprocessError.command); | ||
expectType<number>(subprocessError.durationMs); | ||
expectAssignable<Error>(subprocessError); | ||
expectType<number | undefined>(subprocessError.exitCode); | ||
expectType<string | undefined>(subprocessError.signalName); | ||
expectError(subprocessError.other); | ||
} | ||
|
||
expectAssignable<Options>({} as const); | ||
expectAssignable<Options>({argv0: 'test'} as const); | ||
expectNotAssignable<Options>({other: 'test'} as const); | ||
expectNotAssignable<Options>('test'); | ||
|
||
await nanoSpawn('test', {argv0: 'test'} as const); | ||
expectError(await nanoSpawn('test', {argv0: true} as const)); | ||
await nanoSpawn('test', {preferLocal: true} as const); | ||
expectError(await nanoSpawn('test', {preferLocal: 'true'} as const)); | ||
await nanoSpawn('test', {env: {}} as const); | ||
await nanoSpawn('test', {env: {TEST: 'test'}} as const); | ||
Check failure on line 50 in source/index.test-d.ts
|
||
expectError(await nanoSpawn('test', {env: true} as const)); | ||
expectError(await nanoSpawn('test', {env: {TEST: true}} as const)); | ||
Check failure on line 52 in source/index.test-d.ts
|
||
await nanoSpawn('test', {stdin: 'pipe'} as const); | ||
await nanoSpawn('test', {stdin: {string: 'test'} as const} as const); | ||
expectError(await nanoSpawn('test', {stdin: {string: true} as const} as const)); | ||
expectError(await nanoSpawn('test', {stdin: {other: 'test'} as const} as const)); | ||
expectError(await nanoSpawn('test', {stdin: true} as const)); | ||
await nanoSpawn('test', {stdout: 'pipe'} as const); | ||
expectError(await nanoSpawn('test', {stdout: {string: 'test'} as const} as const)); | ||
expectError(await nanoSpawn('test', {stdout: true} as const)); | ||
await nanoSpawn('test', {stderr: 'pipe'} as const); | ||
expectError(await nanoSpawn('test', {stderr: {string: 'test'} as const} as const)); | ||
expectError(await nanoSpawn('test', {stderr: true} as const)); | ||
await nanoSpawn('test', {stdio: ['pipe', 'pipe', 'pipe'] as const} as const); | ||
await nanoSpawn('test', {stdio: [{string: 'test'} as const, 'pipe', 'pipe'] as const} as const); | ||
expectError(await nanoSpawn('test', {stdio: ['pipe', {string: 'test'} as const, 'pipe'] as const} as const)); | ||
expectError(await nanoSpawn('test', {stdio: ['pipe', 'pipe', {string: 'test'} as const] as const} as const)); | ||
expectError(await nanoSpawn('test', {stdio: [{string: true} as const, 'pipe', 'pipe'] as const} as const)); | ||
expectError(await nanoSpawn('test', {stdio: [{other: 'test'} as const, 'pipe', 'pipe'] as const} as const)); | ||
expectError(await nanoSpawn('test', {stdio: [true, true, true] as const} as const)); | ||
await nanoSpawn('test', {stdio: 'pipe'} as const); | ||
expectError(await nanoSpawn('test', {stdio: true} as const)); | ||
expectError(await nanoSpawn('test', {other: 'test'} as const)); | ||
|
||
expectError(await nanoSpawn()); | ||
expectError(await nanoSpawn(true)); | ||
await nanoSpawn('test', [] as const); | ||
await nanoSpawn('test', ['one'] as const); | ||
expectError(await nanoSpawn('test', [true] as const)); | ||
await nanoSpawn('test', {} as const); | ||
expectError(await nanoSpawn('test', true)); | ||
await nanoSpawn('test', ['one'] as const, {} as const); | ||
expectError(await nanoSpawn('test', ['one'] as const, true)); | ||
expectError(await nanoSpawn('test', ['one'] as const, {} as const, true)); | ||
|
||
expectError(await nanoSpawn('test').pipe()); | ||
expectError(await nanoSpawn('test').pipe(true)); | ||
await nanoSpawn('test').pipe('test', [] as const); | ||
await nanoSpawn('test').pipe('test', ['one'] as const); | ||
expectError(await nanoSpawn('test').pipe('test', [true] as const)); | ||
await nanoSpawn('test').pipe('test', {} as const); | ||
expectError(await nanoSpawn('test').pipe('test', true)); | ||
await nanoSpawn('test').pipe('test', ['one'] as const, {} as const); | ||
expectError(await nanoSpawn('test').pipe('test', ['one'] as const, true)); | ||
expectError(await nanoSpawn('test').pipe('test', ['one'] as const, {} as const, true)); | ||
|
||
expectError(await nanoSpawn('test').pipe('test').pipe()); | ||
expectError(await nanoSpawn('test').pipe('test').pipe(true)); | ||
await nanoSpawn('test').pipe('test').pipe('test', [] as const); | ||
await nanoSpawn('test').pipe('test').pipe('test', ['one'] as const); | ||
expectError(await nanoSpawn('test').pipe('test').pipe('test', [true] as const)); | ||
await nanoSpawn('test').pipe('test').pipe('test', {} as const); | ||
expectError(await nanoSpawn('test').pipe('test').pipe('test', true)); | ||
await nanoSpawn('test').pipe('test').pipe('test', ['one'] as const, {} as const); | ||
expectError(await nanoSpawn('test').pipe('test').pipe('test', ['one'] as const, true)); | ||
expectError(await nanoSpawn('test').pipe('test').pipe('test', ['one'] as const, {} as const, true)); | ||
|
||
expectType<Subprocess>(nanoSpawn('test').pipe('test')); | ||
expectType<Subprocess>(nanoSpawn('test').pipe('test').pipe('test')); | ||
expectType<Result>(await nanoSpawn('test').pipe('test')); | ||
expectType<Result>(await nanoSpawn('test').pipe('test').pipe('test')); | ||
|
||
for await (const line of nanoSpawn('test')) { | ||
expectType<string>(line); | ||
} | ||
|
||
for await (const line of nanoSpawn('test').pipe('test')) { | ||
expectType<string>(line); | ||
} | ||
|
||
for await (const line of nanoSpawn('test').stdout) { | ||
expectType<string>(line); | ||
} | ||
|
||
for await (const line of nanoSpawn('test').pipe('test').stdout) { | ||
expectType<string>(line); | ||
} | ||
|
||
for await (const line of nanoSpawn('test').stderr) { | ||
expectType<string>(line); | ||
} | ||
|
||
for await (const line of nanoSpawn('test').pipe('test').stderr) { | ||
expectType<string>(line); | ||
} | ||
|
||
const subprocess = nanoSpawn('test'); | ||
expectType<Subprocess>(subprocess); | ||
|
||
const nodeChildProcess = await subprocess.nodeChildProcess; | ||
expectType<ChildProcess>(nodeChildProcess); | ||
expectType<number | undefined>(nodeChildProcess.pid); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "nodenext", | ||
"moduleResolution": "nodenext", | ||
"target": "ES2022", | ||
"strict": true | ||
}, | ||
"files": [ | ||
"source/index.d.ts" | ||
] | ||
} |