Rework module structure and improve typings
This commit is contained in:
parent
9694ee88e4
commit
ce89d6df3e
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
sample_output
|
sample_output
|
||||||
|
yarn-error.log
|
62
README.md
62
README.md
@ -41,14 +41,12 @@ main();
|
|||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
### { stream }
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
/**
|
/**
|
||||||
* Convert an array into a readable stream of its elements
|
* Convert an array into a readable stream of its elements
|
||||||
* @param array The array of elements to stream
|
* @param array The array of elements to stream
|
||||||
*/
|
*/
|
||||||
export declare function fromArray(array: any[]): NodeJS.ReadableStream;
|
fromArray(array: any[]): NodeJS.ReadableStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a ReadWrite stream that maps streamed chunks
|
* Return a ReadWrite stream that maps streamed chunks
|
||||||
@ -57,15 +55,9 @@ export declare function fromArray(array: any[]): NodeJS.ReadableStream;
|
|||||||
* @param options.readableObjectMode Whether this stream should behave as a readable stream of objects
|
* @param options.readableObjectMode Whether this stream should behave as a readable stream of objects
|
||||||
* @param options.writableObjectMode Whether this stream should behave as a writable stream of objects
|
* @param options.writableObjectMode Whether this stream should behave as a writable stream of objects
|
||||||
*/
|
*/
|
||||||
export declare function map<T, R>(
|
map<T, R>(
|
||||||
mapper: (chunk: T, encoding: string) => R,
|
mapper: (chunk: T, encoding: string) => R,
|
||||||
{
|
options?: ThroughOptions,
|
||||||
readableObjectMode,
|
|
||||||
writableObjectMode,
|
|
||||||
}?: {
|
|
||||||
readableObjectMode?: boolean | undefined;
|
|
||||||
writableObjectMode?: boolean | undefined;
|
|
||||||
},
|
|
||||||
): NodeJS.ReadWriteStream;
|
): NodeJS.ReadWriteStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,49 +67,57 @@ export declare function map<T, R>(
|
|||||||
* @param options.readableObjectMode Whether this stream should behave as a readable stream of objects
|
* @param options.readableObjectMode Whether this stream should behave as a readable stream of objects
|
||||||
* @param options.writableObjectMode Whether this stream should behave as a writable stream of objects
|
* @param options.writableObjectMode Whether this stream should behave as a writable stream of objects
|
||||||
*/
|
*/
|
||||||
export declare function flatMap<T, R>(
|
flatMap<T, R>(
|
||||||
mapper:
|
mapper:
|
||||||
| ((chunk: T, encoding: string) => R[])
|
| ((chunk: T, encoding: string) => R[])
|
||||||
| ((chunk: T, encoding: string) => Promise<R[]>),
|
| ((chunk: T, encoding: string) => Promise<R[]>),
|
||||||
{
|
options?: ThroughOptions,
|
||||||
readableObjectMode,
|
|
||||||
writableObjectMode,
|
|
||||||
}?: {
|
|
||||||
readableObjectMode?: boolean | undefined;
|
|
||||||
writableObjectMode?: boolean | undefined;
|
|
||||||
},
|
|
||||||
): NodeJS.ReadWriteStream;
|
): NodeJS.ReadWriteStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a ReadWrite stream that splits streamed chunks using the given separator
|
* Return a ReadWrite stream that splits streamed chunks using the given separator
|
||||||
* @param separator The separator to split by, defaulting to "\n"
|
* @param separator The separator to split by, defaulting to "\n"
|
||||||
*/
|
*/
|
||||||
export declare function split(separator?: string): NodeJS.ReadWriteStream;
|
split(
|
||||||
|
separator?: string | RegExp,
|
||||||
|
): NodeJS.ReadWriteStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a ReadWrite stream that joins streamed chunks using the given separator
|
* Return a ReadWrite stream that joins streamed chunks using the given separator
|
||||||
* @param separator The separator to join with
|
* @param separator The separator to join with
|
||||||
*/
|
*/
|
||||||
export declare function join(separator: string): NodeJS.ReadWriteStream;
|
join(separator: string): NodeJS.ReadWriteStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a ReadWrite stream that collects streamed objects or bytes into an array or buffer
|
* Return a ReadWrite stream that collects streamed chunks into an array or buffer
|
||||||
* @param options
|
* @param options
|
||||||
* @param options.objectMode Whether this stream should behave as a stream of objects
|
* @param options.objectMode Whether this stream should behave as a stream of objects
|
||||||
*/
|
*/
|
||||||
export declare function collect({
|
collect(
|
||||||
objectMode,
|
options?: ReadableOptions,
|
||||||
}?: {
|
): NodeJS.ReadWriteStream;
|
||||||
objectMode?: boolean | undefined;
|
|
||||||
}): NodeJS.ReadWriteStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a stream of readable streams concatenated together
|
* Return a stream of readable streams concatenated together
|
||||||
* @param streams The readable streams to concatenate
|
* @param streams The readable streams to concatenate
|
||||||
*/
|
*/
|
||||||
export declare function concat(
|
concat(
|
||||||
...streams: NodeJS.ReadableStream[]
|
...streams: NodeJS.ReadableStream[]
|
||||||
): NodeJS.ReadableStream;
|
): NodeJS.ReadableStream;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interfaces
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface ReadableOptions {
|
||||||
|
objectMode?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThroughOptions {
|
||||||
|
readableObjectMode?: boolean;
|
||||||
|
writableObjectMode?: boolean;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### { utils }
|
### { utils }
|
||||||
@ -128,7 +128,7 @@ export declare function concat(
|
|||||||
*
|
*
|
||||||
* @param ms The number of milliseconds to wait
|
* @param ms The number of milliseconds to wait
|
||||||
*/
|
*/
|
||||||
export declare function sleep(ms: number): Promise<{}>;
|
sleep(ms: number): Promise<{}>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a value after the given delay in milliseconds
|
* Resolve a value after the given delay in milliseconds
|
||||||
@ -136,7 +136,7 @@ export declare function sleep(ms: number): Promise<{}>;
|
|||||||
* @param value Value to resolve
|
* @param value Value to resolve
|
||||||
* @param ms Number of milliseconds to wait
|
* @param ms Number of milliseconds to wait
|
||||||
*/
|
*/
|
||||||
export declare function delay<T>(value: T, ms: number): Promise<T>;
|
delay<T>(value: T, ms: number): Promise<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve once the given event emitter emits the specified event
|
* Resolve once the given event emitter emits the specified event
|
||||||
@ -144,7 +144,7 @@ export declare function delay<T>(value: T, ms: number): Promise<T>;
|
|||||||
* @param emitter Event emitter to watch
|
* @param emitter Event emitter to watch
|
||||||
* @param event Event to watch
|
* @param event Event to watch
|
||||||
*/
|
*/
|
||||||
export declare function once<T>(
|
once<T>(
|
||||||
emitter: NodeJS.EventEmitter,
|
emitter: NodeJS.EventEmitter,
|
||||||
event: string,
|
event: string,
|
||||||
): Promise<T>;
|
): Promise<T>;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mhysa",
|
"name": "mhysa",
|
||||||
"version": "0.5.0-beta.0",
|
"version": "0.5.0-beta.1",
|
||||||
"description": "Promise, Stream and EventEmitter utils for Node.js",
|
"description": "Promise, Stream and EventEmitter utils for Node.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"promise",
|
"promise",
|
||||||
@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "**/*.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
|
@ -1,15 +1,8 @@
|
|||||||
import test from "ava";
|
import test from "ava";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { Readable } from "stream";
|
import { Readable } from "stream";
|
||||||
import {
|
import { fromArray, map, flatMap, split, join, collect, concat } from "./";
|
||||||
fromArray,
|
|
||||||
map,
|
|
||||||
flatMap,
|
|
||||||
split,
|
|
||||||
join,
|
|
||||||
collect,
|
|
||||||
concat,
|
|
||||||
} from "./stream";
|
|
||||||
test.cb("fromArray() streams array elements in flowing mode", t => {
|
test.cb("fromArray() streams array elements in flowing mode", t => {
|
||||||
t.plan(3);
|
t.plan(3);
|
||||||
const elements = ["a", "b", "c"];
|
const elements = ["a", "b", "c"];
|
223
src/index.ts
223
src/index.ts
@ -1,6 +1,217 @@
|
|||||||
import * as utils from "./utils";
|
import { Transform, Readable } from "stream";
|
||||||
import * as stream from "./stream";
|
import * as _utils from "./utils";
|
||||||
export = {
|
export const utils = _utils;
|
||||||
utils,
|
|
||||||
...stream,
|
export interface ReadableOptions {
|
||||||
};
|
objectMode?: boolean;
|
||||||
|
}
|
||||||
|
export interface ThroughOptions {
|
||||||
|
readableObjectMode?: boolean;
|
||||||
|
writableObjectMode?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an array into a readable stream of its elements
|
||||||
|
* @param array The array of elements to stream
|
||||||
|
*/
|
||||||
|
export function fromArray(array: any[]): NodeJS.ReadableStream {
|
||||||
|
let cursor = 0;
|
||||||
|
return new Readable({
|
||||||
|
objectMode: true,
|
||||||
|
read() {
|
||||||
|
if (cursor < array.length) {
|
||||||
|
this.push(array[cursor]);
|
||||||
|
cursor++;
|
||||||
|
} else {
|
||||||
|
this.push(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a ReadWrite stream that maps streamed chunks
|
||||||
|
* @param mapper The mapper function, mapping each (chunk, encoding) to a new chunk (or a promise of such)
|
||||||
|
* @param options
|
||||||
|
* @param options.readableObjectMode Whether this stream should behave as a readable stream of objects
|
||||||
|
* @param options.writableObjectMode Whether this stream should behave as a writable stream of objects
|
||||||
|
*/
|
||||||
|
export function map<T, R>(
|
||||||
|
mapper: (chunk: T, encoding: string) => R,
|
||||||
|
options: ThroughOptions = {
|
||||||
|
readableObjectMode: true,
|
||||||
|
writableObjectMode: true,
|
||||||
|
},
|
||||||
|
): NodeJS.ReadWriteStream {
|
||||||
|
return new Transform({
|
||||||
|
...options,
|
||||||
|
async transform(chunk, encoding, callback) {
|
||||||
|
let isPromise = false;
|
||||||
|
try {
|
||||||
|
const mapped = mapper(chunk, encoding);
|
||||||
|
isPromise = mapped instanceof Promise;
|
||||||
|
callback(undefined, await mapped);
|
||||||
|
} catch (err) {
|
||||||
|
if (isPromise) {
|
||||||
|
// Calling the callback asynchronously with an error wouldn't emit the error, so emit directly
|
||||||
|
this.emit("error", err);
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a ReadWrite stream that flat maps streamed chunks
|
||||||
|
* @param mapper The mapper function, mapping each (chunk, encoding) to an array of new chunks (or a promise of such)
|
||||||
|
* @param options
|
||||||
|
* @param options.readableObjectMode Whether this stream should behave as a readable stream of objects
|
||||||
|
* @param options.writableObjectMode Whether this stream should behave as a writable stream of objects
|
||||||
|
*/
|
||||||
|
export function flatMap<T, R>(
|
||||||
|
mapper:
|
||||||
|
| ((chunk: T, encoding: string) => R[])
|
||||||
|
| ((chunk: T, encoding: string) => Promise<R[]>),
|
||||||
|
options: ThroughOptions = {
|
||||||
|
readableObjectMode: true,
|
||||||
|
writableObjectMode: true,
|
||||||
|
},
|
||||||
|
): NodeJS.ReadWriteStream {
|
||||||
|
return new Transform({
|
||||||
|
...options,
|
||||||
|
async transform(chunk, encoding, callback) {
|
||||||
|
let isPromise = false;
|
||||||
|
try {
|
||||||
|
const mapped = mapper(chunk, encoding);
|
||||||
|
isPromise = mapped instanceof Promise;
|
||||||
|
(await mapped).forEach(c => this.push(c));
|
||||||
|
callback();
|
||||||
|
} catch (err) {
|
||||||
|
if (isPromise) {
|
||||||
|
// Calling the callback asynchronously with an error wouldn't emit the error, so emit directly
|
||||||
|
this.emit("error", err);
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a ReadWrite stream that splits streamed chunks using the given separator
|
||||||
|
* @param separator The separator to split by, defaulting to "\n"
|
||||||
|
*/
|
||||||
|
export function split(
|
||||||
|
separator: string | RegExp = "\n",
|
||||||
|
): NodeJS.ReadWriteStream {
|
||||||
|
let buffered: string = "";
|
||||||
|
return new Transform({
|
||||||
|
readableObjectMode: true,
|
||||||
|
writableObjectMode: true,
|
||||||
|
async transform(chunk: string, encoding, callback) {
|
||||||
|
const splitted = chunk.split(separator);
|
||||||
|
if (buffered.length > 0 && splitted.length > 1) {
|
||||||
|
splitted[0] = buffered.concat(splitted[0]);
|
||||||
|
buffered = "";
|
||||||
|
}
|
||||||
|
buffered += splitted[splitted.length - 1];
|
||||||
|
splitted.slice(0, -1).forEach((part: string) => this.push(part));
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
flush(callback) {
|
||||||
|
callback(undefined, buffered);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a ReadWrite stream that joins streamed chunks using the given separator
|
||||||
|
* @param separator The separator to join with
|
||||||
|
*/
|
||||||
|
export function join(separator: string): NodeJS.ReadWriteStream {
|
||||||
|
let isFirstChunk = true;
|
||||||
|
return new Transform({
|
||||||
|
readableObjectMode: true,
|
||||||
|
writableObjectMode: true,
|
||||||
|
async transform(chunk, encoding, callback) {
|
||||||
|
if (!isFirstChunk) {
|
||||||
|
this.push(separator);
|
||||||
|
}
|
||||||
|
this.push(chunk);
|
||||||
|
isFirstChunk = false;
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a ReadWrite stream that collects streamed chunks into an array or buffer
|
||||||
|
* @param options
|
||||||
|
* @param options.objectMode Whether this stream should behave as a stream of objects
|
||||||
|
*/
|
||||||
|
export function collect(
|
||||||
|
options: ReadableOptions = { objectMode: false },
|
||||||
|
): NodeJS.ReadWriteStream {
|
||||||
|
const collected: any[] = [];
|
||||||
|
return new Transform({
|
||||||
|
readableObjectMode: options.objectMode,
|
||||||
|
writableObjectMode: options.objectMode,
|
||||||
|
transform(data, encoding, callback) {
|
||||||
|
collected.push(data);
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
flush(callback) {
|
||||||
|
this.push(
|
||||||
|
options.objectMode ? collected : Buffer.concat(collected),
|
||||||
|
);
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a stream of readable streams concatenated together
|
||||||
|
* @param streams The readable streams to concatenate
|
||||||
|
*/
|
||||||
|
export function concat(
|
||||||
|
...streams: NodeJS.ReadableStream[]
|
||||||
|
): NodeJS.ReadableStream {
|
||||||
|
let isStarted = false;
|
||||||
|
let currentStreamIndex = 0;
|
||||||
|
const startCurrentStream = () => {
|
||||||
|
if (currentStreamIndex >= streams.length) {
|
||||||
|
wrapper.push(null);
|
||||||
|
} else {
|
||||||
|
streams[currentStreamIndex]
|
||||||
|
.on("data", chunk => {
|
||||||
|
if (!wrapper.push(chunk)) {
|
||||||
|
streams[currentStreamIndex].pause();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on("error", err => wrapper.emit("error", err))
|
||||||
|
.on("end", () => {
|
||||||
|
currentStreamIndex++;
|
||||||
|
startCurrentStream();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = new Readable({
|
||||||
|
objectMode: true,
|
||||||
|
read() {
|
||||||
|
if (!isStarted) {
|
||||||
|
isStarted = true;
|
||||||
|
startCurrentStream();
|
||||||
|
}
|
||||||
|
if (currentStreamIndex < streams.length) {
|
||||||
|
streams[currentStreamIndex].resume();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
199
src/stream.ts
199
src/stream.ts
@ -1,199 +0,0 @@
|
|||||||
import { Transform, Readable } from "stream";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an array into a readable stream of its elements
|
|
||||||
* @param array The array of elements to stream
|
|
||||||
*/
|
|
||||||
export function fromArray(array: any[]): NodeJS.ReadableStream {
|
|
||||||
let cursor = 0;
|
|
||||||
return new Readable({
|
|
||||||
objectMode: true,
|
|
||||||
read() {
|
|
||||||
if (cursor < array.length) {
|
|
||||||
this.push(array[cursor]);
|
|
||||||
cursor++;
|
|
||||||
} else {
|
|
||||||
this.push(null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a ReadWrite stream that maps streamed chunks
|
|
||||||
* @param mapper The mapper function, mapping each (chunk, encoding) to a new chunk (or a promise of such)
|
|
||||||
* @param options
|
|
||||||
* @param options.readableObjectMode Whether this stream should behave as a readable stream of objects
|
|
||||||
* @param options.writableObjectMode Whether this stream should behave as a writable stream of objects
|
|
||||||
*/
|
|
||||||
export function map<T, R>(
|
|
||||||
mapper: (chunk: T, encoding: string) => R,
|
|
||||||
{ readableObjectMode = true, writableObjectMode = true } = {},
|
|
||||||
): NodeJS.ReadWriteStream {
|
|
||||||
return new Transform({
|
|
||||||
readableObjectMode,
|
|
||||||
writableObjectMode,
|
|
||||||
async transform(chunk, encoding, callback) {
|
|
||||||
let isPromise = false;
|
|
||||||
try {
|
|
||||||
const mapped = mapper(chunk, encoding);
|
|
||||||
isPromise = mapped instanceof Promise;
|
|
||||||
callback(undefined, await mapped);
|
|
||||||
} catch (err) {
|
|
||||||
if (isPromise) {
|
|
||||||
// Calling the callback asynchronously with an error wouldn't emit the error, so emit directly
|
|
||||||
this.emit("error", err);
|
|
||||||
callback();
|
|
||||||
} else {
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a ReadWrite stream that flat maps streamed chunks
|
|
||||||
* @param mapper The mapper function, mapping each (chunk, encoding) to an array of new chunks (or a promise of such)
|
|
||||||
* @param options
|
|
||||||
* @param options.readableObjectMode Whether this stream should behave as a readable stream of objects
|
|
||||||
* @param options.writableObjectMode Whether this stream should behave as a writable stream of objects
|
|
||||||
*/
|
|
||||||
export function flatMap<T, R>(
|
|
||||||
mapper:
|
|
||||||
| ((chunk: T, encoding: string) => R[])
|
|
||||||
| ((chunk: T, encoding: string) => Promise<R[]>),
|
|
||||||
{ readableObjectMode = true, writableObjectMode = true } = {},
|
|
||||||
): NodeJS.ReadWriteStream {
|
|
||||||
return new Transform({
|
|
||||||
readableObjectMode,
|
|
||||||
writableObjectMode,
|
|
||||||
async transform(chunk, encoding, callback) {
|
|
||||||
let isPromise = false;
|
|
||||||
try {
|
|
||||||
const mapped = mapper(chunk, encoding);
|
|
||||||
isPromise = mapped instanceof Promise;
|
|
||||||
(await mapped).forEach(c => this.push(c));
|
|
||||||
callback();
|
|
||||||
} catch (err) {
|
|
||||||
if (isPromise) {
|
|
||||||
// Calling the callback asynchronously with an error wouldn't emit the error, so emit directly
|
|
||||||
this.emit("error", err);
|
|
||||||
callback();
|
|
||||||
} else {
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a ReadWrite stream that splits streamed chunks using the given separator
|
|
||||||
* @param separator The separator to split by, defaulting to "\n"
|
|
||||||
*/
|
|
||||||
export function split(
|
|
||||||
separator: string | RegExp = "\n",
|
|
||||||
): NodeJS.ReadWriteStream {
|
|
||||||
let buffered: string = "";
|
|
||||||
return new Transform({
|
|
||||||
readableObjectMode: true,
|
|
||||||
writableObjectMode: true,
|
|
||||||
async transform(chunk: string, encoding, callback) {
|
|
||||||
const splitted = chunk.split(separator);
|
|
||||||
if (buffered.length > 0 && splitted.length > 1) {
|
|
||||||
splitted[0] = buffered.concat(splitted[0]);
|
|
||||||
buffered = "";
|
|
||||||
}
|
|
||||||
buffered += splitted[splitted.length - 1];
|
|
||||||
splitted.slice(0, -1).forEach((part: string) => this.push(part));
|
|
||||||
callback();
|
|
||||||
},
|
|
||||||
flush(callback) {
|
|
||||||
callback(undefined, buffered);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a ReadWrite stream that joins streamed chunks using the given separator
|
|
||||||
* @param separator The separator to join with
|
|
||||||
*/
|
|
||||||
export function join(separator: string): NodeJS.ReadWriteStream {
|
|
||||||
let isFirstChunk = true;
|
|
||||||
return new Transform({
|
|
||||||
readableObjectMode: true,
|
|
||||||
writableObjectMode: true,
|
|
||||||
async transform(chunk, encoding, callback) {
|
|
||||||
if (!isFirstChunk) {
|
|
||||||
this.push(separator);
|
|
||||||
}
|
|
||||||
this.push(chunk);
|
|
||||||
isFirstChunk = false;
|
|
||||||
callback();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a ReadWrite stream that collects streamed chunks into an array or buffer
|
|
||||||
* @param options
|
|
||||||
* @param options.objectMode Whether this stream should behave as a stream of objects
|
|
||||||
*/
|
|
||||||
export function collect({ objectMode = false } = {}): NodeJS.ReadWriteStream {
|
|
||||||
const collected: any[] = [];
|
|
||||||
return new Transform({
|
|
||||||
readableObjectMode: objectMode,
|
|
||||||
writableObjectMode: objectMode,
|
|
||||||
transform(data, encoding, callback) {
|
|
||||||
collected.push(data);
|
|
||||||
callback();
|
|
||||||
},
|
|
||||||
flush(callback) {
|
|
||||||
this.push(objectMode ? collected : Buffer.concat(collected));
|
|
||||||
callback();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a stream of readable streams concatenated together
|
|
||||||
* @param streams The readable streams to concatenate
|
|
||||||
*/
|
|
||||||
export function concat(
|
|
||||||
...streams: NodeJS.ReadableStream[]
|
|
||||||
): NodeJS.ReadableStream {
|
|
||||||
let isStarted = false;
|
|
||||||
let currentStreamIndex = 0;
|
|
||||||
const startCurrentStream = () => {
|
|
||||||
if (currentStreamIndex >= streams.length) {
|
|
||||||
wrapper.push(null);
|
|
||||||
} else {
|
|
||||||
streams[currentStreamIndex]
|
|
||||||
.on("data", chunk => {
|
|
||||||
if (!wrapper.push(chunk)) {
|
|
||||||
streams[currentStreamIndex].pause();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on("error", err => wrapper.emit("error", err))
|
|
||||||
.on("end", () => {
|
|
||||||
currentStreamIndex++;
|
|
||||||
startCurrentStream();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = new Readable({
|
|
||||||
objectMode: true,
|
|
||||||
read() {
|
|
||||||
if (!isStarted) {
|
|
||||||
isStarted = true;
|
|
||||||
startCurrentStream();
|
|
||||||
}
|
|
||||||
if (currentStreamIndex < streams.length) {
|
|
||||||
streams[currentStreamIndex].resume();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
@ -10,7 +10,7 @@
|
|||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"lib": ["es2017"],
|
"lib": ["es2016"],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"declaration": true
|
"declaration": true
|
||||||
},
|
},
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"no-console": false,
|
"no-console": false,
|
||||||
"no-implicit-dependencies": [true, "dev"],
|
"no-implicit-dependencies": [true, "dev"],
|
||||||
"prettier": true,
|
"prettier": true,
|
||||||
"ordered-imports": false
|
"ordered-imports": false,
|
||||||
|
"interface-name": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user