diff --git a/src/matrix/storage/idb/QueryTarget.ts b/src/matrix/storage/idb/QueryTarget.ts index e02e28fc..b2df0f9f 100644 --- a/src/matrix/storage/idb/QueryTarget.ts +++ b/src/matrix/storage/idb/QueryTarget.ts @@ -20,15 +20,15 @@ type Reducer = (acc: B, val: A) => B interface QueryTargetInterface { openCursor: (range?: IDBKeyRange | null , direction?: IDBCursorDirection) => IDBRequest - openKeyCursor: (range: IDBKeyRange, direction: IDBCursorDirection) => IDBRequest + openKeyCursor: (range?: IDBKeyRange, direction?: IDBCursorDirection) => IDBRequest supports: (method: string) => boolean - keyPath: string + keyPath: string | string[] get: (key: IDBValidKey) => IDBRequest getKey: (key: IDBValidKey) => IDBRequest } export class QueryTarget { - private _target: QueryTargetInterface + protected _target: QueryTargetInterface constructor(target: QueryTargetInterface) { this._target = target; @@ -60,7 +60,11 @@ export class QueryTarget { } else { return reqAsPromise(this._target.get(key)).then(value => { if (value) { - return value[this._target.keyPath]; + let keyPath = this._target.keyPath; + if (typeof keyPath === "string") { + keyPath = [keyPath]; + } + return keyPath.reduce((obj, key) => obj[key], value); } }); } diff --git a/src/matrix/storage/idb/Store.ts b/src/matrix/storage/idb/Store.ts index e1f63eec..17fb3762 100644 --- a/src/matrix/storage/idb/Store.ts +++ b/src/matrix/storage/idb/Store.ts @@ -19,126 +19,135 @@ import {IDBRequestAttemptError} from "./error"; const LOG_REQUESTS = false; -function logRequest(method, params, source) { +function logRequest(method: string, params: any[], source: any) { const storeName = source?.name; const databaseName = source?.transaction?.db?.name; console.info(`${databaseName}.${storeName}.${method}(${params.map(p => JSON.stringify(p)).join(", ")})`); } -class QueryTargetWrapper { - constructor(qt) { +class QueryTargetWrapper { + private _qt: IDBIndex | IDBObjectStore + + constructor(qt: IDBIndex | IDBObjectStore) { this._qt = qt; } - get keyPath() { - if (this._qt.objectStore) { - return this._qt.objectStore.keyPath; + get keyPath(): string | string[] { + if (this._qt["objectStore"]) { + return (this._qt as IDBIndex).objectStore.keyPath; } else { return this._qt.keyPath; } } - supports(methodName) { + get _qtStore(): IDBObjectStore { + return this._qt as IDBObjectStore; + } + + supports(methodName: string): boolean { return !!this._qt[methodName]; } - openKeyCursor(...params) { + openKeyCursor(range?: IDBKeyRange, direction?: IDBCursorDirection): IDBRequest { try { // not supported on Edge 15 if (!this._qt.openKeyCursor) { - LOG_REQUESTS && logRequest("openCursor", params, this._qt); - return this.openCursor(...params); + LOG_REQUESTS && logRequest("openCursor", [range, direction], this._qt); + return this.openCursor(range, direction); } - LOG_REQUESTS && logRequest("openKeyCursor", params, this._qt); - return this._qt.openKeyCursor(...params); + LOG_REQUESTS && logRequest("openKeyCursor", [range, direction], this._qt); + return this._qt.openKeyCursor(range, direction) } catch(err) { - throw new IDBRequestAttemptError("openKeyCursor", this._qt, err, params); + throw new IDBRequestAttemptError("openKeyCursor", this._qt, err, [range, direction]); } } - openCursor(...params) { + openCursor(range?: IDBKeyRange, direction?: IDBCursorDirection): IDBRequest { try { - LOG_REQUESTS && logRequest("openCursor", params, this._qt); - return this._qt.openCursor(...params); + LOG_REQUESTS && logRequest("openCursor", [], this._qt); + return this._qt.openCursor(range, direction) } catch(err) { - throw new IDBRequestAttemptError("openCursor", this._qt, err, params); + throw new IDBRequestAttemptError("openCursor", this._qt, err, [range, direction]); } } - put(...params) { + put(item: T, key?: IDBValidKey): IDBRequest { try { - LOG_REQUESTS && logRequest("put", params, this._qt); - return this._qt.put(...params); + LOG_REQUESTS && logRequest("put", [item, key], this._qt); + return this._qtStore.put(item, key); } catch(err) { - throw new IDBRequestAttemptError("put", this._qt, err, params); + throw new IDBRequestAttemptError("put", this._qt, err, [item, key]); } } - add(...params) { + add(item: T, key?: IDBValidKey): IDBRequest { try { - LOG_REQUESTS && logRequest("add", params, this._qt); - return this._qt.add(...params); + LOG_REQUESTS && logRequest("add", [item, key], this._qt); + return this._qtStore.add(item, key); } catch(err) { - throw new IDBRequestAttemptError("add", this._qt, err, params); + throw new IDBRequestAttemptError("add", this._qt, err, [item, key]); } } - get(...params) { + get(key: IDBValidKey): IDBRequest { try { - LOG_REQUESTS && logRequest("get", params, this._qt); - return this._qt.get(...params); + LOG_REQUESTS && logRequest("get", [key], this._qt); + return this._qt.get(key); } catch(err) { - throw new IDBRequestAttemptError("get", this._qt, err, params); + throw new IDBRequestAttemptError("get", this._qt, err, [key]); } } - getKey(...params) { + getKey(key: IDBValidKey): IDBRequest { try { - LOG_REQUESTS && logRequest("getKey", params, this._qt); - return this._qt.getKey(...params); + LOG_REQUESTS && logRequest("getKey", [key], this._qt); + return this._qt.getKey(key) } catch(err) { - throw new IDBRequestAttemptError("getKey", this._qt, err, params); + throw new IDBRequestAttemptError("getKey", this._qt, err, [key]); } } - delete(...params) { + delete(key: IDBValidKey | IDBKeyRange): IDBRequest { try { - LOG_REQUESTS && logRequest("delete", params, this._qt); - return this._qt.delete(...params); + LOG_REQUESTS && logRequest("delete", [key], this._qt); + return this._qtStore.delete(key); } catch(err) { - throw new IDBRequestAttemptError("delete", this._qt, err, params); + throw new IDBRequestAttemptError("delete", this._qt, err, [key]); } } - index(...params) { + index(name: string): IDBIndex { try { - return this._qt.index(...params); + return this._qtStore.index(name); } catch(err) { // TODO: map to different error? this is not a request - throw new IDBRequestAttemptError("index", this._qt, err, params); + throw new IDBRequestAttemptError("index", this._qt, err, [name]); } } } -export class Store extends QueryTarget { - constructor(idbStore, transaction) { - super(new QueryTargetWrapper(idbStore)); +export class Store extends QueryTarget { + private _transaction: IDBTransaction + + constructor(idbStore: IDBObjectStore, transaction: IDBTransaction) { + super(new QueryTargetWrapper(idbStore)); this._transaction = transaction; } get IDBKeyRange() { + // @ts-ignore return this._transaction.IDBKeyRange; } - get _idbStore() { - return this._target; + get _idbStore(): QueryTargetWrapper { + return (this._target as QueryTargetWrapper); } - index(indexName) { - return new QueryTarget(new QueryTargetWrapper(this._idbStore.index(indexName))); + index(indexName: string): QueryTarget { + return new QueryTarget(new QueryTargetWrapper(this._idbStore.index(indexName))); } - put(value) { + put(value: T) { // If this request fails, the error will bubble up to the transaction and abort it, // which is the behaviour we want. Therefore, it is ok to not create a promise for this // request and await it. @@ -152,12 +161,12 @@ export class Store extends QueryTarget { this._idbStore.put(value); } - add(value) { + add(value: T) { // ok to not monitor result of request, see comment in `put`. this._idbStore.add(value); } - delete(keyOrKeyRange) { + delete(keyOrKeyRange: IDBValidKey | IDBKeyRange) { // ok to not monitor result of request, see comment in `put`. this._idbStore.delete(keyOrKeyRange); }