diff options
author | RaindropsSys <raindrops@equestria.dev> | 2023-11-17 23:25:29 +0100 |
---|---|---|
committer | RaindropsSys <raindrops@equestria.dev> | 2023-11-17 23:25:29 +0100 |
commit | 953ddd82e48dd206cef5ac94456549aed13b3ad5 (patch) | |
tree | 8f003106ee2e7f422e5a22d2ee04d0db302e66c0 /includes/external/matrix/node_modules/matrix-js-sdk/src/store | |
parent | 62a9199846b0c07c03218703b33e8385764f42d9 (diff) | |
download | pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.gz pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.bz2 pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.zip |
Updated 30 files and deleted 2976 files (automated)
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/src/store')
9 files changed, 0 insertions, 2377 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/index.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/index.ts deleted file mode 100644 index 650dd9a..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/index.ts +++ /dev/null @@ -1,248 +0,0 @@ -/* -Copyright 2015 - 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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 { EventType } from "../@types/event"; -import { Room } from "../models/room"; -import { User } from "../models/user"; -import { IEvent, MatrixEvent } from "../models/event"; -import { Filter } from "../filter"; -import { RoomSummary } from "../models/room-summary"; -import { IMinimalEvent, IRooms, ISyncResponse } from "../sync-accumulator"; -import { IStartClientOpts } from "../client"; -import { IStateEventWithRoomId } from "../@types/search"; -import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDeviceMessage"; -import { EventEmitterEvents } from "../models/typed-event-emitter"; - -export interface ISavedSync { - nextBatch: string; - roomsData: IRooms; - accountData: IMinimalEvent[]; -} - -/** - * A store for most of the data js-sdk needs to store, apart from crypto data - */ -export interface IStore { - readonly accountData: Map<string, MatrixEvent>; // type : content - - // XXX: The indexeddb store exposes a non-standard emitter for: - // "degraded" event for when it falls back to being a memory store due to errors. - // "closed" event for when the database closes unexpectedly - on?: (event: EventEmitterEvents | "degraded" | "closed", handler: (...args: any[]) => void) => void; - - /** @returns whether or not the database was newly created in this session. */ - isNewlyCreated(): Promise<boolean>; - - /** - * Get the sync token. - */ - getSyncToken(): string | null; - - /** - * Set the sync token. - */ - setSyncToken(token: string): void; - - /** - * Store the given room. - * @param room - The room to be stored. All properties must be stored. - */ - storeRoom(room: Room): void; - - /** - * Retrieve a room by its' room ID. - * @param roomId - The room ID. - * @returns The room or null. - */ - getRoom(roomId: string): Room | null; - - /** - * Retrieve all known rooms. - * @returns A list of rooms, which may be empty. - */ - getRooms(): Room[]; - - /** - * Permanently delete a room. - */ - removeRoom(roomId: string): void; - - /** - * Retrieve a summary of all the rooms. - * @returns A summary of each room. - */ - getRoomSummaries(): RoomSummary[]; - - /** - * Store a User. - * @param user - The user to store. - */ - storeUser(user: User): void; - - /** - * Retrieve a User by its' user ID. - * @param userId - The user ID. - * @returns The user or null. - */ - getUser(userId: string): User | null; - - /** - * Retrieve all known users. - * @returns A list of users, which may be empty. - */ - getUsers(): User[]; - - /** - * Retrieve scrollback for this room. - * @param room - The matrix room - * @param limit - The max number of old events to retrieve. - * @returns An array of objects which will be at most 'limit' - * length and at least 0. The objects are the raw event JSON. - */ - scrollback(room: Room, limit: number): MatrixEvent[]; - - /** - * Store events for a room. - * @param room - The room to store events for. - * @param events - The events to store. - * @param token - The token associated with these events. - * @param toStart - True if these are paginated results. - */ - storeEvents(room: Room, events: MatrixEvent[], token: string | null, toStart: boolean): void; - - /** - * Store a filter. - */ - storeFilter(filter: Filter): void; - - /** - * Retrieve a filter. - * @returns A filter or null. - */ - getFilter(userId: string, filterId: string): Filter | null; - - /** - * Retrieve a filter ID with the given name. - * @param filterName - The filter name. - * @returns The filter ID or null. - */ - getFilterIdByName(filterName: string): string | null; - - /** - * Set a filter name to ID mapping. - */ - setFilterIdByName(filterName: string, filterId?: string): void; - - /** - * Store user-scoped account data events - * @param events - The events to store. - */ - storeAccountDataEvents(events: MatrixEvent[]): void; - - /** - * Get account data event by event type - * @param eventType - The event type being queried - */ - getAccountData(eventType: EventType | string): MatrixEvent | undefined; - - /** - * setSyncData does nothing as there is no backing data store. - * - * @param syncData - The sync data - * @returns An immediately resolved promise. - */ - setSyncData(syncData: ISyncResponse): Promise<void>; - - /** - * We never want to save because we have nothing to save to. - * - * @returns If the store wants to save - */ - wantsSave(): boolean; - - /** - * Save does nothing as there is no backing data store. - */ - save(force?: boolean): void; - - /** - * Startup does nothing. - * @returns An immediately resolved promise. - */ - startup(): Promise<void>; - - /** - * @returns Promise which resolves with a sync response to restore the - * client state to where it was at the last save, or null if there - * is no saved sync data. - */ - getSavedSync(): Promise<ISavedSync | null>; - - /** - * @returns If there is a saved sync, the nextBatch token - * for this sync, otherwise null. - */ - getSavedSyncToken(): Promise<string | null>; - - /** - * Delete all data from this store. Does nothing since this store - * doesn't store anything. - * @returns An immediately resolved promise. - */ - deleteAllData(): Promise<void>; - - /** - * Returns the out-of-band membership events for this room that - * were previously loaded. - * @returns the events, potentially an empty array if OOB loading didn't yield any new members - * @returns in case the members for this room haven't been stored yet - */ - getOutOfBandMembers(roomId: string): Promise<IStateEventWithRoomId[] | null>; - - /** - * Stores the out-of-band membership events for this room. Note that - * it still makes sense to store an empty array as the OOB status for the room is - * marked as fetched, and getOutOfBandMembers will return an empty array instead of null - * @param membershipEvents - the membership events to store - * @returns when all members have been stored - */ - setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void>; - - clearOutOfBandMembers(roomId: string): Promise<void>; - - getClientOptions(): Promise<IStartClientOpts | undefined>; - - storeClientOptions(options: IStartClientOpts): Promise<void>; - - getPendingEvents(roomId: string): Promise<Partial<IEvent>[]>; - - setPendingEvents(roomId: string, events: Partial<IEvent>[]): Promise<void>; - - /** - * Stores batches of outgoing to-device messages - */ - saveToDeviceBatches(batch: ToDeviceBatchWithTxnId[]): Promise<void>; - - /** - * Fetches the oldest batch of to-device messages in the queue - */ - getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null>; - - /** - * Removes a specific batch of to-device messages from the queue - */ - removeToDeviceBatch(id: number): Promise<void>; -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-backend.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-backend.ts deleted file mode 100644 index 008867d..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-backend.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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 { ISavedSync } from "./index"; -import { IEvent, IStateEventWithRoomId, IStoredClientOpts, ISyncResponse } from "../matrix"; -import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDeviceMessage"; - -export interface IIndexedDBBackend { - connect(onClose?: () => void): Promise<void>; - syncToDatabase(userTuples: UserTuple[]): Promise<void>; - isNewlyCreated(): Promise<boolean>; - setSyncData(syncData: ISyncResponse): Promise<void>; - getSavedSync(): Promise<ISavedSync | null>; - getNextBatchToken(): Promise<string>; - clearDatabase(): Promise<void>; - getOutOfBandMembers(roomId: string): Promise<IStateEventWithRoomId[] | null>; - setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void>; - clearOutOfBandMembers(roomId: string): Promise<void>; - getUserPresenceEvents(): Promise<UserTuple[]>; - getClientOptions(): Promise<IStoredClientOpts | undefined>; - storeClientOptions(options: IStoredClientOpts): Promise<void>; - saveToDeviceBatches(batches: ToDeviceBatchWithTxnId[]): Promise<void>; - getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null>; - removeToDeviceBatch(id: number): Promise<void>; -} - -export type UserTuple = [userId: string, presenceEvent: Partial<IEvent>]; diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-local-backend.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-local-backend.ts deleted file mode 100644 index 80fed44..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-local-backend.ts +++ /dev/null @@ -1,597 +0,0 @@ -/* -Copyright 2017 - 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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 { IMinimalEvent, ISyncData, ISyncResponse, SyncAccumulator } from "../sync-accumulator"; -import * as utils from "../utils"; -import * as IndexedDBHelpers from "../indexeddb-helpers"; -import { logger } from "../logger"; -import { IStateEventWithRoomId, IStoredClientOpts } from "../matrix"; -import { ISavedSync } from "./index"; -import { IIndexedDBBackend, UserTuple } from "./indexeddb-backend"; -import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDeviceMessage"; - -type DbMigration = (db: IDBDatabase) => void; -const DB_MIGRATIONS: DbMigration[] = [ - (db): void => { - // Make user store, clobber based on user ID. (userId property of User objects) - db.createObjectStore("users", { keyPath: ["userId"] }); - - // Make account data store, clobber based on event type. - // (event.type property of MatrixEvent objects) - db.createObjectStore("accountData", { keyPath: ["type"] }); - - // Make /sync store (sync tokens, room data, etc), always clobber (const key). - db.createObjectStore("sync", { keyPath: ["clobber"] }); - }, - (db): void => { - const oobMembersStore = db.createObjectStore("oob_membership_events", { - keyPath: ["room_id", "state_key"], - }); - oobMembersStore.createIndex("room", "room_id"); - }, - (db): void => { - db.createObjectStore("client_options", { keyPath: ["clobber"] }); - }, - (db): void => { - db.createObjectStore("to_device_queue", { autoIncrement: true }); - }, - // Expand as needed. -]; -const VERSION = DB_MIGRATIONS.length; - -/** - * Helper method to collect results from a Cursor and promiseify it. - * @param store - The store to perform openCursor on. - * @param keyRange - Optional key range to apply on the cursor. - * @param resultMapper - A function which is repeatedly called with a - * Cursor. - * Return the data you want to keep. - * @returns Promise which resolves to an array of whatever you returned from - * resultMapper. - */ -function selectQuery<T>( - store: IDBObjectStore, - keyRange: IDBKeyRange | IDBValidKey | undefined, - resultMapper: (cursor: IDBCursorWithValue) => T, -): Promise<T[]> { - const query = store.openCursor(keyRange); - return new Promise((resolve, reject) => { - const results: T[] = []; - query.onerror = (): void => { - reject(new Error("Query failed: " + query.error)); - }; - // collect results - query.onsuccess = (): void => { - const cursor = query.result; - if (!cursor) { - resolve(results); - return; // end of results - } - results.push(resultMapper(cursor)); - cursor.continue(); - }; - }); -} - -function txnAsPromise(txn: IDBTransaction): Promise<Event> { - return new Promise((resolve, reject) => { - txn.oncomplete = function (event): void { - resolve(event); - }; - txn.onerror = function (): void { - reject(txn.error); - }; - }); -} - -function reqAsEventPromise(req: IDBRequest): Promise<Event> { - return new Promise((resolve, reject) => { - req.onsuccess = function (event): void { - resolve(event); - }; - req.onerror = function (): void { - reject(req.error); - }; - }); -} - -function reqAsPromise(req: IDBRequest): Promise<IDBRequest> { - return new Promise((resolve, reject) => { - req.onsuccess = (): void => resolve(req); - req.onerror = (err): void => reject(err); - }); -} - -function reqAsCursorPromise<T>(req: IDBRequest<T>): Promise<T> { - return reqAsEventPromise(req).then((event) => req.result); -} - -export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { - public static exists(indexedDB: IDBFactory, dbName: string): Promise<boolean> { - dbName = "matrix-js-sdk:" + (dbName || "default"); - return IndexedDBHelpers.exists(indexedDB, dbName); - } - - private readonly dbName: string; - private readonly syncAccumulator: SyncAccumulator; - private db?: IDBDatabase; - private disconnected = true; - private _isNewlyCreated = false; - private syncToDatabasePromise?: Promise<void>; - private pendingUserPresenceData: UserTuple[] = []; - - /** - * Does the actual reading from and writing to the indexeddb - * - * Construct a new Indexed Database store backend. This requires a call to - * `connect()` before this store can be used. - * @param indexedDB - The Indexed DB interface e.g - * `window.indexedDB` - * @param dbName - Optional database name. The same name must be used - * to open the same database. - */ - public constructor(private readonly indexedDB: IDBFactory, dbName = "default") { - this.dbName = "matrix-js-sdk:" + dbName; - this.syncAccumulator = new SyncAccumulator(); - } - - /** - * Attempt to connect to the database. This can fail if the user does not - * grant permission. - * @returns Promise which resolves if successfully connected. - */ - public connect(onClose?: () => void): Promise<void> { - if (!this.disconnected) { - logger.log(`LocalIndexedDBStoreBackend.connect: already connected or connecting`); - return Promise.resolve(); - } - - this.disconnected = false; - - logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`); - const req = this.indexedDB.open(this.dbName, VERSION); - req.onupgradeneeded = (ev): void => { - const db = req.result; - const oldVersion = ev.oldVersion; - logger.log(`LocalIndexedDBStoreBackend.connect: upgrading from ${oldVersion}`); - if (oldVersion < 1) { - // The database did not previously exist - this._isNewlyCreated = true; - } - DB_MIGRATIONS.forEach((migration, index) => { - if (oldVersion <= index) migration(db); - }); - }; - - req.onblocked = (): void => { - logger.log(`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`); - }; - - logger.log(`LocalIndexedDBStoreBackend.connect: awaiting connection...`); - return reqAsEventPromise(req).then(async () => { - logger.log(`LocalIndexedDBStoreBackend.connect: connected`); - this.db = req.result; - - // add a poorly-named listener for when deleteDatabase is called - // so we can close our db connections. - this.db.onversionchange = (): void => { - this.db?.close(); // this does not call onclose - this.disconnected = true; - this.db = undefined; - onClose?.(); - }; - this.db.onclose = (): void => { - this.disconnected = true; - this.db = undefined; - onClose?.(); - }; - - await this.init(); - }); - } - - /** @returns whether or not the database was newly created in this session. */ - public isNewlyCreated(): Promise<boolean> { - return Promise.resolve(this._isNewlyCreated); - } - - /** - * Having connected, load initial data from the database and prepare for use - * @returns Promise which resolves on success - */ - private init(): Promise<unknown> { - return Promise.all([this.loadAccountData(), this.loadSyncData()]).then(([accountData, syncData]) => { - logger.log(`LocalIndexedDBStoreBackend: loaded initial data`); - this.syncAccumulator.accumulate( - { - next_batch: syncData.nextBatch, - rooms: syncData.roomsData, - account_data: { - events: accountData, - }, - }, - true, - ); - }); - } - - /** - * Returns the out-of-band membership events for this room that - * were previously loaded. - * @returns the events, potentially an empty array if OOB loading didn't yield any new members - * @returns in case the members for this room haven't been stored yet - */ - public getOutOfBandMembers(roomId: string): Promise<IStateEventWithRoomId[] | null> { - return new Promise<IStateEventWithRoomId[] | null>((resolve, reject) => { - const tx = this.db!.transaction(["oob_membership_events"], "readonly"); - const store = tx.objectStore("oob_membership_events"); - const roomIndex = store.index("room"); - const range = IDBKeyRange.only(roomId); - const request = roomIndex.openCursor(range); - - const membershipEvents: IStateEventWithRoomId[] = []; - // did we encounter the oob_written marker object - // amongst the results? That means OOB member - // loading already happened for this room - // but there were no members to persist as they - // were all known already - let oobWritten = false; - - request.onsuccess = (): void => { - const cursor = request.result; - if (!cursor) { - // Unknown room - if (!membershipEvents.length && !oobWritten) { - return resolve(null); - } - return resolve(membershipEvents); - } - const record = cursor.value; - if (record.oob_written) { - oobWritten = true; - } else { - membershipEvents.push(record); - } - cursor.continue(); - }; - request.onerror = (err): void => { - reject(err); - }; - }).then((events) => { - logger.log(`LL: got ${events?.length} membershipEvents from storage for room ${roomId} ...`); - return events; - }); - } - - /** - * Stores the out-of-band membership events for this room. Note that - * it still makes sense to store an empty array as the OOB status for the room is - * marked as fetched, and getOutOfBandMembers will return an empty array instead of null - * @param membershipEvents - the membership events to store - */ - public async setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> { - logger.log(`LL: backend about to store ${membershipEvents.length}` + ` members for ${roomId}`); - const tx = this.db!.transaction(["oob_membership_events"], "readwrite"); - const store = tx.objectStore("oob_membership_events"); - membershipEvents.forEach((e) => { - store.put(e); - }); - // aside from all the events, we also write a marker object to the store - // to mark the fact that OOB members have been written for this room. - // It's possible that 0 members need to be written as all where previously know - // but we still need to know whether to return null or [] from getOutOfBandMembers - // where null means out of band members haven't been stored yet for this room - const markerObject = { - room_id: roomId, - oob_written: true, - state_key: 0, - }; - store.put(markerObject); - await txnAsPromise(tx); - logger.log(`LL: backend done storing for ${roomId}!`); - } - - public async clearOutOfBandMembers(roomId: string): Promise<void> { - // the approach to delete all members for a room - // is to get the min and max state key from the index - // for that room, and then delete between those - // keys in the store. - // this should be way faster than deleting every member - // individually for a large room. - const readTx = this.db!.transaction(["oob_membership_events"], "readonly"); - const store = readTx.objectStore("oob_membership_events"); - const roomIndex = store.index("room"); - const roomRange = IDBKeyRange.only(roomId); - - const minStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, "next")).then( - (cursor) => (<IDBValidKey[]>cursor?.primaryKey)[1], - ); - const maxStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, "prev")).then( - (cursor) => (<IDBValidKey[]>cursor?.primaryKey)[1], - ); - const [minStateKey, maxStateKey] = await Promise.all([minStateKeyProm, maxStateKeyProm]); - - const writeTx = this.db!.transaction(["oob_membership_events"], "readwrite"); - const writeStore = writeTx.objectStore("oob_membership_events"); - const membersKeyRange = IDBKeyRange.bound([roomId, minStateKey], [roomId, maxStateKey]); - - logger.log( - `LL: Deleting all users + marker in storage for room ${roomId}, with key range:`, - [roomId, minStateKey], - [roomId, maxStateKey], - ); - await reqAsPromise(writeStore.delete(membersKeyRange)); - } - - /** - * Clear the entire database. This should be used when logging out of a client - * to prevent mixing data between accounts. - * @returns Resolved when the database is cleared. - */ - public clearDatabase(): Promise<void> { - return new Promise((resolve) => { - logger.log(`Removing indexeddb instance: ${this.dbName}`); - const req = this.indexedDB.deleteDatabase(this.dbName); - - req.onblocked = (): void => { - logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`); - }; - - req.onerror = (): void => { - // in firefox, with indexedDB disabled, this fails with a - // DOMError. We treat this as non-fatal, so that we can still - // use the app. - logger.warn(`unable to delete js-sdk store indexeddb: ${req.error}`); - resolve(); - }; - - req.onsuccess = (): void => { - logger.log(`Removed indexeddb instance: ${this.dbName}`); - resolve(); - }; - }); - } - - /** - * @param copy - If false, the data returned is from internal - * buffers and must not be mutated. Otherwise, a copy is made before - * returning such that the data can be safely mutated. Default: true. - * - * @returns Promise which resolves with a sync response to restore the - * client state to where it was at the last save, or null if there - * is no saved sync data. - */ - public getSavedSync(copy = true): Promise<ISavedSync | null> { - const data = this.syncAccumulator.getJSON(); - if (!data.nextBatch) return Promise.resolve(null); - if (copy) { - // We must deep copy the stored data so that the /sync processing code doesn't - // corrupt the internal state of the sync accumulator (it adds non-clonable keys) - return Promise.resolve(utils.deepCopy(data)); - } else { - return Promise.resolve(data); - } - } - - public getNextBatchToken(): Promise<string> { - return Promise.resolve(this.syncAccumulator.getNextBatchToken()); - } - - public setSyncData(syncData: ISyncResponse): Promise<void> { - return Promise.resolve().then(() => { - this.syncAccumulator.accumulate(syncData); - }); - } - - /** - * Sync users and all accumulated sync data to the database. - * If a previous sync is in flight, the new data will be added to the - * next sync and the current sync's promise will be returned. - * @param userTuples - The user tuples - * @returns Promise which resolves if the data was persisted. - */ - public async syncToDatabase(userTuples: UserTuple[]): Promise<void> { - if (this.syncToDatabasePromise) { - logger.warn("Skipping syncToDatabase() as persist already in flight"); - this.pendingUserPresenceData.push(...userTuples); - return this.syncToDatabasePromise; - } - userTuples.unshift(...this.pendingUserPresenceData); - this.syncToDatabasePromise = this.doSyncToDatabase(userTuples); - return this.syncToDatabasePromise; - } - - private async doSyncToDatabase(userTuples: UserTuple[]): Promise<void> { - try { - const syncData = this.syncAccumulator.getJSON(true); - await Promise.all([ - this.persistUserPresenceEvents(userTuples), - this.persistAccountData(syncData.accountData), - this.persistSyncData(syncData.nextBatch, syncData.roomsData), - ]); - } finally { - this.syncToDatabasePromise = undefined; - } - } - - /** - * Persist rooms /sync data along with the next batch token. - * @param nextBatch - The next_batch /sync value. - * @param roomsData - The 'rooms' /sync data from a SyncAccumulator - * @returns Promise which resolves if the data was persisted. - */ - private persistSyncData(nextBatch: string, roomsData: ISyncResponse["rooms"]): Promise<void> { - logger.log("Persisting sync data up to", nextBatch); - return utils.promiseTry<void>(() => { - const txn = this.db!.transaction(["sync"], "readwrite"); - const store = txn.objectStore("sync"); - store.put({ - clobber: "-", // constant key so will always clobber - nextBatch, - roomsData, - }); // put == UPSERT - return txnAsPromise(txn).then(() => { - logger.log("Persisted sync data up to", nextBatch); - }); - }); - } - - /** - * Persist a list of account data events. Events with the same 'type' will - * be replaced. - * @param accountData - An array of raw user-scoped account data events - * @returns Promise which resolves if the events were persisted. - */ - private persistAccountData(accountData: IMinimalEvent[]): Promise<void> { - return utils.promiseTry<void>(() => { - const txn = this.db!.transaction(["accountData"], "readwrite"); - const store = txn.objectStore("accountData"); - for (const event of accountData) { - store.put(event); // put == UPSERT - } - return txnAsPromise(txn).then(); - }); - } - - /** - * Persist a list of [user id, presence event] they are for. - * Users with the same 'userId' will be replaced. - * Presence events should be the event in its raw form (not the Event - * object) - * @param tuples - An array of [userid, event] tuples - * @returns Promise which resolves if the users were persisted. - */ - private persistUserPresenceEvents(tuples: UserTuple[]): Promise<void> { - return utils.promiseTry<void>(() => { - const txn = this.db!.transaction(["users"], "readwrite"); - const store = txn.objectStore("users"); - for (const tuple of tuples) { - store.put({ - userId: tuple[0], - event: tuple[1], - }); // put == UPSERT - } - return txnAsPromise(txn).then(); - }); - } - - /** - * Load all user presence events from the database. This is not cached. - * FIXME: It would probably be more sensible to store the events in the - * sync. - * @returns A list of presence events in their raw form. - */ - public getUserPresenceEvents(): Promise<UserTuple[]> { - return utils.promiseTry<UserTuple[]>(() => { - const txn = this.db!.transaction(["users"], "readonly"); - const store = txn.objectStore("users"); - return selectQuery(store, undefined, (cursor) => { - return [cursor.value.userId, cursor.value.event]; - }); - }); - } - - /** - * Load all the account data events from the database. This is not cached. - * @returns A list of raw global account events. - */ - private loadAccountData(): Promise<IMinimalEvent[]> { - logger.log(`LocalIndexedDBStoreBackend: loading account data...`); - return utils.promiseTry<IMinimalEvent[]>(() => { - const txn = this.db!.transaction(["accountData"], "readonly"); - const store = txn.objectStore("accountData"); - return selectQuery(store, undefined, (cursor) => { - return cursor.value; - }).then((result: IMinimalEvent[]) => { - logger.log(`LocalIndexedDBStoreBackend: loaded account data`); - return result; - }); - }); - } - - /** - * Load the sync data from the database. - * @returns An object with "roomsData" and "nextBatch" keys. - */ - private loadSyncData(): Promise<ISyncData> { - logger.log(`LocalIndexedDBStoreBackend: loading sync data...`); - return utils.promiseTry<ISyncData>(() => { - const txn = this.db!.transaction(["sync"], "readonly"); - const store = txn.objectStore("sync"); - return selectQuery(store, undefined, (cursor) => { - return cursor.value; - }).then((results: ISyncData[]) => { - logger.log(`LocalIndexedDBStoreBackend: loaded sync data`); - if (results.length > 1) { - logger.warn("loadSyncData: More than 1 sync row found."); - } - return results.length > 0 ? results[0] : ({} as ISyncData); - }); - }); - } - - public getClientOptions(): Promise<IStoredClientOpts | undefined> { - return Promise.resolve().then(() => { - const txn = this.db!.transaction(["client_options"], "readonly"); - const store = txn.objectStore("client_options"); - return selectQuery(store, undefined, (cursor) => { - return cursor.value?.options; - }).then((results) => results[0]); - }); - } - - public async storeClientOptions(options: IStoredClientOpts): Promise<void> { - const txn = this.db!.transaction(["client_options"], "readwrite"); - const store = txn.objectStore("client_options"); - store.put({ - clobber: "-", // constant key so will always clobber - options: options, - }); // put == UPSERT - await txnAsPromise(txn); - } - - public async saveToDeviceBatches(batches: ToDeviceBatchWithTxnId[]): Promise<void> { - const txn = this.db!.transaction(["to_device_queue"], "readwrite"); - const store = txn.objectStore("to_device_queue"); - for (const batch of batches) { - store.add(batch); - } - await txnAsPromise(txn); - } - - public async getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> { - const txn = this.db!.transaction(["to_device_queue"], "readonly"); - const store = txn.objectStore("to_device_queue"); - const cursor = await reqAsCursorPromise(store.openCursor()); - if (!cursor) return null; - - const resultBatch = cursor.value as ToDeviceBatchWithTxnId; - - return { - id: cursor.key as number, - txnId: resultBatch.txnId, - eventType: resultBatch.eventType, - batch: resultBatch.batch, - }; - } - - public async removeToDeviceBatch(id: number): Promise<void> { - const txn = this.db!.transaction(["to_device_queue"], "readwrite"); - const store = txn.objectStore("to_device_queue"); - store.delete(id); - await txnAsPromise(txn); - } -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-remote-backend.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-remote-backend.ts deleted file mode 100644 index 7e2aa0c..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-remote-backend.ts +++ /dev/null @@ -1,203 +0,0 @@ -/* -Copyright 2017 - 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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 { logger } from "../logger"; -import { defer, IDeferred } from "../utils"; -import { ISavedSync } from "./index"; -import { IStoredClientOpts } from "../client"; -import { IStateEventWithRoomId, ISyncResponse } from "../matrix"; -import { IIndexedDBBackend, UserTuple } from "./indexeddb-backend"; -import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDeviceMessage"; - -export class RemoteIndexedDBStoreBackend implements IIndexedDBBackend { - private worker?: Worker; - private nextSeq = 0; - // The currently in-flight requests to the actual backend - private inFlight: Record<number, IDeferred<any>> = {}; // seq: promise - // Once we start connecting, we keep the promise and re-use it - // if we try to connect again - private startPromise?: Promise<void>; - // Callback for when the IndexedDB gets closed unexpectedly - private onClose?(): void; - - /** - * An IndexedDB store backend where the actual backend sits in a web - * worker. - * - * Construct a new Indexed Database store backend. This requires a call to - * `connect()` before this store can be used. - * @param workerFactory - Factory which produces a Worker - * @param dbName - Optional database name. The same name must be used - * to open the same database. - */ - public constructor(private readonly workerFactory: () => Worker, private readonly dbName?: string) {} - - /** - * Attempt to connect to the database. This can fail if the user does not - * grant permission. - * @returns Promise which resolves if successfully connected. - */ - public connect(onClose?: () => void): Promise<void> { - this.onClose = onClose; - return this.ensureStarted().then(() => this.doCmd("connect")); - } - - /** - * Clear the entire database. This should be used when logging out of a client - * to prevent mixing data between accounts. - * @returns Resolved when the database is cleared. - */ - public clearDatabase(): Promise<void> { - return this.ensureStarted().then(() => this.doCmd("clearDatabase")); - } - - /** @returns whether or not the database was newly created in this session. */ - public isNewlyCreated(): Promise<boolean> { - return this.doCmd("isNewlyCreated"); - } - - /** - * @returns Promise which resolves with a sync response to restore the - * client state to where it was at the last save, or null if there - * is no saved sync data. - */ - public getSavedSync(): Promise<ISavedSync> { - return this.doCmd("getSavedSync"); - } - - public getNextBatchToken(): Promise<string> { - return this.doCmd("getNextBatchToken"); - } - - public setSyncData(syncData: ISyncResponse): Promise<void> { - return this.doCmd("setSyncData", [syncData]); - } - - public syncToDatabase(userTuples: UserTuple[]): Promise<void> { - return this.doCmd("syncToDatabase", [userTuples]); - } - - /** - * Returns the out-of-band membership events for this room that - * were previously loaded. - * @returns the events, potentially an empty array if OOB loading didn't yield any new members - * @returns in case the members for this room haven't been stored yet - */ - public getOutOfBandMembers(roomId: string): Promise<IStateEventWithRoomId[] | null> { - return this.doCmd("getOutOfBandMembers", [roomId]); - } - - /** - * Stores the out-of-band membership events for this room. Note that - * it still makes sense to store an empty array as the OOB status for the room is - * marked as fetched, and getOutOfBandMembers will return an empty array instead of null - * @param membershipEvents - the membership events to store - * @returns when all members have been stored - */ - public setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> { - return this.doCmd("setOutOfBandMembers", [roomId, membershipEvents]); - } - - public clearOutOfBandMembers(roomId: string): Promise<void> { - return this.doCmd("clearOutOfBandMembers", [roomId]); - } - - public getClientOptions(): Promise<IStoredClientOpts | undefined> { - return this.doCmd("getClientOptions"); - } - - public storeClientOptions(options: IStoredClientOpts): Promise<void> { - return this.doCmd("storeClientOptions", [options]); - } - - /** - * Load all user presence events from the database. This is not cached. - * @returns A list of presence events in their raw form. - */ - public getUserPresenceEvents(): Promise<UserTuple[]> { - return this.doCmd("getUserPresenceEvents"); - } - - public async saveToDeviceBatches(batches: ToDeviceBatchWithTxnId[]): Promise<void> { - return this.doCmd("saveToDeviceBatches", [batches]); - } - - public async getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> { - return this.doCmd("getOldestToDeviceBatch"); - } - - public async removeToDeviceBatch(id: number): Promise<void> { - return this.doCmd("removeToDeviceBatch", [id]); - } - - private ensureStarted(): Promise<void> { - if (!this.startPromise) { - this.worker = this.workerFactory(); - this.worker.onmessage = this.onWorkerMessage; - - // tell the worker the db name. - this.startPromise = this.doCmd("setupWorker", [this.dbName]).then(() => { - logger.log("IndexedDB worker is ready"); - }); - } - return this.startPromise; - } - - private doCmd<T>(command: string, args?: any): Promise<T> { - // wrap in a q so if the postMessage throws, - // the promise automatically gets rejected - return Promise.resolve().then(() => { - const seq = this.nextSeq++; - const def = defer<T>(); - - this.inFlight[seq] = def; - - this.worker?.postMessage({ command, seq, args }); - - return def.promise; - }); - } - - private onWorkerMessage = (ev: MessageEvent): void => { - const msg = ev.data; - - if (msg.command == "closed") { - this.onClose?.(); - } else if (msg.command == "cmd_success" || msg.command == "cmd_fail") { - if (msg.seq === undefined) { - logger.error("Got reply from worker with no seq"); - return; - } - - const def = this.inFlight[msg.seq]; - if (def === undefined) { - logger.error("Got reply for unknown seq " + msg.seq); - return; - } - delete this.inFlight[msg.seq]; - - if (msg.command == "cmd_success") { - def.resolve(msg.result); - } else { - const error = new Error(msg.error.message); - error.name = msg.error.name; - def.reject(error); - } - } else { - logger.warn("Unrecognised message from worker: ", msg); - } - }; -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-store-worker.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-store-worker.ts deleted file mode 100644 index 52a7fa6..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-store-worker.ts +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright 2017 - 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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 { LocalIndexedDBStoreBackend } from "./indexeddb-local-backend"; -import { logger } from "../logger"; - -interface ICmd { - command: string; - seq: number; - args: any[]; -} - -/** - * This class lives in the webworker and drives a LocalIndexedDBStoreBackend - * controlled by messages from the main process. - * - * @example - * It should be instantiated by a web worker script provided by the application - * in a script, for example: - * ``` - * import {IndexedDBStoreWorker} from 'matrix-js-sdk/lib/indexeddb-worker.js'; - * const remoteWorker = new IndexedDBStoreWorker(postMessage); - * onmessage = remoteWorker.onMessage; - * ``` - * - * Note that it is advisable to import this class by referencing the file directly to - * avoid a dependency on the whole js-sdk. - * - */ -export class IndexedDBStoreWorker { - private backend?: LocalIndexedDBStoreBackend; - - /** - * @param postMessage - The web worker postMessage function that - * should be used to communicate back to the main script. - */ - public constructor(private readonly postMessage: InstanceType<typeof Worker>["postMessage"]) {} - - private onClose = (): void => { - this.postMessage.call(null, { - command: "closed", - }); - }; - - /** - * Passes a message event from the main script into the class. This method - * can be directly assigned to the web worker `onmessage` variable. - * - * @param ev - The message event - */ - public onMessage = (ev: MessageEvent): void => { - const msg: ICmd = ev.data; - let prom: Promise<any> | undefined; - - switch (msg.command) { - case "setupWorker": - // this is the 'indexedDB' global (where global != window - // because it's a web worker and there is no window). - this.backend = new LocalIndexedDBStoreBackend(indexedDB, msg.args[0]); - prom = Promise.resolve(); - break; - case "connect": - prom = this.backend?.connect(this.onClose); - break; - case "isNewlyCreated": - prom = this.backend?.isNewlyCreated(); - break; - case "clearDatabase": - prom = this.backend?.clearDatabase(); - break; - case "getSavedSync": - prom = this.backend?.getSavedSync(false); - break; - case "setSyncData": - prom = this.backend?.setSyncData(msg.args[0]); - break; - case "syncToDatabase": - prom = this.backend?.syncToDatabase(msg.args[0]); - break; - case "getUserPresenceEvents": - prom = this.backend?.getUserPresenceEvents(); - break; - case "getNextBatchToken": - prom = this.backend?.getNextBatchToken(); - break; - case "getOutOfBandMembers": - prom = this.backend?.getOutOfBandMembers(msg.args[0]); - break; - case "clearOutOfBandMembers": - prom = this.backend?.clearOutOfBandMembers(msg.args[0]); - break; - case "setOutOfBandMembers": - prom = this.backend?.setOutOfBandMembers(msg.args[0], msg.args[1]); - break; - case "getClientOptions": - prom = this.backend?.getClientOptions(); - break; - case "storeClientOptions": - prom = this.backend?.storeClientOptions(msg.args[0]); - break; - case "saveToDeviceBatches": - prom = this.backend?.saveToDeviceBatches(msg.args[0]); - break; - case "getOldestToDeviceBatch": - prom = this.backend?.getOldestToDeviceBatch(); - break; - case "removeToDeviceBatch": - prom = this.backend?.removeToDeviceBatch(msg.args[0]); - break; - } - - if (prom === undefined) { - this.postMessage({ - command: "cmd_fail", - seq: msg.seq, - // Can't be an Error because they're not structured cloneable - error: "Unrecognised command", - }); - return; - } - - prom.then( - (ret) => { - this.postMessage.call(null, { - command: "cmd_success", - seq: msg.seq, - result: ret, - }); - }, - (err) => { - logger.error("Error running command: " + msg.command, err); - this.postMessage.call(null, { - command: "cmd_fail", - seq: msg.seq, - // Just send a string because Error objects aren't cloneable - error: { - message: err.message, - name: err.name, - }, - }); - }, - ); - }; -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb.ts deleted file mode 100644 index cc77bf9..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb.ts +++ /dev/null @@ -1,383 +0,0 @@ -/* -Copyright 2017 - 2021 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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. -*/ - -/* eslint-disable @babel/no-invalid-this */ - -import { MemoryStore, IOpts as IBaseOpts } from "./memory"; -import { LocalIndexedDBStoreBackend } from "./indexeddb-local-backend"; -import { RemoteIndexedDBStoreBackend } from "./indexeddb-remote-backend"; -import { User } from "../models/user"; -import { IEvent, MatrixEvent } from "../models/event"; -import { logger } from "../logger"; -import { ISavedSync } from "./index"; -import { IIndexedDBBackend } from "./indexeddb-backend"; -import { ISyncResponse } from "../sync-accumulator"; -import { TypedEventEmitter } from "../models/typed-event-emitter"; -import { IStateEventWithRoomId } from "../@types/search"; -import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDeviceMessage"; -import { IStoredClientOpts } from "../client"; - -/** - * This is an internal module. See {@link IndexedDBStore} for the public class. - */ - -// If this value is too small we'll be writing very often which will cause -// noticeable stop-the-world pauses. If this value is too big we'll be writing -// so infrequently that the /sync size gets bigger on reload. Writing more -// often does not affect the length of the pause since the entire /sync -// response is persisted each time. -const WRITE_DELAY_MS = 1000 * 60 * 5; // once every 5 minutes - -interface IOpts extends IBaseOpts { - /** The Indexed DB interface e.g. `window.indexedDB` */ - indexedDB: IDBFactory; - /** Optional database name. The same name must be used to open the same database. */ - dbName?: string; - /** Optional factory to spin up a Worker to execute the IDB transactions within. */ - workerFactory?: () => Worker; -} - -type EventHandlerMap = { - // Fired when an IDB command fails on a degradable path, and the store falls back to MemoryStore - // This signals the potential for data volatility. - degraded: (e: Error) => void; - // Fired when the IndexedDB gets closed unexpectedly, for example, if the underlying storage is removed or - // if the user clears the database in the browser's history preferences. - closed: () => void; -}; - -export class IndexedDBStore extends MemoryStore { - public static exists(indexedDB: IDBFactory, dbName: string): Promise<boolean> { - return LocalIndexedDBStoreBackend.exists(indexedDB, dbName); - } - - /** - * The backend instance. - * Call through to this API if you need to perform specific indexeddb actions like deleting the database. - */ - public readonly backend: IIndexedDBBackend; - - private startedUp = false; - private syncTs = 0; - // Records the last-modified-time of each user at the last point we saved - // the database, such that we can derive the set if users that have been - // modified since we last saved. - private userModifiedMap: Record<string, number> = {}; // user_id : timestamp - private emitter = new TypedEventEmitter<keyof EventHandlerMap, EventHandlerMap>(); - - /** - * Construct a new Indexed Database store, which extends MemoryStore. - * - * This store functions like a MemoryStore except it periodically persists - * the contents of the store to an IndexedDB backend. - * - * All data is still kept in-memory but can be loaded from disk by calling - * `startup()`. This can make startup times quicker as a complete - * sync from the server is not required. This does not reduce memory usage as all - * the data is eagerly fetched when `startup()` is called. - * ``` - * let opts = { indexedDB: window.indexedDB, localStorage: window.localStorage }; - * let store = new IndexedDBStore(opts); - * await store.startup(); // load from indexed db - * let client = sdk.createClient({ - * store: store, - * }); - * client.startClient(); - * client.on("sync", function(state, prevState, data) { - * if (state === "PREPARED") { - * console.log("Started up, now with go faster stripes!"); - * } - * }); - * ``` - * - * @param opts - Options object. - */ - public constructor(opts: IOpts) { - super(opts); - - if (!opts.indexedDB) { - throw new Error("Missing required option: indexedDB"); - } - - if (opts.workerFactory) { - this.backend = new RemoteIndexedDBStoreBackend(opts.workerFactory, opts.dbName); - } else { - this.backend = new LocalIndexedDBStoreBackend(opts.indexedDB, opts.dbName); - } - } - - public on = this.emitter.on.bind(this.emitter); - - /** - * @returns Resolved when loaded from indexed db. - */ - public startup(): Promise<void> { - if (this.startedUp) { - logger.log(`IndexedDBStore.startup: already started`); - return Promise.resolve(); - } - - logger.log(`IndexedDBStore.startup: connecting to backend`); - return this.backend - .connect(this.onClose) - .then(() => { - logger.log(`IndexedDBStore.startup: loading presence events`); - return this.backend.getUserPresenceEvents(); - }) - .then((userPresenceEvents) => { - logger.log(`IndexedDBStore.startup: processing presence events`); - userPresenceEvents.forEach(([userId, rawEvent]) => { - const u = new User(userId); - if (rawEvent) { - u.setPresenceEvent(new MatrixEvent(rawEvent)); - } - this.userModifiedMap[u.userId] = u.getLastModifiedTime(); - this.storeUser(u); - }); - this.startedUp = true; - }); - } - - private onClose = (): void => { - this.emitter.emit("closed"); - }; - - /** - * @returns Promise which resolves with a sync response to restore the - * client state to where it was at the last save, or null if there - * is no saved sync data. - */ - public getSavedSync = this.degradable((): Promise<ISavedSync | null> => { - return this.backend.getSavedSync(); - }, "getSavedSync"); - - /** @returns whether or not the database was newly created in this session. */ - public isNewlyCreated = this.degradable((): Promise<boolean> => { - return this.backend.isNewlyCreated(); - }, "isNewlyCreated"); - - /** - * @returns If there is a saved sync, the nextBatch token - * for this sync, otherwise null. - */ - public getSavedSyncToken = this.degradable((): Promise<string | null> => { - return this.backend.getNextBatchToken(); - }, "getSavedSyncToken"); - - /** - * Delete all data from this store. - * @returns Promise which resolves if the data was deleted from the database. - */ - public deleteAllData = this.degradable((): Promise<void> => { - super.deleteAllData(); - return this.backend.clearDatabase().then( - () => { - logger.log("Deleted indexeddb data."); - }, - (err) => { - logger.error(`Failed to delete indexeddb data: ${err}`); - throw err; - }, - ); - }); - - /** - * Whether this store would like to save its data - * Note that obviously whether the store wants to save or - * not could change between calling this function and calling - * save(). - * - * @returns True if calling save() will actually save - * (at the time this function is called). - */ - public wantsSave(): boolean { - const now = Date.now(); - return now - this.syncTs > WRITE_DELAY_MS; - } - - /** - * Possibly write data to the database. - * - * @param force - True to force a save to happen - * @returns Promise resolves after the write completes - * (or immediately if no write is performed) - */ - public save(force = false): Promise<void> { - if (force || this.wantsSave()) { - return this.reallySave(); - } - return Promise.resolve(); - } - - private reallySave = this.degradable((): Promise<void> => { - this.syncTs = Date.now(); // set now to guard against multi-writes - - // work out changed users (this doesn't handle deletions but you - // can't 'delete' users as they are just presence events). - const userTuples: [userId: string, presenceEvent: Partial<IEvent>][] = []; - for (const u of this.getUsers()) { - if (this.userModifiedMap[u.userId] === u.getLastModifiedTime()) continue; - if (!u.events.presence) continue; - - userTuples.push([u.userId, u.events.presence.event]); - - // note that we've saved this version of the user - this.userModifiedMap[u.userId] = u.getLastModifiedTime(); - } - - return this.backend.syncToDatabase(userTuples); - }); - - public setSyncData = this.degradable((syncData: ISyncResponse): Promise<void> => { - return this.backend.setSyncData(syncData); - }, "setSyncData"); - - /** - * Returns the out-of-band membership events for this room that - * were previously loaded. - * @returns the events, potentially an empty array if OOB loading didn't yield any new members - * @returns in case the members for this room haven't been stored yet - */ - public getOutOfBandMembers = this.degradable((roomId: string): Promise<IStateEventWithRoomId[] | null> => { - return this.backend.getOutOfBandMembers(roomId); - }, "getOutOfBandMembers"); - - /** - * Stores the out-of-band membership events for this room. Note that - * it still makes sense to store an empty array as the OOB status for the room is - * marked as fetched, and getOutOfBandMembers will return an empty array instead of null - * @param membershipEvents - the membership events to store - * @returns when all members have been stored - */ - public setOutOfBandMembers = this.degradable( - (roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> => { - super.setOutOfBandMembers(roomId, membershipEvents); - return this.backend.setOutOfBandMembers(roomId, membershipEvents); - }, - "setOutOfBandMembers", - ); - - public clearOutOfBandMembers = this.degradable((roomId: string) => { - super.clearOutOfBandMembers(roomId); - return this.backend.clearOutOfBandMembers(roomId); - }, "clearOutOfBandMembers"); - - public getClientOptions = this.degradable((): Promise<IStoredClientOpts | undefined> => { - return this.backend.getClientOptions(); - }, "getClientOptions"); - - public storeClientOptions = this.degradable((options: IStoredClientOpts): Promise<void> => { - super.storeClientOptions(options); - return this.backend.storeClientOptions(options); - }, "storeClientOptions"); - - /** - * All member functions of `IndexedDBStore` that access the backend use this wrapper to - * watch for failures after initial store startup, including `QuotaExceededError` as - * free disk space changes, etc. - * - * When IndexedDB fails via any of these paths, we degrade this back to a `MemoryStore` - * in place so that the current operation and all future ones are in-memory only. - * - * @param func - The degradable work to do. - * @param fallback - The method name for fallback. - * @returns A wrapped member function. - */ - private degradable<A extends Array<any>, R = void>( - func: DegradableFn<A, R>, - fallback?: keyof MemoryStore, - ): DegradableFn<A, R> { - const fallbackFn = fallback ? (super[fallback] as Function) : null; - - return async (...args) => { - try { - return await func.call(this, ...args); - } catch (e) { - logger.error("IndexedDBStore failure, degrading to MemoryStore", e); - this.emitter.emit("degraded", e as Error); - try { - // We try to delete IndexedDB after degrading since this store is only a - // cache (the app will still function correctly without the data). - // It's possible that deleting repair IndexedDB for the next app load, - // potentially by making a little more space available. - logger.log("IndexedDBStore trying to delete degraded data"); - await this.backend.clearDatabase(); - logger.log("IndexedDBStore delete after degrading succeeded"); - } catch (e) { - logger.warn("IndexedDBStore delete after degrading failed", e); - } - // Degrade the store from being an instance of `IndexedDBStore` to instead be - // an instance of `MemoryStore` so that future API calls use the memory path - // directly and skip IndexedDB entirely. This should be safe as - // `IndexedDBStore` already extends from `MemoryStore`, so we are making the - // store become its parent type in a way. The mutator methods of - // `IndexedDBStore` also maintain the state that `MemoryStore` uses (many are - // not overridden at all). - if (fallbackFn) { - return fallbackFn.call(this, ...args); - } - } - }; - } - - // XXX: ideally these would be stored in indexeddb as part of the room but, - // we don't store rooms as such and instead accumulate entire sync responses atm. - public async getPendingEvents(roomId: string): Promise<Partial<IEvent>[]> { - if (!this.localStorage) return super.getPendingEvents(roomId); - - const serialized = this.localStorage.getItem(pendingEventsKey(roomId)); - if (serialized) { - try { - return JSON.parse(serialized); - } catch (e) { - logger.error("Could not parse persisted pending events", e); - } - } - return []; - } - - public async setPendingEvents(roomId: string, events: Partial<IEvent>[]): Promise<void> { - if (!this.localStorage) return super.setPendingEvents(roomId, events); - - if (events.length > 0) { - this.localStorage.setItem(pendingEventsKey(roomId), JSON.stringify(events)); - } else { - this.localStorage.removeItem(pendingEventsKey(roomId)); - } - } - - public saveToDeviceBatches(batches: ToDeviceBatchWithTxnId[]): Promise<void> { - return this.backend.saveToDeviceBatches(batches); - } - - public getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> { - return this.backend.getOldestToDeviceBatch(); - } - - public removeToDeviceBatch(id: number): Promise<void> { - return this.backend.removeToDeviceBatch(id); - } -} - -/** - * @param roomId - ID of the current room - * @returns Storage key to retrieve pending events - */ -function pendingEventsKey(roomId: string): string { - return `mx_pending_events_${roomId}`; -} - -type DegradableFn<A extends Array<any>, T> = (...args: A) => Promise<T>; diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/local-storage-events-emitter.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/local-storage-events-emitter.ts deleted file mode 100644 index adb70cb..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/local-storage-events-emitter.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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 { TypedEventEmitter } from "../models/typed-event-emitter"; - -export enum LocalStorageErrors { - Global = "Global", - SetItemError = "setItem", - GetItemError = "getItem", - RemoveItemError = "removeItem", - ClearError = "clear", - QuotaExceededError = "QuotaExceededError", -} - -type EventHandlerMap = { - [LocalStorageErrors.Global]: (error: Error) => void; - [LocalStorageErrors.SetItemError]: (error: Error) => void; - [LocalStorageErrors.GetItemError]: (error: Error) => void; - [LocalStorageErrors.RemoveItemError]: (error: Error) => void; - [LocalStorageErrors.ClearError]: (error: Error) => void; - [LocalStorageErrors.QuotaExceededError]: (error: Error) => void; -}; - -/** - * Used in element-web as a temporary hack to handle all the localStorage errors on the highest level possible - * As of 15.11.2021 (DD/MM/YYYY) we're not properly handling local storage exceptions anywhere. - * This store, as an event emitter, is used to re-emit local storage exceptions so that we can handle them - * and show some kind of a "It's dead Jim" modal to the users, telling them that hey, - * maybe you should check out your disk, as it's probably dying and your session may die with it. - * See: https://github.com/vector-im/element-web/issues/18423 - */ -class LocalStorageErrorsEventsEmitter extends TypedEventEmitter<LocalStorageErrors, EventHandlerMap> {} -export const localStorageErrorsEventsEmitter = new LocalStorageErrorsEventsEmitter(); diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/memory.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/memory.ts deleted file mode 100644 index d859ddd..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/memory.ts +++ /dev/null @@ -1,436 +0,0 @@ -/* -Copyright 2015 - 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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. -*/ - -/** - * This is an internal module. See {@link MemoryStore} for the public class. - */ - -import { EventType } from "../@types/event"; -import { Room } from "../models/room"; -import { User } from "../models/user"; -import { IEvent, MatrixEvent } from "../models/event"; -import { RoomState, RoomStateEvent } from "../models/room-state"; -import { RoomMember } from "../models/room-member"; -import { Filter } from "../filter"; -import { ISavedSync, IStore } from "./index"; -import { RoomSummary } from "../models/room-summary"; -import { ISyncResponse } from "../sync-accumulator"; -import { IStateEventWithRoomId } from "../@types/search"; -import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDeviceMessage"; -import { IStoredClientOpts } from "../client"; -import { MapWithDefault } from "../utils"; - -function isValidFilterId(filterId?: string | number | null): boolean { - const isValidStr = - typeof filterId === "string" && - !!filterId && - filterId !== "undefined" && // exclude these as we've serialized undefined in localStorage before - filterId !== "null"; - - return isValidStr || typeof filterId === "number"; -} - -export interface IOpts { - /** The local storage instance to persist some forms of data such as tokens. Rooms will NOT be stored. */ - localStorage?: Storage; -} - -export class MemoryStore implements IStore { - private rooms: Record<string, Room> = {}; // roomId: Room - private users: Record<string, User> = {}; // userId: User - private syncToken: string | null = null; - // userId: { - // filterId: Filter - // } - private filters: MapWithDefault<string, Map<string, Filter>> = new MapWithDefault(() => new Map()); - public accountData: Map<string, MatrixEvent> = new Map(); // type: content - protected readonly localStorage?: Storage; - private oobMembers: Map<string, IStateEventWithRoomId[]> = new Map(); // roomId: [member events] - private pendingEvents: { [roomId: string]: Partial<IEvent>[] } = {}; - private clientOptions?: IStoredClientOpts; - private pendingToDeviceBatches: IndexedToDeviceBatch[] = []; - private nextToDeviceBatchId = 0; - - /** - * Construct a new in-memory data store for the Matrix Client. - * @param opts - Config options - */ - public constructor(opts: IOpts = {}) { - this.localStorage = opts.localStorage; - } - - /** - * Retrieve the token to stream from. - * @returns The token or null. - */ - public getSyncToken(): string | null { - return this.syncToken; - } - - /** @returns whether or not the database was newly created in this session. */ - public isNewlyCreated(): Promise<boolean> { - return Promise.resolve(true); - } - - /** - * Set the token to stream from. - * @param token - The token to stream from. - */ - public setSyncToken(token: string): void { - this.syncToken = token; - } - - /** - * Store the given room. - * @param room - The room to be stored. All properties must be stored. - */ - public storeRoom(room: Room): void { - this.rooms[room.roomId] = room; - // add listeners for room member changes so we can keep the room member - // map up-to-date. - room.currentState.on(RoomStateEvent.Members, this.onRoomMember); - // add existing members - room.currentState.getMembers().forEach((m) => { - this.onRoomMember(null, room.currentState, m); - }); - } - - /** - * Called when a room member in a room being tracked by this store has been - * updated. - */ - private onRoomMember = (event: MatrixEvent | null, state: RoomState, member: RoomMember): void => { - if (member.membership === "invite") { - // We do NOT add invited members because people love to typo user IDs - // which would then show up in these lists (!) - return; - } - - const user = this.users[member.userId] || new User(member.userId); - if (member.name) { - user.setDisplayName(member.name); - if (member.events.member) { - user.setRawDisplayName(member.events.member.getDirectionalContent().displayname); - } - } - if (member.events.member && member.events.member.getContent().avatar_url) { - user.setAvatarUrl(member.events.member.getContent().avatar_url); - } - this.users[user.userId] = user; - }; - - /** - * Retrieve a room by its' room ID. - * @param roomId - The room ID. - * @returns The room or null. - */ - public getRoom(roomId: string): Room | null { - return this.rooms[roomId] || null; - } - - /** - * Retrieve all known rooms. - * @returns A list of rooms, which may be empty. - */ - public getRooms(): Room[] { - return Object.values(this.rooms); - } - - /** - * Permanently delete a room. - */ - public removeRoom(roomId: string): void { - if (this.rooms[roomId]) { - this.rooms[roomId].currentState.removeListener(RoomStateEvent.Members, this.onRoomMember); - } - delete this.rooms[roomId]; - } - - /** - * Retrieve a summary of all the rooms. - * @returns A summary of each room. - */ - public getRoomSummaries(): RoomSummary[] { - return Object.values(this.rooms).map(function (room) { - return room.summary!; - }); - } - - /** - * Store a User. - * @param user - The user to store. - */ - public storeUser(user: User): void { - this.users[user.userId] = user; - } - - /** - * Retrieve a User by its' user ID. - * @param userId - The user ID. - * @returns The user or null. - */ - public getUser(userId: string): User | null { - return this.users[userId] || null; - } - - /** - * Retrieve all known users. - * @returns A list of users, which may be empty. - */ - public getUsers(): User[] { - return Object.values(this.users); - } - - /** - * Retrieve scrollback for this room. - * @param room - The matrix room - * @param limit - The max number of old events to retrieve. - * @returns An array of objects which will be at most 'limit' - * length and at least 0. The objects are the raw event JSON. - */ - public scrollback(room: Room, limit: number): MatrixEvent[] { - return []; - } - - /** - * Store events for a room. The events have already been added to the timeline - * @param room - The room to store events for. - * @param events - The events to store. - * @param token - The token associated with these events. - * @param toStart - True if these are paginated results. - */ - public storeEvents(room: Room, events: MatrixEvent[], token: string | null, toStart: boolean): void { - // no-op because they've already been added to the room instance. - } - - /** - * Store a filter. - */ - public storeFilter(filter: Filter): void { - if (!filter?.userId || !filter?.filterId) return; - this.filters.getOrCreate(filter.userId).set(filter.filterId, filter); - } - - /** - * Retrieve a filter. - * @returns A filter or null. - */ - public getFilter(userId: string, filterId: string): Filter | null { - return this.filters.get(userId)?.get(filterId) || null; - } - - /** - * Retrieve a filter ID with the given name. - * @param filterName - The filter name. - * @returns The filter ID or null. - */ - public getFilterIdByName(filterName: string): string | null { - if (!this.localStorage) { - return null; - } - const key = "mxjssdk_memory_filter_" + filterName; - // XXX Storage.getItem doesn't throw ... - // or are we using something different - // than window.localStorage in some cases - // that does throw? - // that would be very naughty - try { - const value = this.localStorage.getItem(key); - if (isValidFilterId(value)) { - return value; - } - } catch (e) {} - return null; - } - - /** - * Set a filter name to ID mapping. - */ - public setFilterIdByName(filterName: string, filterId?: string): void { - if (!this.localStorage) { - return; - } - const key = "mxjssdk_memory_filter_" + filterName; - try { - if (isValidFilterId(filterId)) { - this.localStorage.setItem(key, filterId!); - } else { - this.localStorage.removeItem(key); - } - } catch (e) {} - } - - /** - * Store user-scoped account data events. - * N.B. that account data only allows a single event per type, so multiple - * events with the same type will replace each other. - * @param events - The events to store. - */ - public storeAccountDataEvents(events: MatrixEvent[]): void { - events.forEach((event) => { - // MSC3391: an event with content of {} should be interpreted as deleted - const isDeleted = !Object.keys(event.getContent()).length; - if (isDeleted) { - this.accountData.delete(event.getType()); - } else { - this.accountData.set(event.getType(), event); - } - }); - } - - /** - * Get account data event by event type - * @param eventType - The event type being queried - * @returns the user account_data event of given type, if any - */ - public getAccountData(eventType: EventType | string): MatrixEvent | undefined { - return this.accountData.get(eventType); - } - - /** - * setSyncData does nothing as there is no backing data store. - * - * @param syncData - The sync data - * @returns An immediately resolved promise. - */ - public setSyncData(syncData: ISyncResponse): Promise<void> { - return Promise.resolve(); - } - - /** - * We never want to save becase we have nothing to save to. - * - * @returns If the store wants to save - */ - public wantsSave(): boolean { - return false; - } - - /** - * Save does nothing as there is no backing data store. - * @param force - True to force a save (but the memory - * store still can't save anything) - */ - public save(force: boolean): void {} - - /** - * Startup does nothing as this store doesn't require starting up. - * @returns An immediately resolved promise. - */ - public startup(): Promise<void> { - return Promise.resolve(); - } - - /** - * @returns Promise which resolves with a sync response to restore the - * client state to where it was at the last save, or null if there - * is no saved sync data. - */ - public getSavedSync(): Promise<ISavedSync | null> { - return Promise.resolve(null); - } - - /** - * @returns If there is a saved sync, the nextBatch token - * for this sync, otherwise null. - */ - public getSavedSyncToken(): Promise<string | null> { - return Promise.resolve(null); - } - - /** - * Delete all data from this store. - * @returns An immediately resolved promise. - */ - public deleteAllData(): Promise<void> { - this.rooms = { - // roomId: Room - }; - this.users = { - // userId: User - }; - this.syncToken = null; - this.filters = new MapWithDefault(() => new Map()); - this.accountData = new Map(); // type : content - return Promise.resolve(); - } - - /** - * Returns the out-of-band membership events for this room that - * were previously loaded. - * @returns the events, potentially an empty array if OOB loading didn't yield any new members - * @returns in case the members for this room haven't been stored yet - */ - public getOutOfBandMembers(roomId: string): Promise<IStateEventWithRoomId[] | null> { - return Promise.resolve(this.oobMembers.get(roomId) || null); - } - - /** - * Stores the out-of-band membership events for this room. Note that - * it still makes sense to store an empty array as the OOB status for the room is - * marked as fetched, and getOutOfBandMembers will return an empty array instead of null - * @param membershipEvents - the membership events to store - * @returns when all members have been stored - */ - public setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> { - this.oobMembers.set(roomId, membershipEvents); - return Promise.resolve(); - } - - public clearOutOfBandMembers(roomId: string): Promise<void> { - this.oobMembers.delete(roomId); - return Promise.resolve(); - } - - public getClientOptions(): Promise<IStoredClientOpts | undefined> { - return Promise.resolve(this.clientOptions); - } - - public storeClientOptions(options: IStoredClientOpts): Promise<void> { - this.clientOptions = Object.assign({}, options); - return Promise.resolve(); - } - - public async getPendingEvents(roomId: string): Promise<Partial<IEvent>[]> { - return this.pendingEvents[roomId] ?? []; - } - - public async setPendingEvents(roomId: string, events: Partial<IEvent>[]): Promise<void> { - this.pendingEvents[roomId] = events; - } - - public saveToDeviceBatches(batches: ToDeviceBatchWithTxnId[]): Promise<void> { - for (const batch of batches) { - this.pendingToDeviceBatches.push({ - id: this.nextToDeviceBatchId++, - eventType: batch.eventType, - txnId: batch.txnId, - batch: batch.batch, - }); - } - return Promise.resolve(); - } - - public async getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> { - if (this.pendingToDeviceBatches.length === 0) return null; - return this.pendingToDeviceBatches[0]; - } - - public removeToDeviceBatch(id: number): Promise<void> { - this.pendingToDeviceBatches = this.pendingToDeviceBatches.filter((batch) => batch.id !== id); - return Promise.resolve(); - } -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/stub.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/store/stub.ts deleted file mode 100644 index e4402ed..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/store/stub.ts +++ /dev/null @@ -1,267 +0,0 @@ -/* -Copyright 2015 - 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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. -*/ - -/** - * This is an internal module. - */ - -import { EventType } from "../@types/event"; -import { Room } from "../models/room"; -import { User } from "../models/user"; -import { IEvent, MatrixEvent } from "../models/event"; -import { Filter } from "../filter"; -import { ISavedSync, IStore } from "./index"; -import { RoomSummary } from "../models/room-summary"; -import { ISyncResponse } from "../sync-accumulator"; -import { IStateEventWithRoomId } from "../@types/search"; -import { IndexedToDeviceBatch, ToDeviceBatch } from "../models/ToDeviceMessage"; -import { IStoredClientOpts } from "../client"; - -/** - * Construct a stub store. This does no-ops on most store methods. - */ -export class StubStore implements IStore { - public readonly accountData = new Map(); // stub - private fromToken: string | null = null; - - /** @returns whether or not the database was newly created in this session. */ - public isNewlyCreated(): Promise<boolean> { - return Promise.resolve(true); - } - - /** - * Get the sync token. - */ - public getSyncToken(): string | null { - return this.fromToken; - } - - /** - * Set the sync token. - */ - public setSyncToken(token: string): void { - this.fromToken = token; - } - - /** - * No-op. - */ - public storeRoom(room: Room): void {} - - /** - * No-op. - */ - public getRoom(roomId: string): Room | null { - return null; - } - - /** - * No-op. - * @returns An empty array. - */ - public getRooms(): Room[] { - return []; - } - - /** - * Permanently delete a room. - */ - public removeRoom(roomId: string): void { - return; - } - - /** - * No-op. - * @returns An empty array. - */ - public getRoomSummaries(): RoomSummary[] { - return []; - } - - /** - * No-op. - */ - public storeUser(user: User): void {} - - /** - * No-op. - */ - public getUser(userId: string): User | null { - return null; - } - - /** - * No-op. - */ - public getUsers(): User[] { - return []; - } - - /** - * No-op. - */ - public scrollback(room: Room, limit: number): MatrixEvent[] { - return []; - } - - /** - * Store events for a room. - * @param room - The room to store events for. - * @param events - The events to store. - * @param token - The token associated with these events. - * @param toStart - True if these are paginated results. - */ - public storeEvents(room: Room, events: MatrixEvent[], token: string | null, toStart: boolean): void {} - - /** - * Store a filter. - */ - public storeFilter(filter: Filter): void {} - - /** - * Retrieve a filter. - * @returns A filter or null. - */ - public getFilter(userId: string, filterId: string): Filter | null { - return null; - } - - /** - * Retrieve a filter ID with the given name. - * @param filterName - The filter name. - * @returns The filter ID or null. - */ - public getFilterIdByName(filterName: string): string | null { - return null; - } - - /** - * Set a filter name to ID mapping. - */ - public setFilterIdByName(filterName: string, filterId?: string): void {} - - /** - * Store user-scoped account data events - * @param events - The events to store. - */ - public storeAccountDataEvents(events: MatrixEvent[]): void {} - - /** - * Get account data event by event type - * @param eventType - The event type being queried - */ - public getAccountData(eventType: EventType | string): MatrixEvent | undefined { - return undefined; - } - - /** - * setSyncData does nothing as there is no backing data store. - * - * @param syncData - The sync data - * @returns An immediately resolved promise. - */ - public setSyncData(syncData: ISyncResponse): Promise<void> { - return Promise.resolve(); - } - - /** - * We never want to save because we have nothing to save to. - * - * @returns If the store wants to save - */ - public wantsSave(): boolean { - return false; - } - - /** - * Save does nothing as there is no backing data store. - */ - public save(): void {} - - /** - * Startup does nothing. - * @returns An immediately resolved promise. - */ - public startup(): Promise<void> { - return Promise.resolve(); - } - - /** - * @returns Promise which resolves with a sync response to restore the - * client state to where it was at the last save, or null if there - * is no saved sync data. - */ - public getSavedSync(): Promise<ISavedSync | null> { - return Promise.resolve(null); - } - - /** - * @returns If there is a saved sync, the nextBatch token - * for this sync, otherwise null. - */ - public getSavedSyncToken(): Promise<string | null> { - return Promise.resolve(null); - } - - /** - * Delete all data from this store. Does nothing since this store - * doesn't store anything. - * @returns An immediately resolved promise. - */ - public deleteAllData(): Promise<void> { - return Promise.resolve(); - } - - public getOutOfBandMembers(): Promise<IStateEventWithRoomId[] | null> { - return Promise.resolve(null); - } - - public setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> { - return Promise.resolve(); - } - - public clearOutOfBandMembers(): Promise<void> { - return Promise.resolve(); - } - - public getClientOptions(): Promise<IStoredClientOpts | undefined> { - return Promise.resolve(undefined); - } - - public storeClientOptions(options: IStoredClientOpts): Promise<void> { - return Promise.resolve(); - } - - public async getPendingEvents(roomId: string): Promise<Partial<IEvent>[]> { - return []; - } - - public setPendingEvents(roomId: string, events: Partial<IEvent>[]): Promise<void> { - return Promise.resolve(); - } - - public async saveToDeviceBatches(batch: ToDeviceBatch[]): Promise<void> { - return Promise.resolve(); - } - - public getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> { - return Promise.resolve(null); - } - - public async removeToDeviceBatch(id: number): Promise<void> { - return Promise.resolve(); - } -} |