Skip to content

Commit

Permalink
feat(pipe): add piped operators [WIP - DO NOT MERGE] (#75)
Browse files Browse the repository at this point in the history
* feat(pipe): add piped operators

* feat(pipe): add through concat

* feat(pipe): add through defaultIfEmpty

* feat(pipe): add through delay

* feat(pipe): add through delayEach

* feat(pipe): add through distinct

* feat(pipe): add through distinctUntilChanged

* feat(pipe): add through doWhile

* feat(pipe): add through endwith

* feat(pipe): add through except

* feat(pipe): add through expand

* feat(pipe): add through filter

* feat(pipe): add through finally

* feat(pipe): add through flatmap

* feat(pipe): add through flatten

* feat(pipe): add through groupby

* feat(pipe): add through groupjoin

* feat(pipe): add through ignoreelements

* feat(pipe): add through innerjoin

* feat(pipe): add through intersect

* feat(pipe): add through map

* feat(pipe): add through memoize

* feat(pipe): add through merge

* feat(pipe): add through mergeAll

* feat(pipe): add through minby

* feat(pipe): add through onerrorresumenext

* feat(pipe): add through pairwise

* feat(pipe): add through pluck

* feat(pipe): add through publish

* feat(pipe): add through repeat

* feat(pipe): add through retry

* feat(pipe): add through reverse

* feat(pipe): add through scan

* feat(pipe): add through scanRight

* feat(pipe): add through share

* feat(pipe): add through skip

* feat(pipe): add through skipLast

* feat(pipe): add through skipUntil

* feat(pipe): add through skipWhile

* feat(pipe): add through slice

* feat(pipe): add through startwith

* feat(pipe): add through take

* feat(pipe): add through takelast

* feat(pipe): add through takeuntil

* feat(pipe): add through takewhile

* feat(pipe): add through tap

* feat(pipe): add through throttle

* feat(pipe): add through timeinterval

* feat(pipe): add through timeout

* feat(pipe): add through timestamp

* feat(pipe): add through union

* feat(pipe): add through buffer

* feat(pipe): add through catch

* feat(pipe): add through catchWith

* feat(pipe): add through concat

* feat(pipe): add through concatall

* feat(pipe): add through defaultifempty

* feat(pipe): add through distinct

* feat(pipe): add through distinctuntilchanged

* feat(pipe): add through dowhile

* feat(pipe): add through endwith

* feat(pipe): add through except

* feat(pipe): add through expand

* feat(pipe): add through filter

* feat(pipe): add through finally

* feat(pipe): add through flatmap

* feat(pipe): add through flatten

* feat(pipe): add through groupjoin

* feat(pipe): add through ignorelements

* feat(pipe): add through innerjoin

* feat(pipe): add through intersect

* feat(pipe): add through map

* feat(pipe): add through maxby

* feat(pipe): add through memoie

* feat(pipe): add through minby

* feat(pipe): add through onerrorresumenext

* feat(pipe): add through pairwise

* feat(pipe): add through pluck

* feat(pipe): add through publish

* feat(pipe): add through repeat

* feat(pipe): add through retry

* feat(pipe): add through reverse

* feat(pipe): add through scan

* feat(pipe): add through scanright

* feat(pipe): add through share

* feat(pipe): add through skip

* feat(pipe): add through skiplast

* feat(pipe): add through skipwhile

* feat(pipe): add through slice

* feat(pipe): add through startwith

* feat(pipe): add through take

* feat(pipe): add through takelast

* feat(pipe): add through takewhile

* feat(pipe): add through tap

* feat(pipe): add through union

* feat(pipe): add through pipe

* feat(pipe): moving pipe and forEach to core

* feat(pipe): adds of and from to base

* feat(pipe): fix build

* style(lint): update code lint friendly (#116)

* feat(from): make from on non-iterables coerce to iterables (#117)

* feat(pipe): add to __modules

* feat(pipe): add to __modules

* feat(pipe): adding piped tests

* fix pipe exports (#119)

* build(gulpfile): allow building UMD intermediate step standalone for debugging

* fix(ix): declare prototype pipe method type so it isn't minified away

* fix(pipe): export pipe operators separately so they're not minified away

* test(operators): add helper to test all three operator variants

* fix(reduce): fix scan/reduce proto method argument checks

* test(spec): execute iterable operator tests on all operator variants

* test(spec): execute asynciterable operator tests on all operator variants

* fix(ix): export OrderedIterableBase so thenBy method names are protected from Uglify

* chore(lint): fix lint

* test(helpers): disable missing pipe fn logging
  • Loading branch information
mattpodwysocki authored Oct 29, 2017
1 parent 0cce755 commit 76a4b4f
Show file tree
Hide file tree
Showing 376 changed files with 4,055 additions and 2,049 deletions.
18 changes: 9 additions & 9 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const { Observable, Scheduler, Subject, ReplaySubject } = require(`rxjs`);
const releasesRootDir = `targets`;
const knownTargets = [`es5`, `es2015`, `esnext`];
const knownModules = [`cjs`, `esm`, `cls`, `umd`];
const moduleFormatsToSkipCombosOf = { cls: true };
const metadataFiles = [`LICENSE`, `readme.md`, `CHANGELOG.md`];
const packageJSONFields = [
`version`, `license`, `description`,
Expand Down Expand Up @@ -272,7 +271,7 @@ const compileUglifyJS = ((cache, commonConfig) => memoizeTask(cache, function ug
compress: { unsafe: true, },
output: { comments: false, beautify: false },
mangle: { eval: true, safari10: true, // <-- Works around a Safari 10 bug: // https://github.com/mishoo/UglifyJS2/issues/1753
properties: { reserved }
properties: { reserved: [`configurable`, `enumerable`, ...reserved] }
}
},
})
Expand Down Expand Up @@ -462,9 +461,10 @@ function gulpConcurrent(tasks, concurrency = 'parallel') {
const buildConcurrent = (tasks) => () =>
gulpConcurrent(tasks)()
.concat(Observable
.defer(() => Observable
.merge(...knownTargets.map((target) =>
del(`${_dir(UMDSourceTargets[target], `cls`)}/**`)))));
.defer(() => modules.indexOf(`cls`) > -1 ?
Observable.empty() :
Observable.merge(...knownTargets.map((target) =>
del(`${_dir(target, `cls`)}/**`)))));

const testConcurrency = process.env.IS_APPVEYOR_CI ? 'series' : 'parallel';

Expand All @@ -479,7 +479,7 @@ function getTasks(name) {
if (targets.indexOf(`ts`) !== -1) tasks.push(`${name}:ts`);
if (targets.indexOf(`ix`) !== -1) tasks.push(`${name}:ix`);
for (const [target, format] of combinations(targets, modules)) {
if (format in moduleFormatsToSkipCombosOf) {
if (format === `cls` && (name === `test` || modules.indexOf(`cls`) === -1)) {
continue;
}
tasks.push(`${name}:${_task(target, format)}`);
Expand All @@ -495,10 +495,10 @@ function _dir(target, format) { return path.join(releasesRootDir, ...(!format ?

function* combinations(_targets, _modules) {

const targets = known(knownTargets, _targets || (_targets = [`all`]));
const modules = known(knownModules, _modules || (_modules = [`all`]));
const targets = known(knownTargets, _targets || [`all`]);
const modules = known(knownModules, _modules || [`all`]);

if (_targets[0] === `all` && _modules[0] === `all`) {
if (targets[0] === `all` && modules[0] === `all`) {
yield [`ts`, ``];
yield [`ix`, ``];
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"release": "./npm-release.sh",
"doc": "shx rm -rf ./doc && esdoc",
"commitmsg": "validate-commit-msg",
"lint:src": "tslint --fix --type-check -p tsconfig.json -c tslint.json \"src/**/*.ts\"",
"lint:spec": "tslint --fix --type-check -p spec/tsconfig.json -c tslint.json \"spec/**/*.ts\"",
"lint:src": "tslint --fix --project -p tsconfig.json -c tslint.json \"src/**/*.ts\"",
"lint:spec": "tslint --fix --project -p spec/tsconfig.json -c tslint.json \"spec/**/*.ts\"",
"prepublishOnly": "echo \"Error: do 'npm run release' instead of 'npm publish'\" && exit 1"
},
"author": "Matthew Podwysocki <[email protected]>",
Expand Down
16 changes: 15 additions & 1 deletion spec/Ix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@ const targets = [`es5`, `es2015`, `esnext`];
const formats = [`cjs`, `esm`, `cls`, `umd`];

function throwInvalidImportError(name: string, value: string, values: string[]) {
throw new Error('Unrecognized ' + name + ' \'' + value + '\'. Please run tests with \'--' + name + ' <any of ' + values.join(', ') + '>\'');
throw new Error(
'Unrecognized ' +
name +
" '" +
value +
"'. Please run tests with '--" +
name +
' <any of ' +
values.join(', ') +
">'"
);
}

let modulePath = ``;
Expand All @@ -28,10 +38,14 @@ import { Iterable as Iterable_ } from '../src/Ix';
import { AsyncSink as AsyncSink_ } from '../src/Ix';
import { AsyncIterable as AsyncIterable_ } from '../src/Ix';
import { iterable as iterable_ } from '../src/Ix.internal';
import { iterablePipe as iterablePipe_ } from '../src/Ix.internal';
import { asynciterable as asynciterable_ } from '../src/Ix.internal';
import { asynciterablePipe as asynciterablePipe_ } from '../src/Ix.internal';

export let Iterable: typeof Iterable_ = Ix.Iterable;
export let AsyncSink: typeof AsyncSink_ = Ix.AsyncSink;
export let AsyncIterable: typeof AsyncIterable_ = Ix.AsyncIterable;
export let iterable: typeof iterable_ = IxInternal.iterable;
export let iterablePipe: typeof iterablePipe_ = IxInternal.iterablePipe;
export let asynciterable: typeof asynciterable_ = IxInternal.asynciterable;
export let asynciterablePipe: typeof asynciterablePipe_ = IxInternal.asynciterablePipe;
16 changes: 8 additions & 8 deletions spec/asynciterable-operators/average-spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as Ix from '../Ix';
import * as test from 'tape-async';
const { average } = Ix.asynciterable;
import { testOperator } from '../asynciterablehelpers';
const test = testOperator([Ix.asynciterable.average]);
const { empty } = Ix.asynciterable;
const { of } = Ix.asynciterable;
const { of } = Ix.AsyncIterable;

test('Iterable#average empty', async (t: test.Test) => {
test('Iterable#average empty', async (t, [average]) => {
const xs = empty<number>();
try {
await average(xs);
Expand All @@ -14,13 +14,13 @@ test('Iterable#average empty', async (t: test.Test) => {
t.end();
});

test('Iterable#average', async (t: test.Test) => {
test('Iterable#average', async (t, [average]) => {
const res = await average(of(1, 2, 3));
t.equal(res, 2);
t.end();
});

test('Iterable#average with selector empty', async (t: test.Test) => {
test('Iterable#average with selector empty', async (t, [average]) => {
const xs = empty<number>();
try {
await average(xs, async x => x * 2);
Expand All @@ -30,13 +30,13 @@ test('Iterable#average with selector empty', async (t: test.Test) => {
t.end();
});

test('Iterable#average with selector', async (t: test.Test) => {
test('Iterable#average with selector', async (t, [average]) => {
const res = await average(of(1, 2, 3), x => x * 2);
t.equal(res, 4);
t.end();
});

test('Iterable#average laws', async (t: test.Test) => {
test('Iterable#average laws', async (t, [average]) => {
const xs = of(1, 2, 3);
t.equal(await average(xs), await average(xs, x => x));
t.end();
Expand Down
14 changes: 7 additions & 7 deletions spec/asynciterable-operators/buffer-spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as Ix from '../Ix';
import * as test from 'tape-async';
const { buffer } = Ix.asynciterable;
import { testOperator } from '../asynciterablehelpers';
const test = testOperator([Ix.asynciterable.buffer]);
const { empty } = Ix.asynciterable;
const { range } = Ix.asynciterable;
const { sequenceEqual } = Ix.iterable;
const { toArray } = Ix.asynciterable;

test('AsyncIterable#buffer no skip non-full buffer', async t => {
test('AsyncIterable#buffer no skip non-full buffer', async (t, [buffer]) => {
const rng = range(0, 10);

const res = await toArray(buffer(rng, 3));
Expand All @@ -19,7 +19,7 @@ test('AsyncIterable#buffer no skip non-full buffer', async t => {
t.end();
});

test('AsyncIterable#buffer no skip all full', async t => {
test('AsyncIterable#buffer no skip all full', async (t, [buffer]) => {
const rng = range(0, 10);

const res = await toArray(buffer(rng, 5));
Expand All @@ -30,15 +30,15 @@ test('AsyncIterable#buffer no skip all full', async t => {
t.end();
});

test('AsyncIterable#buffer no skip empty buffer', async t => {
test('AsyncIterable#buffer no skip empty buffer', async (t, [buffer]) => {
const rng = empty<number>();

const res = await toArray(buffer(rng, 5));
t.equal(0, res.length);
t.end();
});

test('AsyncIterable#buffer skip non-full buffer', async t => {
test('AsyncIterable#buffer skip non-full buffer', async (t, [buffer]) => {
const rng = range(0, 10);

const res = await toArray(buffer(rng, 3, 2));
Expand All @@ -52,7 +52,7 @@ test('AsyncIterable#buffer skip non-full buffer', async t => {
t.end();
});

test('AsyncIterable#buffer skip full buffer', async t => {
test('AsyncIterable#buffer skip full buffer', async (t, [buffer]) => {
const rng = range(0, 10);

const res = await toArray(buffer(rng, 3, 4));
Expand Down
10 changes: 5 additions & 5 deletions spec/asynciterable-operators/catch-spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import * as Ix from '../Ix';
import * as test from 'tape-async';
const { _catch } = Ix.asynciterable;
import { testOperator } from '../asynciterablehelpers';
const test = testOperator([Ix.asynciterable._catch]);
const { concat } = Ix.asynciterable;
const { range } = Ix.asynciterable;
const { sequenceEqual } = Ix.asynciterable;
const { _throw } = Ix.asynciterable;
import { hasNext } from '../asynciterablehelpers';

test('AsyncIterable#catch with no errors', async t => {
test('AsyncIterable#catch with no errors', async (t, [_catch]) => {
const res = _catch(range(0, 5), range(5, 5));
t.true(await sequenceEqual(res, range(0, 5)));
t.end();
});

test('AsyncIterable#catch with concat error', async t => {
test('AsyncIterable#catch with concat error', async (t, [_catch]) => {
const res = _catch(
concat(range(0, 5), _throw(new Error())),
range(5, 5)
Expand All @@ -23,7 +23,7 @@ test('AsyncIterable#catch with concat error', async t => {
t.end();
});

test('AsyncIterable#catch still throws', async t => {
test('AsyncIterable#catch still throws', async (t, [_catch]) => {
const e1 = new Error();
const er1 = _throw(e1);

Expand Down
22 changes: 15 additions & 7 deletions spec/asynciterable-operators/catchwith-spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
import * as Ix from '../Ix';
import * as test from 'tape-async';
const { catchWith } = Ix.asynciterable;
const { of } = Ix.asynciterable;
import { testOperator } from '../asynciterablehelpers';
const test = testOperator([Ix.asynciterable.catchWith]);
const { of } = Ix.AsyncIterable;
const { range } = Ix.asynciterable;
const { sequenceEqual } = Ix.asynciterable;
const { single } = Ix.asynciterable;
const { _throw } = Ix.asynciterable;

test('AsyncIterable#catchWith error catches', async t => {
test('AsyncIterable#catchWith error catches', async (t, [catchWith]) => {
const err = new Error();
const res = await single(catchWith(_throw(err), async e => { t.same(err, e); return of(42); }));
const res = await single(
catchWith(_throw(err), async e => {
t.same(err, e);
return of(42);
})
);
t.equal(42, res);
t.end();
});

test('AsyncIterable#catchWith no error misses', async t => {
test('AsyncIterable#catchWith no error misses', async (t, [catchWith]) => {
const xs = range(0, 10);
const res = catchWith(xs, async e => { t.fail(); return of(42); });
const res = catchWith(xs, async e => {
t.fail();
return of(42);
});
t.true(await sequenceEqual(res, xs));
t.end();
});
6 changes: 3 additions & 3 deletions spec/asynciterable-operators/chain-spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as Ix from '../Ix';
import * as test from 'tape-async';
import { testOperator } from '../asynciterablehelpers';
const test = testOperator([Ix.asynciterable.chain]);
const { empty } = Ix.asynciterable;
const { chain } = Ix.asynciterable;
import { noNext } from '../asynciterablehelpers';

test('Itearble#chain calls function immediately', async t => {
test('Itearble#chain calls function immediately', async (t, [chain]) => {
let called = false;
const xs = chain(empty<number>(), x => { called = true; return x; });
t.true(called);
Expand Down
29 changes: 13 additions & 16 deletions spec/asynciterable-operators/concat-spec.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
import * as Ix from '../Ix';
import * as test from 'tape-async';
const { concat } = Ix.asynciterable;
const { concatAll } = Ix.asynciterable;
import { testOperator } from '../asynciterablehelpers';
const testConcat = testOperator([Ix.asynciterable.concat]);
const testConcatAll = testOperator([Ix.asynciterable.concatAll]);
const { map } = Ix.asynciterable;
const { of } = Ix.asynciterable;
const { of } = Ix.AsyncIterable;
const { range } = Ix.asynciterable;
const { sequenceEqual } = Ix.asynciterable;
const { tap } = Ix.asynciterable;

test('AsyncIterable#concat concatAll behavior', async t => {
testConcatAll('AsyncIterable#concat concatAll behavior', async (t, [concatAll]) => {
const res = concatAll(of(of(1, 2, 3), of(4, 5)));
t.true(await sequenceEqual(res, of(1, 2, 3, 4, 5)));
t.end();
});

test('Iterable#concat concatAll order of effects', async t => {
testConcatAll('Iterable#concat concatAll order of effects', async (t, [concatAll]) => {
let i = 0;
const xss = tap(map(range(0, 3), x => range(0, x + 1)), { next: async () => { ++i; } });
const xss = tap(map(range(0, 3), x => range(0, x + 1)), {
next: async () => {
++i;
}
});
const res = map(concatAll(xss), x => i + ' - ' + x);

t.true(await sequenceEqual(res, of(
'1 - 0',
'2 - 0',
'2 - 1',
'3 - 0',
'3 - 1',
'3 - 2'
)));
t.true(await sequenceEqual(res, of('1 - 0', '2 - 0', '2 - 1', '3 - 0', '3 - 1', '3 - 2')));
t.end();
});

test('AsyncIterable#concat behavior', async t => {
testConcat('AsyncIterable#concat behavior', async (t, [concat]) => {
const res = concat(of(1, 2, 3), of(4, 5));
t.true(await sequenceEqual(res, of(1, 2, 3, 4, 5)));
t.end();
Expand Down
Loading

0 comments on commit 76a4b4f

Please sign in to comment.