From 08bd3dc0e8a3c2370e4e8abbaa241eaafc144f4c Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sun, 28 May 2017 01:10:54 +0200 Subject: add linting rules and fix them --- src/query.ts | 241 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 147 insertions(+), 94 deletions(-) (limited to 'src/query.ts') diff --git a/src/query.ts b/src/query.ts index c593f061e..78b810371 100644 --- a/src/query.ts +++ b/src/query.ts @@ -21,42 +21,42 @@ * @author Florian Dold */ -"use strict"; - -export interface JoinResult { +/** + * Result of an inner join. + */ +export interface JoinResult { left: L; right: R; } -export interface JoinLeftResult { +/** + * Result of a left outer join. + */ +export interface JoinLeftResult { left: L; right?: R; } +/** + * Definition of an object store. + */ export class Store { - name: string; - validator?: (v: T) => T; - storeParams?: IDBObjectStoreParameters; - - constructor(name: string, storeParams?: IDBObjectStoreParameters, - validator?: (v: T) => T) { - this.name = name; - this.validator = validator; - this.storeParams = storeParams; + constructor(public name: string, + public storeParams?: IDBObjectStoreParameters, + public validator?: (v: T) => T) { } } -export class Index { - indexName: string; +/** + * Definition of an index. + */ +export class Index { storeName: string; - keyPath: string | string[]; - constructor(s: Store, indexName: string, keyPath: string | string[]) { + constructor(s: Store, public indexName: string, public keyPath: string | string[]) { this.storeName = s.name; - this.indexName = indexName; - this.keyPath = keyPath; } } @@ -65,17 +65,58 @@ export class Index { * with indices. */ export interface QueryStream { - indexJoin(index: Index, - keyFn: (obj: T) => I): QueryStream>; - indexJoinLeft(index: Index, - keyFn: (obj: T) => I): QueryStream>; - keyJoin(store: Store, - keyFn: (obj: T) => I): QueryStream>; - filter(f: (T: any) => boolean): QueryStream; + /** + * Join the current query with values from an index. + * The left side of the join is extracted via a function from the stream's + * result, the right side of the join is the key of the index. + */ + indexJoin(index: Index, keyFn: (obj: T) => I): QueryStream>; + /** + * Join the current query with values from an index, and keep values in the + * current stream that don't have a match. The left side of the join is + * extracted via a function from the stream's result, the right side of the + * join is the key of the index. + */ + indexJoinLeft(index: Index, + keyFn: (obj: T) => I): QueryStream>; + /** + * Join the current query with values from another object store. + * The left side of the join is extracted via a function over the current query, + * the right side of the join is the key of the object store. + */ + keyJoin(store: Store, keyFn: (obj: T) => I): QueryStream>; + + /** + * Only keep elements in the result stream for which the predicate returns + * true. + */ + filter(f: (x: T) => boolean): QueryStream; + + /** + * Reduce the stream, resulting in a single value. + */ reduce(f: (v: T, acc: S) => S, start?: S): Promise; - map(f: (x:T) => S): QueryStream; + + /** + * Map each element of the stream using a function, resulting in another + * stream of a different type. + */ + map(f: (x: T) => S): QueryStream; + + /** + * Map each element of the stream to a potentially empty array, and collect + * the result in a stream of the flattened arrays. + */ flatMap(f: (x: T) => S[]): QueryStream; + + /** + * Collect the stream into an array and return a promise for it. + */ toArray(): Promise; + + /** + * Get the first value of the stream. + */ first(): QueryValue; then(onfulfill: any, onreject: any): any; @@ -99,7 +140,7 @@ abstract class BaseQueryValue implements QueryValue { } map(f: (x: T) => S): QueryValue { - return new MapQueryValue(this, f); + return new MapQueryValue(this, f); } cond(f: (x: T) => boolean, onTrue: (r: QueryRoot) => R, onFalse: (r: QueryRoot) => R): Promise { @@ -141,7 +182,7 @@ class FirstQueryValue extends BaseQueryValue { } } -class MapQueryValue extends BaseQueryValue { +class MapQueryValue extends BaseQueryValue { mapFn: (x: T) => S; v: BaseQueryValue; @@ -157,7 +198,10 @@ class MapQueryValue extends BaseQueryValue { } -export let AbortTransaction = Symbol("abort_transaction"); +/** + * Exception that should be thrown by client code to abort a transaction. + */ +export const AbortTransaction = Symbol("abort_transaction"); /** * Get an unresolved promise together with its extracted resolve / reject @@ -193,26 +237,27 @@ abstract class QueryStreamBase implements QueryStream, PromiseLike { return new FirstQueryValue(this); } - then(onfulfilled: (value: void) => R | PromiseLike, onrejected: (reason: any) => R | PromiseLike): PromiseLike { + then(onfulfilled: (value: void) => R | PromiseLike, + onrejected: (reason: any) => R | PromiseLike): PromiseLike { return this.root.then(onfulfilled, onrejected); } flatMap(f: (x: T) => S[]): QueryStream { - return new QueryStreamFlatMap(this, f); + return new QueryStreamFlatMap(this, f); } map(f: (x: T) => S): QueryStream { return new QueryStreamMap(this, f); } - indexJoin(index: Index, - keyFn: (obj: T) => I): QueryStream> { + indexJoin(index: Index, + keyFn: (obj: T) => I): QueryStream> { this.root.addStoreAccess(index.storeName, false); return new QueryStreamIndexJoin(this, index.storeName, index.indexName, keyFn); } - indexJoinLeft(index: Index, - keyFn: (obj: T) => I): QueryStream> { + indexJoinLeft(index: Index, + keyFn: (obj: T) => I): QueryStream> { this.root.addStoreAccess(index.storeName, false); return new QueryStreamIndexJoinLeft(this, index.storeName, index.indexName, keyFn); } @@ -228,8 +273,8 @@ abstract class QueryStreamBase implements QueryStream, PromiseLike { } toArray(): Promise { - let {resolve, promise} = openPromise(); - let values: T[] = []; + const {resolve, promise} = openPromise(); + const values: T[] = []; this.subscribe((isDone, value) => { if (isDone) { @@ -245,7 +290,7 @@ abstract class QueryStreamBase implements QueryStream, PromiseLike { } reduce(f: (x: any, acc?: A) => A, init?: A): Promise { - let {resolve, promise} = openPromise(); + const {resolve, promise} = openPromise(); let acc = init; this.subscribe((isDone, value) => { @@ -265,10 +310,7 @@ abstract class QueryStreamBase implements QueryStream, PromiseLike { type FilterFn = (e: any) => boolean; type SubscribeFn = (done: boolean, value: any, tx: IDBTransaction) => void; type SubscribeOneFn = (value: any, tx: IDBTransaction) => void; - -interface FlatMapFn { - (v: T): T[]; -} +type FlatMapFn = (v: T) => T[]; class QueryStreamFilter extends QueryStreamBase { s: QueryStreamBase; @@ -294,7 +336,7 @@ class QueryStreamFilter extends QueryStreamBase { } -class QueryStreamFlatMap extends QueryStreamBase { +class QueryStreamFlatMap extends QueryStreamBase { s: QueryStreamBase; flatMapFn: (v: T) => S[]; @@ -310,16 +352,16 @@ class QueryStreamFlatMap extends QueryStreamBase { f(true, undefined, tx); return; } - let values = this.flatMapFn(value); - for (let v in values) { - f(false, value, tx) + const values = this.flatMapFn(value); + for (const v in values) { + f(false, value, tx); } }); } } -class QueryStreamMap extends QueryStreamBase { +class QueryStreamMap extends QueryStreamBase { s: QueryStreamBase; mapFn: (v: S) => T; @@ -335,7 +377,7 @@ class QueryStreamMap extends QueryStreamBase { f(true, undefined, tx); return; } - let mappedValue = this.mapFn(value); + const mappedValue = this.mapFn(value); f(false, mappedValue, tx); }); } @@ -363,15 +405,15 @@ class QueryStreamIndexJoin extends QueryStreamBase> { f(true, undefined, tx); return; } - let s = tx.objectStore(this.storeName).index(this.indexName); - let req = s.openCursor(IDBKeyRange.only(this.key(value))); + const s = tx.objectStore(this.storeName).index(this.indexName); + const req = s.openCursor(IDBKeyRange.only(this.key(value))); req.onsuccess = () => { - let cursor = req.result; + const cursor = req.result; if (cursor) { f(false, {left: value, right: cursor.value}, tx); cursor.continue(); } - } + }; }); } } @@ -402,7 +444,7 @@ class QueryStreamIndexJoinLeft extends QueryStreamBase { - let cursor = req.result; + const cursor = req.result; if (cursor) { gotMatch = true; f(false, {left: value, right: cursor.value}, tx); @@ -412,7 +454,7 @@ class QueryStreamIndexJoinLeft extends QueryStreamBase extends QueryStreamBase> { f(true, undefined, tx); return; } - let s = tx.objectStore(this.storeName); - let req = s.openCursor(IDBKeyRange.only(this.key(value))); + const s = tx.objectStore(this.storeName); + const req = s.openCursor(IDBKeyRange.only(this.key(value))); req.onsuccess = () => { - let cursor = req.result; + const cursor = req.result; if (cursor) { - f(false, {left:value, right: cursor.value}, tx); + f(false, {left: value, right: cursor.value}, tx); cursor.continue(); } else { f(true, undefined, tx); } - } + }; }); } } @@ -464,7 +506,7 @@ class IterQueryStream extends QueryStreamBase { this.storeName = storeName; this.subscribers = []; - let doIt = (tx: IDBTransaction) => { + const doIt = (tx: IDBTransaction) => { const {indexName = void 0, only = void 0} = this.options; let s: any; if (indexName !== void 0) { @@ -473,24 +515,24 @@ class IterQueryStream extends QueryStreamBase { } else { s = tx.objectStore(this.storeName); } - let kr: IDBKeyRange | undefined = undefined; + let kr: IDBKeyRange | undefined; if (only !== undefined) { kr = IDBKeyRange.only(this.options.only); } - let req = s.openCursor(kr); + const req = s.openCursor(kr); req.onsuccess = () => { - let cursor: IDBCursorWithValue = req.result; + const cursor: IDBCursorWithValue = req.result; if (cursor) { - for (let f of this.subscribers) { + for (const f of this.subscribers) { f(false, cursor.value, tx); } cursor.continue(); } else { - for (let f of this.subscribers) { + for (const f of this.subscribers) { f(true, undefined, tx); } } - } + }; }; this.root.addWork(doIt); @@ -503,8 +545,7 @@ class IterQueryStream extends QueryStreamBase { export class QueryRoot implements PromiseLike { - private work: ((t: IDBTransaction) => void)[] = []; - db: IDBDatabase; + private work: Array<((t: IDBTransaction) => void)> = []; private stores = new Set(); private kickoffPromise: Promise; @@ -518,20 +559,23 @@ export class QueryRoot implements PromiseLike { private finished: boolean = false; - constructor(db: IDBDatabase) { - this.db = db; + constructor(public db: IDBDatabase) { } - then(onfulfilled: (value: void) => R | PromiseLike, onrejected: (reason: any) => R | PromiseLike): PromiseLike { + then(onfulfilled: (value: void) => R | PromiseLike, + onrejected: (reason: any) => R | PromiseLike): PromiseLike { return this.finish().then(onfulfilled, onrejected); } - checkFinished() { + private checkFinished() { if (this.finished) { throw Error("Can't add work to query after it was started"); } } + /** + * Get a stream of all objects in the store. + */ iter(store: Store): QueryStream { this.checkFinished(); this.stores.add(store.name); @@ -539,6 +583,9 @@ export class QueryRoot implements PromiseLike { return new IterQueryStream(this, store.name, {}); } + /** + * Count the number of objects in a store. + */ count(store: Store): Promise { this.checkFinished(); const {resolve, promise} = openPromise(); @@ -549,7 +596,7 @@ export class QueryRoot implements PromiseLike { req.onsuccess = () => { resolve(req.result); }; - } + }; this.addWork(doCount, store.name, false); return Promise.resolve() @@ -558,6 +605,9 @@ export class QueryRoot implements PromiseLike { } + /** + * Delete all objects in a store that match a predicate. + */ deleteIf(store: Store, predicate: (x: T, n: number) => boolean): QueryRoot { this.checkFinished(); const doDeleteIf = (tx: IDBTransaction) => { @@ -565,27 +615,27 @@ export class QueryRoot implements PromiseLike { const req = s.openCursor(); let n = 0; req.onsuccess = () => { - let cursor: IDBCursorWithValue = req.result; + const cursor: IDBCursorWithValue = req.result; if (cursor) { if (predicate(cursor.value, n++)) { cursor.delete(); } cursor.continue(); - } - } + } + }; }; this.addWork(doDeleteIf, store.name, true); return this; } - iterIndex(index: Index, - only?: S): QueryStream { + iterIndex(index: Index, + only?: S): QueryStream { this.checkFinished(); this.stores.add(index.storeName); this.scheduleFinish(); return new IterQueryStream(this, index.storeName, { + indexName: index.indexName, only, - indexName: index.indexName }); } @@ -596,7 +646,7 @@ export class QueryRoot implements PromiseLike { */ put(store: Store, val: T): QueryRoot { this.checkFinished(); - let doPut = (tx: IDBTransaction) => { + const doPut = (tx: IDBTransaction) => { tx.objectStore(store.name).put(val); }; this.scheduleFinish(); @@ -608,11 +658,11 @@ export class QueryRoot implements PromiseLike { putWithResult(store: Store, val: T): Promise { this.checkFinished(); const {resolve, promise} = openPromise(); - let doPutWithResult = (tx: IDBTransaction) => { - let req = tx.objectStore(store.name).put(val); + const doPutWithResult = (tx: IDBTransaction) => { + const req = tx.objectStore(store.name).put(val); req.onsuccess = () => { resolve(req.result); - } + }; this.scheduleFinish(); }; this.addWork(doPutWithResult, store.name, true); @@ -622,17 +672,20 @@ export class QueryRoot implements PromiseLike { } + /** + * Get, modify and store an element inside a transaction. + */ mutate(store: Store, key: any, f: (v: T) => T): QueryRoot { this.checkFinished(); - let doPut = (tx: IDBTransaction) => { - let reqGet = tx.objectStore(store.name).get(key); + const doPut = (tx: IDBTransaction) => { + const reqGet = tx.objectStore(store.name).get(key); reqGet.onsuccess = () => { - let r = reqGet.result; + const r = reqGet.result; let m: T; try { m = f(r); } catch (e) { - if (e == AbortTransaction) { + if (e === AbortTransaction) { tx.abort(); return; } @@ -640,7 +693,7 @@ export class QueryRoot implements PromiseLike { } tx.objectStore(store.name).put(m); - } + }; }; this.scheduleFinish(); this.addWork(doPut, store.name, true); @@ -656,7 +709,7 @@ export class QueryRoot implements PromiseLike { putAll(store: Store, iterable: T[]): QueryRoot { this.checkFinished(); const doPutAll = (tx: IDBTransaction) => { - for (let obj of iterable) { + for (const obj of iterable) { tx.objectStore(store.name).put(obj); } }; @@ -707,8 +760,8 @@ export class QueryRoot implements PromiseLike { /** * Get one object from a store by its key. */ - getIndexed(index: Index, - key: I): Promise { + getIndexed(index: Index, + key: I): Promise { this.checkFinished(); if (key === void 0) { throw Error("key must not be undefined"); @@ -748,7 +801,7 @@ export class QueryRoot implements PromiseLike { this.kickoffPromise = new Promise((resolve, reject) => { // At this point, we can't add any more work this.finished = true; - if (this.work.length == 0) { + if (this.work.length === 0) { resolve(); return; } @@ -760,7 +813,7 @@ export class QueryRoot implements PromiseLike { tx.onabort = () => { reject(Error("transaction aborted")); }; - for (let w of this.work) { + for (const w of this.work) { w(tx); } }); -- cgit v1.2.3