pax_global_header 0000666 0000000 0000000 00000000064 14035743575 0014527 g ustar 00root root 0000000 0000000 52 comment=c17901233590aa49675a7fd0f42d70b9bed1c580
get-stream-6.0.1/ 0000775 0000000 0000000 00000000000 14035743575 0013603 5 ustar 00root root 0000000 0000000 get-stream-6.0.1/.editorconfig 0000664 0000000 0000000 00000000257 14035743575 0016264 0 ustar 00root root 0000000 0000000 root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.yml]
indent_style = space
indent_size = 2
get-stream-6.0.1/.gitattributes 0000664 0000000 0000000 00000000023 14035743575 0016471 0 ustar 00root root 0000000 0000000 * text=auto eol=lf
get-stream-6.0.1/.github/ 0000775 0000000 0000000 00000000000 14035743575 0015143 5 ustar 00root root 0000000 0000000 get-stream-6.0.1/.github/funding.yml 0000664 0000000 0000000 00000000164 14035743575 0017321 0 ustar 00root root 0000000 0000000 github: sindresorhus
open_collective: sindresorhus
tidelift: npm/get-stream
custom: https://sindresorhus.com/donate
get-stream-6.0.1/.github/security.md 0000664 0000000 0000000 00000000263 14035743575 0017335 0 ustar 00root root 0000000 0000000 # Security Policy
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
get-stream-6.0.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14035743575 0017200 5 ustar 00root root 0000000 0000000 get-stream-6.0.1/.github/workflows/main.yml 0000664 0000000 0000000 00000000664 14035743575 0020655 0 ustar 00root root 0000000 0000000 name: CI
on:
- push
- pull_request
jobs:
test:
name: Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version:
- 14
- 12
- 10
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
get-stream-6.0.1/.gitignore 0000664 0000000 0000000 00000000027 14035743575 0015572 0 ustar 00root root 0000000 0000000 node_modules
yarn.lock
get-stream-6.0.1/.npmrc 0000664 0000000 0000000 00000000023 14035743575 0014716 0 ustar 00root root 0000000 0000000 package-lock=false
get-stream-6.0.1/buffer-stream.js 0000664 0000000 0000000 00000001576 14035743575 0016714 0 ustar 00root root 0000000 0000000 'use strict';
const {PassThrough: PassThroughStream} = require('stream');
module.exports = options => {
options = {...options};
const {array} = options;
let {encoding} = options;
const isBuffer = encoding === 'buffer';
let objectMode = false;
if (array) {
objectMode = !(encoding || isBuffer);
} else {
encoding = encoding || 'utf8';
}
if (isBuffer) {
encoding = null;
}
const stream = new PassThroughStream({objectMode});
if (encoding) {
stream.setEncoding(encoding);
}
let length = 0;
const chunks = [];
stream.on('data', chunk => {
chunks.push(chunk);
if (objectMode) {
length = chunks.length;
} else {
length += chunk.length;
}
});
stream.getBufferedValue = () => {
if (array) {
return chunks;
}
return isBuffer ? Buffer.concat(chunks, length) : chunks.join('');
};
stream.getBufferedLength = () => length;
return stream;
};
get-stream-6.0.1/fixture 0000664 0000000 0000000 00000000010 14035743575 0015203 0 ustar 00root root 0000000 0000000 unicorn
get-stream-6.0.1/index.d.ts 0000664 0000000 0000000 00000007116 14035743575 0015511 0 ustar 00root root 0000000 0000000 ///
import {Stream} from 'stream';
declare class MaxBufferErrorClass extends Error {
readonly name: 'MaxBufferError';
constructor();
}
declare namespace getStream {
interface Options {
/**
Maximum length of the returned string. If it exceeds this value before the stream ends, the promise will be rejected with a `MaxBufferError` error.
@default Infinity
*/
readonly maxBuffer?: number;
}
interface OptionsWithEncoding extends Options {
/**
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffer) of the incoming stream.
@default 'utf8'
*/
readonly encoding?: EncodingType;
}
type MaxBufferError = MaxBufferErrorClass;
}
declare const getStream: {
/**
Get the `stream` as a string.
@returns A promise that resolves when the end event fires on the stream, indicating that there is no more data to be read. The stream is switched to flowing mode.
@example
```
import * as fs from 'fs';
import getStream = require('get-stream');
(async () => {
const stream = fs.createReadStream('unicorn.txt');
console.log(await getStream(stream));
// ,,))))))));,
// __)))))))))))))),
// \|/ -\(((((''''((((((((.
// -*-==//////(('' . `)))))),
// /|\ ))| o ;-. '((((( ,(,
// ( `| / ) ;))))' ,_))^;(~
// | | | ,))((((_ _____------~~~-. %,;(;(>';'~
// o_); ; )))(((` ~---~ `:: \ %%~~)(v;(`('~
// ; ''''```` `: `:::|\,__,%% );`'; ~
// | _ ) / `:|`----' `-'
// ______/\/~ | / /
// /~;;.____/;;' / ___--,-( `;;;/
// / // _;______;'------~~~~~ /;;/\ /
// // | | / ; \;;,\
// (<_ | ; /',/-----' _>
// \_| ||_ //~;~~~~~~~~~
// `\_| (,~~
// \~\
// ~~
})();
```
*/
(stream: Stream, options?: getStream.OptionsWithEncoding): Promise;
/**
Get the `stream` as a buffer.
It honors the `maxBuffer` option as above, but it refers to byte length rather than string length.
*/
buffer(
stream: Stream,
options?: getStream.Options
): Promise;
/**
Get the `stream` as an array of values.
It honors both the `maxBuffer` and `encoding` options. The behavior changes slightly based on the encoding chosen:
- When `encoding` is unset, it assumes an [object mode stream](https://nodesource.com/blog/understanding-object-streams/) and collects values emitted from `stream` unmodified. In this case `maxBuffer` refers to the number of items in the array (not the sum of their sizes).
- When `encoding` is set to `buffer`, it collects an array of buffers. `maxBuffer` refers to the summed byte lengths of every buffer in the array.
- When `encoding` is set to anything else, it collects an array of strings. `maxBuffer` refers to the summed character lengths of every string in the array.
*/
array(
stream: Stream,
options?: getStream.Options
): Promise;
array(
stream: Stream,
options: getStream.OptionsWithEncoding<'buffer'>
): Promise;
array(
stream: Stream,
options: getStream.OptionsWithEncoding
): Promise;
MaxBufferError: typeof MaxBufferErrorClass;
};
export = getStream;
get-stream-6.0.1/index.js 0000664 0000000 0000000 00000002721 14035743575 0015252 0 ustar 00root root 0000000 0000000 'use strict';
const {constants: BufferConstants} = require('buffer');
const stream = require('stream');
const {promisify} = require('util');
const bufferStream = require('./buffer-stream');
const streamPipelinePromisified = promisify(stream.pipeline);
class MaxBufferError extends Error {
constructor() {
super('maxBuffer exceeded');
this.name = 'MaxBufferError';
}
}
async function getStream(inputStream, options) {
if (!inputStream) {
throw new Error('Expected a stream');
}
options = {
maxBuffer: Infinity,
...options
};
const {maxBuffer} = options;
const stream = bufferStream(options);
await new Promise((resolve, reject) => {
const rejectPromise = error => {
// Don't retrieve an oversized buffer.
if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
error.bufferedData = stream.getBufferedValue();
}
reject(error);
};
(async () => {
try {
await streamPipelinePromisified(inputStream, stream);
resolve();
} catch (error) {
rejectPromise(error);
}
})();
stream.on('data', () => {
if (stream.getBufferedLength() > maxBuffer) {
rejectPromise(new MaxBufferError());
}
});
});
return stream.getBufferedValue();
}
module.exports = getStream;
module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'});
module.exports.array = (stream, options) => getStream(stream, {...options, array: true});
module.exports.MaxBufferError = MaxBufferError;
get-stream-6.0.1/index.test-d.ts 0000664 0000000 0000000 00000002115 14035743575 0016460 0 ustar 00root root 0000000 0000000 import * as fs from 'fs';
import {expectType} from 'tsd';
import getStream = require('.');
import {MaxBufferError} from '.';
const stream = fs.createReadStream('foo');
expectType>(getStream(stream));
expectType>(getStream(stream, {maxBuffer: 10}));
expectType>(getStream(stream, {encoding: 'utf8'}));
expectType>(getStream.buffer(stream));
expectType>(getStream.buffer(stream, {maxBuffer: 10}));
expectType>(getStream.array(stream));
expectType>(getStream.array<{}>(stream));
expectType>(getStream.array(stream, {maxBuffer: 10}));
expectType>(getStream.array(stream, {encoding: 'buffer'}));
expectType>(
getStream.array(stream, {maxBuffer: 10, encoding: 'buffer'})
);
expectType>(getStream.array(stream, {encoding: 'utf8'}));
expectType>(
getStream.array(stream, {maxBuffer: 10, encoding: 'utf8'})
);
const maxBufferError = new MaxBufferError();
expectType(maxBufferError);
get-stream-6.0.1/license 0000664 0000000 0000000 00000002135 14035743575 0015151 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) Sindre Sorhus (https://sindresorhus.com)
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.
get-stream-6.0.1/package.json 0000664 0000000 0000000 00000001463 14035743575 0016075 0 ustar 00root root 0000000 0000000 {
"name": "get-stream",
"version": "6.0.1",
"description": "Get a stream as a string, buffer, or array",
"license": "MIT",
"repository": "sindresorhus/get-stream",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=10"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts",
"buffer-stream.js"
],
"keywords": [
"get",
"stream",
"promise",
"concat",
"string",
"text",
"buffer",
"read",
"data",
"consume",
"readable",
"readablestream",
"array",
"object"
],
"devDependencies": {
"@types/node": "^14.0.27",
"ava": "^2.4.0",
"into-stream": "^5.0.0",
"tsd": "^0.13.1",
"xo": "^0.24.0"
}
}
get-stream-6.0.1/readme.md 0000664 0000000 0000000 00000010143 14035743575 0015361 0 ustar 00root root 0000000 0000000 # get-stream
> Get a stream as a string, buffer, or array
## Install
```
$ npm install get-stream
```
## Usage
```js
const fs = require('fs');
const getStream = require('get-stream');
(async () => {
const stream = fs.createReadStream('unicorn.txt');
console.log(await getStream(stream));
/*
,,))))))));,
__)))))))))))))),
\|/ -\(((((''''((((((((.
-*-==//////(('' . `)))))),
/|\ ))| o ;-. '((((( ,(,
( `| / ) ;))))' ,_))^;(~
| | | ,))((((_ _____------~~~-. %,;(;(>';'~
o_); ; )))(((` ~---~ `:: \ %%~~)(v;(`('~
; ''''```` `: `:::|\,__,%% );`'; ~
| _ ) / `:|`----' `-'
______/\/~ | / /
/~;;.____/;;' / ___--,-( `;;;/
/ // _;______;'------~~~~~ /;;/\ /
// | | / ; \;;,\
(<_ | ; /',/-----' _>
\_| ||_ //~;~~~~~~~~~
`\_| (,~~
\~\
~~
*/
})();
```
## API
The methods returns a promise that resolves when the `end` event fires on the stream, indicating that there is no more data to be read. The stream is switched to flowing mode.
### getStream(stream, options?)
Get the `stream` as a string.
#### options
Type: `object`
##### encoding
Type: `string`\
Default: `'utf8'`
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffer) of the incoming stream.
##### maxBuffer
Type: `number`\
Default: `Infinity`
Maximum length of the returned string. If it exceeds this value before the stream ends, the promise will be rejected with a `getStream.MaxBufferError` error.
### getStream.buffer(stream, options?)
Get the `stream` as a buffer.
It honors the `maxBuffer` option as above, but it refers to byte length rather than string length.
### getStream.array(stream, options?)
Get the `stream` as an array of values.
It honors both the `maxBuffer` and `encoding` options. The behavior changes slightly based on the encoding chosen:
- When `encoding` is unset, it assumes an [object mode stream](https://nodesource.com/blog/understanding-object-streams/) and collects values emitted from `stream` unmodified. In this case `maxBuffer` refers to the number of items in the array (not the sum of their sizes).
- When `encoding` is set to `buffer`, it collects an array of buffers. `maxBuffer` refers to the summed byte lengths of every buffer in the array.
- When `encoding` is set to anything else, it collects an array of strings. `maxBuffer` refers to the summed character lengths of every string in the array.
## Errors
If the input stream emits an `error` event, the promise will be rejected with the error. The buffered data will be attached to the `bufferedData` property of the error.
```js
(async () => {
try {
await getStream(streamThatErrorsAtTheEnd('unicorn'));
} catch (error) {
console.log(error.bufferedData);
//=> 'unicorn'
}
})()
```
## FAQ
### How is this different from [`concat-stream`](https://github.com/maxogden/concat-stream)?
This module accepts a stream instead of being one and returns a promise instead of using a callback. The API is simpler and it only supports returning a string, buffer, or array. It doesn't have a fragile type inference. You explicitly choose what you want. And it doesn't depend on the huge `readable-stream` package.
## Related
- [get-stdin](https://github.com/sindresorhus/get-stdin) - Get stdin as a string or buffer
---
get-stream-6.0.1/test.js 0000664 0000000 0000000 00000007637 14035743575 0015135 0 ustar 00root root 0000000 0000000 import fs from 'fs';
import {constants as BufferConstants} from 'buffer';
import {Readable as ReadableStream} from 'stream';
import test from 'ava';
import intoStream from 'into-stream';
import getStream from '.';
function makeSetup(intoStream) {
const setup = (streamDef, options) => getStream(intoStream(streamDef), options);
setup.array = (streamDef, options) => getStream.array(intoStream(streamDef), options);
setup.buffer = (streamDef, options) => getStream.buffer(intoStream(streamDef), options);
return setup;
}
const setup = makeSetup(intoStream);
setup.object = makeSetup(intoStream.object);
test('get stream as a buffer', async t => {
t.true((await getStream.buffer(fs.createReadStream('fixture'))).equals(Buffer.from('unicorn\n')));
});
test('get stream as an array', async t => {
const fixture = fs.createReadStream('index.js', 'utf8');
fixture.setEncoding('utf8');
t.is(typeof (await getStream.array(fixture))[0], 'string');
});
test('get object stream as an array', async t => {
const result = await setup.object.array([{foo: true}, {bar: false}]);
t.deepEqual(result, [{foo: true}, {bar: false}]);
});
test('get non-object stream as an array of strings', async t => {
const result = await setup.array(['foo', 'bar'], {encoding: 'utf8'});
t.deepEqual(result, ['foo', 'bar']);
});
test('get non-object stream as an array of Buffers', async t => {
const result = await setup.array(['foo', 'bar'], {encoding: 'buffer'});
t.deepEqual(result, [Buffer.from('foo'), Buffer.from('bar')]);
});
test('getStream should not affect additional listeners attached to the stream', async t => {
t.plan(3);
const fixture = intoStream(['foo', 'bar']);
fixture.on('data', chunk => t.true(Buffer.isBuffer(chunk)));
t.is(await getStream(fixture), 'foobar');
});
test('maxBuffer throws when size is exceeded', async t => {
await t.throwsAsync(setup(['abcd'], {maxBuffer: 3}));
await t.notThrowsAsync(setup(['abc'], {maxBuffer: 3}));
await t.throwsAsync(setup.buffer(['abcd'], {maxBuffer: 3}));
await t.notThrowsAsync(setup.buffer(['abc'], {maxBuffer: 3}));
});
test('maxBuffer applies to length of arrays when in objectMode', async t => {
await t.throwsAsync(getStream.array(intoStream.object([{a: 1}, {b: 2}, {c: 3}, {d: 4}]), {maxBuffer: 3}), /maxBuffer exceeded/);
await t.notThrowsAsync(getStream.array(intoStream.object([{a: 1}, {b: 2}, {c: 3}]), {maxBuffer: 3}));
});
test('maxBuffer applies to length of data when not in objectMode', async t => {
await t.throwsAsync(setup.array(['ab', 'cd', 'ef'], {encoding: 'utf8', maxBuffer: 5}), /maxBuffer exceeded/);
await t.notThrowsAsync(setup.array(['ab', 'cd', 'ef'], {encoding: 'utf8', maxBuffer: 6}));
await t.throwsAsync(setup.array(['ab', 'cd', 'ef'], {encoding: 'buffer', maxBuffer: 5}), /maxBuffer exceeded/);
await t.notThrowsAsync(setup.array(['ab', 'cd', 'ef'], {encoding: 'buffer', maxBuffer: 6}));
});
test('maxBuffer throws a MaxBufferError', async t => {
await t.throwsAsync(setup(['abcd'], {maxBuffer: 3}), getStream.MaxBufferError);
});
test('maxBuffer throws a MaxBufferError even if the stream is larger than Buffer MAX_LENGTH', async t => {
// Create a stream 1 byte larger than the maximum size a buffer is allowed to be
function * largeStream() {
yield Buffer.allocUnsafe(BufferConstants.MAX_LENGTH);
yield Buffer.allocUnsafe(1);
}
await t.throwsAsync(setup(largeStream(), {maxBuffer: BufferConstants.MAX_LENGTH, encoding: 'buffer'}), /maxBuffer exceeded/);
});
test('Promise rejects when input stream emits an error', async t => {
const readable = new ReadableStream();
const data = 'invisible pink unicorn';
const error = new Error('Made up error');
const reads = data.match(/.{1,5}/g);
readable._read = function () {
if (reads.length === 0) {
setImmediate(() => {
this.emit('error', error);
});
return;
}
this.push(reads.shift());
};
const error2 = await t.throwsAsync(getStream(readable));
t.is(error2, error);
t.is(error2.bufferedData, data);
});