diff --git a/src/matrix/storage/idb/Transaction.js b/src/matrix/storage/idb/Transaction.js index 71513730..8b85b795 100644 --- a/src/matrix/storage/idb/Transaction.js +++ b/src/matrix/storage/idb/Transaction.js @@ -22,18 +22,18 @@ import {RoomSummaryStore} from "./stores/RoomSummaryStore"; import {InviteStore} from "./stores/InviteStore"; import {TimelineEventStore} from "./stores/TimelineEventStore"; import {TimelineRelationStore} from "./stores/TimelineRelationStore"; -import {RoomStateStore} from "./stores/RoomStateStore.js"; +import {RoomStateStore} from "./stores/RoomStateStore"; import {RoomMemberStore} from "./stores/RoomMemberStore"; -import {TimelineFragmentStore} from "./stores/TimelineFragmentStore.js"; -import {PendingEventStore} from "./stores/PendingEventStore.js"; -import {UserIdentityStore} from "./stores/UserIdentityStore.js"; -import {DeviceIdentityStore} from "./stores/DeviceIdentityStore.js"; -import {OlmSessionStore} from "./stores/OlmSessionStore.js"; -import {InboundGroupSessionStore} from "./stores/InboundGroupSessionStore.js"; -import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore.js"; -import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore.js"; -import {OperationStore} from "./stores/OperationStore.js"; -import {AccountDataStore} from "./stores/AccountDataStore.js"; +import {TimelineFragmentStore} from "./stores/TimelineFragmentStore"; +import {PendingEventStore} from "./stores/PendingEventStore"; +import {UserIdentityStore} from "./stores/UserIdentityStore"; +import {DeviceIdentityStore} from "./stores/DeviceIdentityStore"; +import {OlmSessionStore} from "./stores/OlmSessionStore"; +import {InboundGroupSessionStore} from "./stores/InboundGroupSessionStore"; +import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore"; +import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore"; +import {OperationStore} from "./stores/OperationStore"; +import {AccountDataStore} from "./stores/AccountDataStore"; export class Transaction { constructor(txn, allowedStoreNames, IDBKeyRange) { diff --git a/src/matrix/storage/idb/schema.js b/src/matrix/storage/idb/schema.js index 50e298d7..8313c02c 100644 --- a/src/matrix/storage/idb/schema.js +++ b/src/matrix/storage/idb/schema.js @@ -3,7 +3,7 @@ import {RoomMember, EVENT_TYPE as MEMBER_EVENT_TYPE} from "../../room/members/Ro import {addRoomToIdentity} from "../../e2ee/DeviceTracker.js"; import {RoomMemberStore} from "./stores/RoomMemberStore"; import {SessionStore} from "./stores/SessionStore"; -import {encodeScopeTypeKey} from "./stores/OperationStore.js"; +import {encodeScopeTypeKey} from "./stores/OperationStore"; import {MAX_UNICODE} from "./stores/common"; // FUNCTIONS SHOULD ONLY BE APPENDED!! diff --git a/src/matrix/storage/idb/stores/AccountDataStore.js b/src/matrix/storage/idb/stores/AccountDataStore.ts similarity index 57% rename from src/matrix/storage/idb/stores/AccountDataStore.js rename to src/matrix/storage/idb/stores/AccountDataStore.ts index 7f22a518..32aec513 100644 --- a/src/matrix/storage/idb/stores/AccountDataStore.js +++ b/src/matrix/storage/idb/stores/AccountDataStore.ts @@ -13,17 +13,26 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import {Store} from "../Store"; +import {Content} from "../../types"; + +interface AccountDataEntry { + type: string; + content: Content; +} export class AccountDataStore { - constructor(store) { - this._store = store; - } + private _store: Store; - async get(type) { - return await this._store.get(type); - } + constructor(store: Store) { + this._store = store; + } - set(event) { - return this._store.put(event); - } + async get(type: string): Promise { + return await this._store.get(type); + } + + set(event: AccountDataEntry): void { + this._store.put(event); + } } diff --git a/src/matrix/storage/idb/stores/DeviceIdentityStore.js b/src/matrix/storage/idb/stores/DeviceIdentityStore.ts similarity index 64% rename from src/matrix/storage/idb/stores/DeviceIdentityStore.js rename to src/matrix/storage/idb/stores/DeviceIdentityStore.ts index 207cfb20..9800fcca 100644 --- a/src/matrix/storage/idb/stores/DeviceIdentityStore.js +++ b/src/matrix/storage/idb/stores/DeviceIdentityStore.ts @@ -15,33 +15,46 @@ limitations under the License. */ import {MAX_UNICODE, MIN_UNICODE} from "./common"; +import {Store} from "../Store"; -function encodeKey(userId, deviceId) { +interface DeviceIdentity { + userId: string; + deviceId: string; + ed25519Key: string; + curve25519Key: string; + algorithms: string[]; + displayName: string; + key: string; +} + +function encodeKey(userId: string, deviceId: string): string { return `${userId}|${deviceId}`; } -function decodeKey(key) { +function decodeKey(key: string): { userId: string, deviceId: string } { const [userId, deviceId] = key.split("|"); return {userId, deviceId}; } export class DeviceIdentityStore { - constructor(store) { + private _store: Store; + + constructor(store: Store) { this._store = store; } - getAllForUserId(userId) { + getAllForUserId(userId: string): Promise { const range = this._store.IDBKeyRange.lowerBound(encodeKey(userId, "")); return this._store.selectWhile(range, device => { return device.userId === userId; }); } - async getAllDeviceIds(userId) { - const deviceIds = []; + async getAllDeviceIds(userId: string): Promise { + const deviceIds: string[] = []; const range = this._store.IDBKeyRange.lowerBound(encodeKey(userId, "")); await this._store.iterateKeys(range, key => { - const decodedKey = decodeKey(key); + const decodedKey = decodeKey(key as string); // prevent running into the next room if (decodedKey.userId === userId) { deviceIds.push(decodedKey.deviceId); @@ -52,27 +65,27 @@ export class DeviceIdentityStore { return deviceIds; } - get(userId, deviceId) { + get(userId: string, deviceId: string): Promise { return this._store.get(encodeKey(userId, deviceId)); } - set(deviceIdentity) { + set(deviceIdentity: DeviceIdentity): void { deviceIdentity.key = encodeKey(deviceIdentity.userId, deviceIdentity.deviceId); this._store.put(deviceIdentity); } - getByCurve25519Key(curve25519Key) { + getByCurve25519Key(curve25519Key: string): Promise { return this._store.index("byCurve25519Key").get(curve25519Key); } - remove(userId, deviceId) { - this._store.delete(encodeKey(userId, deviceId)); + remove(userId: string, deviceId: string): Promise { + return this._store.delete(encodeKey(userId, deviceId)); } - removeAllForUser(userId) { + removeAllForUser(userId: string): Promise { // exclude both keys as they are theoretical min and max, // but we should't have a match for just the room id, or room id with max const range = this._store.IDBKeyRange.bound(encodeKey(userId, MIN_UNICODE), encodeKey(userId, MAX_UNICODE), true, true); - this._store.delete(range); + return this._store.delete(range); } } diff --git a/src/matrix/storage/idb/stores/GroupSessionDecryptionStore.js b/src/matrix/storage/idb/stores/GroupSessionDecryptionStore.ts similarity index 55% rename from src/matrix/storage/idb/stores/GroupSessionDecryptionStore.js rename to src/matrix/storage/idb/stores/GroupSessionDecryptionStore.ts index da47639d..b6636f13 100644 --- a/src/matrix/storage/idb/stores/GroupSessionDecryptionStore.js +++ b/src/matrix/storage/idb/stores/GroupSessionDecryptionStore.ts @@ -15,30 +15,40 @@ limitations under the License. */ import {MIN_UNICODE, MAX_UNICODE} from "./common"; +import {Store} from "../Store"; -function encodeKey(roomId, sessionId, messageIndex) { +function encodeKey(roomId: string, sessionId: string, messageIndex: number | string): string { return `${roomId}|${sessionId}|${messageIndex}`; } +interface GroupSessionDecryption { + eventId: string; + timestamp: number; +} + +type GroupSessionEntry = GroupSessionDecryption & { key: string } + export class GroupSessionDecryptionStore { - constructor(store) { + private _store: Store; + + constructor(store: Store) { this._store = store; } - get(roomId, sessionId, messageIndex) { + get(roomId: string, sessionId: string, messageIndex: number): Promise { return this._store.get(encodeKey(roomId, sessionId, messageIndex)); } - set(roomId, sessionId, messageIndex, decryption) { - decryption.key = encodeKey(roomId, sessionId, messageIndex); - this._store.put(decryption); + set(roomId: string, sessionId: string, messageIndex: number, decryption: GroupSessionDecryption): void { + (decryption as GroupSessionEntry).key = encodeKey(roomId, sessionId, messageIndex); + this._store.put(decryption as GroupSessionEntry); } - removeAllForRoom(roomId) { + removeAllForRoom(roomId: string): Promise { const range = this._store.IDBKeyRange.bound( encodeKey(roomId, MIN_UNICODE, MIN_UNICODE), encodeKey(roomId, MAX_UNICODE, MAX_UNICODE) ); - this._store.delete(range); + return this._store.delete(range); } } diff --git a/src/matrix/storage/idb/stores/InboundGroupSessionStore.js b/src/matrix/storage/idb/stores/InboundGroupSessionStore.ts similarity index 63% rename from src/matrix/storage/idb/stores/InboundGroupSessionStore.js rename to src/matrix/storage/idb/stores/InboundGroupSessionStore.ts index 488f2510..286eaf4e 100644 --- a/src/matrix/storage/idb/stores/InboundGroupSessionStore.js +++ b/src/matrix/storage/idb/stores/InboundGroupSessionStore.ts @@ -15,36 +15,49 @@ limitations under the License. */ import {MIN_UNICODE, MAX_UNICODE} from "./common"; +import {Store} from "../Store"; -function encodeKey(roomId, senderKey, sessionId) { +interface InboundGroupSession { + roomId: string; + senderKey: string; + sessionId: string; + session?: string; + claimedKeys?: { [algorithm : string] : string }; + eventIds?: string[]; + key: string; +} + +function encodeKey(roomId: string, senderKey: string, sessionId: string): string { return `${roomId}|${senderKey}|${sessionId}`; } export class InboundGroupSessionStore { - constructor(store) { + private _store: Store; + + constructor(store: Store) { this._store = store; } - async has(roomId, senderKey, sessionId) { + async has(roomId: string, senderKey: string, sessionId: string): Promise { const key = encodeKey(roomId, senderKey, sessionId); const fetchedKey = await this._store.getKey(key); return key === fetchedKey; } - get(roomId, senderKey, sessionId) { + get(roomId: string, senderKey: string, sessionId: string): Promise { return this._store.get(encodeKey(roomId, senderKey, sessionId)); } - set(session) { + set(session: InboundGroupSession): void { session.key = encodeKey(session.roomId, session.senderKey, session.sessionId); this._store.put(session); } - removeAllForRoom(roomId) { + removeAllForRoom(roomId: string): Promise { const range = this._store.IDBKeyRange.bound( encodeKey(roomId, MIN_UNICODE, MIN_UNICODE), encodeKey(roomId, MAX_UNICODE, MAX_UNICODE) ); - this._store.delete(range); + return this._store.delete(range); } } diff --git a/src/matrix/storage/idb/stores/OlmSessionStore.js b/src/matrix/storage/idb/stores/OlmSessionStore.ts similarity index 61% rename from src/matrix/storage/idb/stores/OlmSessionStore.js rename to src/matrix/storage/idb/stores/OlmSessionStore.ts index d81cc048..1daa0b21 100644 --- a/src/matrix/storage/idb/stores/OlmSessionStore.js +++ b/src/matrix/storage/idb/stores/OlmSessionStore.ts @@ -13,26 +13,38 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import {Store} from "../Store"; -function encodeKey(senderKey, sessionId) { +function encodeKey(senderKey: string, sessionId: string): string { return `${senderKey}|${sessionId}`; } -function decodeKey(key) { +function decodeKey(key: string): { senderKey: string, sessionId: string } { const [senderKey, sessionId] = key.split("|"); return {senderKey, sessionId}; } +interface OlmSession { + session: string; + sessionId: string; + senderKey: string; + lastUsed: number; +} + +type OlmSessionEntry = OlmSession & { key: string }; + export class OlmSessionStore { - constructor(store) { + private _store: Store; + + constructor(store: Store) { this._store = store; } - async getSessionIds(senderKey) { - const sessionIds = []; + async getSessionIds(senderKey: string): Promise { + const sessionIds: string[] = []; const range = this._store.IDBKeyRange.lowerBound(encodeKey(senderKey, "")); await this._store.iterateKeys(range, key => { - const decodedKey = decodeKey(key); + const decodedKey = decodeKey(key as string); // prevent running into the next room if (decodedKey.senderKey === senderKey) { sessionIds.push(decodedKey.sessionId); @@ -43,23 +55,23 @@ export class OlmSessionStore { return sessionIds; } - getAll(senderKey) { + getAll(senderKey: string): Promise { const range = this._store.IDBKeyRange.lowerBound(encodeKey(senderKey, "")); return this._store.selectWhile(range, session => { return session.senderKey === senderKey; }); } - get(senderKey, sessionId) { + get(senderKey: string, sessionId: string): Promise { return this._store.get(encodeKey(senderKey, sessionId)); } - set(session) { - session.key = encodeKey(session.senderKey, session.sessionId); - return this._store.put(session); + set(session: OlmSession): void { + (session as OlmSessionEntry).key = encodeKey(session.senderKey, session.sessionId); + this._store.put(session as OlmSessionEntry); } - remove(senderKey, sessionId) { + remove(senderKey: string, sessionId: string): Promise { return this._store.delete(encodeKey(senderKey, sessionId)); } } diff --git a/src/matrix/storage/idb/stores/OperationStore.js b/src/matrix/storage/idb/stores/OperationStore.ts similarity index 54% rename from src/matrix/storage/idb/stores/OperationStore.js rename to src/matrix/storage/idb/stores/OperationStore.ts index 961e36af..cccd8e2d 100644 --- a/src/matrix/storage/idb/stores/OperationStore.js +++ b/src/matrix/storage/idb/stores/OperationStore.ts @@ -14,23 +14,46 @@ See the License for the specific language governing permissions and limitations under the License. */ import {MIN_UNICODE, MAX_UNICODE} from "./common"; +import {Store} from "../Store"; -export function encodeScopeTypeKey(scope, type) { +export function encodeScopeTypeKey(scope: string, type: string): string { return `${scope}|${type}`; } +interface BaseOperation { + id: string; + scope: string; + userIds: string[]; +} + +type OperationType = { type: "share_room_key"; roomKeyMessage: RoomKeyMessage; } + +type Operation = BaseOperation & OperationType + +type OperationEntry = Operation & { scopeTypeKey: string; } + +interface RoomKeyMessage { + room_id: string; + session_id: string; + session_key: string; + algorithm: string; + chain_index: number; +} + export class OperationStore { - constructor(store) { + private _store: Store; + + constructor(store: Store) { this._store = store; } - getAll() { + getAll(): Promise { return this._store.selectAll(); } - async getAllByTypeAndScope(type, scope) { + async getAllByTypeAndScope(type: string, scope: string): Promise { const key = encodeScopeTypeKey(scope, type); - const results = []; + const results: Operation[] = []; await this._store.index("byScopeAndType").iterateWhile(key, value => { if (value.scopeTypeKey !== key) { return false; @@ -41,20 +64,20 @@ export class OperationStore { return results; } - add(operation) { - operation.scopeTypeKey = encodeScopeTypeKey(operation.scope, operation.type); - this._store.add(operation); + add(operation: Operation): void { + (operation as OperationEntry).scopeTypeKey = encodeScopeTypeKey(operation.scope, operation.type); + this._store.add(operation as OperationEntry); } - update(operation) { - this._store.put(operation); + update(operation: Operation): void { + this._store.put(operation as OperationEntry); } - remove(id) { - this._store.delete(id); + remove(id: string): Promise { + return this._store.delete(id); } - async removeAllForScope(scope) { + async removeAllForScope(scope: string): Promise { const range = this._store.IDBKeyRange.bound( encodeScopeTypeKey(scope, MIN_UNICODE), encodeScopeTypeKey(scope, MAX_UNICODE) @@ -64,5 +87,6 @@ export class OperationStore { cur.delete(); return true; }); + return; } } diff --git a/src/matrix/storage/idb/stores/OutboundGroupSessionStore.js b/src/matrix/storage/idb/stores/OutboundGroupSessionStore.ts similarity index 64% rename from src/matrix/storage/idb/stores/OutboundGroupSessionStore.js rename to src/matrix/storage/idb/stores/OutboundGroupSessionStore.ts index 9710765f..82a87625 100644 --- a/src/matrix/storage/idb/stores/OutboundGroupSessionStore.js +++ b/src/matrix/storage/idb/stores/OutboundGroupSessionStore.ts @@ -13,21 +13,30 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import {Store} from "../Store"; + +interface OutboundSession { + roomId: string; + session: string; + createdAt: number; +} export class OutboundGroupSessionStore { - constructor(store) { + private _store: Store; + + constructor(store: Store) { this._store = store; } - remove(roomId) { - this._store.delete(roomId); + remove(roomId: string): Promise { + return this._store.delete(roomId); } - get(roomId) { + get(roomId: string): Promise { return this._store.get(roomId); } - set(session) { + set(session: OutboundSession): void { this._store.put(session); } } diff --git a/src/matrix/storage/idb/stores/PendingEventStore.js b/src/matrix/storage/idb/stores/PendingEventStore.ts similarity index 63% rename from src/matrix/storage/idb/stores/PendingEventStore.js rename to src/matrix/storage/idb/stores/PendingEventStore.ts index 61071f11..01991ce8 100644 --- a/src/matrix/storage/idb/stores/PendingEventStore.js +++ b/src/matrix/storage/idb/stores/PendingEventStore.ts @@ -16,23 +16,40 @@ limitations under the License. import { encodeUint32, decodeUint32 } from "../utils"; import {KeyLimits} from "../../common"; +import {Store} from "../Store"; +import {Content} from "../../types"; -function encodeKey(roomId, queueIndex) { +interface PendingEntry { + roomId: string; + queueIndex: number; + eventType: string; + content: Content; + relatexTxnId: string | null; + relatedEventId: string | null; + txnId?: string; + needsEncryption: boolean; + needsUpload: boolean; + key: string; +} + +function encodeKey(roomId: string, queueIndex: number): string { return `${roomId}|${encodeUint32(queueIndex)}`; } -function decodeKey(key) { +function decodeKey(key: string): { roomId: string, queueIndex: number } { const [roomId, encodedQueueIndex] = key.split("|"); const queueIndex = decodeUint32(encodedQueueIndex); return {roomId, queueIndex}; } export class PendingEventStore { - constructor(eventStore) { + private _eventStore: Store; + + constructor(eventStore: Store) { this._eventStore = eventStore; } - async getMaxQueueIndex(roomId) { + async getMaxQueueIndex(roomId: string): Promise { const range = this._eventStore.IDBKeyRange.bound( encodeKey(roomId, KeyLimits.minStorageKey), encodeKey(roomId, KeyLimits.maxStorageKey), @@ -41,38 +58,38 @@ export class PendingEventStore { ); const maxKey = await this._eventStore.findMaxKey(range); if (maxKey) { - return decodeKey(maxKey).queueIndex; + return decodeKey(maxKey as string).queueIndex; } } - remove(roomId, queueIndex) { + remove(roomId: string, queueIndex: number): Promise { const keyRange = this._eventStore.IDBKeyRange.only(encodeKey(roomId, queueIndex)); - this._eventStore.delete(keyRange); + return this._eventStore.delete(keyRange); } - async exists(roomId, queueIndex) { + async exists(roomId: string, queueIndex: number): Promise { const keyRange = this._eventStore.IDBKeyRange.only(encodeKey(roomId, queueIndex)); const key = await this._eventStore.getKey(keyRange); return !!key; } - add(pendingEvent) { + add(pendingEvent: PendingEntry): void { pendingEvent.key = encodeKey(pendingEvent.roomId, pendingEvent.queueIndex); this._eventStore.add(pendingEvent); } - update(pendingEvent) { + update(pendingEvent: PendingEntry): void { this._eventStore.put(pendingEvent); } - getAll() { + getAll(): Promise { return this._eventStore.selectAll(); } - removeAllForRoom(roomId) { + removeAllForRoom(roomId: string): Promise { const minKey = encodeKey(roomId, KeyLimits.minStorageKey); const maxKey = encodeKey(roomId, KeyLimits.maxStorageKey); const range = this._eventStore.IDBKeyRange.bound(minKey, maxKey); - this._eventStore.delete(range); + return this._eventStore.delete(range); } } diff --git a/src/matrix/storage/idb/stores/RoomMemberStore.ts b/src/matrix/storage/idb/stores/RoomMemberStore.ts index e389bb77..00cf607f 100644 --- a/src/matrix/storage/idb/stores/RoomMemberStore.ts +++ b/src/matrix/storage/idb/stores/RoomMemberStore.ts @@ -52,7 +52,7 @@ export class RoomMemberStore { set(member: MemberData): void { // Object.assign would be more typesafe, but small objects - (member as any).key = encodeKey(member.roomId, member.userId); + (member as MemberStorageEntry).key = encodeKey(member.roomId, member.userId); this._roomMembersStore.put(member as MemberStorageEntry); } diff --git a/src/matrix/storage/idb/stores/RoomStateStore.js b/src/matrix/storage/idb/stores/RoomStateStore.ts similarity index 66% rename from src/matrix/storage/idb/stores/RoomStateStore.js rename to src/matrix/storage/idb/stores/RoomStateStore.ts index db54458f..441d61e4 100644 --- a/src/matrix/storage/idb/stores/RoomStateStore.js +++ b/src/matrix/storage/idb/stores/RoomStateStore.ts @@ -16,31 +16,41 @@ limitations under the License. */ import {MAX_UNICODE} from "./common"; +import {Store} from "../Store"; +import {StateEvent} from "../../types"; -function encodeKey(roomId, eventType, stateKey) { +function encodeKey(roomId: string, eventType: string, stateKey: string) { return `${roomId}|${eventType}|${stateKey}`; } +export interface RoomStateEntry { + roomId: string; + event: StateEvent; + key: string; +} + export class RoomStateStore { - constructor(idbStore) { + private _roomStateStore: Store; + + constructor(idbStore: Store) { this._roomStateStore = idbStore; } - get(roomId, type, stateKey) { + get(roomId: string, type: string, stateKey: string): Promise { const key = encodeKey(roomId, type, stateKey); return this._roomStateStore.get(key); } - set(roomId, event) { + set(roomId: string, event: StateEvent): void { const key = encodeKey(roomId, event.type, event.state_key); const entry = {roomId, event, key}; - return this._roomStateStore.put(entry); + this._roomStateStore.put(entry); } - removeAllForRoom(roomId) { + removeAllForRoom(roomId: string): Promise { // exclude both keys as they are theoretical min and max, // but we should't have a match for just the room id, or room id with max const range = this._roomStateStore.IDBKeyRange.bound(roomId, `${roomId}|${MAX_UNICODE}`, true, true); - this._roomStateStore.delete(range); + return this._roomStateStore.delete(range); } } diff --git a/src/matrix/storage/idb/stores/TimelineEventStore.ts b/src/matrix/storage/idb/stores/TimelineEventStore.ts index eb4c70cc..f659bdbd 100644 --- a/src/matrix/storage/idb/stores/TimelineEventStore.ts +++ b/src/matrix/storage/idb/stores/TimelineEventStore.ts @@ -27,7 +27,7 @@ interface Annotation { firstTimestamp: number; } -interface StorageEntry { +interface TimelineEventEntry { roomId: string; fragmentId: number; eventIndex: number; @@ -35,10 +35,10 @@ interface StorageEntry { displayName?: string; avatarUrl?: string; annotations?: { [key : string]: Annotation }; - key: string; - eventIdKey: string; } +type TimelineEventStorageEntry = TimelineEventEntry & { key: string, eventIdKey: string }; + function encodeKey(roomId: string, fragmentId: number, eventIndex: number): string { return `${roomId}|${encodeUint32(fragmentId)}|${encodeUint32(eventIndex)}`; } @@ -126,9 +126,9 @@ class Range { * @property {?Gap} gap if a gap entry, the gap */ export class TimelineEventStore { - private _timelineStore: Store; + private _timelineStore: Store; - constructor(timelineStore: Store) { + constructor(timelineStore: Store) { this._timelineStore = timelineStore; } @@ -175,7 +175,7 @@ export class TimelineEventStore { * @param amount * @return a promise resolving to an array with 0 or more entries, in ascending order. */ - async lastEvents(roomId: string, fragmentId: number, amount: number): Promise { + async lastEvents(roomId: string, fragmentId: number, amount: number): Promise { const eventKey = EventKey.maxKey; eventKey.fragmentId = fragmentId; return this.eventsBefore(roomId, eventKey, amount); @@ -187,7 +187,7 @@ export class TimelineEventStore { * @param amount * @return a promise resolving to an array with 0 or more entries, in ascending order. */ - async firstEvents(roomId: string, fragmentId: number, amount: number): Promise { + async firstEvents(roomId: string, fragmentId: number, amount: number): Promise { const eventKey = EventKey.minKey; eventKey.fragmentId = fragmentId; return this.eventsAfter(roomId, eventKey, amount); @@ -200,7 +200,7 @@ export class TimelineEventStore { * @param amount * @return a promise resolving to an array with 0 or more entries, in ascending order. */ - eventsAfter(roomId: string, eventKey: EventKey, amount: number): Promise { + eventsAfter(roomId: string, eventKey: EventKey, amount: number): Promise { const idbRange = this.lowerBoundRange(eventKey, true).asIDBKeyRange(roomId); return this._timelineStore.selectLimit(idbRange, amount); } @@ -212,7 +212,7 @@ export class TimelineEventStore { * @param amount * @return a promise resolving to an array with 0 or more entries, in ascending order. */ - async eventsBefore(roomId: string, eventKey: EventKey, amount: number): Promise { + async eventsBefore(roomId: string, eventKey: EventKey, amount: number): Promise { const range = this.upperBoundRange(eventKey, true).asIDBKeyRange(roomId); const events = await this._timelineStore.selectLimitReverse(range, amount); events.reverse(); // because we fetched them backwards @@ -265,11 +265,11 @@ export class TimelineEventStore { * @return nothing. To wait for the operation to finish, await the transaction it's part of. * @throws {StorageError} ... */ - insert(entry: StorageEntry): void { - entry.key = encodeKey(entry.roomId, entry.fragmentId, entry.eventIndex); - entry.eventIdKey = encodeEventIdKey(entry.roomId, entry.event.event_id); + insert(entry: TimelineEventEntry): void { + (entry as TimelineEventStorageEntry).key = encodeKey(entry.roomId, entry.fragmentId, entry.eventIndex); + (entry as TimelineEventStorageEntry).eventIdKey = encodeEventIdKey(entry.roomId, entry.event.event_id); // TODO: map error? or in idb/store? - this._timelineStore.add(entry); + this._timelineStore.add(entry as TimelineEventStorageEntry); } /** Updates the entry into the store with the given [roomId, eventKey] combination. @@ -277,15 +277,15 @@ export class TimelineEventStore { * @param entry the entry to update. * @return nothing. To wait for the operation to finish, await the transaction it's part of. */ - update(entry: StorageEntry): void { - this._timelineStore.put(entry); + update(entry: TimelineEventEntry): void { + this._timelineStore.put(entry as TimelineEventStorageEntry); } - get(roomId: string, eventKey: EventKey): Promise { + get(roomId: string, eventKey: EventKey): Promise { return this._timelineStore.get(encodeKey(roomId, eventKey.fragmentId, eventKey.eventIndex)); } - getByEventId(roomId: string, eventId: string): Promise { + getByEventId(roomId: string, eventId: string): Promise { return this._timelineStore.index("byEventId").get(encodeEventIdKey(roomId, eventId)); } diff --git a/src/matrix/storage/idb/stores/TimelineFragmentStore.js b/src/matrix/storage/idb/stores/TimelineFragmentStore.ts similarity index 70% rename from src/matrix/storage/idb/stores/TimelineFragmentStore.js rename to src/matrix/storage/idb/stores/TimelineFragmentStore.ts index 07a8ff42..813fc3f3 100644 --- a/src/matrix/storage/idb/stores/TimelineFragmentStore.js +++ b/src/matrix/storage/idb/stores/TimelineFragmentStore.ts @@ -17,17 +17,31 @@ limitations under the License. import { StorageError } from "../../common"; import {KeyLimits} from "../../common"; import { encodeUint32 } from "../utils"; +import {Store} from "../Store"; -function encodeKey(roomId, fragmentId) { +interface Fragment { + roomId: string; + id: number; + previousId: number | null; + nextId: number | null; + previousToken: string | null; + nextToken: string | null; +} + +type FragmentEntry = Fragment & { key: string } + +function encodeKey(roomId: string, fragmentId: number): string { return `${roomId}|${encodeUint32(fragmentId)}`; } export class TimelineFragmentStore { - constructor(store) { + private _store: Store; + + constructor(store: Store) { this._store = store; } - _allRange(roomId) { + _allRange(roomId: string): IDBKeyRange { try { return this._store.IDBKeyRange.bound( encodeKey(roomId, KeyLimits.minStorageKey), @@ -38,13 +52,13 @@ export class TimelineFragmentStore { } } - all(roomId) { + all(roomId: string): Promise { return this._store.selectAll(this._allRange(roomId)); } /** Returns the fragment without a nextToken and without nextId, if any, with the largest id if there are multiple (which should not happen) */ - liveFragment(roomId) { + liveFragment(roomId: string): Promise { // why do we need this? // Ok, take the case where you've got a /context fragment and a /sync fragment // They are not connected. So, upon loading the persister, which one do we take? We can't sort them ... @@ -60,20 +74,20 @@ export class TimelineFragmentStore { // should generate an id an return it? // depends if we want to do anything smart with fragment ids, // like give them meaning depending on range. not for now probably ... - add(fragment) { - fragment.key = encodeKey(fragment.roomId, fragment.id); - this._store.add(fragment); + add(fragment: Fragment): void { + (fragment as FragmentEntry).key = encodeKey(fragment.roomId, fragment.id); + this._store.add(fragment as FragmentEntry); } - update(fragment) { + update(fragment: FragmentEntry): void { this._store.put(fragment); } - get(roomId, fragmentId) { + get(roomId: string, fragmentId: number): Promise { return this._store.get(encodeKey(roomId, fragmentId)); } - removeAllForRoom(roomId) { - this._store.delete(this._allRange(roomId)); + removeAllForRoom(roomId: string): Promise { + return this._store.delete(this._allRange(roomId)); } } diff --git a/src/matrix/storage/idb/stores/UserIdentityStore.js b/src/matrix/storage/idb/stores/UserIdentityStore.ts similarity index 67% rename from src/matrix/storage/idb/stores/UserIdentityStore.js rename to src/matrix/storage/idb/stores/UserIdentityStore.ts index 1cf6d636..1d94a666 100644 --- a/src/matrix/storage/idb/stores/UserIdentityStore.js +++ b/src/matrix/storage/idb/stores/UserIdentityStore.ts @@ -13,21 +13,30 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import {Store} from "../Store"; + +interface UserIdentity { + userId: string; + roomIds: string[]; + deviceTrackingStatus: number; +} export class UserIdentityStore { - constructor(store) { + private _store: Store; + + constructor(store: Store) { this._store = store; } - get(userId) { + get(userId: string): Promise { return this._store.get(userId); } - set(userIdentity) { + set(userIdentity: UserIdentity): void { this._store.put(userIdentity); } - remove(userId) { + remove(userId: string): Promise { return this._store.delete(userId); } }