Initial commit
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Mathias Buus
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+550
@@ -0,0 +1,550 @@
|
||||
# streamx
|
||||
|
||||
An iteration of the Node.js core streams with a series of improvements.
|
||||
|
||||
```
|
||||
npm install streamx
|
||||
```
|
||||
|
||||
[](https://github.com/streamxorg/streamx/actions?query=workflow%3A%22Build+Status%22)
|
||||
|
||||
## Main improvements from Node.js core stream
|
||||
|
||||
#### Proper lifecycle support.
|
||||
|
||||
Streams have an `_open` function that is called before any read/write operation and a `_destroy`
|
||||
function that is always run as the last part of the stream.
|
||||
|
||||
This makes it easy to maintain state.
|
||||
|
||||
#### Easy error handling
|
||||
|
||||
Fully integrates a `.destroy()` function. When called the stream will wait for any
|
||||
pending operation to finish and call the stream destroy logic.
|
||||
|
||||
Close is _always_ the last event emitted and `destroy` is always run.
|
||||
|
||||
#### `pipe()` error handles
|
||||
|
||||
`pipe` accepts a callback that is called when the pipeline is fully drained.
|
||||
It also error handles the streams provided and destroys both streams if either
|
||||
of them fail.
|
||||
|
||||
#### All streams are both binary and object mode streams
|
||||
|
||||
A `map` function can be provided to map your input data into buffers
|
||||
or other formats. To indicate how much buffer space each data item takes
|
||||
an `byteLength` function can be provided as well.
|
||||
|
||||
This removes the need for two modes of streams.
|
||||
|
||||
#### Simplicity
|
||||
|
||||
This is a full rewrite, all contained in one file.
|
||||
|
||||
Lots of stream methods are simplified based on how I and devs I work with actually use streams in the wild.
|
||||
|
||||
#### Backwards compat
|
||||
|
||||
streamx aims to be compatible with Node.js streams whenever it is reasonable to do so.
|
||||
|
||||
This means that streamx streams behave a lot like Node.js streams from the outside but still provides the
|
||||
improvements above.
|
||||
|
||||
#### Smaller browser footprint
|
||||
|
||||
streamx has a much smaller footprint when compiled for the browser:
|
||||
|
||||
```
|
||||
$ for x in stream{,x}; do echo $x: $(browserify -r $x | wc -c) bytes; done
|
||||
stream: 173844 bytes
|
||||
streamx: 46943 bytes
|
||||
```
|
||||
|
||||
With optimizations turned on, the difference is even more stark:
|
||||
|
||||
```
|
||||
$ for x in stream{,x}; do echo $x: $(browserify -r $x -p tinyify | wc -c) bytes; done
|
||||
stream: 62649 bytes
|
||||
streamx: 8460 bytes
|
||||
$ for x in stream{,x}; do echo $x: $(browserify -r $x -p tinyify | gzip | wc -c) "bytes (gzipped)"; done
|
||||
stream: 18053 bytes (gzipped)
|
||||
streamx: 2806 bytes (gzipped)
|
||||
```
|
||||
|
||||
#### AbortSignal support
|
||||
|
||||
To make it easier to integrate streams in a `async/await` flow, all streams support a `signal` option
|
||||
that accepts a [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to as an
|
||||
alternative means to `.destroy` streams.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const { Readable } = require('streamx')
|
||||
|
||||
const rs = new Readable({
|
||||
read(cb) {
|
||||
this.push('Cool data')
|
||||
cb(null)
|
||||
}
|
||||
})
|
||||
|
||||
rs.on('data', (data) => console.log('data:', data))
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
This streamx package contains 4 streams similar to Node.js core.
|
||||
|
||||
## Readable Stream
|
||||
|
||||
#### `rs = new stream.Readable([options])`
|
||||
|
||||
Create a new readable stream.
|
||||
|
||||
Options include:
|
||||
|
||||
```
|
||||
{
|
||||
highWaterMark: 16384, // max buffer size in bytes
|
||||
map: (data) => data, // optional function to map input data
|
||||
byteLength: (data) => size, // optional function that calculates the byte size of input data
|
||||
signal: abortController.signal, // optional AbortSignal that triggers `.destroy` when on `abort`
|
||||
eagerOpen: false // eagerly open the stream
|
||||
}
|
||||
```
|
||||
|
||||
In addition you can pass the `open`, `read`, and `destroy` functions as shorthands in
|
||||
the constructor instead of overwrite the methods below.
|
||||
|
||||
The default byteLength function returns the byte length of buffers and `1024`
|
||||
for any other object. This means the buffer will contain around 16 non buffers
|
||||
or buffers worth 16kb when full if the defaults are used.
|
||||
|
||||
If you set highWaterMark to `0` then all read ahead buffering on the stream
|
||||
is disabled and it will only call `_read` when a user reads rather than ahead of time.
|
||||
|
||||
#### `rs._read(cb)`
|
||||
|
||||
This function is called when the stream wants you to push new data.
|
||||
Overwrite this and add your own read logic.
|
||||
You should call the callback when you are fully done with the read.
|
||||
|
||||
Can also be set using `options.read` in the constructor.
|
||||
|
||||
Note that this function differs from Node.js streams in that it takes
|
||||
the "read finished" callback.
|
||||
|
||||
#### `drained = rs.push(data)`
|
||||
|
||||
Push new data to the stream. Returns true if the buffer is not full
|
||||
and you should push more data if you can.
|
||||
|
||||
If you call `rs.push(null)` you signal to the stream that no more
|
||||
data will be pushed and that you want to end the stream.
|
||||
|
||||
#### `data = rs.read()`
|
||||
|
||||
Read a piece of data from the stream buffer. If the buffer is currently empty
|
||||
`null` will be returned and you should wait for `readable` to be emitted before
|
||||
trying again. If the stream has been ended it will also return `null`.
|
||||
|
||||
Note that this method differs from Node.js streams in that it does not accept
|
||||
an optional amounts of bytes to consume.
|
||||
|
||||
#### `rs.unshift(data)`
|
||||
|
||||
Add a piece of data to the front of the buffer. Use this if you read too much
|
||||
data using the `rs.read()` function.
|
||||
|
||||
#### `rs._open(cb)`
|
||||
|
||||
This function is called once before the first read is issued. Use this function
|
||||
to implement your own open logic.
|
||||
|
||||
Can also be set using `options.open` in the constructor.
|
||||
|
||||
#### `rs._destroy(cb)`
|
||||
|
||||
This function is called just before the stream is fully destroyed. You should
|
||||
use this to implement whatever teardown logic you need. The final part of the
|
||||
stream life cycle is always to call destroy itself so this function will always
|
||||
be called whether or not the stream ends gracefully or forcefully.
|
||||
|
||||
Can also be set using `options.destroy` in the constructor.
|
||||
|
||||
Note that the `_destroy` might be called without the open function being called
|
||||
in case no read was ever performed on the stream.
|
||||
|
||||
#### `rs._predestroy()`
|
||||
|
||||
A simple hook that is called as soon as the first `stream.destroy()` call is invoked.
|
||||
|
||||
Use this in case you need to cancel pending reads (if possible) instead of waiting for them to finish.
|
||||
|
||||
Can also be set using `options.predestroy` in the constructor.
|
||||
|
||||
#### `rs.destroy([error])`
|
||||
|
||||
Forcefully destroy the stream. Will call `_destroy` as soon as all pending reads have finished.
|
||||
Once the stream is fully destroyed `close` will be emitted.
|
||||
|
||||
If you pass an error this error will be emitted just before `close` is, signifying a reason
|
||||
as to why this stream was destroyed.
|
||||
|
||||
#### `rs.pause()`
|
||||
|
||||
Pauses the stream. You will only need to call this if you want to pause a resumed stream.
|
||||
|
||||
Returns this stream instance.
|
||||
|
||||
#### `rs.resume()`
|
||||
|
||||
Will start reading data from the stream as fast as possible.
|
||||
|
||||
If you do not call this, you need to use the `read()` method to read data or the `pipe()` method to
|
||||
pipe the stream somewhere else or the `data` handler.
|
||||
|
||||
If none of these option are used the stream will stay paused.
|
||||
|
||||
Returns this stream instance.
|
||||
|
||||
#### `rs.setEncoding(encoding)`
|
||||
|
||||
Set an encoding to change how data is interpreted. E.g. `utf-8`.
|
||||
|
||||
#### `bool = Readable.isPaused(rs)`
|
||||
|
||||
Returns `true` if the stream is paused, else `false`.
|
||||
|
||||
#### `writableStream = rs.pipe(writableStream, [callback])`
|
||||
|
||||
Efficently pipe the readable stream to a writable stream (can be Node.js core stream or a stream from this package).
|
||||
If you provide a callback the callback is called when the pipeline has fully finished with an optional error in case
|
||||
it failed.
|
||||
|
||||
To cancel the pipeline destroy either of the streams.
|
||||
|
||||
#### `rs.on('readable')`
|
||||
|
||||
Emitted when data is pushed to the stream if the buffer was previously empty.
|
||||
|
||||
#### `rs.on('data', data)`
|
||||
|
||||
Emitted when data is being read from the stream. If you attach a data handler you are implicitly resuming the stream.
|
||||
|
||||
#### `rs.on('end')`
|
||||
|
||||
Emitted when the readable stream has ended and no data is left in it's buffer.
|
||||
|
||||
#### `rs.on('close')`
|
||||
|
||||
Emitted when the readable stream has fully closed (i.e. it's destroy function has completed)
|
||||
|
||||
#### `rs.on('error', err)`
|
||||
|
||||
Emitted if any of the stream operations fail with an error. `close` is always emitted right after this.
|
||||
|
||||
#### `rs.on('piping', dest)`
|
||||
|
||||
Emitted when the readable stream is pipeing to a destination.
|
||||
|
||||
#### `rs.on('open')`
|
||||
|
||||
Emitted after `rs._open(cb)` execution.
|
||||
|
||||
#### `rs.destroying`
|
||||
|
||||
Boolean property indicating whether or not this stream has started to be destroyed.
|
||||
|
||||
#### `rs.destroyed`
|
||||
|
||||
Boolean property indicating whether or not this stream has been destroyed.
|
||||
|
||||
#### `rs.readable`
|
||||
|
||||
Returns `true` if the stream is an active streamx readable stream. Returns `undefined` if not.
|
||||
|
||||
#### `bool = Readable.isBackpressured(rs)`
|
||||
|
||||
Static method to check if a readable stream is currently under backpressure.
|
||||
|
||||
#### `stream = Readable.from(arrayOrBufferOrStringOrAsyncIterator)`
|
||||
|
||||
Static method to turn an array or buffer or string or AsyncIterator into a readable stream.
|
||||
|
||||
## Writable Stream
|
||||
|
||||
#### `ws = new stream.Writable([options])`
|
||||
|
||||
Create a new writable stream.
|
||||
|
||||
Options include:
|
||||
|
||||
```
|
||||
{
|
||||
highWaterMark: 16384, // max buffer size in bytes
|
||||
map: (data) => data, // optional function to map input data
|
||||
byteLength: (data) => size, // optional function that calculates the byte size of input data
|
||||
signal: abortController.signal // optional AbortSignal that triggers `.destroy` when on `abort`
|
||||
}
|
||||
```
|
||||
|
||||
In addition you can pass the `open`, `write`, `final`, and `destroy` functions as shorthands in
|
||||
the constructor instead of overwrite the methods below.
|
||||
|
||||
The default byteLength function returns the byte length of buffers and `1024`
|
||||
for any other object. This means the buffer will contain around 16 non buffers
|
||||
or buffers worth 16kb when full if the defaults are used.
|
||||
|
||||
#### `ws._open(cb)`
|
||||
|
||||
This function is called once before the first write is issued. Use this function
|
||||
to implement your own open logic.
|
||||
|
||||
Can also be set using `options.open` in the constructor.
|
||||
|
||||
#### `ws._destroy(cb)`
|
||||
|
||||
This function is called just before the stream is fully destroyed. You should
|
||||
use this to implement whatever teardown logic you need. The final part of the
|
||||
stream life cycle is always to call destroy itself so this function will always
|
||||
be called whether or not the stream ends gracefully or forcefully.
|
||||
|
||||
Can also be set using `options.destroy` in the constructor.
|
||||
|
||||
Note that the `_destroy` might be called without the open function being called
|
||||
in case no write was ever performed on the stream.
|
||||
|
||||
#### `ws._predestroy()`
|
||||
|
||||
A simple hook that is called as soon as the first `stream.destroy()` call is invoked.
|
||||
|
||||
Use this in case you need to cancel pending writes (if possible) instead of waiting for them to finish.
|
||||
|
||||
Can also be set using `options.predestroy` in the constructor.
|
||||
|
||||
#### `ws.destroy([error])`
|
||||
|
||||
Forcefully destroy the stream. Will call `_destroy` as soon as all pending reads have finished.
|
||||
Once the stream is fully destroyed `close` will be emitted.
|
||||
|
||||
If you pass an error this error will be emitted just before `close` is, signifying a reason
|
||||
as to why this stream was destroyed.
|
||||
|
||||
#### `drained = ws.write(data)`
|
||||
|
||||
Write a piece of data to the stream. Returns `true` if the stream buffer is not full and you
|
||||
should keep writing to it if you can. If `false` is returned the stream will emit `drain`
|
||||
once it's buffer is fully drained.
|
||||
|
||||
#### `ws._write(data, callback)`
|
||||
|
||||
This function is called when the stream want to write some data. Use this to implement your own
|
||||
write logic. When done call the callback and the stream will call it again if more data exists in the buffer.
|
||||
|
||||
Can also be set using `options.write` in the constructor.
|
||||
|
||||
#### `ws._writev(batch, callback)`
|
||||
|
||||
Similar to `_write` but passes an array of all data in the current write buffer instead of the oldest one.
|
||||
Useful if the destination you are writing the data to supports batching.
|
||||
|
||||
Can also be set using `options.writev` in the constructor.
|
||||
|
||||
#### `ws.end()`
|
||||
|
||||
Gracefully end the writable stream. Call this when you no longer want to write to the stream.
|
||||
|
||||
Once all writes have been fully drained `finish` will be emitted.
|
||||
|
||||
Returns this stream instance.
|
||||
|
||||
#### `ws.cork()`
|
||||
|
||||
Buffer written data in memory. Useful for accumulating small chunks of data into a batch to be consumed by `writev`.
|
||||
|
||||
#### `ws.uncork()`
|
||||
|
||||
Disable `ws.cork()`.
|
||||
|
||||
#### `ws._final(callback)`
|
||||
|
||||
This function is called just before `finish` is emitted, i.e. when all writes have flushed but `ws.end()`
|
||||
have been called. Use this to implement any logic that should happen after all writes but before finish.
|
||||
|
||||
Can also be set using `options.final` in the constructor.
|
||||
|
||||
#### `ws.on('finish')`
|
||||
|
||||
Emitted when the stream has been ended and all writes have been drained.
|
||||
|
||||
#### `ws.on('close')`
|
||||
|
||||
Emitted when the readable stream has fully closed (i.e. it's destroy function has completed)
|
||||
|
||||
#### `ws.on('error', err)`
|
||||
|
||||
Emitted if any of the stream operations fail with an error. `close` is always emitted right after this.
|
||||
|
||||
#### `ws.on('pipe', src)`
|
||||
|
||||
Emitted when a readable stream is being piped to the writable one.
|
||||
|
||||
#### `ws.on('open')`
|
||||
|
||||
Emitted after `ws._open(cb)` execution.
|
||||
|
||||
#### `ws.on('drain')`
|
||||
|
||||
Emitted after all data was drained if `ws.write(data)` returned `false`.
|
||||
|
||||
#### `ws.destroying`
|
||||
|
||||
Boolean property indicating whether or not this stream has started to be destroyed.
|
||||
|
||||
#### `ws.destroyed`
|
||||
|
||||
Boolean property indicating whether or not this stream has been destroyed.
|
||||
|
||||
#### `ws.writable`
|
||||
|
||||
Returns `true` if the stream is an active streamx writable stream. Returns `undefined` if not.
|
||||
|
||||
#### `bool = Writable.isBackpressured(ws)`
|
||||
|
||||
Static method to check if a writable stream is currently under backpressure.
|
||||
|
||||
#### `bool = await Writable.drained(ws)`
|
||||
|
||||
Static helper to wait for a stream to drain the currently queued writes.
|
||||
Returns true if they were drained and false otherwise if the stream was destroyed.
|
||||
|
||||
## Duplex Stream
|
||||
|
||||
#### `s = new stream.Duplex([options])`
|
||||
|
||||
A duplex stream is a stream that is both readable and writable.
|
||||
|
||||
Since JS does not support multiple inheritance it inherits directly from Readable
|
||||
but implements the Writable API as well.
|
||||
|
||||
If you want to provide only a map function for the readable side use `mapReadable` instead.
|
||||
If you want to provide only a byteLength function for the readable side use `byteLengthReadable` instead.
|
||||
|
||||
Same goes for the writable side but using `mapWritable` and `byteLengthWritable` instead.
|
||||
|
||||
## Transform Stream
|
||||
|
||||
A Transform stream is a duplex stream with an `._transform` template method that allows to
|
||||
asynchronously map the input to a different output.
|
||||
|
||||
The transform stream overrides the `_write` and `_read` operations of `Readable` and `Writable` but
|
||||
still allows the setting of these options in the constructor. Usually it is unnecessary to pass
|
||||
in `read` or `write`/`writev` or to override the corresponding `._read`, `._write` or `._writev` operation.
|
||||
|
||||
#### `ts = new stream.Transform([options])`
|
||||
|
||||
A transform stream is a duplex stream that maps the data written to it and emits that as readable data.
|
||||
|
||||
Has the same options as a duplex stream except you can provide a `transform` function also.
|
||||
|
||||
#### `ts._transform(data, callback)`
|
||||
|
||||
Transform the incoming data. Call `callback(null, mappedData)` or use `ts.push(mappedData)` to
|
||||
return data to the readable side of the stream.
|
||||
|
||||
Per default the transform function just remits the incoming data making it act as a pass-through stream.
|
||||
|
||||
## Pipeline
|
||||
|
||||
`pipeline` allows to stream form a readable through a set of duplex streams to a writable entry.
|
||||
|
||||
```js
|
||||
const { pipeline, Readable, Transform, Writable } = require('streamx')
|
||||
const lastStream = pipeline(
|
||||
Readable.from([1, 2, 3]),
|
||||
new Transform({
|
||||
transform (from, cb) {
|
||||
this.push(from.toString())
|
||||
cb()
|
||||
}
|
||||
}),
|
||||
new Writable({
|
||||
write (data, cb) {
|
||||
console.log(data)
|
||||
cb()
|
||||
}
|
||||
})
|
||||
error => {
|
||||
// Callback once write has finished
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
#### `lastStream = stream.pipeline(...streams, [done])`
|
||||
|
||||
Pipe all streams together and return the last stream piped to.
|
||||
When the last stream finishes the pipeline ended succesfully.
|
||||
|
||||
If any of the streams error, whether they are Node.js core streams
|
||||
or streamx streams, all streams in the pipeline are shutdown.
|
||||
|
||||
Optionally you can pass a done callback to know when the pipeline is done.
|
||||
|
||||
#### `promise = stream.pipelinePromise(...streams)`
|
||||
|
||||
Same as normal pipeline except instead of returning the last stream it returns
|
||||
a promise representing the done callback. Note you should error handle this
|
||||
promise if you use this version.
|
||||
|
||||
## Helpers
|
||||
|
||||
#### `bool = isStream(stream)`
|
||||
|
||||
#### `bool = isStreamx(stream)`
|
||||
|
||||
#### `bool = isDisturbed(stream)`
|
||||
|
||||
Indicates if the stream has been opened or started to be destroyed.
|
||||
|
||||
#### `bool = isEnding(stream)`
|
||||
|
||||
Indicates if a readable stream has started it's ending process.
|
||||
|
||||
#### `bool = isEnded(stream)`
|
||||
|
||||
Indicates if a readable stream ended, so all it's readings.
|
||||
|
||||
#### `bool = isFinishing(stream)`
|
||||
|
||||
Indicates if a writable stream has started it's ending process.
|
||||
|
||||
#### `bool = isFinished(stream)`
|
||||
|
||||
Indicates if a writable stream ended, so all it's writings.
|
||||
|
||||
#### `err = getStreamError(stream, [options])`
|
||||
|
||||
Returns `null` if the stream has no errors.
|
||||
|
||||
## Utilities
|
||||
|
||||
Streamx aims to be minimal and stable. It therefore only contains a minimal set of utilities.
|
||||
To help discover of other modules that help you build streamx apps, we link some useful utilities here
|
||||
|
||||
- [stream-composer](https://github.com/mafintosh/stream-composer) - Compose streams like Node's `stream.compose` and the `duplexify` and `pumpify` modules.
|
||||
- [teex](https://github.com/mafintosh/teex) - Clone a readable stream into multiple new readable instances.
|
||||
- [merge-readable](https://github.com/holepunchto/merge-readable) - Merge multiple readers into a new readable with optional mapping of data
|
||||
|
||||
## Contributing
|
||||
|
||||
If you want to help contribute to streamx a good way to start is to help writing more test
|
||||
cases, compatibility tests, documentation, or performance benchmarks.
|
||||
|
||||
If in doubt open an issue :)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
import { BufferEncoding, EventMap, EventEmitter } from './runtime'
|
||||
|
||||
interface StreamCallback {
|
||||
(err: Error | null): void
|
||||
}
|
||||
|
||||
type Pipeline<S extends Writable> = [src: Readable, ...transforms: Duplex[], dest: S]
|
||||
|
||||
declare function pipeline<S extends Writable>(streams: Pipeline<S>, cb?: StreamCallback): S
|
||||
declare function pipeline<S extends Writable>(...args: Pipeline<S>): S
|
||||
declare function pipeline<S extends Writable>(...args: [...Pipeline<S>, cb: StreamCallback]): S
|
||||
|
||||
declare function pipelinePromise<S extends Writable>(...args: Pipeline<S>): Promise<S>
|
||||
|
||||
declare function isStream(stream: Stream): stream is Stream
|
||||
declare function isStreamx(stream: Stream): boolean
|
||||
declare function isEnding(stream: Stream): boolean
|
||||
declare function isEnded(stream: Stream): boolean
|
||||
declare function isFinishing(stream: Stream): boolean
|
||||
declare function isFinished(stream: Stream): boolean
|
||||
declare function isDisturbed(stream: Stream): boolean
|
||||
|
||||
interface GetStreamErrorOptions {
|
||||
all?: boolean
|
||||
}
|
||||
|
||||
declare function getStreamError(stream: Stream, opts?: GetStreamErrorOptions): Error | null
|
||||
|
||||
interface StreamEvents extends EventMap {
|
||||
close: []
|
||||
error: [err: Error]
|
||||
}
|
||||
|
||||
interface StreamOptions<S extends Stream = Stream> {
|
||||
byteLength?(data: unknown): number
|
||||
destroy?(this: S, cb: StreamCallback): void
|
||||
eagerOpen?: boolean
|
||||
highWaterMark?: number
|
||||
map?(data: unknown): unknown
|
||||
open?(this: S, cb: StreamCallback): void
|
||||
predestroy?(this: S): void
|
||||
signal?: AbortSignal
|
||||
}
|
||||
|
||||
interface Stream<M extends StreamEvents = StreamEvents> extends EventEmitter<M> {
|
||||
_open(cb: StreamCallback): void
|
||||
_predestroy(): void
|
||||
_destroy(cb: StreamCallback): void
|
||||
|
||||
readonly readable: boolean
|
||||
readonly writable: boolean
|
||||
readonly destroyed: boolean
|
||||
readonly destroying: boolean
|
||||
|
||||
destroy(err?: Error | null): void
|
||||
}
|
||||
|
||||
declare class Stream {
|
||||
constructor(opts?: StreamOptions)
|
||||
}
|
||||
|
||||
interface WritableEvents extends StreamEvents {
|
||||
drain: []
|
||||
finish: []
|
||||
pipe: [src: Readable]
|
||||
}
|
||||
|
||||
interface WritableOptions<S extends Writable = Writable> extends StreamOptions<S> {
|
||||
byteLengthWritable?(data: unknown): number
|
||||
final?(this: S, cb: StreamCallback): void
|
||||
mapWritable?(data: unknown): unknown
|
||||
write?(this: S, data: unknown, cb: StreamCallback): void
|
||||
writev?(this: S, batch: unknown[], cb: StreamCallback): void
|
||||
}
|
||||
|
||||
interface Writable<M extends WritableEvents = WritableEvents> extends Stream<M> {
|
||||
_write(data: unknown, cb: StreamCallback): void
|
||||
_writev(batch: unknown[], cb: StreamCallback): void
|
||||
_final(cb: StreamCallback): void
|
||||
|
||||
write(data: unknown): unknown
|
||||
|
||||
end(data: unknown): this
|
||||
|
||||
cork(): void
|
||||
uncork(): void
|
||||
}
|
||||
|
||||
declare class Writable<M extends WritableEvents = WritableEvents> extends Stream<M> {
|
||||
constructor(opts?: WritableOptions)
|
||||
|
||||
static isBackpressured(ws: Writable): boolean
|
||||
|
||||
static drained(ws: Writable): Promise<unknown>
|
||||
}
|
||||
|
||||
interface ReadableEvents extends StreamEvents {
|
||||
data: [data: unknown]
|
||||
end: []
|
||||
piping: [dest: Writable]
|
||||
readable: []
|
||||
}
|
||||
|
||||
interface ReadableOptions<S extends Readable = Readable> extends StreamOptions<S> {
|
||||
byteLengthReadable?(data: unknown): number
|
||||
encoding?: BufferEncoding
|
||||
mapReadable?(data: unknown): unknown
|
||||
read?(this: S, cb: StreamCallback): void
|
||||
}
|
||||
|
||||
interface Readable<M extends ReadableEvents = ReadableEvents>
|
||||
extends Stream<M>, AsyncIterable<unknown> {
|
||||
_read(cb: StreamCallback): void
|
||||
|
||||
push(data: unknown | null): boolean
|
||||
unshift(data: unknown | null): void
|
||||
read(): unknown | null
|
||||
|
||||
resume(): this
|
||||
pause(): this
|
||||
|
||||
pipe<S extends Writable>(dest: S, cb?: StreamCallback): S
|
||||
|
||||
setEncoding(encoding: BufferEncoding): this
|
||||
}
|
||||
|
||||
declare class Readable<M extends ReadableEvents = ReadableEvents> extends Stream<M> {
|
||||
constructor(opts?: ReadableOptions)
|
||||
|
||||
static deferred(fn: () => Promise<Readable>, opts?: TransformOptions): Transform
|
||||
|
||||
static from(data: unknown | unknown[] | AsyncIterable<unknown>, opts?: ReadableOptions): Readable
|
||||
|
||||
static isBackpressured(rs: Readable): boolean
|
||||
|
||||
static isPaused(rs: Readable): boolean
|
||||
}
|
||||
|
||||
interface DuplexEvents extends ReadableEvents, WritableEvents {}
|
||||
|
||||
interface DuplexOptions<S extends Duplex = Duplex> extends ReadableOptions<S>, WritableOptions<S> {}
|
||||
|
||||
interface Duplex<M extends DuplexEvents = DuplexEvents> extends Readable<M>, Writable<M> {}
|
||||
|
||||
declare class Duplex<M extends DuplexEvents = DuplexEvents> extends Stream<M> {
|
||||
constructor(opts?: DuplexOptions)
|
||||
}
|
||||
|
||||
interface TransformCallback {
|
||||
(err: Error | null, mappedData: unknown): void
|
||||
}
|
||||
|
||||
interface TransformEvents extends DuplexEvents {}
|
||||
|
||||
interface TransformOptions<S extends Transform = Transform> extends DuplexOptions<S> {
|
||||
flush?(this: S, cb: StreamCallback): void
|
||||
transform?(this: S, data: unknown, cb: TransformCallback): void
|
||||
}
|
||||
|
||||
interface Transform<M extends TransformEvents = TransformEvents> extends Duplex<M> {
|
||||
_flush(cb: StreamCallback): void
|
||||
_transform(Data: unknown, cb: TransformCallback): void
|
||||
}
|
||||
|
||||
declare class Transform<M extends TransformEvents = TransformEvents> extends Duplex<M> {
|
||||
constructor(opts?: TransformOptions)
|
||||
}
|
||||
|
||||
export {
|
||||
type Pipeline,
|
||||
pipeline,
|
||||
pipelinePromise,
|
||||
isStream,
|
||||
isStreamx,
|
||||
isEnding,
|
||||
isEnded,
|
||||
isFinishing,
|
||||
isFinished,
|
||||
isDisturbed,
|
||||
type GetStreamErrorOptions,
|
||||
getStreamError,
|
||||
type StreamEvents,
|
||||
type StreamOptions,
|
||||
Stream,
|
||||
type WritableEvents,
|
||||
type WritableOptions,
|
||||
Writable,
|
||||
type ReadableEvents,
|
||||
type ReadableOptions,
|
||||
Readable,
|
||||
type DuplexEvents,
|
||||
type DuplexOptions,
|
||||
Duplex,
|
||||
type TransformEvents,
|
||||
type TransformOptions,
|
||||
Transform,
|
||||
Transform as PassThrough
|
||||
}
|
||||
+1314
File diff suppressed because it is too large
Load Diff
+13
@@ -0,0 +1,13 @@
|
||||
declare class StreamError extends Error {
|
||||
readonly code: string
|
||||
|
||||
static isStreamDestroyed(err: Error | null): boolean
|
||||
static isPrematureClose(err: Error | null): boolean
|
||||
static isAborted(err: Error | null): boolean
|
||||
|
||||
static STREAM_DESTROYED(): StreamError
|
||||
static PREMATURE_CLOSE(): StreamError
|
||||
static ABORTED(): StreamError
|
||||
}
|
||||
|
||||
export = StreamError
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
module.exports = class StreamError extends Error {
|
||||
constructor(msg, code, fn = StreamError) {
|
||||
super(msg)
|
||||
|
||||
this.code = code
|
||||
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, fn)
|
||||
}
|
||||
}
|
||||
|
||||
static isStreamDestroyed(err) {
|
||||
return err && err.code === 'STREAM_DESTROYED'
|
||||
}
|
||||
|
||||
static isPrematureClose(err) {
|
||||
return err && err.code === 'PREMATURE_CLOSE'
|
||||
}
|
||||
|
||||
static isAborted(err) {
|
||||
return err && err.code === 'ABORTED'
|
||||
}
|
||||
|
||||
static isBadArgument(err) {
|
||||
return err && err.code === 'BAD_ARGUMENT'
|
||||
}
|
||||
|
||||
get name() {
|
||||
return 'StreamError'
|
||||
}
|
||||
|
||||
static STREAM_DESTROYED() {
|
||||
return new StreamError('Stream was destroyed', 'STREAM_DESTROYED', StreamError.STREAM_DESTROYED)
|
||||
}
|
||||
|
||||
static PREMATURE_CLOSE(msg = 'Premature close') {
|
||||
return new StreamError(msg, 'PREMATURE_CLOSE', StreamError.PREMATURE_CLOSE)
|
||||
}
|
||||
|
||||
static ABORTED() {
|
||||
return new StreamError('Stream aborted', 'ABORTED', StreamError.ABORTED)
|
||||
}
|
||||
|
||||
static BAD_ARGUMENT(msg = 'Bad argument') {
|
||||
return new StreamError(msg, 'BAD_ARGUMENT', StreamError.BAD_ARGUMENT)
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "streamx",
|
||||
"version": "2.28.0",
|
||||
"description": "An iteration of the Node.js core streams with a series of improvements",
|
||||
"main": "index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./index.d.ts",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./package": "./package.json",
|
||||
"./errors": {
|
||||
"types": "./lib/errors.d.ts",
|
||||
"default": "./lib/errors"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"events-universal": "^1.0.0",
|
||||
"fast-fifo": "^1.3.2",
|
||||
"text-decoder": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"b4a": "^1.6.6",
|
||||
"brittle": "^3.1.1",
|
||||
"end-of-stream": "^1.4.4",
|
||||
"lunte": "^1.8.0",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-config-holepunch": "^2.0.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"runtime.d.ts",
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"format": "prettier . --write",
|
||||
"test": "brittle test/all.js && brittle-bare test/all.js",
|
||||
"lint": "prettier . --check && lunte"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mafintosh/streamx.git"
|
||||
},
|
||||
"author": "Mathias Buus (@mafintosh)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mafintosh/streamx/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mafintosh/streamx"
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
type BufferEncoding =
|
||||
| 'ascii'
|
||||
| 'base64'
|
||||
| 'binary'
|
||||
| 'hex'
|
||||
| 'latin1'
|
||||
| 'ucs-2'
|
||||
| 'ucs2'
|
||||
| 'utf-16le'
|
||||
| 'utf-8'
|
||||
| 'utf16le'
|
||||
| 'utf8'
|
||||
|
||||
interface EventMap {
|
||||
[event: string | symbol]: unknown[]
|
||||
}
|
||||
|
||||
interface EventHandler<in A extends unknown[] = unknown[], out R = unknown> {
|
||||
(...args: A): R
|
||||
}
|
||||
|
||||
interface EventEmitter<in out M extends EventMap = EventMap> {
|
||||
addListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
|
||||
|
||||
addOnceListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
|
||||
|
||||
prependListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
|
||||
|
||||
prependOnceListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
|
||||
|
||||
removeListener<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
|
||||
|
||||
removeAllListeners<E extends keyof M>(name?: E): this
|
||||
|
||||
on<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
|
||||
|
||||
once<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
|
||||
|
||||
off<E extends keyof M, R>(name: E, fn: EventHandler<M[E], R>): this
|
||||
|
||||
emit<E extends keyof M>(name: E, ...args: M[E]): boolean
|
||||
|
||||
listeners<E extends keyof M, R>(name: E): EventHandler<M[E], R>
|
||||
|
||||
rawListeners<E extends keyof M, R>(name: E): EventHandler<M[E], R>[]
|
||||
|
||||
eventNames(): (keyof M)[]
|
||||
|
||||
listenerCount<E extends keyof M>(name: E): number
|
||||
|
||||
getMaxListeners(): number
|
||||
setMaxListeners(n: number): void
|
||||
}
|
||||
|
||||
export { BufferEncoding, EventMap, EventEmitter }
|
||||
Reference in New Issue
Block a user