├── .editorconfig
├── .github
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .npmignore
├── .travis.yml
├── .vscode
└── settings.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── package.json
├── src
├── FromStream.ts
├── FromStreamDisposable.ts
├── addListeners.ts
├── index.ts
└── types.ts
├── test
├── index.ts
└── tsconfig.json
├── tsconfig.commonjs.json
├── tsconfig.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | tab_width = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 | insert_final_newline = false
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | **Code to reproduce the issue:**
8 |
9 |
10 | **Expected behavior:**
11 |
12 |
13 | **Actual behavior:**
14 |
15 |
16 | **Versions of packages used:**
17 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | - [ ] I added new tests for the issue I fixed or the feature I built
7 | - [ ] I ran `npm test` for the package I'm modifying
8 | - [ ] I used `npm run commit` instead of `git commit`
9 |
10 |
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 |
7 | # Runtime data
8 | pids
9 | *.pid
10 | *.seed
11 |
12 | # Directory for instrumented libs generated by jscoverage/JSCover
13 | lib-cov
14 |
15 | # Coverage directory used by tools like istanbul
16 | coverage
17 |
18 | # nyc test coverage
19 | .nyc_output
20 |
21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
22 | .grunt
23 |
24 | # node-waf configuration
25 | .lock-wscript
26 |
27 | # Compiled binary addons (http://nodejs.org/api/addons.html)
28 | build/Release
29 |
30 | # Dependency directories
31 | node_modules
32 | jspm_packages
33 |
34 | # Optional npm cache directory
35 | .npm
36 |
37 | # Optional REPL history
38 | .node_repl_history
39 |
40 | # generated files
41 | lib
42 | .tmp
43 | test/test.txt
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mostjs-community/most-node-streams/a1612ea72ab37f770ea18c786b71578533afb4d8/.npmignore
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 6
4 | - 7
5 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.fontFamily": "'Fira Code Medium', 'Courier New', monospace, 'Droid Sans Fallback'",
3 |
4 | "editor.fontLigatures": true,
5 |
6 | "editor.rulers": [80, 160],
7 |
8 | "editor.wrappingColumn": 120,
9 |
10 | "editor.wrappingIndent": "indent",
11 |
12 | "editor.tabSize": 2,
13 |
14 | "editor.insertSpaces": true,
15 |
16 | "editor.formatOnType": true,
17 |
18 | "typescript.tsdk": "node_modules/typescript/lib"
19 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # [1.0.0](https://github.com/TylorS/most-node-streams/compare/81c3747...v1.0.0) (2017-01-16)
3 |
4 |
5 | ### Bug Fixes
6 |
7 | * **fromReadable:** default to 'data' ([b800406](https://github.com/TylorS/most-node-streams/commit/b800406))
8 |
9 |
10 | ### Features
11 |
12 | * **most-node-streams:** initial implementation ([81c3747](https://github.com/TylorS/most-node-streams/commit/81c3747))
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | First of all, thank you so much, we need your help.
4 |
5 | ## Contributing a fix or feature
6 |
7 | 1. Fork the repository
8 | 2. Switch to a new branch `git checkout -b [branchName]`
9 | 3. Produce your fix or feature
10 | 4. Use `npm run commit` instead of `git commit` PLEASE!
11 | 5. Submit a pull request for review
12 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Tylor Steinberger
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # most-node-streams
2 |
3 | > Convert Node.js Streams to Most.js Streams
4 |
5 | Allows you to translate basic Node.js Streams into Most.js Streams.
6 |
7 | WARNING:
8 | This does not attempt to cover the use case where you need backpressure or flow control.
9 | If you need backpressure or flow control then please continue to use Node.js Streams.
10 |
11 | ## Let me have it!
12 | ```sh
13 | npm install --save most-node-streams
14 | ```
15 |
16 | ## API
17 |
18 | #### `fromReadable(stream: NodeJS.ReadableStream, dataEventName?: string): Stream`
19 |
20 | Creates a Most.js Stream from a Node.js Readable Stream. Optionally takes an event name
21 | to recieve events defaulting to `data` if none is provided.
22 |
23 | #### `fromWritable(stream: NodeJS.WritableStream): Stream`
24 |
25 | Creates a Most.js Stream that replicates the values being written to a WritableStream.
26 |
27 | #### `toWritable (nodeStream: NodeJS.WritableStream, mostStream: Stream): Subscription`
28 |
29 | Subscribes to a stream and replicates its values into a NodeJS WritableStream.
30 |
31 | #### `fromStream(nodeStream: NodeStream, options?: FromStreamOptions): Stream`
32 |
33 | This is the function that fromReadable and fromWritable are built from for when you need a little
34 | more configuration.
35 |
36 | ## Types
37 |
38 | #### `FromStreamOptions`
39 |
40 | ```typscript
41 | export interface FromStreamOptions {
42 | endEventName?: string;
43 | dataEventName?: string;
44 | }
45 | ```
46 |
47 | #### `NodeStram`
48 |
49 | ```typescript
50 | export type NodeStream =
51 | NodeJS.WritableStream | NodeJS.ReadableStream | NodeJS.ReadWriteStream;
52 | ```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "most-node-streams",
3 | "version": "1.0.0",
4 | "description": "Convert Node.js streams to Most.js Streams",
5 | "main": "lib/commonjs",
6 | "scripts": {
7 | "test:lint": "tslint src/**/*.ts src/*.ts",
8 | "test:unit": "TS_NODE_PROJECT=test/tsconfig.json mocha -r ts-node/register test/*.ts",
9 | "test": "npm run test:lint && npm run test:unit",
10 | "commit": "git-cz",
11 | "changelog": "conventional-changelog --infile CHANGELOG.md --same-file --release-count 0 --preset angular",
12 | "postchangelog": "git add CHANGELOG.md && git commit -m 'docs(CHANGELOG): append to changelog'",
13 | "build:es2015": "tsc -P tsconfig.json",
14 | "build:commonjs": "tsc -P tsconfig.commonjs.json",
15 | "build": "npm run build:es2015 && npm run build:commonjs",
16 | "preversion": "npm run build",
17 | "postversion": "npm run changelog && git push origin master --tags && npm publish",
18 | "release:minor": "npm version minor -m 'chore(package): v%s'",
19 | "release:major": "npm version major -m 'chore(package): v%s'"
20 | },
21 | "repository": {
22 | "type": "git",
23 | "url": "git+https://github.com/TylorS/most-node-streams.git"
24 | },
25 | "keywords": [
26 | "most",
27 | "node",
28 | "streams",
29 | "convert"
30 | ],
31 | "author": "Tylor Steinberger ",
32 | "license": "MIT",
33 | "bugs": {
34 | "url": "https://github.com/TylorS/most-node-streams/issues"
35 | },
36 | "homepage": "https://github.com/TylorS/most-node-streams#readme",
37 | "config": {
38 | "ghooks": {
39 | "commit-msg": "node ./node_modules/.bin/validate-commit-msg"
40 | }
41 | },
42 | "jsnext:main": "lib/es2015/index.js",
43 | "module": "lib/es2015/index.js",
44 | "typings": "lib/es2015/index.d.ts",
45 | "devDependencies": {
46 | "@motorcycle/tslint": "^1.2.0",
47 | "@types/mocha": "^2.2.33",
48 | "@types/node": "^6.0.51",
49 | "commitizen": "^2.8.6",
50 | "conventional-changelog-cli": "^1.2.0",
51 | "cz-conventional-changelog": "^1.2.0",
52 | "ghooks": "^1.3.2",
53 | "mocha": "^3.2.0",
54 | "stdio-mock": "^1.0.1",
55 | "ts-node": "^1.7.0",
56 | "tslint": "^4.0.2",
57 | "typescript": "^2.2.0-dev.20161127",
58 | "validate-commit-msg": "^2.8.2"
59 | },
60 | "dependencies": {
61 | "@most/multicast": "^1.2.4",
62 | "most": "^1.1.0"
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/FromStream.ts:
--------------------------------------------------------------------------------
1 | import { never, Disposable, Sink, Scheduler } from 'most';
2 | import { MulticastSource } from '@most/multicast';
3 | import { FromStreamDisposable } from './FromStreamDisposable';
4 | import { addListeners } from './addListeners';
5 | import { NodeStream } from './types';
6 |
7 | export class FromStream extends MulticastSource {
8 | private stream: NodeStream;
9 | private endEventName: string;
10 | private dataEventName: string;
11 |
12 | // From MulticastSource
13 | private _disposable: Disposable;
14 |
15 | constructor(stream: NodeStream, endEventName: string, dataEventName: string) {
16 | super(never().source);
17 |
18 | this.stream = stream;
19 | this.endEventName = endEventName;
20 | this.dataEventName = dataEventName;
21 | }
22 |
23 | public run(sink: Sink, scheduler: Scheduler) {
24 | const n = this.add(sink);
25 |
26 | if (n === 1) {
27 | const stream = this.stream;
28 |
29 | this._disposable =
30 | addListeners(stream, this.endEventName, this.dataEventName, sink, scheduler);
31 |
32 | if (typeof (stream as NodeJS.ReadableStream).resume === 'function') {
33 | (stream as NodeJS.ReadableStream).resume();
34 | }
35 | }
36 |
37 | return new FromStreamDisposable(this, sink);
38 | }
39 | }
--------------------------------------------------------------------------------
/src/FromStreamDisposable.ts:
--------------------------------------------------------------------------------
1 | import { Sink, Disposable } from 'most';
2 | import { FromStream } from './FromStream';
3 |
4 | export class FromStreamDisposable implements Disposable {
5 | private source: FromStream;
6 | private sink: Sink;
7 | private disposed: boolean;
8 |
9 | constructor(source: FromStream, sink: Sink) {
10 | this.source = source;
11 | this.sink = sink;
12 | this.disposed = false;
13 | }
14 |
15 | public dispose() {
16 | if (this.disposed) return;
17 | this.disposed = true;
18 | const remaining = this.source.remove(this.sink);
19 |
20 | return remaining === 0 && (this.source as any)._dispose();
21 | }
22 | }
--------------------------------------------------------------------------------
/src/addListeners.ts:
--------------------------------------------------------------------------------
1 | import { Sink, Scheduler, Disposable, PropagateTask } from 'most';
2 | import { NodeStream } from './types';
3 |
4 | export function addListeners(
5 | stream: NodeStream,
6 | endEventName: string,
7 | dataEventName: string,
8 | sink: Sink,
9 | scheduler: Scheduler): Disposable
10 | {
11 | const event = (value: any) => scheduler.asap(PropagateTask.event(value, sink));
12 | const error = (err: Error) => scheduler.asap(PropagateTask.error(err, sink));
13 | const end = (value: any) => scheduler.asap(PropagateTask.end(value, sink));
14 |
15 | stream.addListener(dataEventName, event);
16 | stream.addListener(endEventName, end);
17 | stream.addListener('error', error);
18 |
19 | return {
20 | dispose() {
21 | stream.removeListener(dataEventName, event);
22 | stream.removeListener(endEventName, end);
23 | stream.removeListener('error', error);
24 | },
25 | };
26 | }
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Stream, Subscription } from 'most';
2 | import { FromStream } from './FromStream';
3 | import { NodeStream } from './types';
4 |
5 | export interface FromStreamOptions {
6 | endEventName?: string;
7 | dataEventName?: string;
8 | }
9 |
10 | export function fromStream(
11 | nodeStream: NodeStream,
12 | options: FromStreamOptions = {})
13 | {
14 | const { endEventName = 'end', dataEventName = 'data' } = options;
15 |
16 | if (typeof (nodeStream as NodeJS.ReadableStream).pause === 'function')
17 | (nodeStream as NodeJS.ReadableStream).pause();
18 |
19 | return new Stream(new FromStream(nodeStream, endEventName, dataEventName));
20 | }
21 |
22 | export function fromReadable(
23 | nodeStream: NodeJS.ReadableStream,
24 | dataEventName = 'data',
25 | ): Stream {
26 | return fromStream(nodeStream, { dataEventName, endEventName: 'end' });
27 | }
28 |
29 | export function fromWritable(nodeStream: NodeJS.WritableStream) {
30 | return fromStream(nodeStream, { endEventName: 'finish' });
31 | }
32 |
33 | export function toWritable(
34 | nodeStream: NodeJS.WritableStream,
35 | stream: Stream): Subscription
36 | {
37 | return stream.subscribe({
38 | next (x: string | Buffer) {
39 | nodeStream.write(x);
40 | },
41 | error (e: Error) {
42 | nodeStream.emit('error', e);
43 | },
44 | complete() {
45 | // process.stdout && process.stderr are not closable
46 | if (!(nodeStream as any).isStdio) {
47 | nodeStream.end();
48 | }
49 | },
50 | });
51 | }
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | export type NodeStream =
2 | NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream;
--------------------------------------------------------------------------------
/test/index.ts:
--------------------------------------------------------------------------------
1 | import * as assert from 'assert';
2 | import { from } from 'most';
3 | import { stdio } from 'stdio-mock';
4 | import { fromReadable, fromWritable, toWritable } from '../src';
5 | import { join } from 'path';
6 | import { createReadStream, createWriteStream } from 'fs';
7 |
8 | describe('Most Node Streams', () => {
9 | describe('fromWritable', () => {
10 | it('captures events from writable stream', () => {
11 | const writeStream = createWriteStream(join(__dirname, 'test.txt'));
12 | const stream = fromWritable(writeStream).map(x => x.toString());
13 |
14 | const expected = ['1', '2', '3'];
15 |
16 | stream.observe(function (x: any) {
17 | assert.strictEqual(x, expected.join('\n'));
18 | });
19 |
20 | writeStream.write('1\n');
21 | writeStream.write('2\n');
22 | writeStream.write('3');
23 | });
24 | });
25 |
26 | describe('fromReadable', () => {
27 | it('captures events from readable stream', () => {
28 | const readStream = createReadStream(join(__dirname, 'test.txt'));
29 |
30 | const stream = fromReadable(readStream, 'data').map(data => data.toString());
31 |
32 | const expected = ['1', '2', '3'];
33 |
34 | return stream.observe(function (x: any) {
35 | assert.strictEqual(x, expected.join('\n'));
36 | });
37 | });
38 | });
39 |
40 | describe('toWritable', () => {
41 | it('pushes events to a writable stream', (done) => {
42 | const stdout = stdio().stdout;
43 | const expected = ['1', '2', '3'];
44 | const stream = from(expected);
45 |
46 | toWritable(stdout, stream);
47 |
48 | stdout.addListener('end', () => {
49 | assert.deepEqual(stdout.data(), expected);
50 | done();
51 | });
52 | });
53 | });
54 | });
--------------------------------------------------------------------------------
/test/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "moduleResolution": "node",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "lib": [
8 | "es5",
9 | "es2015"
10 | ],
11 | "noImplicitAny": true,
12 | "sourceMap": true,
13 | "noUnusedParameters": true,
14 | "strictNullChecks": true,
15 | "types": [
16 | "node",
17 | "mocha"
18 | ]
19 | },
20 | "include": [
21 | "./**/*.ts"
22 | ]
23 | }
--------------------------------------------------------------------------------
/tsconfig.commonjs.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "moduleResolution": "node",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "lib": [
8 | "dom",
9 | "es5",
10 | "es2015"
11 | ],
12 | "noImplicitAny": true,
13 | "sourceMap": true,
14 | "noUnusedParameters": true,
15 | "strictNullChecks": true,
16 | "outDir": "lib/commonjs",
17 | "types": [
18 | "node"
19 | ]
20 | },
21 | "files": [
22 | "src/index.ts"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "moduleResolution": "node",
5 | "module": "es2015",
6 | "target": "es2015",
7 | "lib": [
8 | "dom",
9 | "es5",
10 | "es2015"
11 | ],
12 | "noImplicitAny": true,
13 | "sourceMap": true,
14 | "noUnusedParameters": true,
15 | "noUnusedLocals": true,
16 | "strictNullChecks": true,
17 | "outDir": "lib/es2015",
18 | "types": [
19 | "node"
20 | ]
21 | },
22 | "files": [
23 | "src/index.ts"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "@motorcycle/tslint"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------