Skip to content

Commit

Permalink
BREAKING CHANGE: Migrate to TypeScript and support ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
jeswr committed Aug 8, 2024
1 parent 331816b commit c332f6a
Show file tree
Hide file tree
Showing 18 changed files with 2,479 additions and 362 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.idea
node_modules
node_modules
dist
esm
41 changes: 0 additions & 41 deletions index.d.ts

This file was deleted.

16 changes: 0 additions & 16 deletions index.js

This file was deleted.

29 changes: 0 additions & 29 deletions join/DynamicNestedLoopJoin.js

This file was deleted.

5 changes: 5 additions & 0 deletions join/DynamicNestedLoopJoin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AsyncIterator, UnionIterator } from 'asynciterator';

export function dynamicNestedLoopJoin<L, R, T>(leftIter: AsyncIterator<L>, funRight: (left: L) => AsyncIterator<R>, funJoin: (left: L, right: R) => T) {
return new UnionIterator(leftIter.map(left => funRight(left).map(right => funJoin(left, right))), { autoStart: false });
}
48 changes: 22 additions & 26 deletions join/HashJoin.js → join/HashJoin.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@

let AsyncIterator = require('asynciterator').AsyncIterator;
import { AsyncIterator } from 'asynciterator';

// https://en.wikipedia.org/wiki/Hash_join
class HashJoin extends AsyncIterator
{
constructor (left, right, funHash, funJoin)
{
export class HashJoin<S, H, T> extends AsyncIterator<T> {
private addedDataListener = false;
private leftMap = new Map<H, S[]>();
private matchIdx = 0;
private match: S | null = null;
private matches: S[];

constructor (
private left: AsyncIterator<S>,
private right: AsyncIterator<S>,
private funHash: (entry: S) => H,
private funJoin: (left: S, right: S) => T
) {
super();

this.addedDataListener = false;
this.left = left;
this.right = right;
this.funHash = funHash;
this.funJoin = funJoin;

this.leftMap = new Map();

this.match = null;
this.matches = [];
this.matchIdx = 0;

this.left.on('error', (error) => this.destroy(error));
this.right.on('error', (error) => this.destroy(error));

this.readable = false;

this.left.on('end', allowJoining.bind(this));

function allowJoining ()
{
const allowJoining = () => {
this.readable = true;
this.right.on('readable', () => this.readable = true);
this.right.on('end', () => { if (!this.hasResults()) this._end(); });
}

this.left.on('end', allowJoining);

this.on('newListener', (eventName) =>
{
if (eventName === 'data')
Expand Down Expand Up @@ -69,7 +66,7 @@ class HashJoin extends AsyncIterator
while (this.matchIdx < this.matches.length)
{
let item = this.matches[this.matchIdx++];
let result = this.funJoin(item, this.match);
let result = this.funJoin(item, this.match!);
if (result !== null)
return result;
}
Expand Down Expand Up @@ -101,17 +98,16 @@ class HashJoin extends AsyncIterator

_addDataListener()
{
this.left.on('data', addItem.bind(this));

function addItem(item)
const addItem = (item: S) =>
{
let hash = this.funHash(item);
if (!this.leftMap.has(hash))
this.leftMap.set(hash, []);
let arr = this.leftMap.get(hash);
arr.push(item);
arr!.push(item);
}

this.left.on('data', addItem);
}
}

module.exports = HashJoin;
34 changes: 0 additions & 34 deletions join/NestedLoopJoin.js

This file was deleted.

5 changes: 5 additions & 0 deletions join/NestedLoopJoin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { UnionIterator, AsyncIterator } from 'asynciterator';

export function nestedLoopJoin<L, R, T>(leftIter: AsyncIterator<L>, rightIter: AsyncIterator<R>, funJoin: (left: L, right: R) => T) {
return new UnionIterator(leftIter.map(left => rightIter.clone().map(right => funJoin(left, right))), { autoStart: false });
}
45 changes: 17 additions & 28 deletions join/SymmetricHashJoin.js → join/SymmetricHashJoin.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@

let AsyncIterator = require('asynciterator').AsyncIterator;
import { AsyncIterator } from 'asynciterator';

// https://en.wikipedia.org/wiki/Symmetric_Hash_Join
class SymmetricHashJoin extends AsyncIterator
{
constructor (left, right, funHash, funJoin)
export class SymmetricHashJoin<S, H, T> extends AsyncIterator<T> {
private usedLeft = false;
private leftMap: Map<H, S[]> | null = new Map<H, S[]>();
private rightMap: Map<H, S[]> | null = new Map<H, S[]>();
private matchIdx = 0;
private match: S | null = null;
private matches: S[] | null = [];

constructor (private left: AsyncIterator<S>, private right: AsyncIterator<S>, private funHash: (entry: S) => H, private funJoin: (left: S, right: S) => T)
{
super();

this.left = left;
this.right = right;

this.funHash = funHash;
this.funJoin = funJoin;

this.usedLeft = false;
this.leftMap = new Map();
this.rightMap = new Map();

this.on('end', () => this._cleanup() );

this.match = null;
this.matches = [];
this.matchIdx = 0;

if (this.left.readable || this.right.readable)
{
this.readable = true;
Expand Down Expand Up @@ -70,18 +61,18 @@ class SymmetricHashJoin extends AsyncIterator
if (this.ended)
return null;

while (this.matchIdx < this.matches.length)
while (this.matchIdx < this.matches!.length)
{
let item = this.matches[this.matchIdx++];
let result = this.usedLeft ? this.funJoin(this.match, item) : this.funJoin(item, this.match);
let item = this.matches![this.matchIdx++];
let result = this.usedLeft ? this.funJoin(this.match!, item) : this.funJoin(item, this.match!);
if (result !== null)
return result;
}

if (!this.hasResults())
this._end();

let item = null;
let item: S | null = null;
// try both streams if the first one has no value
for (let i = 0; i < 2; ++i)
{
Expand All @@ -106,18 +97,16 @@ class SymmetricHashJoin extends AsyncIterator
} else if (this.left.done) {
this.rightMap = null;
} else {
let map = this.usedLeft ? this.leftMap : this.rightMap;
let map = (this.usedLeft ? this.leftMap : this.rightMap)!;
if (!map.has(hash))
map.set(hash, []);
let arr = map.get(hash);
let arr = map.get(hash)!;
arr.push(item);
}

this.match = item;
this.matches = (this.usedLeft ? this.rightMap : this.leftMap).get(hash) || [];
this.matches = (this.usedLeft ? this.rightMap : this.leftMap)!.get(hash) || [];
this.matchIdx = 0;
}
}
}

module.exports = SymmetricHashJoin;
4 changes: 4 additions & 0 deletions join/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './SymmetricHashJoin';
export * from './HashJoin';
export * from './NestedLoopJoin';
export * from './DynamicNestedLoopJoin';
Loading

0 comments on commit c332f6a

Please sign in to comment.