diff options
author | 2023-08-14 14:23:14 -0500 | |
---|---|---|
committer | 2023-08-14 14:23:14 -0500 | |
commit | 44cf30a25209b331e6e8a95a4b40a768ede3604a (patch) | |
tree | 66c4abd963c863da7793327e44b86f287278ec81 /packages/create-astro/src/shell.ts | |
parent | a34a48826cbbcf749f05ba19ce0edaa701437e62 (diff) | |
download | astro-44cf30a25209b331e6e8a95a4b40a768ede3604a.tar.gz astro-44cf30a25209b331e6e8a95a4b40a768ede3604a.tar.zst astro-44cf30a25209b331e6e8a95a4b40a768ede3604a.zip |
chore: slim create-astro deps (#8077)
Diffstat (limited to 'packages/create-astro/src/shell.ts')
-rw-r--r-- | packages/create-astro/src/shell.ts | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/packages/create-astro/src/shell.ts b/packages/create-astro/src/shell.ts new file mode 100644 index 000000000..4941d788c --- /dev/null +++ b/packages/create-astro/src/shell.ts @@ -0,0 +1,44 @@ +// This is an extremely simplified version of [`execa`](https://github.com/sindresorhus/execa) +// intended to keep our dependency size down +import type { StdioOptions } from 'node:child_process'; +import type { Readable } from 'node:stream'; + +import { text as textFromStream } from 'node:stream/consumers'; +import { spawn } from 'node:child_process'; +import { setTimeout as sleep } from 'node:timers/promises'; + +export interface ExecaOptions { + cwd?: string | URL; + stdio?: StdioOptions; + timeout?: number; +} +export interface Output { + stdout: string; + stderr: string; + exitCode: number; +} +const text = (stream: NodeJS.ReadableStream | Readable | null) => stream ? textFromStream(stream).then(t => t.trimEnd()) : ''; + +export async function shell(command: string, flags: string[], opts: ExecaOptions = {}): Promise<Output> { + const controller = opts.timeout ? new AbortController() : undefined; + const child = spawn(command, flags, { + cwd: opts.cwd, + shell: true, + stdio: opts.stdio, + signal: controller?.signal + }) + const stdout = await text(child.stdout); + const stderr = await text(child.stderr); + if (opts.timeout) { + sleep(opts.timeout).then(() => { + controller!.abort(); + throw { stdout, stderr, exitCode: 1 } + }) + } + await new Promise((resolve) => child.on('exit', resolve)) + const { exitCode } = child; + if (exitCode !== 0) { + throw { stdout, stderr, exitCode }; + } + return { stdout, stderr, exitCode } +} |