Skip to content

Commit

Permalink
Features:
Browse files Browse the repository at this point in the history
- Distinct
- Concat
- All
- Update Any
- Add first test
  • Loading branch information
jinhduong committed Apr 25, 2018
1 parent ea5a480 commit 4a5822c
Show file tree
Hide file tree
Showing 14 changed files with 209 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}\\demo\\typescript\\index.js",
"program": "${workspaceFolder}\\dist\\demo\\index.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
]
Expand Down
11 changes: 3 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,15 @@ asyncData.then(data => {
- [x] selectMany
- [x] join
- [x] leftJoin
- [ ] groupJoin
- [x] groupJoin
- [x] orderBy
- [x] orderByDescending
- [x] take
- [x] takeWhile
- [x] skip
- [x] skipWhile
- [x] groupBy
- [ ] distinct
- [x] distinct
- [ ] concat
- [ ] zip
- [ ] union
Expand All @@ -137,15 +137,10 @@ asyncData.then(data => {
- [x] lastOrDefault : `Promise<T | null>`
- [x] single
- [x] singleOrDefault
- [ ] elementAt
- [ ] elementAtOrDefault
- [ ] orderByDescending
- [ ] defaultIfEmpty
- [x] contains
- [ ] reserve
- [ ] sequenceEqual
- [x] any : `Promise<boolean>`
- [ ] all
- [x] all : `Promise<boolean>`
- [x] count : `Promise<number>`
- [x] min : `Promise<number>`
- [x] max : `Promise<number>`
Expand Down
91 changes: 91 additions & 0 deletions src/demo/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Queryable } from '../implements';
const cTable = require('console.table');

let players = new Promise<{ name, overall, nationId, skills }[]>((resolve, reject) => {
// skills: attack, stamia, speed, shoot
console.log('get players...');
setTimeout(() => {
resolve([
{ name: 'Ronaldo', overall: 96, nationId: 1, skills: [96, 85, 87, 91] },
{ name: 'Messi', overall: 98, nationId: 2, skills: [97, 85, 91, 93] },
{ name: 'Mbappe', overall: 86, nationId: 3, skills: [89, 81, 95, 83] },
{ name: 'Matial', overall: 81, nationId: 3, skills: [81, 81, 89, 81] },
{ name: 'Salah', overall: 89, nationId: 4, skills: [88, 82, 97, 86] }
]);
}, 1000);
})

let nations = new Promise<{ id, name, areaId }[]>(resolve => {
console.log('get nations...');
setTimeout(() => {
resolve([
{ id: 1, name: 'Portugal', areaId: 1 },
{ id: 2, name: 'Argentina', areaId: 2 },
{ id: 3, name: 'France', areaId: 1 },
{ id: 4, name: 'Egypt', areaId: 3 }
]);
}, 2000);
})

let continents = new Promise<{ id, areaName }[]>(resolve => {
console.log('get continents...');
setTimeout(() => {
resolve([
{ id: 1, areaName: 'Euro' },
{ id: 2, areaName: 'South America' },
]);
}, 2300);
})

function main() {
let query10 = Queryable
.from(players)
.selectMany(x => x.skills)
.distinct();

query10.toList().then(d => console.table(d));

let query9 = Queryable
.from(players)
.concat(players);

query9.toList().then(d => console.table(d));

let query = Queryable
.from(players)
.where(x => x.overall > 85)
.select(x => {
return {
name: x.name,
stars: (() => { x.overall > 90 ? 5 : 4 })(),
realOverall: Queryable.fromSync(x.skills).avarage(),
nationId: x.nationId
}
})
.join(nations, (x, y) => x.nationId == y.id)
.leftJoin(continents, (plNation, con) => plNation.y.areaId == con.id)
.select(x => {
return {
name: x.x.name,
stars: x.x.stars,
realOverall: x.x.realOverall,
nation: x.y.name,
area: x.areaName
}
})
.groupBy(x => x.area)
.select(x => {
return {
area: x.key,
avg: (Queryable.fromSync(x.items).avarage(x => x.realOverall))
}
});

query.toList().then(data => {
console.table(data)
});
}

main();


22 changes: 20 additions & 2 deletions src/implements/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import {
WhereClause, SelectClause, SelectManyClause, JoinClause, LeftJoinClause, OrderByClause,
OrderByDescendingClause, GroupByClause, GroupJoinClause, FirstClause, LastClause, CountClause,
SumClause, AvarageClause, MinClause, MaxClause, SingleClause, TakeClause, SkipWhileClause,
SkipClause, TakeWhileClause, AnyClause, ContainsClause
SkipClause, TakeWhileClause, AnyClause, ContainsClause, AllClause
} from "../methods";
import { Queryable } from './queryable';
import { DistinctClause } from '../methods/distinct';
import { ConcatClause } from '../methods/concat';

export class IteratorMethods<T> implements IMethods<T> {

Expand All @@ -25,7 +27,7 @@ export class IteratorMethods<T> implements IMethods<T> {

clone(): IMethods<T> {
const _cloneCollection = Object.assign([], this._iteratorCollection);
return new IteratorMethods(_cloneCollection,this._source);
return new IteratorMethods(_cloneCollection, this._source);
}

where(iterator: (entity: T) => boolean): IMethods<T> {
Expand Down Expand Up @@ -75,6 +77,16 @@ export class IteratorMethods<T> implements IMethods<T> {
return this as any;
}

distinct(comparer?: (aEntity: T, bEntity: T) => boolean): IMethods<T> {
this._iteratorCollection.push(new DistinctClause(comparer));
return this;
}

concat(another: T[] | Promise<T[]>): IMethods<T> {
this._iteratorCollection.push(new ConcatClause(another));
return this;
}

// Return S[] | Promise<S[]>
toList<S>(): any {
return this.runIterators();
Expand Down Expand Up @@ -175,6 +187,12 @@ export class IteratorMethods<T> implements IMethods<T> {
});
}

all<T>(iterator: (entity: T) => boolean): Promise<boolean> {
return this.filterReturn(this.toList(), (data) => {
return new AllClause(iterator).execute(data);
});
}

contains(entity: T): Promise<boolean> {
return this.filterReturn(this.toList(), (data) => {
return new ContainsClause(entity).execute(data);
Expand Down
5 changes: 4 additions & 1 deletion src/intefaces/methods.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export interface IMethods<T> {
leftJoin<S, U extends T & S>(source: S[] | Promise<S[]>, iterator: (aEntity: T, bEntity: S) => boolean): IMethods<U>;
groupBy(iterator: (entity: T) => any): IMethods<{ key: any, items: T[] }>;
groupJoin<S>(source: S[] | Promise<S[]>, joinIterator: (aEntity: T, bEntity: S) => boolean, groupIterator: (entity: { x: T, y: S }) => any): IMethods<{ key: any, items: T[] }>;
distinct(comparer?: (aEntity: T, bEntity: T) => boolean): IMethods<T>
concat(another: T[] | Promise<T[]>): IMethods<T>

// Execute methods
toList<S extends T>(): Promise<S[]>;
Expand All @@ -25,6 +27,7 @@ export interface IMethods<T> {
max<S>(iterator: (entity: T) => S): Promise<number>;
avarage<S>(iterator?: (entity: T) => S): Promise<number>;
any<T>(iterator: (entity: T) => boolean): Promise<boolean>;
all<T>(iterator: (entity: T) => boolean): Promise<boolean>;
contains(entity: T): Promise<boolean>;

// Methods with optional iterator
Expand All @@ -34,5 +37,5 @@ export interface IMethods<T> {
lastOrDefault(iterator?: (entity: T) => boolean): Promise<T>;
single(iterator?: (entity: T) => boolean): Promise<T>;
singleOrDefault(iterator?: (entity: T) => boolean): Promise<T>;
count(iterator?: (entity: T) => boolean): Promise<number>;
count(iterator?: (entity: T) => boolean): Promise<number>;
}
21 changes: 21 additions & 0 deletions src/methods/all.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { IIterator } from "../intefaces/iterator.interface";
import { BaseIterator } from "../implements/baseIterator";

export class AllClause<T> extends BaseIterator<T> implements IIterator<T> {

_iterator: (item: T) => boolean;

execute(source: T[] | any[]): T[] | T | any {
if (!source) return false;
else {
return (source as T[]).every((x) => {
return this._iterator(x);
});
}
}

constructor(func: (item: T) => boolean) {
super();
this._iterator = func;
}
}
2 changes: 1 addition & 1 deletion src/methods/any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class AnyClause<T> extends BaseIterator<T> implements IIterator<T> {
execute(source: T[] | any[]): T[] | T | any {
if (!source) return false;
else {
return (source as T[]).every((x) => {
return (source as T[]).some((x) => {
return this._iterator(x);
});
}
Expand Down
15 changes: 15 additions & 0 deletions src/methods/concat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { BaseIterator } from '../implements';
import { IIterator } from '../intefaces';

export class ConcatClause<T> extends BaseIterator<T> implements IIterator<T>{
nextSource;

execute(source: T[]): T[] {
return source.concat(this.nextSource);
}

constructor(another: T[] | Promise<T[]>) {
super();
this.nextSource = another;
}
}
17 changes: 17 additions & 0 deletions src/methods/distinct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { IIterator } from '../intefaces';
import { BaseIterator } from '../implements';
import { Utils } from '../utils';

export class DistinctClause<T> extends BaseIterator<T> implements IIterator<T> {
_comparer: (aEntity: T, bEntity: T) => boolean;

execute(source: T[]): T[] {
if (!this._comparer)
return Utils.distinct(source);
}

constructor(comparer?: (aEntity: T, bEntity: T) => boolean) {
super();
this._comparer = comparer;
}
}
3 changes: 2 additions & 1 deletion src/methods/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ export * from './skipWhile';
export * from './sum';
export * from './take';
export * from './takeWhile';
export * from './where';
export * from './where';
export * from './all';
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './object';
6 changes: 6 additions & 0 deletions src/utils/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@ export class Utils {
public static isPromise(obj) {
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
}

public static distinct(array: any[]) {
return array.filter((val, index, self) => {
return self.indexOf(val) === index;
}).filter(x => x != undefined);
}
}
14 changes: 14 additions & 0 deletions test/distinct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { players, continents, nations } from './source';
import { expect } from 'chai';
import { Queryable } from '../dist';

describe('distinct', () => {
const query = Queryable.from(nations)
.join(continents, (x, y) => x.areaId === y.id)
.select(x => x.y.areaName);

it('can run', async () => {
const first = await query.distinct();
expect(first).to.not.equal(undefined);
})
});
13 changes: 13 additions & 0 deletions test/first.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { players, continents, nations } from './source';
import { expect } from 'chai';
import { Queryable } from '../dist';

describe('first', () => {
const query = Queryable.from(players);

it('can run', async () => {
const first = await query.first();
expect(first).to.not.equal(undefined);
expect(first).to.not.equal(null);
})
});

0 comments on commit 4a5822c

Please sign in to comment.