Skip to content

Commit

Permalink
New features
Browse files Browse the repository at this point in the history
  • Loading branch information
jinhduong committed Apr 23, 2018
1 parent 19aa24c commit cc436f3
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 20 deletions.
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ main();
- [x] join
- [x] leftJoin
- [ ] groupJoin
- [ ] orderBy
- [ ] orderByDescending
- [x] orderBy
- [x] orderByDescending
- [ ] thenBy
- [ ] thenByDescending
- [x] take
Expand All @@ -67,29 +67,29 @@ main();
- [ ] union
- [ ] intersect
- [ ] except
- [x] first : `Promise`
- [x] firstOrDefault : `Promise`
- [x] last : `Promise`
- [x] lastOrDefault : `Promise`
- [ ] single
- [ ] singleOrDefault
- [x] first : `Promise<T>`
- [x] firstOrDefault : `Promise<T | null>`
- [x] last : `Promise<T>`
- [x] lastOrDefault : `Promise<T | null>`
- [x] single
- [x] singleOrDefault
- [ ] elementAt
- [ ] elementAtOrDefault
- [ ] orderByDescending
- [ ] defaultIfEmpty
- [ ] contains
- [ ] reserve
- [ ] sequenceEqual
- [ ] any
- [x] any : `Promise<boolean>`
- [ ] all
- [x] count : `Promise`
- [x] count : `Promise<number>`
- [ ] longCount
- [ ] min
- [ ] max
- [ ] sum
- [ ] average
- [x] min : `Promise<number>`
- [x] max : `Promise<number>`
- [x] sum : `Promise<number>`
- [x] average
- [ ] aggregate
- [x] toList : `Promise`
- [x] toList : `Promise<T>`


### License
Expand Down
5 changes: 3 additions & 2 deletions src/demo/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ async function main() {
// Just query not execute query
let query = queryable
.from(promiseApi)
.where(x => x.overall > 90)
.selectMany(x => x.skills);
.join(staticLoopkup, (x, y) => x.nationId == y.id)
.orderBy(x => x.x.name);

const data = await query.toList();
console.log(data);

}

main();
Expand Down
65 changes: 64 additions & 1 deletion src/implements/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,17 @@ import { TakeWhileClause } from "../methods/takeWhile";
import { JoinClause } from "../methods/join";
import { LeftJoinClause } from "../methods/leftJoin";
import { SelectManyClause } from "../methods/selectMany";
import { SumClause } from "../methods/sum";
import { MinClause } from "../methods/min";
import { MaxClause } from "../methods/max";
import { SingleClause } from "../methods/single";
import { AnyClause } from "../methods/any";
import { AvarageClause } from "../methods/average";
import { OrderByClause } from "../methods/orderBy";
import { OrderByDescendingClause } from "../methods/orderByDescending";

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

// Contains all iterators
_iteratorCollection: Array<IIterator<T>> = [];

Expand Down Expand Up @@ -54,6 +62,16 @@ export class IteratorMethods<T> implements Methods<T> {
return this as any;
}

orderBy(iterator: (entity: T) => T): Methods<T> {
this._iteratorCollection.push(new OrderByClause(iterator));
return this;
}

orderByDescending(iterator: (entity: T) => T): Methods<T> {
this._iteratorCollection.push(new OrderByDescendingClause(iterator));
return this;
}

toList<S>(): Promise<S[]> {

// From cache
Expand Down Expand Up @@ -107,6 +125,44 @@ export class IteratorMethods<T> implements Methods<T> {
});
}

sum<S>(iterator: (entity: T) => S): Promise<number> {
return this.toList().then((data: T[]) => {
return (new SumClause(iterator).execute(data) || null) as number;
});
}

avarage<S>(iterator: (entity: T) => S): Promise<number> {
return this.toList().then((data: T[]) => {
return (new AvarageClause(iterator).execute(data) || 0) as number;
});
}

min<S>(iterator: (entity: T) => S): Promise<number> {
return this.toList().then((data: T[]) => {
return (new MinClause(iterator).execute(data) || null) as number;
});
}

max<S>(iterator: (entity: T) => S): Promise<number> {
return this.toList().then((data: T[]) => {
return (new MaxClause(iterator).execute(data) || null) as number;
});
}

single(iterator?: (entity: T) => boolean): Promise<T> {
return this.toList().then((data: T[]) => {
if (!data) throw new Error("Single require source is not null");
return new SingleClause(iterator).execute(data);

});
}

singleOrDefault(iterator?: (entity: T) => boolean): Promise<T> {
return this.toList().then((data: T[]) => {
return new SingleClause(iterator).execute(data) || null;
});
}

take(value: number): Methods<T> {
this._iteratorCollection.push(new TakeClause(value));
return this;
Expand All @@ -121,11 +177,18 @@ export class IteratorMethods<T> implements Methods<T> {
this._iteratorCollection.push(new SkipWhileClause(iterator));
return this;
}

takeWhile(iterator: (entity: T) => boolean): Methods<T> {
this._iteratorCollection.push(new TakeWhileClause(iterator));
return this;
}

any<T>(iterator: (entity: T) => boolean): Promise<boolean> {
return this.toList().then((data: T[]) => {
return new AnyClause(iterator).execute(data);
});
}

// Private funstions

private runIterators(syncSource: T[]) {
Expand Down
9 changes: 9 additions & 0 deletions src/intefaces/methods.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export interface Methods<T> {
skip(value: number): Methods<T>;
skipWhile(iterator: (entity: T) => boolean): Methods<T>;
takeWhile(iterator: (entity: T) => boolean): Methods<T>;
orderBy(iterator: (entity: T) => T): Methods<T>;
orderByDescending(iterator: (entity: T) => T): Methods<T>;
join<S>(source: S[] | Promise<S[]>, iterator: (aEntity: T, bEntity: S) => boolean): Methods<{ x: T, y: S }>;
leftJoin<S, U extends T & S>(source: S[] | Promise<S[]>, iterator: (aEntity: T, bEntity: S) => boolean): Methods<U>;

Expand All @@ -16,5 +18,12 @@ export interface Methods<T> {
firstOrDefault(iterator?: (entity: T) => boolean): Promise<T>;
last(iterator?: (entity: T) => boolean): Promise<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>;
sum<S>(iterator: (entity: T) => S): Promise<number>;
min<S>(iterator: (entity: T) => S): Promise<number>;
max<S>(iterator: (entity: T) => S): Promise<number>;
avarage<S>(iterator: (entity: T) => S): Promise<number>;
any<T>(iterator: (entity: T) => boolean): Promise<boolean>;
}
19 changes: 19 additions & 0 deletions src/methods/any.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IIterator } from "../intefaces/iterator.interface";

export class AnyClause<T> implements IIterator<T> {

_iterator: (item: T) => boolean;

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

constructor(func: (item: T) => boolean) {
this._iterator = func;
}
}
23 changes: 23 additions & 0 deletions src/methods/average.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IIterator } from "../intefaces/iterator.interface";
import { SelectClause } from "./select";

export class AvarageClause<T> implements IIterator<T> {

_iterator: (item: T) => any;

execute(source: any[] | T[]): T[] | T | any {
if (!source) return 0;

let _result = new SelectClause(this._iterator).execute(source) as number[];

if (!_result) return 0;

if (!Number.isNaN(_result[0])) throw new Error("Avarage operator need type of number");

return (_result.reduce((a, b) => a + b, 0)) / _result.length;
}

constructor(func?: (item: T) => any) {
this._iterator = func;
}
}
23 changes: 23 additions & 0 deletions src/methods/max.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IIterator } from "../intefaces/iterator.interface";
import { SelectClause } from "./select";

export class MaxClause<T> implements IIterator<T> {

_iterator: (item: T) => any;

execute(source: any[] | T[]): T[] | T | any {
if (!source) return 0;

let _result = new SelectClause(this._iterator).execute(source) as number[];

if (!_result) return 0;

if (!Number.isNaN(_result[0])) throw new Error("Sum operator require type of number");

return Math.max(..._result);
}

constructor(func?: (item: T) => any) {
this._iterator = func;
}
}
23 changes: 23 additions & 0 deletions src/methods/min.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IIterator } from "../intefaces/iterator.interface";
import { SelectClause } from "./select";

export class MinClause<T> implements IIterator<T> {

_iterator: (item: T) => any;

execute(source: any[] | T[]): T[] | T | any {
if (!source) return 0;

let _result = new SelectClause(this._iterator).execute(source) as number[];

if (!_result) return 0;

if (!Number.isNaN(_result[0])) throw new Error("Sum operator require type of number");

return Math.min(..._result);
}

constructor(func?: (item: T) => any) {
this._iterator = func;
}
}
45 changes: 45 additions & 0 deletions src/methods/orderBy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { IIterator } from "../intefaces/iterator.interface";
import { SelectClause } from "./select";

export class OrderByClause<T> implements IIterator<T> {

_iterator: (item: T) => any;

execute(source: T[]): T[] | any[] {

if (!source) return null;

// Object contains all data in array follow by [index] : {object}
let _tmp = {};

source.forEach((x: T, i: number) => {
_tmp[i] = x;
});

// Make lookup list base on input iterator function
let _result = (source as T[]).map((x: T, index: number) => {
return {
value: (this._iterator(x)),
index: index
}
});

if (!_result) return null;

// Sort on loopkup list
_result.sort((a: { value, index }, b: { value, index }) => {
if (a.value < b.value) return -1;
if (a.value > b.value) return 1;
return 0;
});

// Re-map to original list
return _result.map((x: { value, index }) => {
return _tmp[x.index];
});
}

constructor(func: (item: T) => any) {
this._iterator = func;
}
}
20 changes: 20 additions & 0 deletions src/methods/orderByDescending.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { IIterator } from "../intefaces/iterator.interface";
import { OrderByClause } from "./orderBy";

export class OrderByDescendingClause<T> implements IIterator<T> {

_iterator: (item: T) => any;

execute(source: T[]): T[] | any[] {

if (!source) return null;

let _result = new OrderByClause(this._iterator).execute(source);

return _result.reverse();
}

constructor(func: (item: T) => any) {
this._iterator = func;
}
}
2 changes: 1 addition & 1 deletion src/methods/selectMany.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { SelectClause } from "./select";

export class SelectManyClause<T> implements IIterator<T> {

_iterator: (item: T, index?: number) => boolean;
_iterator: (item: T, index?: number) => any;

execute(source: any[] | T[]): T[] | any[] {
if (!source) return null;
Expand Down
27 changes: 27 additions & 0 deletions src/methods/single.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { IIterator } from "../intefaces/iterator.interface";
import { WhereClause } from "./where";

export class SingleClause<T> implements IIterator<T> {

_iterator: (item: T) => boolean;

execute(source: any[] | T[]): T {
if (!this._iterator) {
return this.getSingle(source);
}
else {
let _result = new WhereClause(this._iterator).execute(source);
return this.getSingle(_result);
}
}

private getSingle(src: any[] | T[]): T | any {
if (src.length > 1) throw new Error("The collection does not contain exactly one element");
else if (src.length === 1)
return src[0];
}

constructor(func?: (item: T) => boolean) {
this._iterator = func;
}
}
Loading

0 comments on commit cc436f3

Please sign in to comment.