summaryrefslogtreecommitdiff
path: root/includes/external/matrix/node_modules/matrix-js-sdk/src/store
diff options
context:
space:
mode:
authorRaindropsSys <raindrops@equestria.dev>2023-11-17 23:25:29 +0100
committerRaindropsSys <raindrops@equestria.dev>2023-11-17 23:25:29 +0100
commit953ddd82e48dd206cef5ac94456549aed13b3ad5 (patch)
tree8f003106ee2e7f422e5a22d2ee04d0db302e66c0 /includes/external/matrix/node_modules/matrix-js-sdk/src/store
parent62a9199846b0c07c03218703b33e8385764f42d9 (diff)
downloadpluralconnect-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')
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/index.ts248
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-backend.ts40
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-local-backend.ts597
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-remote-backend.ts203
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb-store-worker.ts157
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/indexeddb.ts383
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/local-storage-events-emitter.ts46
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/memory.ts436
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/store/stub.ts267
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();
- }
-}