# object-streaming-tools

> Helper functions to simplify creating and concatenating object streams in NodeJs

Latest version **1.4.0** (published 2020-03-31) · MIT license · 0 weekly downloads

## Install

```sh
npm install object-streaming-tools
pnpm add object-streaming-tools
yarn add object-streaming-tools
bun add object-streaming-tools
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.4.0 |
| Published | 2020-03-31 |
| First published | 2017-06-15 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Node | >=6.0.0 |
| Dependencies | 2 |
| Unpacked size | 87.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Author | Markus Westerholz |
| Maintainers | noisygerman |
| Keywords | object, streams, node streams, nodejs, node js, backend |

## Links

- npm: https://www.npmjs.com/package/object-streaming-tools
- Repository: https://github.com/noisygerman/object-streaming-tools
- Homepage: https://github.com/noisygerman/object-streaming-tools#readme
- Issues: https://github.com/noisygerman/object-streaming-tools/issues
- npm.io page: https://npm.io/package/object-streaming-tools

## Dependencies (2)

- [async](https://npm.io/package/async.md) ^2.5.0
- [lodash](https://npm.io/package/lodash.md) ^4.17.4

## Alternatives

- [byte-size](https://npm.io/package/byte-size.md) — 2.1M weekly downloads
- [speed-limiter](https://npm.io/package/speed-limiter.md) — 16.0K weekly downloads
- [@powersync/node](https://npm.io/package/@powersync/node.md) — 10.9K weekly downloads
- [@ledgerhq/coin-cardano](https://npm.io/package/@ledgerhq/coin-cardano.md) — 1.0K weekly downloads
- [@jayesol/jayeson.lib.streamfinder](https://npm.io/package/@jayesol/jayeson.lib.streamfinder.md) — 1.0K weekly downloads

## Recent versions

- 1.4.0 (latest) — 2020-03-31
- 1.3.2 — 2019-07-30
- 1.3.1 — 2019-03-22
- 1.3.0 — 2019-03-08
- 1.2.0 — 2018-05-17
- 1.1.1 — 2017-07-04
- 1.1.0 — 2017-06-26
- 1.0.5 — 2017-06-21
- 1.0.4 — 2017-06-19
- 1.0.3 — 2017-06-19
- 1.0.2 — 2017-06-19
- 1.0.1 — 2017-06-15
- 1.0.0 — 2017-06-15

## README

# Object Streaming Tools

Helper functions to simplify creating and concatenating object streams in NodeJS

## Motivation

Writing NodeJs streams can be quite challenging. While I myself have create
snippets in my IDE to make my life easier when creating them, frequently I
found myself writing the same code over and over again. Since I am lazy,
I don't really like working this way. And frankly, the German in me simply
wanted - nay demanded! - more efficient, DRYer code.

Looking for a solution early 2016, I first explored RxJs3 . While I
very much appreciated the beauty of that project's approach, it seemed overkill
for what I needed. And when I noticed the significant differences between
version 3 and the then up-and-coming version 4, I decided to take another path.
I also looked at Highland.js, which is very similar in its approach to our goals
here, but was not quit there yet, when we started this.

For the enterprise level application I was designing for and working on with a
team at Copperleaf Technologies, I cooked up my first few helper tools that we
then continued to develop as a team throughout the year.

At version 1.0, this library was at the state we shipped it with that application
in May 2017. Copperleaf Technologies has graciously allowed me to take ownership of the project,
so here it is.

I hope some of you will find it useful.

## Basics

---

### start with anything

```JavaScript
const just = require( 'object-streaming-tools/lib/just' );

just( 'Hello World!' )
  .on( 'data', console.log );

// output:
// Hello World!
```

---

### iterate

```JavaScript
const fromArray = require( 'object-streaming-tools/lib/fromArray' );

fromArray( [ 1, 2, 3 ] )
  .on( 'data', console.log );

// output:
// 1
// 2
// 3
```

---

### iterate with the spread (...) operator

```JavaScript
const just = require( 'object-streaming-tools/lib/just' );

just( ...[ 1, 2, 3 ] )
  .on( 'data', console.log );

// output:
// 1
// 2
// 3
```

---

### streamify non-streams

#### when using async functions

```JavaScript
const just  = require( 'object-streaming-tools/lib/just' );
const apply = require( 'object-streaming-tools/lib/apply' );

function log( s, next ){

  console.log( s );
  this.emit( 'bar', 'THIS IS SPARTA!' ); // 'this' context is the apply stream
  setImmediate( next, null, s );

}

just( 'foo' )
  .pipe( apply( log ) )
  .on( 'bar', console.log )
  .resume();

// output:
// foo
// THIS IS SPARTA!
```

#### when using synchronous functions

Note: Just demonstrating here a technique to achieve this using
[asyncify](https://caolan.github.io/async/docs.html#asyncify)
from the [async](https://caolan.github.io/async/) library, which is also used
internally.

```JavaScript
const range    = require( 'object-streaming-tools/lib/range' );
const apply    = require( 'object-streaming-tools/lib/apply' );
const asyncify = require( 'async/asyncify' );

range( 1, 3 )
  .pipe( apply( asyncify( console.log ) ) )
  .resume();

// output:
// 1
// 2
// 3
```

---

### filter

```JavaScript
const just     = require( 'object-streaming-tools/lib/just' );
const filter   = require( 'object-streaming-tools/lib/filter' );
const asyncify = require( 'async/asyncify' );

just( ...[ 0, 1, 2, 3 ] )
  .pipe( filter( asyncify( ( x )=>x >= 2 ) ) )
  .on( 'data', console.log );

// output:
// 2
// 3

// Get rejected items
just( ...[ 0, 1, 2, 3 ] )
  .pipe( filter( asyncify( ( x )=>x >= 2 ) ) )
  .on( filter.RejectedEventKey, console.log )
  .resume();

// output:
// 0
// 1

```

---

### get a range of numbers

```JavaScript
const range = require( 'object-streaming-tools/lib/range' );

range( 1, 3 )
  .on( 'data', console.log );

// output:
// 1
// 2
// 3
```

---

### iterate over object properties

```JavaScript
const just  = require( 'object-streaming-tools/lib/just' );
const forIn = require( 'object-streaming-tools/lib/forIn' );

just( { foo: 'bar' } )
  .pipe( forIn() )
  .on( 'data', ( { key, value } )=>console.log( key, value )  );

// output:
// foo bar
```

---

### group items in a list by a key's values

#### by using the key's identity

```JavaScript
const just     = require( 'object-streaming-tools/lib/just' );
const apply    = require( 'object-streaming-tools/lib/apply' );
const asyncify = require( 'async/asyncify' );
const keyBy    = require( 'object-streaming-tools/lib/keyBy' );

just( ...[ { foo: 'bar' }, { foo: 'baz' } ] )
  .pipe( keyBy( 'foo' ) )
  .pipe( apply( asyncify( JSON.stringify ) ) )
  .pipe( apply( asyncify( console.log ) ) )
  .resume();

// output:
// { "bar": { "foo": "bar" }, "baz": { "foo": "baz" } }
```

#### by using a function to calculate the key

```JavaScript
const just     = require( 'object-streaming-tools/lib/just' );
const keyBy    = require( 'object-streaming-tools/lib/keyBy' );

just( ...[ { foo: 'bar'  }, { foo: 'baz' } ] )
  .pipe( keyBy( ( { foo } )=>foo ) )
  .on( 'data' , ( result )=>console.log( JSON.stringify( result ) ) );

// output:
// { "bar": { "foo": "bar" }, "baz": { "foo": "baz" } }
```

Note: Both approaches above demonstrate various techniques to achieve the same
result. Neither technique is meant to be prescriptive.

---

### emit values of an object

```JavaScript
const just  = require( 'object-streaming-tools/lib/just' );
const values = require( 'object-streaming-tools/lib/forIn' );

just( { foo: 'bar' } )
  .pipe( values() )
  .on( 'data', console.log );

// output:
// bar
```

---

### switch things up

```JavaScript
const range    = require( 'object-streaming-tools/lib/range' );
const switchBy = require( 'object-streaming-tools/lib/switchBy' );
const asyncify = require( 'async/asyncify' );

const lookup = [ 'one', 'three', 'five' ];

const forTrue  = { ifMatches: true,  thenDo: asyncify( x=>lookup[ x ] ) };
const forFalse = { ifMatches: false, thenDo: asyncify( x=>x ) };

range( 1, 5 )
  .pipe( switchBy( asyncify( x=>!!x % 2 ), [ forTrue, forFalse ] ) )
  .on( 'data', console.log );

// output:
// one
// 2
// three
// 4
// five
```

---

### start from a callback

```JavaScript
const fs           = require( 'fs-extra' );
const fromCallback = require( 'object-streaming-tools/lib/fromCallback' );

fromCallback( fs.readJson.bind( null, 'list.json') )
  .pipe( flatten() )
  .on( 'data', console.log;

// output, given the file contents of 'list.json' => [ "foo", "bar", "baz" ]:
// foo bar baz
```

### emit arrays of a specified length

```JavaScript
const items = [1, 2, 3, 4, 5, 6];

just(...items)
  .pipe( asLengthLimitedArrays( 4 ) )
  .on( 'data', console.log );

// output:
// [ 1, 2, 3, 4 ]
// [ 5, 6 ]
```

### creates a slice of the stream starting from start index and up to, but not including, end index

#### end defaults to Infinity
```JavaScript
const items = ['val1', 'val2', 'val3', 'val4', 'val5', 'val6'];
const start = 2;
just(...items)
  .pipe( emitRange( start ) )
  .on( 'data', console.log );

// output:
// val3
// val4
// val5
// val6
```
#### from start to end
```JavaScript
const items = ['val1', 'val2', 'val3', 'val4', 'val5', 'val6'];
const start = 2;
const end = 5;
just(...items)
  .pipe( emitRange( start, end ) )
  .on( 'data', console.log );

// output:
// val3
// val4
```

### emit only unique items in a stream

#### unique
```JavaScript
const items = [1, 2, 3, 4, 4, 5];
just(...items)
  .pipe( unique() )
  .on( 'data', console.log );

// output:
// 1
// 2
// 3
// 4
// 5
```
#### uniqueBy
##### via a string iteratee
```JavaScript
const items = [{id: 'foo'}, {id: 'bar'}, {id: 'foo'}];
const attributeName = 'id'
just(...items)
  .pipe( uniqueBy( attributeName ) )
  .on( 'data', console.log );

// output:
// {id: 'foo'}
// {id: 'bar'}
```

##### via an iteratee function
```JavaScript
const items = [2.1, 1.2, 2.3];
just(...items)
  .pipe( uniqueBy( Math.floor ) )
  .on( 'data', console.log );

// output:
// 2.1
// 1.2
```

TBC

---
_Source: https://npm.io/package/object-streaming-tools · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
