diff options
| author | pack <pack@packgekko.xyz> | 2026-08-09 10:37:07 +0000 |
|---|---|---|
| committer | pack <pack@packgekko.xyz> | 2026-08-09 10:37:07 +0000 |
| commit | 55a4f1fc869e41aca748c63d3018f0448b1606e0 (patch) | |
| tree | d132d1d01772b6d53faee3e63c534dea5706b78a /node_modules/minipass | |
| download | crud-55a4f1fc869e41aca748c63d3018f0448b1606e0.tar.gz | |
first commit
Diffstat (limited to 'node_modules/minipass')
| -rw-r--r-- | node_modules/minipass/LICENSE.md | 55 | ||||
| -rw-r--r-- | node_modules/minipass/README.md | 825 | ||||
| -rw-r--r-- | node_modules/minipass/dist/commonjs/index.d.ts | 545 | ||||
| -rw-r--r-- | node_modules/minipass/dist/commonjs/index.js | 1038 | ||||
| -rw-r--r-- | node_modules/minipass/dist/commonjs/package.json | 3 | ||||
| -rw-r--r-- | node_modules/minipass/dist/esm/index.d.ts | 545 | ||||
| -rw-r--r-- | node_modules/minipass/dist/esm/index.js | 1020 | ||||
| -rw-r--r-- | node_modules/minipass/dist/esm/package.json | 3 | ||||
| -rw-r--r-- | node_modules/minipass/package.json | 77 |
9 files changed, 4111 insertions, 0 deletions
diff --git a/node_modules/minipass/LICENSE.md b/node_modules/minipass/LICENSE.md new file mode 100644 index 0000000..c5402b9 --- /dev/null +++ b/node_modules/minipass/LICENSE.md @@ -0,0 +1,55 @@ +# Blue Oak Model License + +Version 1.0.0 + +## Purpose + +This license gives everyone as much permission to work with +this software as possible, while protecting contributors +from liability. + +## Acceptance + +In order to receive this license, you must agree to its +rules. The rules of this license are both obligations +under that agreement and conditions to your license. +You must not do anything with this software that triggers +a rule that you cannot or will not follow. + +## Copyright + +Each contributor licenses you to do everything with this +software that would otherwise infringe that contributor's +copyright in it. + +## Notices + +You must ensure that everyone who gets a copy of +any part of this software from you, with or without +changes, also gets the text of this license or a link to +<https://blueoakcouncil.org/license/1.0.0>. + +## Excuse + +If anyone notifies you in writing that you have not +complied with [Notices](#notices), you can keep your +license by taking all practical steps to comply within 30 +days after the notice. If you do not do so, your license +ends immediately. + +## Patent + +Each contributor licenses you to do everything with this +software that would otherwise infringe any patent claims +they can license or become able to license. + +## Reliability + +No contributor can revoke this license. + +## No Liability + +***As far as the law allows, this software comes as is, +without any warranty or condition, and no contributor +will be liable to anyone for any damages related to this +software or this license, under any kind of legal claim.*** diff --git a/node_modules/minipass/README.md b/node_modules/minipass/README.md new file mode 100644 index 0000000..1126330 --- /dev/null +++ b/node_modules/minipass/README.md @@ -0,0 +1,825 @@ +# minipass + +A _very_ minimal implementation of a [PassThrough +stream](https://nodejs.org/api/stream.html#stream_class_stream_passthrough) + +[It's very +fast](https://docs.google.com/spreadsheets/d/1K_HR5oh3r80b8WVMWCPPjfuWXUgfkmhlX7FGI6JJ8tY/edit?usp=sharing) +for objects, strings, and buffers. + +Supports `pipe()`ing (including multi-`pipe()` and backpressure +transmission), buffering data until either a `data` event handler +or `pipe()` is added (so you don't lose the first chunk), and +most other cases where PassThrough is a good idea. + +There is a `read()` method, but it's much more efficient to +consume data from this stream via `'data'` events or by calling +`pipe()` into some other stream. Calling `read()` requires the +buffer to be flattened in some cases, which requires copying +memory. + +If you set `objectMode: true` in the options, then whatever is +written will be emitted. Otherwise, it'll do a minimal amount of +Buffer copying to ensure proper Streams semantics when `read(n)` +is called. + +`objectMode` can only be set at instantiation. Attempting to +write something other than a String or Buffer without having set +`objectMode` in the options will throw an error. + +This is not a `through` or `through2` stream. It doesn't +transform the data, it just passes it right through. If you want +to transform the data, extend the class, and override the +`write()` method. Once you're done transforming the data however +you want, call `super.write()` with the transform output. + +For some examples of streams that extend Minipass in various +ways, check out: + +- [minizlib](http://npm.im/minizlib) +- [fs-minipass](http://npm.im/fs-minipass) +- [tar](http://npm.im/tar) +- [minipass-collect](http://npm.im/minipass-collect) +- [minipass-flush](http://npm.im/minipass-flush) +- [minipass-pipeline](http://npm.im/minipass-pipeline) +- [tap](http://npm.im/tap) +- [tap-parser](http://npm.im/tap-parser) +- [treport](http://npm.im/treport) +- [minipass-fetch](http://npm.im/minipass-fetch) +- [pacote](http://npm.im/pacote) +- [make-fetch-happen](http://npm.im/make-fetch-happen) +- [cacache](http://npm.im/cacache) +- [ssri](http://npm.im/ssri) +- [npm-registry-fetch](http://npm.im/npm-registry-fetch) +- [minipass-json-stream](http://npm.im/minipass-json-stream) +- [minipass-sized](http://npm.im/minipass-sized) + +## Usage in TypeScript + +The `Minipass` class takes three type template definitions: + +- `RType` the type being read, which defaults to `Buffer`. If + `RType` is `string`, then the constructor _must_ get an options + object specifying either an `encoding` or `objectMode: true`. + If it's anything other than `string` or `Buffer`, then it + _must_ get an options object specifying `objectMode: true`. +- `WType` the type being written. If `RType` is `Buffer` or + `string`, then this defaults to `ContiguousData` (Buffer, + string, ArrayBuffer, or ArrayBufferView). Otherwise, it + defaults to `RType`. +- `Events` type mapping event names to the arguments emitted + with that event, which extends `Minipass.Events`. + +To declare types for custom events in subclasses, extend the +third parameter with your own event signatures. For example: + +```js +import { Minipass } from 'minipass' + +// a NDJSON stream that emits 'jsonError' when it can't stringify +export interface Events extends Minipass.Events { + jsonError: [e: Error] +} + +export class NDJSONStream extends Minipass<string, any, Events> { + constructor() { + super({ objectMode: true }) + } + + // data is type `any` because that's WType + write(data, encoding, cb) { + try { + const json = JSON.stringify(data) + return super.write(json + '\n', encoding, cb) + } catch (er) { + if (!er instanceof Error) { + er = Object.assign(new Error('json stringify failed'), { + cause: er, + }) + } + // trying to emit with something OTHER than an error will + // fail, because we declared the event arguments type. + this.emit('jsonError', er) + } + } +} + +const s = new NDJSONStream() +s.on('jsonError', e => { + // here, TS knows that e is an Error +}) +``` + +Emitting/handling events that aren't declared in this way is +fine, but the arguments will be typed as `unknown`. + +## Differences from Node.js Streams + +There are several things that make Minipass streams different +from (and in some ways superior to) Node.js core streams. + +Please read these caveats if you are familiar with node-core +streams and intend to use Minipass streams in your programs. + +You can avoid most of these differences entirely (for a very +small performance penalty) by setting `{async: true}` in the +constructor options. + +### Timing + +Minipass streams are designed to support synchronous use-cases. +Thus, data is emitted as soon as it is available, always. It is +buffered until read, but no longer. Another way to look at it is +that Minipass streams are exactly as synchronous as the logic +that writes into them. + +This can be surprising if your code relies on +`PassThrough.write()` always providing data on the next tick +rather than the current one, or being able to call `resume()` and +not have the entire buffer disappear immediately. + +However, without this synchronicity guarantee, there would be no +way for Minipass to achieve the speeds it does, or support the +synchronous use cases that it does. Simply put, waiting takes +time. + +This non-deferring approach makes Minipass streams much easier to +reason about, especially in the context of Promises and other +flow-control mechanisms. + +Example: + +```js +// hybrid module, either works +import { Minipass } from 'minipass' +// or: +const { Minipass } = require('minipass') + +const stream = new Minipass() +stream.on('data', () => console.log('data event')) +console.log('before write') +stream.write('hello') +console.log('after write') +// output: +// before write +// data event +// after write +``` + +### Exception: Async Opt-In + +If you wish to have a Minipass stream with behavior that more +closely mimics Node.js core streams, you can set the stream in +async mode either by setting `async: true` in the constructor +options, or by setting `stream.async = true` later on. + +```js +// hybrid module, either works +import { Minipass } from 'minipass' +// or: +const { Minipass } = require('minipass') + +const asyncStream = new Minipass({ async: true }) +asyncStream.on('data', () => console.log('data event')) +console.log('before write') +asyncStream.write('hello') +console.log('after write') +// output: +// before write +// after write +// data event <-- this is deferred until the next tick +``` + +Switching _out_ of async mode is unsafe, as it could cause data +corruption, and so is not enabled. Example: + +```js +import { Minipass } from 'minipass' +const stream = new Minipass({ encoding: 'utf8' }) +stream.on('data', chunk => console.log(chunk)) +stream.async = true +console.log('before writes') +stream.write('hello') +setStreamSyncAgainSomehow(stream) // <-- this doesn't actually exist! +stream.write('world') +console.log('after writes') +// hypothetical output would be: +// before writes +// world +// after writes +// hello +// NOT GOOD! +``` + +To avoid this problem, once set into async mode, any attempt to +make the stream sync again will be ignored. + +```js +const { Minipass } = require('minipass') +const stream = new Minipass({ encoding: 'utf8' }) +stream.on('data', chunk => console.log(chunk)) +stream.async = true +console.log('before writes') +stream.write('hello') +stream.async = false // <-- no-op, stream already async +stream.write('world') +console.log('after writes') +// actual output: +// before writes +// after writes +// hello +// world +``` + +### No High/Low Water Marks + +Node.js core streams will optimistically fill up a buffer, +returning `true` on all writes until the limit is hit, even if +the data has nowhere to go. Then, they will not attempt to draw +more data in until the buffer size dips below a minimum value. + +Minipass streams are much simpler. The `write()` method will +return `true` if the data has somewhere to go (which is to say, +given the timing guarantees, that the data is already there by +the time `write()` returns). + +If the data has nowhere to go, then `write()` returns false, and +the data sits in a buffer, to be drained out immediately as soon +as anyone consumes it. + +Since nothing is ever buffered unnecessarily, there is much less +copying data, and less bookkeeping about buffer capacity levels. + +### Hazards of Buffering (or: Why Minipass Is So Fast) + +Since data written to a Minipass stream is immediately written +all the way through the pipeline, and `write()` always returns +true/false based on whether the data was fully flushed, +backpressure is communicated immediately to the upstream caller. +This minimizes buffering. + +Consider this case: + +```js +const { PassThrough } = require('stream') +const p1 = new PassThrough({ highWaterMark: 1024 }) +const p2 = new PassThrough({ highWaterMark: 1024 }) +const p3 = new PassThrough({ highWaterMark: 1024 }) +const p4 = new PassThrough({ highWaterMark: 1024 }) + +p1.pipe(p2).pipe(p3).pipe(p4) +p4.on('data', () => console.log('made it through')) + +// this returns false and buffers, then writes to p2 on next tick (1) +// p2 returns false and buffers, pausing p1, then writes to p3 on next tick (2) +// p3 returns false and buffers, pausing p2, then writes to p4 on next tick (3) +// p4 returns false and buffers, pausing p3, then emits 'data' and 'drain' +// on next tick (4) +// p3 sees p4's 'drain' event, and calls resume(), emitting 'resume' and +// 'drain' on next tick (5) +// p2 sees p3's 'drain', calls resume(), emits 'resume' and 'drain' on next tick (6) +// p1 sees p2's 'drain', calls resume(), emits 'resume' and 'drain' on next +// tick (7) + +p1.write(Buffer.alloc(2048)) // returns false +``` + +Along the way, the data was buffered and deferred at each stage, +and multiple event deferrals happened, for an unblocked pipeline +where it was perfectly safe to write all the way through! + +Furthermore, setting a `highWaterMark` of `1024` might lead +someone reading the code to think an advisory maximum of 1KiB is +being set for the pipeline. However, the actual advisory +buffering level is the _sum_ of `highWaterMark` values, since +each one has its own bucket. + +Consider the Minipass case: + +```js +const m1 = new Minipass() +const m2 = new Minipass() +const m3 = new Minipass() +const m4 = new Minipass() + +m1.pipe(m2).pipe(m3).pipe(m4) +m4.on('data', () => console.log('made it through')) + +// m1 is flowing, so it writes the data to m2 immediately +// m2 is flowing, so it writes the data to m3 immediately +// m3 is flowing, so it writes the data to m4 immediately +// m4 is flowing, so it fires the 'data' event immediately, returns true +// m4's write returned true, so m3 is still flowing, returns true +// m3's write returned true, so m2 is still flowing, returns true +// m2's write returned true, so m1 is still flowing, returns true +// No event deferrals or buffering along the way! + +m1.write(Buffer.alloc(2048)) // returns true +``` + +It is extremely unlikely that you _don't_ want to buffer any data +written, or _ever_ buffer data that can be flushed all the way +through. Neither node-core streams nor Minipass ever fail to +buffer written data, but node-core streams do a lot of +unnecessary buffering and pausing. + +As always, the faster implementation is the one that does less +stuff and waits less time to do it. + +### Immediately emit `end` for empty streams (when not paused) + +If a stream is not paused, and `end()` is called before writing +any data into it, then it will emit `end` immediately. + +If you have logic that occurs on the `end` event which you don't +want to potentially happen immediately (for example, closing file +descriptors, moving on to the next entry in an archive parse +stream, etc.) then be sure to call `stream.pause()` on creation, +and then `stream.resume()` once you are ready to respond to the +`end` event. + +However, this is _usually_ not a problem because: + +### Emit `end` When Asked + +One hazard of immediately emitting `'end'` is that you may not +yet have had a chance to add a listener. In order to avoid this +hazard, Minipass streams safely re-emit the `'end'` event if a +new listener is added after `'end'` has been emitted. + +Ie, if you do `stream.on('end', someFunction)`, and the stream +has already emitted `end`, then it will call the handler right +away. (You can think of this somewhat like attaching a new +`.then(fn)` to a previously-resolved Promise.) + +To prevent calling handlers multiple times who would not expect +multiple ends to occur, all listeners are removed from the +`'end'` event whenever it is emitted. + +### Emit `error` When Asked + +The most recent error object passed to the `'error'` event is +stored on the stream. If a new `'error'` event handler is added, +and an error was previously emitted, then the event handler will +be called immediately (or on `process.nextTick` in the case of +async streams). + +This makes it much more difficult to end up trying to interact +with a broken stream, if the error handler is added after an +error was previously emitted. + +### Impact of "immediate flow" on Tee-streams + +A "tee stream" is a stream piping to multiple destinations: + +```js +const tee = new Minipass() +t.pipe(dest1) +t.pipe(dest2) +t.write('foo') // goes to both destinations +``` + +Since Minipass streams _immediately_ process any pending data +through the pipeline when a new pipe destination is added, this +can have surprising effects, especially when a stream comes in +from some other function and may or may not have data in its +buffer. + +```js +// WARNING! WILL LOSE DATA! +const src = new Minipass() +src.write('foo') +src.pipe(dest1) // 'foo' chunk flows to dest1 immediately, and is gone +src.pipe(dest2) // gets nothing! +``` + +One solution is to create a dedicated tee-stream junction that +pipes to both locations, and then pipe to _that_ instead. + +```js +// Safe example: tee to both places +const src = new Minipass() +src.write('foo') +const tee = new Minipass() +tee.pipe(dest1) +tee.pipe(dest2) +src.pipe(tee) // tee gets 'foo', pipes to both locations +``` + +The same caveat applies to `on('data')` event listeners. The +first one added will _immediately_ receive all of the data, +leaving nothing for the second: + +```js +// WARNING! WILL LOSE DATA! +const src = new Minipass() +src.write('foo') +src.on('data', handler1) // receives 'foo' right away +src.on('data', handler2) // nothing to see here! +``` + +Using a dedicated tee-stream can be used in this case as well: + +```js +// Safe example: tee to both data handlers +const src = new Minipass() +src.write('foo') +const tee = new Minipass() +tee.on('data', handler1) +tee.on('data', handler2) +src.pipe(tee) +``` + +All of the hazards in this section are avoided by setting `{ +async: true }` in the Minipass constructor, or by setting +`stream.async = true` afterwards. Note that this does add some +overhead, so should only be done in cases where you are willing +to lose a bit of performance in order to avoid having to refactor +program logic. + +## USAGE + +It's a stream! Use it like a stream and it'll most likely do what +you want. + +```js +import { Minipass } from 'minipass' +const mp = new Minipass(options) // options is optional +mp.write('foo') +mp.pipe(someOtherStream) +mp.end('bar') +``` + +### OPTIONS + +- `encoding` How would you like the data coming _out_ of the + stream to be encoded? Accepts any values that can be passed to + `Buffer.toString()`. +- `objectMode` Emit data exactly as it comes in. This will be + flipped on by default if you write() something other than a + string or Buffer at any point. Setting `objectMode: true` will + prevent setting any encoding value. +- `async` Defaults to `false`. Set to `true` to defer data + emission until next tick. This reduces performance slightly, + but makes Minipass streams use timing behavior closer to Node + core streams. See [Timing](#timing) for more details. +- `signal` An `AbortSignal` that will cause the stream to unhook + itself from everything and become as inert as possible. Note + that providing a `signal` parameter will make `'error'` events + no longer throw if they are unhandled, but they will still be + emitted to handlers if any are attached. + +### API + +Implements the user-facing portions of Node.js's `Readable` and +`Writable` streams. + +### Methods + +- `write(chunk, [encoding], [callback])` - Put data in. (Note + that, in the base Minipass class, the same data will come out.) + Returns `false` if the stream will buffer the next write, or + true if it's still in "flowing" mode. +- `end([chunk, [encoding]], [callback])` - Signal that you have + no more data to write. This will queue an `end` event to be + fired when all the data has been consumed. +- `pause()` - No more data for a while, please. This also + prevents `end` from being emitted for empty streams until the + stream is resumed. +- `resume()` - Resume the stream. If there's data in the buffer, + it is all discarded. Any buffered events are immediately + emitted. +- `pipe(dest)` - Send all output to the stream provided. When + data is emitted, it is immediately written to any and all pipe + destinations. (Or written on next tick in `async` mode.) +- `unpipe(dest)` - Stop piping to the destination stream. This is + immediate, meaning that any asynchronously queued data will + _not_ make it to the destination when running in `async` mode. + - `options.end` - Boolean, end the destination stream when the + source stream ends. Default `true`. + - `options.proxyErrors` - Boolean, proxy `error` events from + the source stream to the destination stream. Note that errors + are _not_ proxied after the pipeline terminates, either due + to the source emitting `'end'` or manually unpiping with + `src.unpipe(dest)`. Default `false`. +- `on(ev, fn)`, `emit(ev, fn)` - Minipass streams are + EventEmitters. Some events are given special treatment, + however. (See below under "events".) +- `promise()` - Returns a Promise that resolves when the stream + emits `end`, or rejects if the stream emits `error`. +- `collect()` - Return a Promise that resolves on `end` with an + array containing each chunk of data that was emitted, or + rejects if the stream emits `error`. Note that this consumes + the stream data. +- `concat()` - Same as `collect()`, but concatenates the data + into a single Buffer object. Will reject the returned promise + if the stream is in objectMode, or if it goes into objectMode + by the end of the data. +- `read(n)` - Consume `n` bytes of data out of the buffer. If `n` + is not provided, then consume all of it. If `n` bytes are not + available, then it returns null. **Note** consuming streams in + this way is less efficient, and can lead to unnecessary Buffer + copying. +- `destroy([er])` - Destroy the stream. If an error is provided, + then an `'error'` event is emitted. If the stream has a + `close()` method, and has not emitted a `'close'` event yet, + then `stream.close()` will be called. Any Promises returned by + `.promise()`, `.collect()` or `.concat()` will be rejected. + After being destroyed, writing to the stream will emit an + error. No more data will be emitted if the stream is destroyed, + even if it was previously buffered. + +### Properties + +- `bufferLength` Read-only. Total number of bytes buffered, or in + the case of objectMode, the total number of objects. +- `encoding` Read-only. The encoding that has been set. +- `flowing` Read-only. Boolean indicating whether a chunk written + to the stream will be immediately emitted. +- `emittedEnd` Read-only. Boolean indicating whether the end-ish + events (ie, `end`, `prefinish`, `finish`) have been emitted. + Note that listening on any end-ish event will immediateyl + re-emit it if it has already been emitted. +- `writable` Whether the stream is writable. Default `true`. Set + to `false` when `end()` +- `readable` Whether the stream is readable. Default `true`. +- `pipes` An array of Pipe objects referencing streams that this + stream is piping into. +- `destroyed` A getter that indicates whether the stream was + destroyed. +- `paused` True if the stream has been explicitly paused, + otherwise false. +- `objectMode` Indicates whether the stream is in `objectMode`. +- `aborted` Readonly property set when the `AbortSignal` + dispatches an `abort` event. + +### Events + +- `data` Emitted when there's data to read. Argument is the data + to read. This is never emitted while not flowing. If a listener + is attached, that will resume the stream. +- `end` Emitted when there's no more data to read. This will be + emitted immediately for empty streams when `end()` is called. + If a listener is attached, and `end` was already emitted, then + it will be emitted again. All listeners are removed when `end` + is emitted. +- `prefinish` An end-ish event that follows the same logic as + `end` and is emitted in the same conditions where `end` is + emitted. Emitted after `'end'`. +- `finish` An end-ish event that follows the same logic as `end` + and is emitted in the same conditions where `end` is emitted. + Emitted after `'prefinish'`. +- `close` An indication that an underlying resource has been + released. Minipass does not emit this event, but will defer it + until after `end` has been emitted, since it throws off some + stream libraries otherwise. +- `drain` Emitted when the internal buffer empties, and it is + again suitable to `write()` into the stream. +- `readable` Emitted when data is buffered and ready to be read + by a consumer. +- `resume` Emitted when stream changes state from buffering to + flowing mode. (Ie, when `resume` is called, `pipe` is called, + or a `data` event listener is added.) + +### Static Methods + +- `Minipass.isStream(stream)` Returns `true` if the argument is a + stream, and false otherwise. To be considered a stream, the + object must be either an instance of Minipass, or an + EventEmitter that has either a `pipe()` method, or both + `write()` and `end()` methods. (Pretty much any stream in + node-land will return `true` for this.) + +## EXAMPLES + +Here are some examples of things you can do with Minipass +streams. + +### simple "are you done yet" promise + +```js +mp.promise().then( + () => { + // stream is finished + }, + er => { + // stream emitted an error + } +) +``` + +### collecting + +```js +mp.collect().then(all => { + // all is an array of all the data emitted + // encoding is supported in this case, so + // so the result will be a collection of strings if + // an encoding is specified, or buffers/objects if not. + // + // In an async function, you may do + // const data = await stream.collect() +}) +``` + +### collecting into a single blob + +This is a bit slower because it concatenates the data into one +chunk for you, but if you're going to do it yourself anyway, it's +convenient this way: + +```js +mp.concat().then(onebigchunk => { + // onebigchunk is a string if the stream + // had an encoding set, or a buffer otherwise. +}) +``` + +### iteration + +You can iterate over streams synchronously or asynchronously in +platforms that support it. + +Synchronous iteration will end when the currently available data +is consumed, even if the `end` event has not been reached. In +string and buffer mode, the data is concatenated, so unless +multiple writes are occurring in the same tick as the `read()`, +sync iteration loops will generally only have a single iteration. + +To consume chunks in this way exactly as they have been written, +with no flattening, create the stream with the `{ objectMode: +true }` option. + +```js +const mp = new Minipass({ objectMode: true }) +mp.write('a') +mp.write('b') +for (let letter of mp) { + console.log(letter) // a, b +} +mp.write('c') +mp.write('d') +for (let letter of mp) { + console.log(letter) // c, d +} +mp.write('e') +mp.end() +for (let letter of mp) { + console.log(letter) // e +} +for (let letter of mp) { + console.log(letter) // nothing +} +``` + +Asynchronous iteration will continue until the end event is reached, +consuming all of the data. + +```js +const mp = new Minipass({ encoding: 'utf8' }) + +// some source of some data +let i = 5 +const inter = setInterval(() => { + if (i-- > 0) mp.write(Buffer.from('foo\n', 'utf8')) + else { + mp.end() + clearInterval(inter) + } +}, 100) + +// consume the data with asynchronous iteration +async function consume() { + for await (let chunk of mp) { + console.log(chunk) + } + return 'ok' +} + +consume().then(res => console.log(res)) +// logs `foo\n` 5 times, and then `ok` +``` + +### subclass that `console.log()`s everything written into it + +```js +class Logger extends Minipass { + write(chunk, encoding, callback) { + console.log('WRITE', chunk, encoding) + return super.write(chunk, encoding, callback) + } + end(chunk, encoding, callback) { + console.log('END', chunk, encoding) + return super.end(chunk, encoding, callback) + } +} + +someSource.pipe(new Logger()).pipe(someDest) +``` + +### same thing, but using an inline anonymous class + +```js +// js classes are fun +someSource + .pipe( + new (class extends Minipass { + emit(ev, ...data) { + // let's also log events, because debugging some weird thing + console.log('EMIT', ev) + return super.emit(ev, ...data) + } + write(chunk, encoding, callback) { + console.log('WRITE', chunk, encoding) + return super.write(chunk, encoding, callback) + } + end(chunk, encoding, callback) { + console.log('END', chunk, encoding) + return super.end(chunk, encoding, callback) + } + })() + ) + .pipe(someDest) +``` + +### subclass that defers 'end' for some reason + +```js +class SlowEnd extends Minipass { + emit(ev, ...args) { + if (ev === 'end') { + console.log('going to end, hold on a sec') + setTimeout(() => { + console.log('ok, ready to end now') + super.emit('end', ...args) + }, 100) + return true + } else { + return super.emit(ev, ...args) + } + } +} +``` + +### transform that creates newline-delimited JSON + +```js +class NDJSONEncode extends Minipass { + write(obj, cb) { + try { + // JSON.stringify can throw, emit an error on that + return super.write(JSON.stringify(obj) + '\n', 'utf8', cb) + } catch (er) { + this.emit('error', er) + } + } + end(obj, cb) { + if (typeof obj === 'function') { + cb = obj + obj = undefined + } + if (obj !== undefined) { + this.write(obj) + } + return super.end(cb) + } +} +``` + +### transform that parses newline-delimited JSON + +```js +class NDJSONDecode extends Minipass { + constructor(options) { + // always be in object mode, as far as Minipass is concerned + super({ objectMode: true }) + this._jsonBuffer = '' + } + write(chunk, encoding, cb) { + if ( + typeof chunk === 'string' && + typeof encoding === 'string' && + encoding !== 'utf8' + ) { + chunk = Buffer.from(chunk, encoding).toString() + } else if (Buffer.isBuffer(chunk)) { + chunk = chunk.toString() + } + if (typeof encoding === 'function') { + cb = encoding + } + const jsonData = (this._jsonBuffer + chunk).split('\n') + this._jsonBuffer = jsonData.pop() + for (let i = 0; i < jsonData.length; i++) { + try { + // JSON.parse can throw, emit an error on that + super.write(JSON.parse(jsonData[i])) + } catch (er) { + this.emit('error', er) + continue + } + } + if (cb) cb() + } +} +``` diff --git a/node_modules/minipass/dist/commonjs/index.d.ts b/node_modules/minipass/dist/commonjs/index.d.ts new file mode 100644 index 0000000..3e75b57 --- /dev/null +++ b/node_modules/minipass/dist/commonjs/index.d.ts @@ -0,0 +1,545 @@ +import { EventEmitter } from 'node:events'; +import { StringDecoder } from 'node:string_decoder'; +/** + * Same as StringDecoder, but exposing the `lastNeed` flag on the type + */ +type SD = StringDecoder & { + lastNeed: boolean; +}; +export type { SD, Pipe, PipeProxyErrors }; +/** + * Return true if the argument is a Minipass stream, Node stream, or something + * else that Minipass can interact with. + */ +export declare const isStream: (s: any) => s is Minipass<any, any, any> | NodeJS.ReadStream | NodeJS.WriteStream | (EventEmitter<any> & { + end(): any; + write(chunk: any, ...args: any[]): any; +}) | (EventEmitter<any> & { + pause(): any; + resume(): any; + pipe(...destArgs: any[]): any; +}) | (NodeJS.ReadStream & { + fd: number; +}) | (NodeJS.WriteStream & { + fd: number; +}); +/** + * Return true if the argument is a valid {@link Minipass.Readable} + */ +export declare const isReadable: (s: any) => s is Minipass.Readable; +/** + * Return true if the argument is a valid {@link Minipass.Writable} + */ +export declare const isWritable: (s: any) => s is Minipass.Readable; +declare const EOF: unique symbol; +declare const MAYBE_EMIT_END: unique symbol; +declare const EMITTED_END: unique symbol; +declare const EMITTING_END: unique symbol; +declare const EMITTED_ERROR: unique symbol; +declare const CLOSED: unique symbol; +declare const READ: unique symbol; +declare const FLUSH: unique symbol; +declare const FLUSHCHUNK: unique symbol; +declare const ENCODING: unique symbol; +declare const DECODER: unique symbol; +declare const FLOWING: unique symbol; +declare const PAUSED: unique symbol; +declare const RESUME: unique symbol; +declare const BUFFER: unique symbol; +declare const PIPES: unique symbol; +declare const BUFFERLENGTH: unique symbol; +declare const BUFFERPUSH: unique symbol; +declare const BUFFERSHIFT: unique symbol; +declare const OBJECTMODE: unique symbol; +declare const DESTROYED: unique symbol; +declare const ERROR: unique symbol; +declare const EMITDATA: unique symbol; +declare const EMITEND: unique symbol; +declare const EMITEND2: unique symbol; +declare const ASYNC: unique symbol; +declare const ABORT: unique symbol; +declare const ABORTED: unique symbol; +declare const SIGNAL: unique symbol; +declare const DATALISTENERS: unique symbol; +declare const DISCARDED: unique symbol; +/** + * Options that may be passed to stream.pipe() + */ +export interface PipeOptions { + /** + * end the destination stream when the source stream ends + */ + end?: boolean; + /** + * proxy errors from the source stream to the destination stream + */ + proxyErrors?: boolean; +} +/** + * Internal class representing a pipe to a destination stream. + * + * @internal + */ +declare class Pipe<T extends unknown> { + src: Minipass<T>; + dest: Minipass<any, T>; + opts: PipeOptions; + ondrain: () => any; + constructor(src: Minipass<T>, dest: Minipass.Writable, opts: PipeOptions); + unpipe(): void; + proxyErrors(_er: any): void; + end(): void; +} +/** + * Internal class representing a pipe to a destination stream where + * errors are proxied. + * + * @internal + */ +declare class PipeProxyErrors<T> extends Pipe<T> { + unpipe(): void; + constructor(src: Minipass<T>, dest: Minipass.Writable, opts: PipeOptions); +} +export declare namespace Minipass { + /** + * Encoding used to create a stream that outputs strings rather than + * Buffer objects. + */ + export type Encoding = BufferEncoding | 'buffer' | null; + /** + * Any stream that Minipass can pipe into + */ + export type Writable = Minipass<any, any, any> | NodeJS.WriteStream | (NodeJS.WriteStream & { + fd: number; + }) | (EventEmitter & { + end(): any; + write(chunk: any, ...args: any[]): any; + }); + /** + * Any stream that can be read from + */ + export type Readable = Minipass<any, any, any> | NodeJS.ReadStream | (NodeJS.ReadStream & { + fd: number; + }) | (EventEmitter & { + pause(): any; + resume(): any; + pipe(...destArgs: any[]): any; + }); + /** + * Utility type that can be iterated sync or async + */ + export type DualIterable<T> = Iterable<T> & AsyncIterable<T>; + type EventArguments = Record<string | symbol, unknown[]>; + /** + * The listing of events that a Minipass class can emit. + * Extend this when extending the Minipass class, and pass as + * the third template argument. The key is the name of the event, + * and the value is the argument list. + * + * Any undeclared events will still be allowed, but the handler will get + * arguments as `unknown[]`. + */ + export interface Events<RType extends any = Buffer> extends EventArguments { + readable: []; + data: [chunk: RType]; + error: [er: unknown]; + abort: [reason: unknown]; + drain: []; + resume: []; + end: []; + finish: []; + prefinish: []; + close: []; + [DESTROYED]: [er?: unknown]; + [ERROR]: [er: unknown]; + } + /** + * String or buffer-like data that can be joined and sliced + */ + export type ContiguousData = Buffer | ArrayBufferLike | ArrayBufferView | string; + export type BufferOrString = Buffer | string; + /** + * Options passed to the Minipass constructor. + */ + export type SharedOptions = { + /** + * Defer all data emission and other events until the end of the + * current tick, similar to Node core streams + */ + async?: boolean; + /** + * A signal which will abort the stream + */ + signal?: AbortSignal; + /** + * Output string encoding. Set to `null` or `'buffer'` (or omit) to + * emit Buffer objects rather than strings. + * + * Conflicts with `objectMode` + */ + encoding?: BufferEncoding | null | 'buffer'; + /** + * Output data exactly as it was written, supporting non-buffer/string + * data (such as arbitrary objects, falsey values, etc.) + * + * Conflicts with `encoding` + */ + objectMode?: boolean; + }; + /** + * Options for a string encoded output + */ + export type EncodingOptions = SharedOptions & { + encoding: BufferEncoding; + objectMode?: false; + }; + /** + * Options for contiguous data buffer output + */ + export type BufferOptions = SharedOptions & { + encoding?: null | 'buffer'; + objectMode?: false; + }; + /** + * Options for objectMode arbitrary output + */ + export type ObjectModeOptions = SharedOptions & { + objectMode: true; + encoding?: null; + }; + /** + * Utility type to determine allowed options based on read type + */ + export type Options<T> = ObjectModeOptions | (T extends string ? EncodingOptions : T extends Buffer ? BufferOptions : SharedOptions); + export {}; +} +/** + * Main export, the Minipass class + * + * `RType` is the type of data emitted, defaults to Buffer + * + * `WType` is the type of data to be written, if RType is buffer or string, + * then any {@link Minipass.ContiguousData} is allowed. + * + * `Events` is the set of event handler signatures that this object + * will emit, see {@link Minipass.Events} + */ +export declare class Minipass<RType extends unknown = Buffer, WType extends unknown = RType extends Minipass.BufferOrString ? Minipass.ContiguousData : RType, Events extends Minipass.Events<RType> = Minipass.Events<RType>> extends EventEmitter implements Minipass.DualIterable<RType> { + [FLOWING]: boolean; + [PAUSED]: boolean; + [PIPES]: Pipe<RType>[]; + [BUFFER]: RType[]; + [OBJECTMODE]: boolean; + [ENCODING]: BufferEncoding | null; + [ASYNC]: boolean; + [DECODER]: SD | null; + [EOF]: boolean; + [EMITTED_END]: boolean; + [EMITTING_END]: boolean; + [CLOSED]: boolean; + [EMITTED_ERROR]: unknown; + [BUFFERLENGTH]: number; + [DESTROYED]: boolean; + [SIGNAL]?: AbortSignal; + [ABORTED]: boolean; + [DATALISTENERS]: number; + [DISCARDED]: boolean; + /** + * true if the stream can be written + */ + writable: boolean; + /** + * true if the stream can be read + */ + readable: boolean; + /** + * If `RType` is Buffer, then options do not need to be provided. + * Otherwise, an options object must be provided to specify either + * {@link Minipass.SharedOptions.objectMode} or + * {@link Minipass.SharedOptions.encoding}, as appropriate. + */ + constructor(...args: [Minipass.ObjectModeOptions] | (RType extends Buffer ? [] | [Minipass.Options<RType>] : [Minipass.Options<RType>])); + /** + * The amount of data stored in the buffer waiting to be read. + * + * For Buffer strings, this will be the total byte length. + * For string encoding streams, this will be the string character length, + * according to JavaScript's `string.length` logic. + * For objectMode streams, this is a count of the items waiting to be + * emitted. + */ + get bufferLength(): number; + /** + * The `BufferEncoding` currently in use, or `null` + */ + get encoding(): BufferEncoding | null; + /** + * @deprecated - This is a read only property + */ + set encoding(_enc: BufferEncoding | null); + /** + * @deprecated - Encoding may only be set at instantiation time + */ + setEncoding(_enc: Minipass.Encoding): void; + /** + * True if this is an objectMode stream + */ + get objectMode(): boolean; + /** + * @deprecated - This is a read-only property + */ + set objectMode(_om: boolean); + /** + * true if this is an async stream + */ + get ['async'](): boolean; + /** + * Set to true to make this stream async. + * + * Once set, it cannot be unset, as this would potentially cause incorrect + * behavior. Ie, a sync stream can be made async, but an async stream + * cannot be safely made sync. + */ + set ['async'](a: boolean); + [ABORT](): void; + /** + * True if the stream has been aborted. + */ + get aborted(): boolean; + /** + * No-op setter. Stream aborted status is set via the AbortSignal provided + * in the constructor options. + */ + set aborted(_: boolean); + /** + * Write data into the stream + * + * If the chunk written is a string, and encoding is not specified, then + * `utf8` will be assumed. If the stream encoding matches the encoding of + * a written string, and the state of the string decoder allows it, then + * the string will be passed through to either the output or the internal + * buffer without any processing. Otherwise, it will be turned into a + * Buffer object for processing into the desired encoding. + * + * If provided, `cb` function is called immediately before return for + * sync streams, or on next tick for async streams, because for this + * base class, a chunk is considered "processed" once it is accepted + * and either emitted or buffered. That is, the callback does not indicate + * that the chunk has been eventually emitted, though of course child + * classes can override this function to do whatever processing is required + * and call `super.write(...)` only once processing is completed. + */ + write(chunk: WType, cb?: () => void): boolean; + write(chunk: WType, encoding?: Minipass.Encoding, cb?: () => void): boolean; + /** + * Low-level explicit read method. + * + * In objectMode, the argument is ignored, and one item is returned if + * available. + * + * `n` is the number of bytes (or in the case of encoding streams, + * characters) to consume. If `n` is not provided, then the entire buffer + * is returned, or `null` is returned if no data is available. + * + * If `n` is greater that the amount of data in the internal buffer, + * then `null` is returned. + */ + read(n?: number | null): RType | null; + [READ](n: number | null, chunk: RType): RType; + /** + * End the stream, optionally providing a final write. + * + * See {@link Minipass#write} for argument descriptions + */ + end(cb?: () => void): this; + end(chunk: WType, cb?: () => void): this; + end(chunk: WType, encoding?: Minipass.Encoding, cb?: () => void): this; + [RESUME](): void; + /** + * Resume the stream if it is currently in a paused state + * + * If called when there are no pipe destinations or `data` event listeners, + * this will place the stream in a "discarded" state, where all data will + * be thrown away. The discarded state is removed if a pipe destination or + * data handler is added, if pause() is called, or if any synchronous or + * asynchronous iteration is started. + */ + resume(): void; + /** + * Pause the stream + */ + pause(): void; + /** + * true if the stream has been forcibly destroyed + */ + get destroyed(): boolean; + /** + * true if the stream is currently in a flowing state, meaning that + * any writes will be immediately emitted. + */ + get flowing(): boolean; + /** + * true if the stream is currently in a paused state + */ + get paused(): boolean; + [BUFFERPUSH](chunk: RType): void; + [BUFFERSHIFT](): RType; + [FLUSH](noDrain?: boolean): void; + [FLUSHCHUNK](chunk: RType): boolean; + /** + * Pipe all data emitted by this stream into the destination provided. + * + * Triggers the flow of data. + */ + pipe<W extends Minipass.Writable>(dest: W, opts?: PipeOptions): W; + /** + * Fully unhook a piped destination stream. + * + * If the destination stream was the only consumer of this stream (ie, + * there are no other piped destinations or `'data'` event listeners) + * then the flow of data will stop until there is another consumer or + * {@link Minipass#resume} is explicitly called. + */ + unpipe<W extends Minipass.Writable>(dest: W): void; + /** + * Alias for {@link Minipass#on} + */ + addListener<Event extends keyof Events>(ev: Event, handler: (...args: Events[Event]) => any): this; + /** + * Mostly identical to `EventEmitter.on`, with the following + * behavior differences to prevent data loss and unnecessary hangs: + * + * - Adding a 'data' event handler will trigger the flow of data + * + * - Adding a 'readable' event handler when there is data waiting to be read + * will cause 'readable' to be emitted immediately. + * + * - Adding an 'endish' event handler ('end', 'finish', etc.) which has + * already passed will cause the event to be emitted immediately and all + * handlers removed. + * + * - Adding an 'error' event handler after an error has been emitted will + * cause the event to be re-emitted immediately with the error previously + * raised. + */ + on<Event extends keyof Events>(ev: Event, handler: (...args: Events[Event]) => any): this; + /** + * Alias for {@link Minipass#off} + */ + removeListener<Event extends keyof Events>(ev: Event, handler: (...args: Events[Event]) => any): this; + /** + * Mostly identical to `EventEmitter.off` + * + * If a 'data' event handler is removed, and it was the last consumer + * (ie, there are no pipe destinations or other 'data' event listeners), + * then the flow of data will stop until there is another consumer or + * {@link Minipass#resume} is explicitly called. + */ + off<Event extends keyof Events>(ev: Event, handler: (...args: Events[Event]) => any): this; + /** + * Mostly identical to `EventEmitter.removeAllListeners` + * + * If all 'data' event handlers are removed, and they were the last consumer + * (ie, there are no pipe destinations), then the flow of data will stop + * until there is another consumer or {@link Minipass#resume} is explicitly + * called. + */ + removeAllListeners<Event extends keyof Events>(ev?: Event): this; + /** + * true if the 'end' event has been emitted + */ + get emittedEnd(): boolean; + [MAYBE_EMIT_END](): void; + /** + * Mostly identical to `EventEmitter.emit`, with the following + * behavior differences to prevent data loss and unnecessary hangs: + * + * If the stream has been destroyed, and the event is something other + * than 'close' or 'error', then `false` is returned and no handlers + * are called. + * + * If the event is 'end', and has already been emitted, then the event + * is ignored. If the stream is in a paused or non-flowing state, then + * the event will be deferred until data flow resumes. If the stream is + * async, then handlers will be called on the next tick rather than + * immediately. + * + * If the event is 'close', and 'end' has not yet been emitted, then + * the event will be deferred until after 'end' is emitted. + * + * If the event is 'error', and an AbortSignal was provided for the stream, + * and there are no listeners, then the event is ignored, matching the + * behavior of node core streams in the presense of an AbortSignal. + * + * If the event is 'finish' or 'prefinish', then all listeners will be + * removed after emitting the event, to prevent double-firing. + */ + emit<Event extends keyof Events>(ev: Event, ...args: Events[Event]): boolean; + [EMITDATA](data: RType): boolean; + [EMITEND](): boolean; + [EMITEND2](): boolean; + /** + * Return a Promise that resolves to an array of all emitted data once + * the stream ends. + */ + collect(): Promise<RType[] & { + dataLength: number; + }>; + /** + * Return a Promise that resolves to the concatenation of all emitted data + * once the stream ends. + * + * Not allowed on objectMode streams. + */ + concat(): Promise<RType>; + /** + * Return a void Promise that resolves once the stream ends. + */ + promise(): Promise<void>; + /** + * Asynchronous `for await of` iteration. + * + * This will continue emitting all chunks until the stream terminates. + */ + [Symbol.asyncIterator](): AsyncGenerator<RType, void, void>; + /** + * Synchronous `for of` iteration. + * + * The iteration will terminate when the internal buffer runs out, even + * if the stream has not yet terminated. + */ + [Symbol.iterator](): Generator<RType, void, void>; + /** + * Destroy a stream, preventing it from being used for any further purpose. + * + * If the stream has a `close()` method, then it will be called on + * destruction. + * + * After destruction, any attempt to write data, read data, or emit most + * events will be ignored. + * + * If an error argument is provided, then it will be emitted in an + * 'error' event. + */ + destroy(er?: unknown): this; + /** + * Alias for {@link isStream} + * + * Former export location, maintained for backwards compatibility. + * + * @deprecated + */ + static get isStream(): (s: any) => s is Minipass<any, any, any> | NodeJS.ReadStream | NodeJS.WriteStream | (EventEmitter<any> & { + end(): any; + write(chunk: any, ...args: any[]): any; + }) | (EventEmitter<any> & { + pause(): any; + resume(): any; + pipe(...destArgs: any[]): any; + }) | (NodeJS.ReadStream & { + fd: number; + }) | (NodeJS.WriteStream & { + fd: number; + }); +} +//# sourceMappingURL=index.d.ts.map
\ No newline at end of file diff --git a/node_modules/minipass/dist/commonjs/index.js b/node_modules/minipass/dist/commonjs/index.js new file mode 100644 index 0000000..91f3a5c --- /dev/null +++ b/node_modules/minipass/dist/commonjs/index.js @@ -0,0 +1,1038 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Minipass = exports.isWritable = exports.isReadable = exports.isStream = void 0; +const proc = typeof process === 'object' && process + ? process + : { + stdout: null, + stderr: null, + }; +const node_events_1 = require("node:events"); +const node_stream_1 = __importDefault(require("node:stream")); +const node_string_decoder_1 = require("node:string_decoder"); +/** + * Return true if the argument is a Minipass stream, Node stream, or something + * else that Minipass can interact with. + */ +const isStream = (s) => !!s && + typeof s === 'object' && + (s instanceof Minipass || + s instanceof node_stream_1.default || + (0, exports.isReadable)(s) || + (0, exports.isWritable)(s)) +/** + * Return true if the argument is a valid {@link Minipass.Readable} + */ +; +exports.isStream = isStream; +/** + * Return true if the argument is a valid {@link Minipass.Readable} + */ +const isReadable = (s) => !!s && + typeof s === 'object' && + s instanceof node_events_1.EventEmitter && + typeof s.pipe === 'function' && + // node core Writable streams have a pipe() method, but it throws + s.pipe !== node_stream_1.default.Writable.prototype.pipe +/** + * Return true if the argument is a valid {@link Minipass.Writable} + */ +; +exports.isReadable = isReadable; +/** + * Return true if the argument is a valid {@link Minipass.Writable} + */ +const isWritable = (s) => !!s && + typeof s === 'object' && + s instanceof node_events_1.EventEmitter && + typeof s.write === 'function' && + typeof s.end === 'function'; +exports.isWritable = isWritable; +const EOF = Symbol('EOF'); +const MAYBE_EMIT_END = Symbol('maybeEmitEnd'); +const EMITTED_END = Symbol('emittedEnd'); +const EMITTING_END = Symbol('emittingEnd'); +const EMITTED_ERROR = Symbol('emittedError'); +const CLOSED = Symbol('closed'); +const READ = Symbol('read'); +const FLUSH = Symbol('flush'); +const FLUSHCHUNK = Symbol('flushChunk'); +const ENCODING = Symbol('encoding'); +const DECODER = Symbol('decoder'); +const FLOWING = Symbol('flowing'); +const PAUSED = Symbol('paused'); +const RESUME = Symbol('resume'); +const BUFFER = Symbol('buffer'); +const PIPES = Symbol('pipes'); +const BUFFERLENGTH = Symbol('bufferLength'); +const BUFFERPUSH = Symbol('bufferPush'); +const BUFFERSHIFT = Symbol('bufferShift'); +const OBJECTMODE = Symbol('objectMode'); +// internal event when stream is destroyed +const DESTROYED = Symbol('destroyed'); +// internal event when stream has an error +const ERROR = Symbol('error'); +const EMITDATA = Symbol('emitData'); +const EMITEND = Symbol('emitEnd'); +const EMITEND2 = Symbol('emitEnd2'); +const ASYNC = Symbol('async'); +const ABORT = Symbol('abort'); +const ABORTED = Symbol('aborted'); +const SIGNAL = Symbol('signal'); +const DATALISTENERS = Symbol('dataListeners'); +const DISCARDED = Symbol('discarded'); +const defer = (fn) => Promise.resolve().then(fn); +const nodefer = (fn) => fn(); +const isEndish = (ev) => ev === 'end' || ev === 'finish' || ev === 'prefinish'; +const isArrayBufferLike = (b) => b instanceof ArrayBuffer || + (!!b && + typeof b === 'object' && + b.constructor && + b.constructor.name === 'ArrayBuffer' && + b.byteLength >= 0); +const isArrayBufferView = (b) => !Buffer.isBuffer(b) && ArrayBuffer.isView(b); +/** + * Internal class representing a pipe to a destination stream. + * + * @internal + */ +class Pipe { + src; + dest; + opts; + ondrain; + constructor(src, dest, opts) { + this.src = src; + this.dest = dest; + this.opts = opts; + this.ondrain = () => src[RESUME](); + this.dest.on('drain', this.ondrain); + } + unpipe() { + this.dest.removeListener('drain', this.ondrain); + } + // only here for the prototype + /* c8 ignore start */ + proxyErrors(_er) { } + /* c8 ignore stop */ + end() { + this.unpipe(); + if (this.opts.end) + this.dest.end(); + } +} +/** + * Internal class representing a pipe to a destination stream where + * errors are proxied. + * + * @internal + */ +class PipeProxyErrors extends Pipe { + unpipe() { + this.src.removeListener('error', this.proxyErrors); + super.unpipe(); + } + constructor(src, dest, opts) { + super(src, dest, opts); + this.proxyErrors = (er) => this.dest.emit('error', er); + src.on('error', this.proxyErrors); + } +} +const isObjectModeOptions = (o) => !!o.objectMode; +const isEncodingOptions = (o) => !o.objectMode && !!o.encoding && o.encoding !== 'buffer'; +/** + * Main export, the Minipass class + * + * `RType` is the type of data emitted, defaults to Buffer + * + * `WType` is the type of data to be written, if RType is buffer or string, + * then any {@link Minipass.ContiguousData} is allowed. + * + * `Events` is the set of event handler signatures that this object + * will emit, see {@link Minipass.Events} + */ +class Minipass extends node_events_1.EventEmitter { + [FLOWING] = false; + [PAUSED] = false; + [PIPES] = []; + [BUFFER] = []; + [OBJECTMODE]; + [ENCODING]; + [ASYNC]; + [DECODER]; + [EOF] = false; + [EMITTED_END] = false; + [EMITTING_END] = false; + [CLOSED] = false; + [EMITTED_ERROR] = null; + [BUFFERLENGTH] = 0; + [DESTROYED] = false; + [SIGNAL]; + [ABORTED] = false; + [DATALISTENERS] = 0; + [DISCARDED] = false; + /** + * true if the stream can be written + */ + writable = true; + /** + * true if the stream can be read + */ + readable = true; + /** + * If `RType` is Buffer, then options do not need to be provided. + * Otherwise, an options object must be provided to specify either + * {@link Minipass.SharedOptions.objectMode} or + * {@link Minipass.SharedOptions.encoding}, as appropriate. + */ + constructor(...args) { + const options = (args[0] || + {}); + super(); + if (options.objectMode && typeof options.encoding === 'string') { + throw new TypeError('Encoding and objectMode may not be used together'); + } + if (isObjectModeOptions(options)) { + this[OBJECTMODE] = true; + this[ENCODING] = null; + } + else if (isEncodingOptions(options)) { + this[ENCODING] = options.encoding; + this[OBJECTMODE] = false; + } + else { + this[OBJECTMODE] = false; + this[ENCODING] = null; + } + this[ASYNC] = !!options.async; + this[DECODER] = this[ENCODING] + ? new node_string_decoder_1.StringDecoder(this[ENCODING]) + : null; + //@ts-ignore - private option for debugging and testing + if (options && options.debugExposeBuffer === true) { + Object.defineProperty(this, 'buffer', { get: () => this[BUFFER] }); + } + //@ts-ignore - private option for debugging and testing + if (options && options.debugExposePipes === true) { + Object.defineProperty(this, 'pipes', { get: () => this[PIPES] }); + } + const { signal } = options; + if (signal) { + this[SIGNAL] = signal; + if (signal.aborted) { + this[ABORT](); + } + else { + signal.addEventListener('abort', () => this[ABORT]()); + } + } + } + /** + * The amount of data stored in the buffer waiting to be read. + * + * For Buffer strings, this will be the total byte length. + * For string encoding streams, this will be the string character length, + * according to JavaScript's `string.length` logic. + * For objectMode streams, this is a count of the items waiting to be + * emitted. + */ + get bufferLength() { + return this[BUFFERLENGTH]; + } + /** + * The `BufferEncoding` currently in use, or `null` + */ + get encoding() { + return this[ENCODING]; + } + /** + * @deprecated - This is a read only property + */ + set encoding(_enc) { + throw new Error('Encoding must be set at instantiation time'); + } + /** + * @deprecated - Encoding may only be set at instantiation time + */ + setEncoding(_enc) { + throw new Error('Encoding must be set at instantiation time'); + } + /** + * True if this is an objectMode stream + */ + get objectMode() { + return this[OBJECTMODE]; + } + /** + * @deprecated - This is a read-only property + */ + set objectMode(_om) { + throw new Error('objectMode must be set at instantiation time'); + } + /** + * true if this is an async stream + */ + get ['async']() { + return this[ASYNC]; + } + /** + * Set to true to make this stream async. + * + * Once set, it cannot be unset, as this would potentially cause incorrect + * behavior. Ie, a sync stream can be made async, but an async stream + * cannot be safely made sync. + */ + set ['async'](a) { + this[ASYNC] = this[ASYNC] || !!a; + } + // drop everything and get out of the flow completely + [ABORT]() { + this[ABORTED] = true; + this.emit('abort', this[SIGNAL]?.reason); + this.destroy(this[SIGNAL]?.reason); + } + /** + * True if the stream has been aborted. + */ + get aborted() { + return this[ABORTED]; + } + /** + * No-op setter. Stream aborted status is set via the AbortSignal provided + * in the constructor options. + */ + set aborted(_) { } + write(chunk, encoding, cb) { + if (this[ABORTED]) + return false; + if (this[EOF]) + throw new Error('write after end'); + if (this[DESTROYED]) { + this.emit('error', Object.assign(new Error('Cannot call write after a stream was destroyed'), { code: 'ERR_STREAM_DESTROYED' })); + return true; + } + if (typeof encoding === 'function') { + cb = encoding; + encoding = 'utf8'; + } + if (!encoding) + encoding = 'utf8'; + const fn = this[ASYNC] ? defer : nodefer; + // convert array buffers and typed array views into buffers + // at some point in the future, we may want to do the opposite! + // leave strings and buffers as-is + // anything is only allowed if in object mode, so throw + if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) { + if (isArrayBufferView(chunk)) { + //@ts-ignore - sinful unsafe type changing + chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength); + } + else if (isArrayBufferLike(chunk)) { + //@ts-ignore - sinful unsafe type changing + chunk = Buffer.from(chunk); + } + else if (typeof chunk !== 'string') { + throw new Error('Non-contiguous data written to non-objectMode stream'); + } + } + // handle object mode up front, since it's simpler + // this yields better performance, fewer checks later. + if (this[OBJECTMODE]) { + // maybe impossible? + /* c8 ignore start */ + if (this[FLOWING] && this[BUFFERLENGTH] !== 0) + this[FLUSH](true); + /* c8 ignore stop */ + if (this[FLOWING]) + this.emit('data', chunk); + else + this[BUFFERPUSH](chunk); + if (this[BUFFERLENGTH] !== 0) + this.emit('readable'); + if (cb) + fn(cb); + return this[FLOWING]; + } + // at this point the chunk is a buffer or string + // don't buffer it up or send it to the decoder + if (!chunk.length) { + if (this[BUFFERLENGTH] !== 0) + this.emit('readable'); + if (cb) + fn(cb); + return this[FLOWING]; + } + // fast-path writing strings of same encoding to a stream with + // an empty buffer, skipping the buffer/decoder dance + if (typeof chunk === 'string' && + // unless it is a string already ready for us to use + !(encoding === this[ENCODING] && !this[DECODER]?.lastNeed)) { + //@ts-ignore - sinful unsafe type change + chunk = Buffer.from(chunk, encoding); + } + if (Buffer.isBuffer(chunk) && this[ENCODING]) { + //@ts-ignore - sinful unsafe type change + chunk = this[DECODER].write(chunk); + } + // Note: flushing CAN potentially switch us into not-flowing mode + if (this[FLOWING] && this[BUFFERLENGTH] !== 0) + this[FLUSH](true); + if (this[FLOWING]) + this.emit('data', chunk); + else + this[BUFFERPUSH](chunk); + if (this[BUFFERLENGTH] !== 0) + this.emit('readable'); + if (cb) + fn(cb); + return this[FLOWING]; + } + /** + * Low-level explicit read method. + * + * In objectMode, the argument is ignored, and one item is returned if + * available. + * + * `n` is the number of bytes (or in the case of encoding streams, + * characters) to consume. If `n` is not provided, then the entire buffer + * is returned, or `null` is returned if no data is available. + * + * If `n` is greater that the amount of data in the internal buffer, + * then `null` is returned. + */ + read(n) { + if (this[DESTROYED]) + return null; + this[DISCARDED] = false; + if (this[BUFFERLENGTH] === 0 || + n === 0 || + (n && n > this[BUFFERLENGTH])) { + this[MAYBE_EMIT_END](); + return null; + } + if (this[OBJECTMODE]) + n = null; + if (this[BUFFER].length > 1 && !this[OBJECTMODE]) { + // not object mode, so if we have an encoding, then RType is string + // otherwise, must be Buffer + this[BUFFER] = [ + (this[ENCODING] + ? this[BUFFER].join('') + : Buffer.concat(this[BUFFER], this[BUFFERLENGTH])), + ]; + } + const ret = this[READ](n || null, this[BUFFER][0]); + this[MAYBE_EMIT_END](); + return ret; + } + [READ](n, chunk) { + if (this[OBJECTMODE]) + this[BUFFERSHIFT](); + else { + const c = chunk; + if (n === c.length || n === null) + this[BUFFERSHIFT](); + else if (typeof c === 'string') { + this[BUFFER][0] = c.slice(n); + chunk = c.slice(0, n); + this[BUFFERLENGTH] -= n; + } + else { + this[BUFFER][0] = c.subarray(n); + chunk = c.subarray(0, n); + this[BUFFERLENGTH] -= n; + } + } + this.emit('data', chunk); + if (!this[BUFFER].length && !this[EOF]) + this.emit('drain'); + return chunk; + } + end(chunk, encoding, cb) { + if (typeof chunk === 'function') { + cb = chunk; + chunk = undefined; + } + if (typeof encoding === 'function') { + cb = encoding; + encoding = 'utf8'; + } + if (chunk !== undefined) + this.write(chunk, encoding); + if (cb) + this.once('end', cb); + this[EOF] = true; + this.writable = false; + // if we haven't written anything, then go ahead and emit, + // even if we're not reading. + // we'll re-emit if a new 'end' listener is added anyway. + // This makes MP more suitable to write-only use cases. + if (this[FLOWING] || !this[PAUSED]) + this[MAYBE_EMIT_END](); + return this; + } + // don't let the internal resume be overwritten + [RESUME]() { + if (this[DESTROYED]) + return; + if (!this[DATALISTENERS] && !this[PIPES].length) { + this[DISCARDED] = true; + } + this[PAUSED] = false; + this[FLOWING] = true; + this.emit('resume'); + if (this[BUFFER].length) + this[FLUSH](); + else if (this[EOF]) + this[MAYBE_EMIT_END](); + else + this.emit('drain'); + } + /** + * Resume the stream if it is currently in a paused state + * + * If called when there are no pipe destinations or `data` event listeners, + * this will place the stream in a "discarded" state, where all data will + * be thrown away. The discarded state is removed if a pipe destination or + * data handler is added, if pause() is called, or if any synchronous or + * asynchronous iteration is started. + */ + resume() { + return this[RESUME](); + } + /** + * Pause the stream + */ + pause() { + this[FLOWING] = false; + this[PAUSED] = true; + this[DISCARDED] = false; + } + /** + * true if the stream has been forcibly destroyed + */ + get destroyed() { + return this[DESTROYED]; + } + /** + * true if the stream is currently in a flowing state, meaning that + * any writes will be immediately emitted. + */ + get flowing() { + return this[FLOWING]; + } + /** + * true if the stream is currently in a paused state + */ + get paused() { + return this[PAUSED]; + } + [BUFFERPUSH](chunk) { + if (this[OBJECTMODE]) + this[BUFFERLENGTH] += 1; + else + this[BUFFERLENGTH] += chunk.length; + this[BUFFER].push(chunk); + } + [BUFFERSHIFT]() { + if (this[OBJECTMODE]) + this[BUFFERLENGTH] -= 1; + else + this[BUFFERLENGTH] -= this[BUFFER][0].length; + return this[BUFFER].shift(); + } + [FLUSH](noDrain = false) { + do { } while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) && + this[BUFFER].length); + if (!noDrain && !this[BUFFER].length && !this[EOF]) + this.emit('drain'); + } + [FLUSHCHUNK](chunk) { + this.emit('data', chunk); + return this[FLOWING]; + } + /** + * Pipe all data emitted by this stream into the destination provided. + * + * Triggers the flow of data. + */ + pipe(dest, opts) { + if (this[DESTROYED]) + return dest; + this[DISCARDED] = false; + const ended = this[EMITTED_END]; + opts = opts || {}; + if (dest === proc.stdout || dest === proc.stderr) + opts.end = false; + else + opts.end = opts.end !== false; + opts.proxyErrors = !!opts.proxyErrors; + // piping an ended stream ends immediately + if (ended) { + if (opts.end) + dest.end(); + } + else { + // "as" here just ignores the WType, which pipes don't care about, + // since they're only consuming from us, and writing to the dest + this[PIPES].push(!opts.proxyErrors + ? new Pipe(this, dest, opts) + : new PipeProxyErrors(this, dest, opts)); + if (this[ASYNC]) + defer(() => this[RESUME]()); + else + this[RESUME](); + } + return dest; + } + /** + * Fully unhook a piped destination stream. + * + * If the destination stream was the only consumer of this stream (ie, + * there are no other piped destinations or `'data'` event listeners) + * then the flow of data will stop until there is another consumer or + * {@link Minipass#resume} is explicitly called. + */ + unpipe(dest) { + const p = this[PIPES].find(p => p.dest === dest); + if (p) { + if (this[PIPES].length === 1) { + if (this[FLOWING] && this[DATALISTENERS] === 0) { + this[FLOWING] = false; + } + this[PIPES] = []; + } + else + this[PIPES].splice(this[PIPES].indexOf(p), 1); + p.unpipe(); + } + } + /** + * Alias for {@link Minipass#on} + */ + addListener(ev, handler) { + return this.on(ev, handler); + } + /** + * Mostly identical to `EventEmitter.on`, with the following + * behavior differences to prevent data loss and unnecessary hangs: + * + * - Adding a 'data' event handler will trigger the flow of data + * + * - Adding a 'readable' event handler when there is data waiting to be read + * will cause 'readable' to be emitted immediately. + * + * - Adding an 'endish' event handler ('end', 'finish', etc.) which has + * already passed will cause the event to be emitted immediately and all + * handlers removed. + * + * - Adding an 'error' event handler after an error has been emitted will + * cause the event to be re-emitted immediately with the error previously + * raised. + */ + on(ev, handler) { + const ret = super.on(ev, handler); + if (ev === 'data') { + this[DISCARDED] = false; + this[DATALISTENERS]++; + if (!this[PIPES].length && !this[FLOWING]) { + this[RESUME](); + } + } + else if (ev === 'readable' && this[BUFFERLENGTH] !== 0) { + super.emit('readable'); + } + else if (isEndish(ev) && this[EMITTED_END]) { + super.emit(ev); + this.removeAllListeners(ev); + } + else if (ev === 'error' && this[EMITTED_ERROR]) { + const h = handler; + if (this[ASYNC]) + defer(() => h.call(this, this[EMITTED_ERROR])); + else + h.call(this, this[EMITTED_ERROR]); + } + return ret; + } + /** + * Alias for {@link Minipass#off} + */ + removeListener(ev, handler) { + return this.off(ev, handler); + } + /** + * Mostly identical to `EventEmitter.off` + * + * If a 'data' event handler is removed, and it was the last consumer + * (ie, there are no pipe destinations or other 'data' event listeners), + * then the flow of data will stop until there is another consumer or + * {@link Minipass#resume} is explicitly called. + */ + off(ev, handler) { + const ret = super.off(ev, handler); + // if we previously had listeners, and now we don't, and we don't + // have any pipes, then stop the flow, unless it's been explicitly + // put in a discarded flowing state via stream.resume(). + if (ev === 'data') { + this[DATALISTENERS] = this.listeners('data').length; + if (this[DATALISTENERS] === 0 && + !this[DISCARDED] && + !this[PIPES].length) { + this[FLOWING] = false; + } + } + return ret; + } + /** + * Mostly identical to `EventEmitter.removeAllListeners` + * + * If all 'data' event handlers are removed, and they were the last consumer + * (ie, there are no pipe destinations), then the flow of data will stop + * until there is another consumer or {@link Minipass#resume} is explicitly + * called. + */ + removeAllListeners(ev) { + const ret = super.removeAllListeners(ev); + if (ev === 'data' || ev === undefined) { + this[DATALISTENERS] = 0; + if (!this[DISCARDED] && !this[PIPES].length) { + this[FLOWING] = false; + } + } + return ret; + } + /** + * true if the 'end' event has been emitted + */ + get emittedEnd() { + return this[EMITTED_END]; + } + [MAYBE_EMIT_END]() { + if (!this[EMITTING_END] && + !this[EMITTED_END] && + !this[DESTROYED] && + this[BUFFER].length === 0 && + this[EOF]) { + this[EMITTING_END] = true; + this.emit('end'); + this.emit('prefinish'); + this.emit('finish'); + if (this[CLOSED]) + this.emit('close'); + this[EMITTING_END] = false; + } + } + /** + * Mostly identical to `EventEmitter.emit`, with the following + * behavior differences to prevent data loss and unnecessary hangs: + * + * If the stream has been destroyed, and the event is something other + * than 'close' or 'error', then `false` is returned and no handlers + * are called. + * + * If the event is 'end', and has already been emitted, then the event + * is ignored. If the stream is in a paused or non-flowing state, then + * the event will be deferred until data flow resumes. If the stream is + * async, then handlers will be called on the next tick rather than + * immediately. + * + * If the event is 'close', and 'end' has not yet been emitted, then + * the event will be deferred until after 'end' is emitted. + * + * If the event is 'error', and an AbortSignal was provided for the stream, + * and there are no listeners, then the event is ignored, matching the + * behavior of node core streams in the presense of an AbortSignal. + * + * If the event is 'finish' or 'prefinish', then all listeners will be + * removed after emitting the event, to prevent double-firing. + */ + emit(ev, ...args) { + const data = args[0]; + // error and close are only events allowed after calling destroy() + if (ev !== 'error' && + ev !== 'close' && + ev !== DESTROYED && + this[DESTROYED]) { + return false; + } + else if (ev === 'data') { + return !this[OBJECTMODE] && !data + ? false + : this[ASYNC] + ? (defer(() => this[EMITDATA](data)), true) + : this[EMITDATA](data); + } + else if (ev === 'end') { + return this[EMITEND](); + } + else if (ev === 'close') { + this[CLOSED] = true; + // don't emit close before 'end' and 'finish' + if (!this[EMITTED_END] && !this[DESTROYED]) + return false; + const ret = super.emit('close'); + this.removeAllListeners('close'); + return ret; + } + else if (ev === 'error') { + this[EMITTED_ERROR] = data; + super.emit(ERROR, data); + const ret = !this[SIGNAL] || this.listeners('error').length + ? super.emit('error', data) + : false; + this[MAYBE_EMIT_END](); + return ret; + } + else if (ev === 'resume') { + const ret = super.emit('resume'); + this[MAYBE_EMIT_END](); + return ret; + } + else if (ev === 'finish' || ev === 'prefinish') { + const ret = super.emit(ev); + this.removeAllListeners(ev); + return ret; + } + // Some other unknown event + const ret = super.emit(ev, ...args); + this[MAYBE_EMIT_END](); + return ret; + } + [EMITDATA](data) { + for (const p of this[PIPES]) { + if (p.dest.write(data) === false) + this.pause(); + } + const ret = this[DISCARDED] ? false : super.emit('data', data); + this[MAYBE_EMIT_END](); + return ret; + } + [EMITEND]() { + if (this[EMITTED_END]) + return false; + this[EMITTED_END] = true; + this.readable = false; + return this[ASYNC] + ? (defer(() => this[EMITEND2]()), true) + : this[EMITEND2](); + } + [EMITEND2]() { + if (this[DECODER]) { + const data = this[DECODER].end(); + if (data) { + for (const p of this[PIPES]) { + p.dest.write(data); + } + if (!this[DISCARDED]) + super.emit('data', data); + } + } + for (const p of this[PIPES]) { + p.end(); + } + const ret = super.emit('end'); + this.removeAllListeners('end'); + return ret; + } + /** + * Return a Promise that resolves to an array of all emitted data once + * the stream ends. + */ + async collect() { + const buf = Object.assign([], { + dataLength: 0, + }); + if (!this[OBJECTMODE]) + buf.dataLength = 0; + // set the promise first, in case an error is raised + // by triggering the flow here. + const p = this.promise(); + this.on('data', c => { + buf.push(c); + if (!this[OBJECTMODE]) + buf.dataLength += c.length; + }); + await p; + return buf; + } + /** + * Return a Promise that resolves to the concatenation of all emitted data + * once the stream ends. + * + * Not allowed on objectMode streams. + */ + async concat() { + if (this[OBJECTMODE]) { + throw new Error('cannot concat in objectMode'); + } + const buf = await this.collect(); + return (this[ENCODING] + ? buf.join('') + : Buffer.concat(buf, buf.dataLength)); + } + /** + * Return a void Promise that resolves once the stream ends. + */ + async promise() { + return new Promise((resolve, reject) => { + this.on(DESTROYED, () => reject(new Error('stream destroyed'))); + this.on('error', er => reject(er)); + this.on('end', () => resolve()); + }); + } + /** + * Asynchronous `for await of` iteration. + * + * This will continue emitting all chunks until the stream terminates. + */ + [Symbol.asyncIterator]() { + // set this up front, in case the consumer doesn't call next() + // right away. + this[DISCARDED] = false; + let stopped = false; + const stop = async () => { + this.pause(); + stopped = true; + return { value: undefined, done: true }; + }; + const next = () => { + if (stopped) + return stop(); + const res = this.read(); + if (res !== null) + return Promise.resolve({ done: false, value: res }); + if (this[EOF]) + return stop(); + let resolve; + let reject; + const onerr = (er) => { + this.off('data', ondata); + this.off('end', onend); + this.off(DESTROYED, ondestroy); + stop(); + reject(er); + }; + const ondata = (value) => { + this.off('error', onerr); + this.off('end', onend); + this.off(DESTROYED, ondestroy); + this.pause(); + resolve({ value, done: !!this[EOF] }); + }; + const onend = () => { + this.off('error', onerr); + this.off('data', ondata); + this.off(DESTROYED, ondestroy); + stop(); + resolve({ done: true, value: undefined }); + }; + const ondestroy = () => onerr(new Error('stream destroyed')); + return new Promise((res, rej) => { + reject = rej; + resolve = res; + this.once(DESTROYED, ondestroy); + this.once('error', onerr); + this.once('end', onend); + this.once('data', ondata); + }); + }; + return { + next, + throw: stop, + return: stop, + [Symbol.asyncIterator]() { + return this; + }, + [Symbol.asyncDispose]: async () => { }, + }; + } + /** + * Synchronous `for of` iteration. + * + * The iteration will terminate when the internal buffer runs out, even + * if the stream has not yet terminated. + */ + [Symbol.iterator]() { + // set this up front, in case the consumer doesn't call next() + // right away. + this[DISCARDED] = false; + let stopped = false; + const stop = () => { + this.pause(); + this.off(ERROR, stop); + this.off(DESTROYED, stop); + this.off('end', stop); + stopped = true; + return { done: true, value: undefined }; + }; + const next = () => { + if (stopped) + return stop(); + const value = this.read(); + return value === null ? stop() : { done: false, value }; + }; + this.once('end', stop); + this.once(ERROR, stop); + this.once(DESTROYED, stop); + return { + next, + throw: stop, + return: stop, + [Symbol.iterator]() { + return this; + }, + [Symbol.dispose]: () => { }, + }; + } + /** + * Destroy a stream, preventing it from being used for any further purpose. + * + * If the stream has a `close()` method, then it will be called on + * destruction. + * + * After destruction, any attempt to write data, read data, or emit most + * events will be ignored. + * + * If an error argument is provided, then it will be emitted in an + * 'error' event. + */ + destroy(er) { + if (this[DESTROYED]) { + if (er) + this.emit('error', er); + else + this.emit(DESTROYED); + return this; + } + this[DESTROYED] = true; + this[DISCARDED] = true; + // throw away all buffered data, it's never coming out + this[BUFFER].length = 0; + this[BUFFERLENGTH] = 0; + const wc = this; + if (typeof wc.close === 'function' && !this[CLOSED]) + wc.close(); + if (er) + this.emit('error', er); + // if no error to emit, still reject pending promises + else + this.emit(DESTROYED); + return this; + } + /** + * Alias for {@link isStream} + * + * Former export location, maintained for backwards compatibility. + * + * @deprecated + */ + static get isStream() { + return exports.isStream; + } +} +exports.Minipass = Minipass; +//# sourceMappingURL=index.js.map
\ No newline at end of file diff --git a/node_modules/minipass/dist/commonjs/package.json b/node_modules/minipass/dist/commonjs/package.json new file mode 100644 index 0000000..5bbefff --- /dev/null +++ b/node_modules/minipass/dist/commonjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/node_modules/minipass/dist/esm/index.d.ts b/node_modules/minipass/dist/esm/index.d.ts new file mode 100644 index 0000000..3e75b57 --- /dev/null +++ b/node_modules/minipass/dist/esm/index.d.ts @@ -0,0 +1,545 @@ +import { EventEmitter } from 'node:events'; +import { StringDecoder } from 'node:string_decoder'; +/** + * Same as StringDecoder, but exposing the `lastNeed` flag on the type + */ +type SD = StringDecoder & { + lastNeed: boolean; +}; +export type { SD, Pipe, PipeProxyErrors }; +/** + * Return true if the argument is a Minipass stream, Node stream, or something + * else that Minipass can interact with. + */ +export declare const isStream: (s: any) => s is Minipass<any, any, any> | NodeJS.ReadStream | NodeJS.WriteStream | (EventEmitter<any> & { + end(): any; + write(chunk: any, ...args: any[]): any; +}) | (EventEmitter<any> & { + pause(): any; + resume(): any; + pipe(...destArgs: any[]): any; +}) | (NodeJS.ReadStream & { + fd: number; +}) | (NodeJS.WriteStream & { + fd: number; +}); +/** + * Return true if the argument is a valid {@link Minipass.Readable} + */ +export declare const isReadable: (s: any) => s is Minipass.Readable; +/** + * Return true if the argument is a valid {@link Minipass.Writable} + */ +export declare const isWritable: (s: any) => s is Minipass.Readable; +declare const EOF: unique symbol; +declare const MAYBE_EMIT_END: unique symbol; +declare const EMITTED_END: unique symbol; +declare const EMITTING_END: unique symbol; +declare const EMITTED_ERROR: unique symbol; +declare const CLOSED: unique symbol; +declare const READ: unique symbol; +declare const FLUSH: unique symbol; +declare const FLUSHCHUNK: unique symbol; +declare const ENCODING: unique symbol; +declare const DECODER: unique symbol; +declare const FLOWING: unique symbol; +declare const PAUSED: unique symbol; +declare const RESUME: unique symbol; +declare const BUFFER: unique symbol; +declare const PIPES: unique symbol; +declare const BUFFERLENGTH: unique symbol; +declare const BUFFERPUSH: unique symbol; +declare const BUFFERSHIFT: unique symbol; +declare const OBJECTMODE: unique symbol; +declare const DESTROYED: unique symbol; +declare const ERROR: unique symbol; +declare const EMITDATA: unique symbol; +declare const EMITEND: unique symbol; +declare const EMITEND2: unique symbol; +declare const ASYNC: unique symbol; +declare const ABORT: unique symbol; +declare const ABORTED: unique symbol; +declare const SIGNAL: unique symbol; +declare const DATALISTENERS: unique symbol; +declare const DISCARDED: unique symbol; +/** + * Options that may be passed to stream.pipe() + */ +export interface PipeOptions { + /** + * end the destination stream when the source stream ends + */ + end?: boolean; + /** + * proxy errors from the source stream to the destination stream + */ + proxyErrors?: boolean; +} +/** + * Internal class representing a pipe to a destination stream. + * + * @internal + */ +declare class Pipe<T extends unknown> { + src: Minipass<T>; + dest: Minipass<any, T>; + opts: PipeOptions; + ondrain: () => any; + constructor(src: Minipass<T>, dest: Minipass.Writable, opts: PipeOptions); + unpipe(): void; + proxyErrors(_er: any): void; + end(): void; +} +/** + * Internal class representing a pipe to a destination stream where + * errors are proxied. + * + * @internal + */ +declare class PipeProxyErrors<T> extends Pipe<T> { + unpipe(): void; + constructor(src: Minipass<T>, dest: Minipass.Writable, opts: PipeOptions); +} +export declare namespace Minipass { + /** + * Encoding used to create a stream that outputs strings rather than + * Buffer objects. + */ + export type Encoding = BufferEncoding | 'buffer' | null; + /** + * Any stream that Minipass can pipe into + */ + export type Writable = Minipass<any, any, any> | NodeJS.WriteStream | (NodeJS.WriteStream & { + fd: number; + }) | (EventEmitter & { + end(): any; + write(chunk: any, ...args: any[]): any; + }); + /** + * Any stream that can be read from + */ + export type Readable = Minipass<any, any, any> | NodeJS.ReadStream | (NodeJS.ReadStream & { + fd: number; + }) | (EventEmitter & { + pause(): any; + resume(): any; + pipe(...destArgs: any[]): any; + }); + /** + * Utility type that can be iterated sync or async + */ + export type DualIterable<T> = Iterable<T> & AsyncIterable<T>; + type EventArguments = Record<string | symbol, unknown[]>; + /** + * The listing of events that a Minipass class can emit. + * Extend this when extending the Minipass class, and pass as + * the third template argument. The key is the name of the event, + * and the value is the argument list. + * + * Any undeclared events will still be allowed, but the handler will get + * arguments as `unknown[]`. + */ + export interface Events<RType extends any = Buffer> extends EventArguments { + readable: []; + data: [chunk: RType]; + error: [er: unknown]; + abort: [reason: unknown]; + drain: []; + resume: []; + end: []; + finish: []; + prefinish: []; + close: []; + [DESTROYED]: [er?: unknown]; + [ERROR]: [er: unknown]; + } + /** + * String or buffer-like data that can be joined and sliced + */ + export type ContiguousData = Buffer | ArrayBufferLike | ArrayBufferView | string; + export type BufferOrString = Buffer | string; + /** + * Options passed to the Minipass constructor. + */ + export type SharedOptions = { + /** + * Defer all data emission and other events until the end of the + * current tick, similar to Node core streams + */ + async?: boolean; + /** + * A signal which will abort the stream + */ + signal?: AbortSignal; + /** + * Output string encoding. Set to `null` or `'buffer'` (or omit) to + * emit Buffer objects rather than strings. + * + * Conflicts with `objectMode` + */ + encoding?: BufferEncoding | null | 'buffer'; + /** + * Output data exactly as it was written, supporting non-buffer/string + * data (such as arbitrary objects, falsey values, etc.) + * + * Conflicts with `encoding` + */ + objectMode?: boolean; + }; + /** + * Options for a string encoded output + */ + export type EncodingOptions = SharedOptions & { + encoding: BufferEncoding; + objectMode?: false; + }; + /** + * Options for contiguous data buffer output + */ + export type BufferOptions = SharedOptions & { + encoding?: null | 'buffer'; + objectMode?: false; + }; + /** + * Options for objectMode arbitrary output + */ + export type ObjectModeOptions = SharedOptions & { + objectMode: true; + encoding?: null; + }; + /** + * Utility type to determine allowed options based on read type + */ + export type Options<T> = ObjectModeOptions | (T extends string ? EncodingOptions : T extends Buffer ? BufferOptions : SharedOptions); + export {}; +} +/** + * Main export, the Minipass class + * + * `RType` is the type of data emitted, defaults to Buffer + * + * `WType` is the type of data to be written, if RType is buffer or string, + * then any {@link Minipass.ContiguousData} is allowed. + * + * `Events` is the set of event handler signatures that this object + * will emit, see {@link Minipass.Events} + */ +export declare class Minipass<RType extends unknown = Buffer, WType extends unknown = RType extends Minipass.BufferOrString ? Minipass.ContiguousData : RType, Events extends Minipass.Events<RType> = Minipass.Events<RType>> extends EventEmitter implements Minipass.DualIterable<RType> { + [FLOWING]: boolean; + [PAUSED]: boolean; + [PIPES]: Pipe<RType>[]; + [BUFFER]: RType[]; + [OBJECTMODE]: boolean; + [ENCODING]: BufferEncoding | null; + [ASYNC]: boolean; + [DECODER]: SD | null; + [EOF]: boolean; + [EMITTED_END]: boolean; + [EMITTING_END]: boolean; + [CLOSED]: boolean; + [EMITTED_ERROR]: unknown; + [BUFFERLENGTH]: number; + [DESTROYED]: boolean; + [SIGNAL]?: AbortSignal; + [ABORTED]: boolean; + [DATALISTENERS]: number; + [DISCARDED]: boolean; + /** + * true if the stream can be written + */ + writable: boolean; + /** + * true if the stream can be read + */ + readable: boolean; + /** + * If `RType` is Buffer, then options do not need to be provided. + * Otherwise, an options object must be provided to specify either + * {@link Minipass.SharedOptions.objectMode} or + * {@link Minipass.SharedOptions.encoding}, as appropriate. + */ + constructor(...args: [Minipass.ObjectModeOptions] | (RType extends Buffer ? [] | [Minipass.Options<RType>] : [Minipass.Options<RType>])); + /** + * The amount of data stored in the buffer waiting to be read. + * + * For Buffer strings, this will be the total byte length. + * For string encoding streams, this will be the string character length, + * according to JavaScript's `string.length` logic. + * For objectMode streams, this is a count of the items waiting to be + * emitted. + */ + get bufferLength(): number; + /** + * The `BufferEncoding` currently in use, or `null` + */ + get encoding(): BufferEncoding | null; + /** + * @deprecated - This is a read only property + */ + set encoding(_enc: BufferEncoding | null); + /** + * @deprecated - Encoding may only be set at instantiation time + */ + setEncoding(_enc: Minipass.Encoding): void; + /** + * True if this is an objectMode stream + */ + get objectMode(): boolean; + /** + * @deprecated - This is a read-only property + */ + set objectMode(_om: boolean); + /** + * true if this is an async stream + */ + get ['async'](): boolean; + /** + * Set to true to make this stream async. + * + * Once set, it cannot be unset, as this would potentially cause incorrect + * behavior. Ie, a sync stream can be made async, but an async stream + * cannot be safely made sync. + */ + set ['async'](a: boolean); + [ABORT](): void; + /** + * True if the stream has been aborted. + */ + get aborted(): boolean; + /** + * No-op setter. Stream aborted status is set via the AbortSignal provided + * in the constructor options. + */ + set aborted(_: boolean); + /** + * Write data into the stream + * + * If the chunk written is a string, and encoding is not specified, then + * `utf8` will be assumed. If the stream encoding matches the encoding of + * a written string, and the state of the string decoder allows it, then + * the string will be passed through to either the output or the internal + * buffer without any processing. Otherwise, it will be turned into a + * Buffer object for processing into the desired encoding. + * + * If provided, `cb` function is called immediately before return for + * sync streams, or on next tick for async streams, because for this + * base class, a chunk is considered "processed" once it is accepted + * and either emitted or buffered. That is, the callback does not indicate + * that the chunk has been eventually emitted, though of course child + * classes can override this function to do whatever processing is required + * and call `super.write(...)` only once processing is completed. + */ + write(chunk: WType, cb?: () => void): boolean; + write(chunk: WType, encoding?: Minipass.Encoding, cb?: () => void): boolean; + /** + * Low-level explicit read method. + * + * In objectMode, the argument is ignored, and one item is returned if + * available. + * + * `n` is the number of bytes (or in the case of encoding streams, + * characters) to consume. If `n` is not provided, then the entire buffer + * is returned, or `null` is returned if no data is available. + * + * If `n` is greater that the amount of data in the internal buffer, + * then `null` is returned. + */ + read(n?: number | null): RType | null; + [READ](n: number | null, chunk: RType): RType; + /** + * End the stream, optionally providing a final write. + * + * See {@link Minipass#write} for argument descriptions + */ + end(cb?: () => void): this; + end(chunk: WType, cb?: () => void): this; + end(chunk: WType, encoding?: Minipass.Encoding, cb?: () => void): this; + [RESUME](): void; + /** + * Resume the stream if it is currently in a paused state + * + * If called when there are no pipe destinations or `data` event listeners, + * this will place the stream in a "discarded" state, where all data will + * be thrown away. The discarded state is removed if a pipe destination or + * data handler is added, if pause() is called, or if any synchronous or + * asynchronous iteration is started. + */ + resume(): void; + /** + * Pause the stream + */ + pause(): void; + /** + * true if the stream has been forcibly destroyed + */ + get destroyed(): boolean; + /** + * true if the stream is currently in a flowing state, meaning that + * any writes will be immediately emitted. + */ + get flowing(): boolean; + /** + * true if the stream is currently in a paused state + */ + get paused(): boolean; + [BUFFERPUSH](chunk: RType): void; + [BUFFERSHIFT](): RType; + [FLUSH](noDrain?: boolean): void; + [FLUSHCHUNK](chunk: RType): boolean; + /** + * Pipe all data emitted by this stream into the destination provided. + * + * Triggers the flow of data. + */ + pipe<W extends Minipass.Writable>(dest: W, opts?: PipeOptions): W; + /** + * Fully unhook a piped destination stream. + * + * If the destination stream was the only consumer of this stream (ie, + * there are no other piped destinations or `'data'` event listeners) + * then the flow of data will stop until there is another consumer or + * {@link Minipass#resume} is explicitly called. + */ + unpipe<W extends Minipass.Writable>(dest: W): void; + /** + * Alias for {@link Minipass#on} + */ + addListener<Event extends keyof Events>(ev: Event, handler: (...args: Events[Event]) => any): this; + /** + * Mostly identical to `EventEmitter.on`, with the following + * behavior differences to prevent data loss and unnecessary hangs: + * + * - Adding a 'data' event handler will trigger the flow of data + * + * - Adding a 'readable' event handler when there is data waiting to be read + * will cause 'readable' to be emitted immediately. + * + * - Adding an 'endish' event handler ('end', 'finish', etc.) which has + * already passed will cause the event to be emitted immediately and all + * handlers removed. + * + * - Adding an 'error' event handler after an error has been emitted will + * cause the event to be re-emitted immediately with the error previously + * raised. + */ + on<Event extends keyof Events>(ev: Event, handler: (...args: Events[Event]) => any): this; + /** + * Alias for {@link Minipass#off} + */ + removeListener<Event extends keyof Events>(ev: Event, handler: (...args: Events[Event]) => any): this; + /** + * Mostly identical to `EventEmitter.off` + * + * If a 'data' event handler is removed, and it was the last consumer + * (ie, there are no pipe destinations or other 'data' event listeners), + * then the flow of data will stop until there is another consumer or + * {@link Minipass#resume} is explicitly called. + */ + off<Event extends keyof Events>(ev: Event, handler: (...args: Events[Event]) => any): this; + /** + * Mostly identical to `EventEmitter.removeAllListeners` + * + * If all 'data' event handlers are removed, and they were the last consumer + * (ie, there are no pipe destinations), then the flow of data will stop + * until there is another consumer or {@link Minipass#resume} is explicitly + * called. + */ + removeAllListeners<Event extends keyof Events>(ev?: Event): this; + /** + * true if the 'end' event has been emitted + */ + get emittedEnd(): boolean; + [MAYBE_EMIT_END](): void; + /** + * Mostly identical to `EventEmitter.emit`, with the following + * behavior differences to prevent data loss and unnecessary hangs: + * + * If the stream has been destroyed, and the event is something other + * than 'close' or 'error', then `false` is returned and no handlers + * are called. + * + * If the event is 'end', and has already been emitted, then the event + * is ignored. If the stream is in a paused or non-flowing state, then + * the event will be deferred until data flow resumes. If the stream is + * async, then handlers will be called on the next tick rather than + * immediately. + * + * If the event is 'close', and 'end' has not yet been emitted, then + * the event will be deferred until after 'end' is emitted. + * + * If the event is 'error', and an AbortSignal was provided for the stream, + * and there are no listeners, then the event is ignored, matching the + * behavior of node core streams in the presense of an AbortSignal. + * + * If the event is 'finish' or 'prefinish', then all listeners will be + * removed after emitting the event, to prevent double-firing. + */ + emit<Event extends keyof Events>(ev: Event, ...args: Events[Event]): boolean; + [EMITDATA](data: RType): boolean; + [EMITEND](): boolean; + [EMITEND2](): boolean; + /** + * Return a Promise that resolves to an array of all emitted data once + * the stream ends. + */ + collect(): Promise<RType[] & { + dataLength: number; + }>; + /** + * Return a Promise that resolves to the concatenation of all emitted data + * once the stream ends. + * + * Not allowed on objectMode streams. + */ + concat(): Promise<RType>; + /** + * Return a void Promise that resolves once the stream ends. + */ + promise(): Promise<void>; + /** + * Asynchronous `for await of` iteration. + * + * This will continue emitting all chunks until the stream terminates. + */ + [Symbol.asyncIterator](): AsyncGenerator<RType, void, void>; + /** + * Synchronous `for of` iteration. + * + * The iteration will terminate when the internal buffer runs out, even + * if the stream has not yet terminated. + */ + [Symbol.iterator](): Generator<RType, void, void>; + /** + * Destroy a stream, preventing it from being used for any further purpose. + * + * If the stream has a `close()` method, then it will be called on + * destruction. + * + * After destruction, any attempt to write data, read data, or emit most + * events will be ignored. + * + * If an error argument is provided, then it will be emitted in an + * 'error' event. + */ + destroy(er?: unknown): this; + /** + * Alias for {@link isStream} + * + * Former export location, maintained for backwards compatibility. + * + * @deprecated + */ + static get isStream(): (s: any) => s is Minipass<any, any, any> | NodeJS.ReadStream | NodeJS.WriteStream | (EventEmitter<any> & { + end(): any; + write(chunk: any, ...args: any[]): any; + }) | (EventEmitter<any> & { + pause(): any; + resume(): any; + pipe(...destArgs: any[]): any; + }) | (NodeJS.ReadStream & { + fd: number; + }) | (NodeJS.WriteStream & { + fd: number; + }); +} +//# sourceMappingURL=index.d.ts.map
\ No newline at end of file diff --git a/node_modules/minipass/dist/esm/index.js b/node_modules/minipass/dist/esm/index.js new file mode 100644 index 0000000..5df5546 --- /dev/null +++ b/node_modules/minipass/dist/esm/index.js @@ -0,0 +1,1020 @@ +const proc = typeof process === 'object' && process + ? process + : { + stdout: null, + stderr: null, + }; +import { EventEmitter } from 'node:events'; +import Stream from 'node:stream'; +import { StringDecoder } from 'node:string_decoder'; +/** + * Return true if the argument is a Minipass stream, Node stream, or something + * else that Minipass can interact with. + */ +export const isStream = (s) => !!s && + typeof s === 'object' && + (s instanceof Minipass || + s instanceof Stream || + isReadable(s) || + isWritable(s)); +/** + * Return true if the argument is a valid {@link Minipass.Readable} + */ +export const isReadable = (s) => !!s && + typeof s === 'object' && + s instanceof EventEmitter && + typeof s.pipe === 'function' && + // node core Writable streams have a pipe() method, but it throws + s.pipe !== Stream.Writable.prototype.pipe; +/** + * Return true if the argument is a valid {@link Minipass.Writable} + */ +export const isWritable = (s) => !!s && + typeof s === 'object' && + s instanceof EventEmitter && + typeof s.write === 'function' && + typeof s.end === 'function'; +const EOF = Symbol('EOF'); +const MAYBE_EMIT_END = Symbol('maybeEmitEnd'); +const EMITTED_END = Symbol('emittedEnd'); +const EMITTING_END = Symbol('emittingEnd'); +const EMITTED_ERROR = Symbol('emittedError'); +const CLOSED = Symbol('closed'); +const READ = Symbol('read'); +const FLUSH = Symbol('flush'); +const FLUSHCHUNK = Symbol('flushChunk'); +const ENCODING = Symbol('encoding'); +const DECODER = Symbol('decoder'); +const FLOWING = Symbol('flowing'); +const PAUSED = Symbol('paused'); +const RESUME = Symbol('resume'); +const BUFFER = Symbol('buffer'); +const PIPES = Symbol('pipes'); +const BUFFERLENGTH = Symbol('bufferLength'); +const BUFFERPUSH = Symbol('bufferPush'); +const BUFFERSHIFT = Symbol('bufferShift'); +const OBJECTMODE = Symbol('objectMode'); +// internal event when stream is destroyed +const DESTROYED = Symbol('destroyed'); +// internal event when stream has an error +const ERROR = Symbol('error'); +const EMITDATA = Symbol('emitData'); +const EMITEND = Symbol('emitEnd'); +const EMITEND2 = Symbol('emitEnd2'); +const ASYNC = Symbol('async'); +const ABORT = Symbol('abort'); +const ABORTED = Symbol('aborted'); +const SIGNAL = Symbol('signal'); +const DATALISTENERS = Symbol('dataListeners'); +const DISCARDED = Symbol('discarded'); +const defer = (fn) => Promise.resolve().then(fn); +const nodefer = (fn) => fn(); +const isEndish = (ev) => ev === 'end' || ev === 'finish' || ev === 'prefinish'; +const isArrayBufferLike = (b) => b instanceof ArrayBuffer || + (!!b && + typeof b === 'object' && + b.constructor && + b.constructor.name === 'ArrayBuffer' && + b.byteLength >= 0); +const isArrayBufferView = (b) => !Buffer.isBuffer(b) && ArrayBuffer.isView(b); +/** + * Internal class representing a pipe to a destination stream. + * + * @internal + */ +class Pipe { + src; + dest; + opts; + ondrain; + constructor(src, dest, opts) { + this.src = src; + this.dest = dest; + this.opts = opts; + this.ondrain = () => src[RESUME](); + this.dest.on('drain', this.ondrain); + } + unpipe() { + this.dest.removeListener('drain', this.ondrain); + } + // only here for the prototype + /* c8 ignore start */ + proxyErrors(_er) { } + /* c8 ignore stop */ + end() { + this.unpipe(); + if (this.opts.end) + this.dest.end(); + } +} +/** + * Internal class representing a pipe to a destination stream where + * errors are proxied. + * + * @internal + */ +class PipeProxyErrors extends Pipe { + unpipe() { + this.src.removeListener('error', this.proxyErrors); + super.unpipe(); + } + constructor(src, dest, opts) { + super(src, dest, opts); + this.proxyErrors = (er) => this.dest.emit('error', er); + src.on('error', this.proxyErrors); + } +} +const isObjectModeOptions = (o) => !!o.objectMode; +const isEncodingOptions = (o) => !o.objectMode && !!o.encoding && o.encoding !== 'buffer'; +/** + * Main export, the Minipass class + * + * `RType` is the type of data emitted, defaults to Buffer + * + * `WType` is the type of data to be written, if RType is buffer or string, + * then any {@link Minipass.ContiguousData} is allowed. + * + * `Events` is the set of event handler signatures that this object + * will emit, see {@link Minipass.Events} + */ +export class Minipass extends EventEmitter { + [FLOWING] = false; + [PAUSED] = false; + [PIPES] = []; + [BUFFER] = []; + [OBJECTMODE]; + [ENCODING]; + [ASYNC]; + [DECODER]; + [EOF] = false; + [EMITTED_END] = false; + [EMITTING_END] = false; + [CLOSED] = false; + [EMITTED_ERROR] = null; + [BUFFERLENGTH] = 0; + [DESTROYED] = false; + [SIGNAL]; + [ABORTED] = false; + [DATALISTENERS] = 0; + [DISCARDED] = false; + /** + * true if the stream can be written + */ + writable = true; + /** + * true if the stream can be read + */ + readable = true; + /** + * If `RType` is Buffer, then options do not need to be provided. + * Otherwise, an options object must be provided to specify either + * {@link Minipass.SharedOptions.objectMode} or + * {@link Minipass.SharedOptions.encoding}, as appropriate. + */ + constructor(...args) { + const options = (args[0] || + {}); + super(); + if (options.objectMode && typeof options.encoding === 'string') { + throw new TypeError('Encoding and objectMode may not be used together'); + } + if (isObjectModeOptions(options)) { + this[OBJECTMODE] = true; + this[ENCODING] = null; + } + else if (isEncodingOptions(options)) { + this[ENCODING] = options.encoding; + this[OBJECTMODE] = false; + } + else { + this[OBJECTMODE] = false; + this[ENCODING] = null; + } + this[ASYNC] = !!options.async; + this[DECODER] = this[ENCODING] + ? new StringDecoder(this[ENCODING]) + : null; + //@ts-ignore - private option for debugging and testing + if (options && options.debugExposeBuffer === true) { + Object.defineProperty(this, 'buffer', { get: () => this[BUFFER] }); + } + //@ts-ignore - private option for debugging and testing + if (options && options.debugExposePipes === true) { + Object.defineProperty(this, 'pipes', { get: () => this[PIPES] }); + } + const { signal } = options; + if (signal) { + this[SIGNAL] = signal; + if (signal.aborted) { + this[ABORT](); + } + else { + signal.addEventListener('abort', () => this[ABORT]()); + } + } + } + /** + * The amount of data stored in the buffer waiting to be read. + * + * For Buffer strings, this will be the total byte length. + * For string encoding streams, this will be the string character length, + * according to JavaScript's `string.length` logic. + * For objectMode streams, this is a count of the items waiting to be + * emitted. + */ + get bufferLength() { + return this[BUFFERLENGTH]; + } + /** + * The `BufferEncoding` currently in use, or `null` + */ + get encoding() { + return this[ENCODING]; + } + /** + * @deprecated - This is a read only property + */ + set encoding(_enc) { + throw new Error('Encoding must be set at instantiation time'); + } + /** + * @deprecated - Encoding may only be set at instantiation time + */ + setEncoding(_enc) { + throw new Error('Encoding must be set at instantiation time'); + } + /** + * True if this is an objectMode stream + */ + get objectMode() { + return this[OBJECTMODE]; + } + /** + * @deprecated - This is a read-only property + */ + set objectMode(_om) { + throw new Error('objectMode must be set at instantiation time'); + } + /** + * true if this is an async stream + */ + get ['async']() { + return this[ASYNC]; + } + /** + * Set to true to make this stream async. + * + * Once set, it cannot be unset, as this would potentially cause incorrect + * behavior. Ie, a sync stream can be made async, but an async stream + * cannot be safely made sync. + */ + set ['async'](a) { + this[ASYNC] = this[ASYNC] || !!a; + } + // drop everything and get out of the flow completely + [ABORT]() { + this[ABORTED] = true; + this.emit('abort', this[SIGNAL]?.reason); + this.destroy(this[SIGNAL]?.reason); + } + /** + * True if the stream has been aborted. + */ + get aborted() { + return this[ABORTED]; + } + /** + * No-op setter. Stream aborted status is set via the AbortSignal provided + * in the constructor options. + */ + set aborted(_) { } + write(chunk, encoding, cb) { + if (this[ABORTED]) + return false; + if (this[EOF]) + throw new Error('write after end'); + if (this[DESTROYED]) { + this.emit('error', Object.assign(new Error('Cannot call write after a stream was destroyed'), { code: 'ERR_STREAM_DESTROYED' })); + return true; + } + if (typeof encoding === 'function') { + cb = encoding; + encoding = 'utf8'; + } + if (!encoding) + encoding = 'utf8'; + const fn = this[ASYNC] ? defer : nodefer; + // convert array buffers and typed array views into buffers + // at some point in the future, we may want to do the opposite! + // leave strings and buffers as-is + // anything is only allowed if in object mode, so throw + if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) { + if (isArrayBufferView(chunk)) { + //@ts-ignore - sinful unsafe type changing + chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength); + } + else if (isArrayBufferLike(chunk)) { + //@ts-ignore - sinful unsafe type changing + chunk = Buffer.from(chunk); + } + else if (typeof chunk !== 'string') { + throw new Error('Non-contiguous data written to non-objectMode stream'); + } + } + // handle object mode up front, since it's simpler + // this yields better performance, fewer checks later. + if (this[OBJECTMODE]) { + // maybe impossible? + /* c8 ignore start */ + if (this[FLOWING] && this[BUFFERLENGTH] !== 0) + this[FLUSH](true); + /* c8 ignore stop */ + if (this[FLOWING]) + this.emit('data', chunk); + else + this[BUFFERPUSH](chunk); + if (this[BUFFERLENGTH] !== 0) + this.emit('readable'); + if (cb) + fn(cb); + return this[FLOWING]; + } + // at this point the chunk is a buffer or string + // don't buffer it up or send it to the decoder + if (!chunk.length) { + if (this[BUFFERLENGTH] !== 0) + this.emit('readable'); + if (cb) + fn(cb); + return this[FLOWING]; + } + // fast-path writing strings of same encoding to a stream with + // an empty buffer, skipping the buffer/decoder dance + if (typeof chunk === 'string' && + // unless it is a string already ready for us to use + !(encoding === this[ENCODING] && !this[DECODER]?.lastNeed)) { + //@ts-ignore - sinful unsafe type change + chunk = Buffer.from(chunk, encoding); + } + if (Buffer.isBuffer(chunk) && this[ENCODING]) { + //@ts-ignore - sinful unsafe type change + chunk = this[DECODER].write(chunk); + } + // Note: flushing CAN potentially switch us into not-flowing mode + if (this[FLOWING] && this[BUFFERLENGTH] !== 0) + this[FLUSH](true); + if (this[FLOWING]) + this.emit('data', chunk); + else + this[BUFFERPUSH](chunk); + if (this[BUFFERLENGTH] !== 0) + this.emit('readable'); + if (cb) + fn(cb); + return this[FLOWING]; + } + /** + * Low-level explicit read method. + * + * In objectMode, the argument is ignored, and one item is returned if + * available. + * + * `n` is the number of bytes (or in the case of encoding streams, + * characters) to consume. If `n` is not provided, then the entire buffer + * is returned, or `null` is returned if no data is available. + * + * If `n` is greater that the amount of data in the internal buffer, + * then `null` is returned. + */ + read(n) { + if (this[DESTROYED]) + return null; + this[DISCARDED] = false; + if (this[BUFFERLENGTH] === 0 || + n === 0 || + (n && n > this[BUFFERLENGTH])) { + this[MAYBE_EMIT_END](); + return null; + } + if (this[OBJECTMODE]) + n = null; + if (this[BUFFER].length > 1 && !this[OBJECTMODE]) { + // not object mode, so if we have an encoding, then RType is string + // otherwise, must be Buffer + this[BUFFER] = [ + (this[ENCODING] + ? this[BUFFER].join('') + : Buffer.concat(this[BUFFER], this[BUFFERLENGTH])), + ]; + } + const ret = this[READ](n || null, this[BUFFER][0]); + this[MAYBE_EMIT_END](); + return ret; + } + [READ](n, chunk) { + if (this[OBJECTMODE]) + this[BUFFERSHIFT](); + else { + const c = chunk; + if (n === c.length || n === null) + this[BUFFERSHIFT](); + else if (typeof c === 'string') { + this[BUFFER][0] = c.slice(n); + chunk = c.slice(0, n); + this[BUFFERLENGTH] -= n; + } + else { + this[BUFFER][0] = c.subarray(n); + chunk = c.subarray(0, n); + this[BUFFERLENGTH] -= n; + } + } + this.emit('data', chunk); + if (!this[BUFFER].length && !this[EOF]) + this.emit('drain'); + return chunk; + } + end(chunk, encoding, cb) { + if (typeof chunk === 'function') { + cb = chunk; + chunk = undefined; + } + if (typeof encoding === 'function') { + cb = encoding; + encoding = 'utf8'; + } + if (chunk !== undefined) + this.write(chunk, encoding); + if (cb) + this.once('end', cb); + this[EOF] = true; + this.writable = false; + // if we haven't written anything, then go ahead and emit, + // even if we're not reading. + // we'll re-emit if a new 'end' listener is added anyway. + // This makes MP more suitable to write-only use cases. + if (this[FLOWING] || !this[PAUSED]) + this[MAYBE_EMIT_END](); + return this; + } + // don't let the internal resume be overwritten + [RESUME]() { + if (this[DESTROYED]) + return; + if (!this[DATALISTENERS] && !this[PIPES].length) { + this[DISCARDED] = true; + } + this[PAUSED] = false; + this[FLOWING] = true; + this.emit('resume'); + if (this[BUFFER].length) + this[FLUSH](); + else if (this[EOF]) + this[MAYBE_EMIT_END](); + else + this.emit('drain'); + } + /** + * Resume the stream if it is currently in a paused state + * + * If called when there are no pipe destinations or `data` event listeners, + * this will place the stream in a "discarded" state, where all data will + * be thrown away. The discarded state is removed if a pipe destination or + * data handler is added, if pause() is called, or if any synchronous or + * asynchronous iteration is started. + */ + resume() { + return this[RESUME](); + } + /** + * Pause the stream + */ + pause() { + this[FLOWING] = false; + this[PAUSED] = true; + this[DISCARDED] = false; + } + /** + * true if the stream has been forcibly destroyed + */ + get destroyed() { + return this[DESTROYED]; + } + /** + * true if the stream is currently in a flowing state, meaning that + * any writes will be immediately emitted. + */ + get flowing() { + return this[FLOWING]; + } + /** + * true if the stream is currently in a paused state + */ + get paused() { + return this[PAUSED]; + } + [BUFFERPUSH](chunk) { + if (this[OBJECTMODE]) + this[BUFFERLENGTH] += 1; + else + this[BUFFERLENGTH] += chunk.length; + this[BUFFER].push(chunk); + } + [BUFFERSHIFT]() { + if (this[OBJECTMODE]) + this[BUFFERLENGTH] -= 1; + else + this[BUFFERLENGTH] -= this[BUFFER][0].length; + return this[BUFFER].shift(); + } + [FLUSH](noDrain = false) { + do { } while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) && + this[BUFFER].length); + if (!noDrain && !this[BUFFER].length && !this[EOF]) + this.emit('drain'); + } + [FLUSHCHUNK](chunk) { + this.emit('data', chunk); + return this[FLOWING]; + } + /** + * Pipe all data emitted by this stream into the destination provided. + * + * Triggers the flow of data. + */ + pipe(dest, opts) { + if (this[DESTROYED]) + return dest; + this[DISCARDED] = false; + const ended = this[EMITTED_END]; + opts = opts || {}; + if (dest === proc.stdout || dest === proc.stderr) + opts.end = false; + else + opts.end = opts.end !== false; + opts.proxyErrors = !!opts.proxyErrors; + // piping an ended stream ends immediately + if (ended) { + if (opts.end) + dest.end(); + } + else { + // "as" here just ignores the WType, which pipes don't care about, + // since they're only consuming from us, and writing to the dest + this[PIPES].push(!opts.proxyErrors + ? new Pipe(this, dest, opts) + : new PipeProxyErrors(this, dest, opts)); + if (this[ASYNC]) + defer(() => this[RESUME]()); + else + this[RESUME](); + } + return dest; + } + /** + * Fully unhook a piped destination stream. + * + * If the destination stream was the only consumer of this stream (ie, + * there are no other piped destinations or `'data'` event listeners) + * then the flow of data will stop until there is another consumer or + * {@link Minipass#resume} is explicitly called. + */ + unpipe(dest) { + const p = this[PIPES].find(p => p.dest === dest); + if (p) { + if (this[PIPES].length === 1) { + if (this[FLOWING] && this[DATALISTENERS] === 0) { + this[FLOWING] = false; + } + this[PIPES] = []; + } + else + this[PIPES].splice(this[PIPES].indexOf(p), 1); + p.unpipe(); + } + } + /** + * Alias for {@link Minipass#on} + */ + addListener(ev, handler) { + return this.on(ev, handler); + } + /** + * Mostly identical to `EventEmitter.on`, with the following + * behavior differences to prevent data loss and unnecessary hangs: + * + * - Adding a 'data' event handler will trigger the flow of data + * + * - Adding a 'readable' event handler when there is data waiting to be read + * will cause 'readable' to be emitted immediately. + * + * - Adding an 'endish' event handler ('end', 'finish', etc.) which has + * already passed will cause the event to be emitted immediately and all + * handlers removed. + * + * - Adding an 'error' event handler after an error has been emitted will + * cause the event to be re-emitted immediately with the error previously + * raised. + */ + on(ev, handler) { + const ret = super.on(ev, handler); + if (ev === 'data') { + this[DISCARDED] = false; + this[DATALISTENERS]++; + if (!this[PIPES].length && !this[FLOWING]) { + this[RESUME](); + } + } + else if (ev === 'readable' && this[BUFFERLENGTH] !== 0) { + super.emit('readable'); + } + else if (isEndish(ev) && this[EMITTED_END]) { + super.emit(ev); + this.removeAllListeners(ev); + } + else if (ev === 'error' && this[EMITTED_ERROR]) { + const h = handler; + if (this[ASYNC]) + defer(() => h.call(this, this[EMITTED_ERROR])); + else + h.call(this, this[EMITTED_ERROR]); + } + return ret; + } + /** + * Alias for {@link Minipass#off} + */ + removeListener(ev, handler) { + return this.off(ev, handler); + } + /** + * Mostly identical to `EventEmitter.off` + * + * If a 'data' event handler is removed, and it was the last consumer + * (ie, there are no pipe destinations or other 'data' event listeners), + * then the flow of data will stop until there is another consumer or + * {@link Minipass#resume} is explicitly called. + */ + off(ev, handler) { + const ret = super.off(ev, handler); + // if we previously had listeners, and now we don't, and we don't + // have any pipes, then stop the flow, unless it's been explicitly + // put in a discarded flowing state via stream.resume(). + if (ev === 'data') { + this[DATALISTENERS] = this.listeners('data').length; + if (this[DATALISTENERS] === 0 && + !this[DISCARDED] && + !this[PIPES].length) { + this[FLOWING] = false; + } + } + return ret; + } + /** + * Mostly identical to `EventEmitter.removeAllListeners` + * + * If all 'data' event handlers are removed, and they were the last consumer + * (ie, there are no pipe destinations), then the flow of data will stop + * until there is another consumer or {@link Minipass#resume} is explicitly + * called. + */ + removeAllListeners(ev) { + const ret = super.removeAllListeners(ev); + if (ev === 'data' || ev === undefined) { + this[DATALISTENERS] = 0; + if (!this[DISCARDED] && !this[PIPES].length) { + this[FLOWING] = false; + } + } + return ret; + } + /** + * true if the 'end' event has been emitted + */ + get emittedEnd() { + return this[EMITTED_END]; + } + [MAYBE_EMIT_END]() { + if (!this[EMITTING_END] && + !this[EMITTED_END] && + !this[DESTROYED] && + this[BUFFER].length === 0 && + this[EOF]) { + this[EMITTING_END] = true; + this.emit('end'); + this.emit('prefinish'); + this.emit('finish'); + if (this[CLOSED]) + this.emit('close'); + this[EMITTING_END] = false; + } + } + /** + * Mostly identical to `EventEmitter.emit`, with the following + * behavior differences to prevent data loss and unnecessary hangs: + * + * If the stream has been destroyed, and the event is something other + * than 'close' or 'error', then `false` is returned and no handlers + * are called. + * + * If the event is 'end', and has already been emitted, then the event + * is ignored. If the stream is in a paused or non-flowing state, then + * the event will be deferred until data flow resumes. If the stream is + * async, then handlers will be called on the next tick rather than + * immediately. + * + * If the event is 'close', and 'end' has not yet been emitted, then + * the event will be deferred until after 'end' is emitted. + * + * If the event is 'error', and an AbortSignal was provided for the stream, + * and there are no listeners, then the event is ignored, matching the + * behavior of node core streams in the presense of an AbortSignal. + * + * If the event is 'finish' or 'prefinish', then all listeners will be + * removed after emitting the event, to prevent double-firing. + */ + emit(ev, ...args) { + const data = args[0]; + // error and close are only events allowed after calling destroy() + if (ev !== 'error' && + ev !== 'close' && + ev !== DESTROYED && + this[DESTROYED]) { + return false; + } + else if (ev === 'data') { + return !this[OBJECTMODE] && !data + ? false + : this[ASYNC] + ? (defer(() => this[EMITDATA](data)), true) + : this[EMITDATA](data); + } + else if (ev === 'end') { + return this[EMITEND](); + } + else if (ev === 'close') { + this[CLOSED] = true; + // don't emit close before 'end' and 'finish' + if (!this[EMITTED_END] && !this[DESTROYED]) + return false; + const ret = super.emit('close'); + this.removeAllListeners('close'); + return ret; + } + else if (ev === 'error') { + this[EMITTED_ERROR] = data; + super.emit(ERROR, data); + const ret = !this[SIGNAL] || this.listeners('error').length + ? super.emit('error', data) + : false; + this[MAYBE_EMIT_END](); + return ret; + } + else if (ev === 'resume') { + const ret = super.emit('resume'); + this[MAYBE_EMIT_END](); + return ret; + } + else if (ev === 'finish' || ev === 'prefinish') { + const ret = super.emit(ev); + this.removeAllListeners(ev); + return ret; + } + // Some other unknown event + const ret = super.emit(ev, ...args); + this[MAYBE_EMIT_END](); + return ret; + } + [EMITDATA](data) { + for (const p of this[PIPES]) { + if (p.dest.write(data) === false) + this.pause(); + } + const ret = this[DISCARDED] ? false : super.emit('data', data); + this[MAYBE_EMIT_END](); + return ret; + } + [EMITEND]() { + if (this[EMITTED_END]) + return false; + this[EMITTED_END] = true; + this.readable = false; + return this[ASYNC] + ? (defer(() => this[EMITEND2]()), true) + : this[EMITEND2](); + } + [EMITEND2]() { + if (this[DECODER]) { + const data = this[DECODER].end(); + if (data) { + for (const p of this[PIPES]) { + p.dest.write(data); + } + if (!this[DISCARDED]) + super.emit('data', data); + } + } + for (const p of this[PIPES]) { + p.end(); + } + const ret = super.emit('end'); + this.removeAllListeners('end'); + return ret; + } + /** + * Return a Promise that resolves to an array of all emitted data once + * the stream ends. + */ + async collect() { + const buf = Object.assign([], { + dataLength: 0, + }); + if (!this[OBJECTMODE]) + buf.dataLength = 0; + // set the promise first, in case an error is raised + // by triggering the flow here. + const p = this.promise(); + this.on('data', c => { + buf.push(c); + if (!this[OBJECTMODE]) + buf.dataLength += c.length; + }); + await p; + return buf; + } + /** + * Return a Promise that resolves to the concatenation of all emitted data + * once the stream ends. + * + * Not allowed on objectMode streams. + */ + async concat() { + if (this[OBJECTMODE]) { + throw new Error('cannot concat in objectMode'); + } + const buf = await this.collect(); + return (this[ENCODING] + ? buf.join('') + : Buffer.concat(buf, buf.dataLength)); + } + /** + * Return a void Promise that resolves once the stream ends. + */ + async promise() { + return new Promise((resolve, reject) => { + this.on(DESTROYED, () => reject(new Error('stream destroyed'))); + this.on('error', er => reject(er)); + this.on('end', () => resolve()); + }); + } + /** + * Asynchronous `for await of` iteration. + * + * This will continue emitting all chunks until the stream terminates. + */ + [Symbol.asyncIterator]() { + // set this up front, in case the consumer doesn't call next() + // right away. + this[DISCARDED] = false; + let stopped = false; + const stop = async () => { + this.pause(); + stopped = true; + return { value: undefined, done: true }; + }; + const next = () => { + if (stopped) + return stop(); + const res = this.read(); + if (res !== null) + return Promise.resolve({ done: false, value: res }); + if (this[EOF]) + return stop(); + let resolve; + let reject; + const onerr = (er) => { + this.off('data', ondata); + this.off('end', onend); + this.off(DESTROYED, ondestroy); + stop(); + reject(er); + }; + const ondata = (value) => { + this.off('error', onerr); + this.off('end', onend); + this.off(DESTROYED, ondestroy); + this.pause(); + resolve({ value, done: !!this[EOF] }); + }; + const onend = () => { + this.off('error', onerr); + this.off('data', ondata); + this.off(DESTROYED, ondestroy); + stop(); + resolve({ done: true, value: undefined }); + }; + const ondestroy = () => onerr(new Error('stream destroyed')); + return new Promise((res, rej) => { + reject = rej; + resolve = res; + this.once(DESTROYED, ondestroy); + this.once('error', onerr); + this.once('end', onend); + this.once('data', ondata); + }); + }; + return { + next, + throw: stop, + return: stop, + [Symbol.asyncIterator]() { + return this; + }, + [Symbol.asyncDispose]: async () => { }, + }; + } + /** + * Synchronous `for of` iteration. + * + * The iteration will terminate when the internal buffer runs out, even + * if the stream has not yet terminated. + */ + [Symbol.iterator]() { + // set this up front, in case the consumer doesn't call next() + // right away. + this[DISCARDED] = false; + let stopped = false; + const stop = () => { + this.pause(); + this.off(ERROR, stop); + this.off(DESTROYED, stop); + this.off('end', stop); + stopped = true; + return { done: true, value: undefined }; + }; + const next = () => { + if (stopped) + return stop(); + const value = this.read(); + return value === null ? stop() : { done: false, value }; + }; + this.once('end', stop); + this.once(ERROR, stop); + this.once(DESTROYED, stop); + return { + next, + throw: stop, + return: stop, + [Symbol.iterator]() { + return this; + }, + [Symbol.dispose]: () => { }, + }; + } + /** + * Destroy a stream, preventing it from being used for any further purpose. + * + * If the stream has a `close()` method, then it will be called on + * destruction. + * + * After destruction, any attempt to write data, read data, or emit most + * events will be ignored. + * + * If an error argument is provided, then it will be emitted in an + * 'error' event. + */ + destroy(er) { + if (this[DESTROYED]) { + if (er) + this.emit('error', er); + else + this.emit(DESTROYED); + return this; + } + this[DESTROYED] = true; + this[DISCARDED] = true; + // throw away all buffered data, it's never coming out + this[BUFFER].length = 0; + this[BUFFERLENGTH] = 0; + const wc = this; + if (typeof wc.close === 'function' && !this[CLOSED]) + wc.close(); + if (er) + this.emit('error', er); + // if no error to emit, still reject pending promises + else + this.emit(DESTROYED); + return this; + } + /** + * Alias for {@link isStream} + * + * Former export location, maintained for backwards compatibility. + * + * @deprecated + */ + static get isStream() { + return isStream; + } +} +//# sourceMappingURL=index.js.map
\ No newline at end of file diff --git a/node_modules/minipass/dist/esm/package.json b/node_modules/minipass/dist/esm/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/node_modules/minipass/dist/esm/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/node_modules/minipass/package.json b/node_modules/minipass/package.json new file mode 100644 index 0000000..800f215 --- /dev/null +++ b/node_modules/minipass/package.json @@ -0,0 +1,77 @@ +{ + "name": "minipass", + "version": "7.1.3", + "description": "minimal implementation of a PassThrough stream", + "main": "./dist/commonjs/index.js", + "types": "./dist/commonjs/index.d.ts", + "module": "./dist/esm/index.js", + "type": "module", + "tshy": { + "selfLink": false, + "compiler": "tsgo", + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + } + }, + "exports": { + "./package.json": "./package.json", + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/commonjs/index.d.ts", + "default": "./dist/commonjs/index.js" + } + } + }, + "files": [ + "dist" + ], + "scripts": { + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "prepare": "tshy", + "pretest": "npm run prepare", + "presnap": "npm run prepare", + "test": "tap", + "snap": "tap", + "format": "prettier --write . --loglevel warn", + "typedoc": "typedoc --tsconfig .tshy/esm.json ./src/*.ts" + }, + "prettier": { + "semi": false, + "printWidth": 75, + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "jsxSingleQuote": false, + "bracketSameLine": true, + "arrowParens": "avoid", + "endOfLine": "lf" + }, + "devDependencies": { + "@types/end-of-stream": "^1.4.2", + "@types/node": "^25.2.3", + "end-of-stream": "^1.4.0", + "node-abort-controller": "^3.1.1", + "prettier": "^3.8.1", + "tap": "^21.6.1", + "through2": "^2.0.3", + "tshy": "^3.3.2", + "typedoc": "^0.28.17" + }, + "repository": "https://github.com/isaacs/minipass", + "keywords": [ + "passthrough", + "stream" + ], + "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } +} |