UNPKG

@whatwg-node/node-fetch

Version:

Fetch API implementation for Node

119 lines (118 loc) 3.98 kB
import { Writable } from 'node:stream'; import { fakeRejectPromise } from '@whatwg-node/promise-helpers'; import { endStream, fakePromise, safeWrite } from './utils.js'; export class PonyfillWritableStream { writable; constructor(underlyingSink) { if (underlyingSink instanceof Writable) { this.writable = underlyingSink; } else if (underlyingSink) { const writable = new Writable({ write(chunk, _encoding, callback) { try { const result = underlyingSink.write?.(chunk, controller); if (result instanceof Promise) { result.then(() => { callback(); }, err => { callback(err); }); } else { callback(); } } catch (err) { callback(err); } }, final(callback) { const result = underlyingSink.close?.(); if (result instanceof Promise) { result.then(() => { callback(); }, err => { callback(err); }); } else { callback(); } }, }); this.writable = writable; const abortCtrl = new AbortController(); const controller = { signal: abortCtrl.signal, error(e) { writable.destroy(e); }, }; writable.once('error', err => abortCtrl.abort(err)); writable.once('close', () => abortCtrl.abort()); } else { this.writable = new Writable(); } } getWriter() { const writable = this.writable; return { closed: new Promise(resolve => { writable.once('close', () => { resolve(undefined); }); }), get desiredSize() { return writable.writableLength; }, ready: new Promise(resolve => { writable.once('drain', () => { resolve(undefined); }); }), releaseLock() { // no-op }, write(chunk) { const promise = fakePromise(); if (chunk == null) { return promise; } return promise.then(() => safeWrite(chunk, writable)); }, close() { if (!writable.errored && writable.closed) { return fakePromise(); } if (writable.errored) { return fakeRejectPromise(writable.errored); } return fakePromise().then(() => endStream(writable)); }, abort(reason) { return new Promise(resolve => { writable.destroy(reason); writable.once('close', resolve); }); }, }; } close() { if (!this.writable.errored && this.writable.closed) { return fakePromise(); } if (this.writable.errored) { return fakeRejectPromise(this.writable.errored); } return fakePromise().then(() => endStream(this.writable)); } abort(reason) { return new Promise(resolve => { this.writable.destroy(reason); this.writable.once('close', resolve); }); } locked = false; }