UNPKG

@strapi/data-transfer

Version:

Data transfer capabilities for Strapi

62 lines (58 loc) 2.2 kB
'use strict'; var node_events = require('node:events'); var promises = require('node:stream/promises'); /** * Async helper for application code that `await`s sequential writes to a `Writable`. * * 1. Waits until `writable.write` invokes its callback (chunk accepted / `_write` finished). * 2. If `write()` returned `false` **and** `writable.writableNeedDrain` is still true after the * callback, waits for `'drain'`. * * We check both: the return value tells us backpressure was signaled; `writableNeedDrain` avoids * awaiting `'drain'` when it already fired before we subscribed (would otherwise hang forever). * * While waiting for `'drain'`, we also race {@link finished} so destroying the writable (e.g. abort) * cannot leave this promise pending forever. */ async function write(writable, chunk) { let flushed = true; await new Promise((resolve, reject)=>{ let settled = false; const finish = (fn)=>{ if (settled) { return; } settled = true; writable.off('error', onError); fn(); }; const onError = (err)=>{ finish(()=>reject(err)); }; writable.once('error', onError); flushed = writable.write(chunk, (err)=>{ if (err) { // Do not reject or remove `error` here: Node may emit `error` after this callback, and // clearing the listener first would leave that emission unhandled. setImmediate(()=>{ if (!settled) { finish(()=>reject(err)); } }); return; } finish(()=>resolve()); }); }); if (!flushed && writable.writableNeedDrain) { // Without `finished`, awaiting only `drain` can hang forever if the writable is destroyed first. await Promise.race([ node_events.once(writable, 'drain'), promises.finished(writable, { readable: false, writable: true }) ]); } } exports.write = write; //# sourceMappingURL=writable-async-write.js.map