|
14 | 14 |
|
15 | 15 | import assert from 'node:assert'
|
16 | 16 | import { createInterface } from 'node:readline'
|
| 17 | +import { Readable } from 'node:stream' |
17 | 18 | import { $, within, ProcessOutput } from './core.ts'
|
18 | 19 | import {
|
19 | 20 | type Duration,
|
@@ -63,12 +64,43 @@ export function sleep(duration: Duration): Promise<void> {
|
63 | 64 | })
|
64 | 65 | }
|
65 | 66 |
|
66 |
| -export async function fetch( |
| 67 | +const responseToReadable = (response: Response, rs: Readable) => { |
| 68 | + const reader = response.body?.getReader() |
| 69 | + if (!reader) { |
| 70 | + rs.push(null) |
| 71 | + return rs |
| 72 | + } |
| 73 | + rs._read = async () => { |
| 74 | + const result = await reader.read() |
| 75 | + if (!result.done) rs.push(Buffer.from(result.value)) |
| 76 | + else rs.push(null) |
| 77 | + } |
| 78 | + return rs |
| 79 | +} |
| 80 | + |
| 81 | +export function fetch( |
67 | 82 | url: RequestInfo,
|
68 | 83 | init?: RequestInit
|
69 |
| -): Promise<Response> { |
| 84 | +): Promise<Response> & { pipe: <D>(dest: D) => D } { |
70 | 85 | $.log({ kind: 'fetch', url, init, verbose: !$.quiet && $.verbose })
|
71 |
| - return nodeFetch(url, init) |
| 86 | + const p = nodeFetch(url, init) |
| 87 | + |
| 88 | + return Object.assign(p, { |
| 89 | + pipe(dest: any, ...args: any[]) { |
| 90 | + const rs = new Readable() |
| 91 | + const _dest = isStringLiteral(dest, ...args) |
| 92 | + ? $({ |
| 93 | + halt: true, |
| 94 | + signal: init?.signal as AbortSignal, |
| 95 | + })(dest as TemplateStringsArray, ...args) |
| 96 | + : dest |
| 97 | + p.then( |
| 98 | + (r) => responseToReadable(r, rs).pipe(_dest.run?.()), |
| 99 | + (err) => _dest.abort?.(err) |
| 100 | + ) |
| 101 | + return _dest |
| 102 | + }, |
| 103 | + }) |
72 | 104 | }
|
73 | 105 |
|
74 | 106 | export function echo(...args: any[]): void
|
|
0 commit comments