diff --git a/.eslintrc.js b/.eslintrc.js index 918ae4365..3059df17f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -85,5 +85,14 @@ module.exports = { // We use a `logger` intermediary module "no-console": "error", }, + }, { + files: [ + "spec/**/*.ts", + ], + rules: { + // We don't need super strict typing in test utilities + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-member-accessibility": "off", + }, }], }; diff --git a/package.json b/package.json index fa89996e6..46a062cc8 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "eslint-config-google": "^0.14.0", "eslint-import-resolver-typescript": "^3.5.1", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-matrix-org": "^0.7.0", + "eslint-plugin-matrix-org": "^0.8.0", "eslint-plugin-unicorn": "^44.0.2", "exorcist": "^2.0.0", "fake-indexeddb": "^4.0.0", diff --git a/spec/integ/matrix-client-syncing.spec.ts b/spec/integ/matrix-client-syncing.spec.ts index 216fbdbb1..8c3969bee 100644 --- a/spec/integ/matrix-client-syncing.spec.ts +++ b/spec/integ/matrix-client-syncing.spec.ts @@ -709,11 +709,11 @@ describe("MatrixClient syncing", () => { const room = client!.getRoom(roomOne)!; const stateAtStart = room.getLiveTimeline().getState(EventTimeline.BACKWARDS)!; const startRoomNameEvent = stateAtStart.getStateEvents('m.room.name', ''); - expect(startRoomNameEvent.getContent().name).toEqual('Old room name'); + expect(startRoomNameEvent!.getContent().name).toEqual('Old room name'); const stateAtEnd = room.getLiveTimeline().getState(EventTimeline.FORWARDS)!; const endRoomNameEvent = stateAtEnd.getStateEvents('m.room.name', ''); - expect(endRoomNameEvent.getContent().name).toEqual('A new room name'); + expect(endRoomNameEvent!.getContent().name).toEqual('A new room name'); }); }); @@ -1599,7 +1599,7 @@ describe("MatrixClient syncing", () => { expect(room.roomId).toBe(roomOne); expect(room.getMyMembership()).toBe("leave"); expect(room.name).toBe("Room Name"); - expect(room.currentState.getStateEvents("m.room.name", "").getId()).toBe("$eventId"); + expect(room.currentState.getStateEvents("m.room.name", "")?.getId()).toBe("$eventId"); expect(room.timeline[0].getContent().body).toBe("Message 1"); expect(room.timeline[1].getContent().body).toBe("Message 2"); client?.stopPeeking(); diff --git a/spec/unit/embedded.spec.ts b/spec/unit/embedded.spec.ts index 436909be7..3e0ead871 100644 --- a/spec/unit/embedded.spec.ts +++ b/spec/unit/embedded.spec.ts @@ -179,7 +179,7 @@ describe("RoomWidgetClient", () => { // It should've also inserted the event into the room object const room = client.getRoom("!1:example.org"); expect(room).not.toBeNull(); - expect(room!.currentState.getStateEvents("org.example.foo", "bar").getEffectiveEvent()).toEqual(event); + expect(room!.currentState.getStateEvents("org.example.foo", "bar")?.getEffectiveEvent()).toEqual(event); }); it("backfills", async () => { @@ -195,7 +195,7 @@ describe("RoomWidgetClient", () => { const room = client.getRoom("!1:example.org"); expect(room).not.toBeNull(); - expect(room!.currentState.getStateEvents("org.example.foo", "bar").getEffectiveEvent()).toEqual(event); + expect(room!.currentState.getStateEvents("org.example.foo", "bar")?.getEffectiveEvent()).toEqual(event); }); }); diff --git a/spec/unit/room-state.spec.ts b/spec/unit/room-state.spec.ts index 5ee44f611..1ac3721a1 100644 --- a/spec/unit/room-state.spec.ts +++ b/spec/unit/room-state.spec.ts @@ -152,7 +152,7 @@ describe("RoomState", function() { it("should return a single MatrixEvent if a state_key was specified", function() { const event = state.getStateEvents("m.room.member", userA); - expect(event.getContent()).toMatchObject({ + expect(event?.getContent()).toMatchObject({ membership: "join", }); }); diff --git a/src/ReEmitter.ts b/src/ReEmitter.ts index 6822e3d1e..2fa6eface 100644 --- a/src/ReEmitter.ts +++ b/src/ReEmitter.ts @@ -22,7 +22,7 @@ import { EventEmitter } from "events"; import { ListenerMap, TypedEventEmitter } from "./models/typed-event-emitter"; export class ReEmitter { - constructor(private readonly target: EventEmitter) {} + public constructor(private readonly target: EventEmitter) {} // Map from emitter to event name to re-emitter private reEmitters = new Map void>>(); @@ -38,7 +38,7 @@ export class ReEmitter { // We include the source as the last argument for event handlers which may need it, // such as read receipt listeners on the client class which won't have the context // of the room. - const forSource = (...args: any[]) => { + const forSource = (...args: any[]): void => { // EventEmitter special cases 'error' to make the emit function throw if no // handler is attached, which sort of makes sense for making sure that something // handles an error, but for re-emitting, there could be a listener on the original @@ -74,7 +74,7 @@ export class TypedReEmitter< Events extends string, Arguments extends ListenerMap, > extends ReEmitter { - constructor(target: TypedEventEmitter) { + public constructor(target: TypedEventEmitter) { super(target); } diff --git a/src/ToDeviceMessageQueue.ts b/src/ToDeviceMessageQueue.ts index 815927679..0b5b1786a 100644 --- a/src/ToDeviceMessageQueue.ts +++ b/src/ToDeviceMessageQueue.ts @@ -31,7 +31,7 @@ export class ToDeviceMessageQueue { private retryTimeout: ReturnType | null = null; private retryAttempts = 0; - constructor(private client: MatrixClient) { + public constructor(private client: MatrixClient) { } public start(): void { diff --git a/src/client.ts b/src/client.ts index a3b44dfa0..c38160c53 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1010,7 +1010,7 @@ export class MatrixClient extends TypedEventEmitter { + this.clientOpts.canResetEntireTimeline = (roomId): boolean => { if (!this.canResetTimelineCallback) { return false; } @@ -1259,7 +1259,7 @@ export class MatrixClient extends TypedEventEmitter * @param {boolean} guest True if this is a guest account. */ - public setGuest(guest: boolean) { + public setGuest(guest: boolean): void { // EXPERIMENTAL: // If the token is a macaroon, it should be encoded in it that it is a 'guest' // access token, which means that the SDK can determine this entirely without @@ -1721,7 +1721,7 @@ export class MatrixClient extends TypedEventEmitter { if (!this.crypto) { throw new Error("End-to-end encryption disabled"); } @@ -2352,11 +2352,11 @@ export class MatrixClient extends TypedEventEmitter { if (!this.crypto) { throw new Error("End-to-end encryption disabled"); } @@ -2575,7 +2575,7 @@ export class MatrixClient extends TypedEventEmitter { if (!this.crypto) { throw new Error("End-to-end encryption disabled"); } @@ -2716,7 +2716,7 @@ export class MatrixClient extends TypedEventEmitter { if (!this.crypto) { throw new Error("End-to-end encryption disabled"); } @@ -3401,7 +3401,7 @@ export class MatrixClient extends TypedEventEmitter { if (!this.crypto) { throw new Error("End-to-end encryption disabled"); } @@ -3685,7 +3685,7 @@ export class MatrixClient extends TypedEventEmitter { return this.unstable_setLiveBeacon(roomId, beaconInfoContent); } @@ -3849,7 +3849,7 @@ export class MatrixClient extends TypedEventEmitter { return this.sendStateEvent(roomId, M_BEACON_INFO.name, beaconInfoContent, this.getUserId()!); } @@ -4121,7 +4121,7 @@ export class MatrixClient extends TypedEventEmitter[] = []; - const doLeave = (roomId: string) => { + const doLeave = (roomId: string): Promise => { return this.leave(roomId).then(() => { delete populationResults[roomId]; }).catch((err) => { + // suppress error populationResults[roomId] = err; - return null; // suppress error }); }; @@ -5904,7 +5904,7 @@ export class MatrixClient extends TypedEventEmitter) { + function intersect(s: Record): void { for (const k of Object.keys(stored)) { if (!s[k]) { delete stored[k]; @@ -586,7 +586,14 @@ export class CrossSigningInfo { } } -function deviceToObject(device: DeviceInfo, userId: string) { +interface DeviceObject extends IObject { + algorithms: string[]; + keys: Record; + device_id: string; + user_id: string; +} + +function deviceToObject(device: DeviceInfo, userId: string): DeviceObject { return { algorithms: device.algorithms, keys: device.keys, @@ -606,7 +613,7 @@ export enum CrossSigningLevel { * Represents the ways in which we trust a user */ export class UserTrustLevel { - constructor( + public constructor( private readonly crossSigningVerified: boolean, private readonly crossSigningVerifiedBefore: boolean, private readonly tofu: boolean, @@ -646,7 +653,7 @@ export class UserTrustLevel { * Represents the ways in which we trust a device */ export class DeviceTrustLevel { - constructor( + public constructor( public readonly crossSigningVerified: boolean, public readonly tofu: boolean, private readonly localVerified: boolean, @@ -775,7 +782,7 @@ export async function requestKeysDuringVerification( // CrossSigningInfo.getCrossSigningKey() to validate/cache const crossSigning = new CrossSigningInfo( original.userId, - { getCrossSigningKey: async (type) => { + { getCrossSigningKey: async (type): Promise => { logger.debug("Cross-signing: requesting secret", type, deviceId); const { promise } = client.requestSecret( `m.cross_signing.${type}`, [deviceId], @@ -801,7 +808,7 @@ export async function requestKeysDuringVerification( }); // also request and cache the key backup key - const backupKeyPromise = (async () => { + const backupKeyPromise = (async (): Promise => { const cachedKey = await client.crypto!.getSessionBackupPrivateKey(); if (!cachedKey) { logger.info("No cached backup key found. Requesting..."); diff --git a/src/crypto/DeviceList.ts b/src/crypto/DeviceList.ts index c4345437c..da40a03f2 100644 --- a/src/crypto/DeviceList.ts +++ b/src/crypto/DeviceList.ts @@ -102,7 +102,7 @@ export class DeviceList extends TypedEventEmitter { await this.cryptoStore.doTxn( 'readonly', [IndexedDBCryptoStore.STORE_DEVICE_DATA], (txn) => { this.cryptoStore.getEndToEndDeviceData(txn, (deviceData) => { @@ -150,7 +150,7 @@ export class DeviceList extends TypedEventEmitter} accountData pre-existing account data, will only be read, not written. * @param {CryptoCallbacks} delegateCryptoCallbacks crypto callbacks to delegate to if the key isn't in cache yet */ - constructor(accountData: Record, delegateCryptoCallbacks?: ICryptoCallbacks) { + public constructor(accountData: Record, delegateCryptoCallbacks?: ICryptoCallbacks) { this.accountDataClientAdapter = new AccountDataClientAdapter(accountData); this.crossSigningCallbacks = new CrossSigningCallbacks(); this.ssssCryptoCallbacks = new SSSSCryptoCallbacks(delegateCryptoCallbacks); @@ -192,7 +192,7 @@ export class EncryptionSetupOperation { * @param {Object} keyBackupInfo * @param {Object} keySignatures */ - constructor( + public constructor( private readonly accountData: Map, private readonly crossSigningKeys?: ICrossSigningKeys, private readonly keyBackupInfo?: IKeyBackupInfo, @@ -272,7 +272,7 @@ class AccountDataClientAdapter /** * @param {Object.} existingValues existing account data */ - constructor(private readonly existingValues: Record) { + public constructor(private readonly existingValues: Record) { super(); } @@ -342,7 +342,7 @@ class CrossSigningCallbacks implements ICryptoCallbacks, ICacheCallbacks { return Promise.resolve(this.privateKeys.get(type) ?? null); } - public saveCrossSigningKeys(privateKeys: Record) { + public saveCrossSigningKeys(privateKeys: Record): void { for (const [type, privateKey] of Object.entries(privateKeys)) { this.privateKeys.set(type, privateKey); } @@ -356,7 +356,7 @@ class CrossSigningCallbacks implements ICryptoCallbacks, ICacheCallbacks { class SSSSCryptoCallbacks { private readonly privateKeys = new Map(); - constructor(private readonly delegateCryptoCallbacks?: ICryptoCallbacks) {} + public constructor(private readonly delegateCryptoCallbacks?: ICryptoCallbacks) {} public async getSecretStorageKey( { keys }: { keys: Record }, diff --git a/src/crypto/OlmDevice.ts b/src/crypto/OlmDevice.ts index 84eec463c..efa34ad41 100644 --- a/src/crypto/OlmDevice.ts +++ b/src/crypto/OlmDevice.ts @@ -177,13 +177,13 @@ export class OlmDevice { // Used by olm to serialise prekey message decryptions public olmPrekeyPromise: Promise = Promise.resolve(); // set by consumers - constructor(private readonly cryptoStore: CryptoStore) { + public constructor(private readonly cryptoStore: CryptoStore) { } /** * @return {array} The version of Olm. */ - static getOlmVersion(): [number, number, number] { + public static getOlmVersion(): [number, number, number] { return global.Olm.get_library_version(); } @@ -1515,7 +1515,9 @@ export class OlmDevice { }); } - async getSharedHistoryInboundGroupSessions(roomId: string): Promise<[senderKey: string, sessionId: string][]> { + public async getSharedHistoryInboundGroupSessions( + roomId: string, + ): Promise<[senderKey: string, sessionId: string][]> { let result: Promise<[senderKey: string, sessionId: string][]>; await this.cryptoStore.doTxn( 'readonly', [ diff --git a/src/crypto/OutgoingRoomKeyRequestManager.ts b/src/crypto/OutgoingRoomKeyRequestManager.ts index d5d1c3003..427234347 100644 --- a/src/crypto/OutgoingRoomKeyRequestManager.ts +++ b/src/crypto/OutgoingRoomKeyRequestManager.ts @@ -102,7 +102,7 @@ export class OutgoingRoomKeyRequestManager { private clientRunning = true; - constructor( + public constructor( private readonly baseApis: MatrixClient, private readonly deviceId: string, private readonly cryptoStore: CryptoStore, @@ -352,7 +352,7 @@ export class OutgoingRoomKeyRequestManager { return; } - const startSendingOutgoingRoomKeyRequests = () => { + const startSendingOutgoingRoomKeyRequests = (): void => { if (this.sendOutgoingRoomKeyRequestsRunning) { throw new Error("RoomKeyRequestSend already in progress!"); } diff --git a/src/crypto/RoomList.ts b/src/crypto/RoomList.ts index f0e09b657..672ef473c 100644 --- a/src/crypto/RoomList.ts +++ b/src/crypto/RoomList.ts @@ -38,7 +38,7 @@ export class RoomList { // Object of roomId -> room e2e info object (body of the m.room.encryption event) private roomEncryption: Record = {}; - constructor(private readonly cryptoStore?: CryptoStore) {} + public constructor(private readonly cryptoStore?: CryptoStore) {} public async init(): Promise { await this.cryptoStore!.doTxn( diff --git a/src/crypto/SecretStorage.ts b/src/crypto/SecretStorage.ts index d1d6285fc..5c13ba4b0 100644 --- a/src/crypto/SecretStorage.ts +++ b/src/crypto/SecretStorage.ts @@ -78,7 +78,7 @@ export class SecretStorage { // as you don't request any secrets. // A better solution would probably be to split this class up into secret storage and // secret sharing which are really two separate things, even though they share an MSC. - constructor( + public constructor( private readonly accountDataAdapter: IAccountDataClient, private readonly cryptoCallbacks: ICryptoCallbacks, private readonly baseApis: B, @@ -381,7 +381,7 @@ export class SecretStorage { const deferred = defer(); this.requests.set(requestId, { name, devices, deferred }); - const cancel = (reason: string) => { + const cancel = (reason: string): void => { // send cancellation event const cancelData = { action: "request_cancellation", diff --git a/src/crypto/algorithms/base.ts b/src/crypto/algorithms/base.ts index 190bfa437..d6c70bc10 100644 --- a/src/crypto/algorithms/base.ts +++ b/src/crypto/algorithms/base.ts @@ -78,7 +78,7 @@ export abstract class EncryptionAlgorithm { protected readonly baseApis: MatrixClient; protected readonly roomId?: string; - constructor(params: IParams) { + public constructor(params: IParams) { this.userId = params.userId; this.deviceId = params.deviceId; this.crypto = params.crypto; @@ -150,7 +150,7 @@ export abstract class DecryptionAlgorithm { protected readonly baseApis: MatrixClient; protected readonly roomId?: string; - constructor(params: DecryptionClassParams) { + public constructor(params: DecryptionClassParams) { this.userId = params.userId; this.crypto = params.crypto; this.olmDevice = params.olmDevice; @@ -242,7 +242,7 @@ export abstract class DecryptionAlgorithm { export class DecryptionError extends Error { public readonly detailedString: string; - constructor(public readonly code: string, msg: string, details?: Record) { + public constructor(public readonly code: string, msg: string, details?: Record) { super(msg); this.code = code; this.name = 'DecryptionError'; @@ -272,7 +272,7 @@ function detailedStringForDecryptionError(err: DecryptionError, details?: Record * @extends Error */ export class UnknownDeviceError extends Error { - constructor( + public constructor( msg: string, public readonly devices: Record>, public event?: MatrixEvent, diff --git a/src/crypto/algorithms/megolm.ts b/src/crypto/algorithms/megolm.ts index dd53bfa05..cbad327a6 100644 --- a/src/crypto/algorithms/megolm.ts +++ b/src/crypto/algorithms/megolm.ts @@ -136,7 +136,7 @@ class OutboundSessionInfo { public sharedWithDevices: Record> = {}; public blockedDevicesNotified: Record> = {}; - constructor(public readonly sessionId: string, public readonly sharedHistory = false) { + public constructor(public readonly sessionId: string, public readonly sharedHistory = false) { this.creationTime = new Date().getTime(); } @@ -248,7 +248,7 @@ class MegolmEncryption extends EncryptionAlgorithm { protected readonly roomId: string; - constructor(params: IParams & Required>) { + public constructor(params: IParams & Required>) { super(params); this.roomId = params.roomId; @@ -347,7 +347,7 @@ class MegolmEncryption extends EncryptionAlgorithm { singleOlmCreationPhase: boolean, blocked: IBlockedMap, session: OutboundSessionInfo, - ) { + ): Promise { // now check if we need to share with any devices const shareMap: Record = {}; @@ -386,13 +386,13 @@ class MegolmEncryption extends EncryptionAlgorithm { ); await Promise.all([ - (async () => { + (async (): Promise => { // share keys with devices that we already have a session for logger.debug(`Sharing keys with existing Olm sessions in ${this.roomId}`, olmSessions); await this.shareKeyWithOlmSessions(session, key, payload, olmSessions); logger.debug(`Shared keys with existing Olm sessions in ${this.roomId}`); })(), - (async () => { + (async (): Promise => { logger.debug( `Sharing keys (start phase 1) with new Olm sessions in ${this.roomId}`, devicesWithoutSession, @@ -415,7 +415,7 @@ class MegolmEncryption extends EncryptionAlgorithm { if (!singleOlmCreationPhase && (Date.now() - start < 10000)) { // perform the second phase of olm session creation if requested, // and if the first phase didn't take too long - (async () => { + (async (): Promise => { // Retry sending keys to devices that we were unable to establish // an olm session for. This time, we use a longer timeout, but we // do this in the background and don't block anything else while we @@ -452,7 +452,7 @@ class MegolmEncryption extends EncryptionAlgorithm { } logger.debug(`Shared keys (all phases done) with new Olm sessions in ${this.roomId}`); })(), - (async () => { + (async (): Promise => { logger.debug(`There are ${Object.entries(blocked).length} blocked devices in ${this.roomId}`, Object.entries(blocked)); @@ -809,7 +809,7 @@ class MegolmEncryption extends EncryptionAlgorithm { errorDevices: IOlmDevice[], otkTimeout: number, failedServers?: string[], - ) { + ): Promise { logger.debug(`Ensuring Olm sessions for devices in ${this.roomId}`); const devicemap = await olmlib.ensureOlmSessionsForDevices( this.olmDevice, this.baseApis, devicesByUser, false, otkTimeout, failedServers, @@ -969,7 +969,7 @@ class MegolmEncryption extends EncryptionAlgorithm { this.encryptionPreparation = { startTime: Date.now(), - promise: (async () => { + promise: (async (): Promise => { try { logger.debug(`Getting devices in ${this.roomId}`); const [devicesInRoom, blocked] = await this.getDevicesInRoom(room); @@ -1231,7 +1231,7 @@ class MegolmDecryption extends DecryptionAlgorithm { protected readonly roomId: string; - constructor(params: DecryptionClassParams>>) { + public constructor(params: DecryptionClassParams>>) { super(params); this.roomId = params.roomId; } diff --git a/src/crypto/backup.ts b/src/crypto/backup.ts index d9c1ba458..f2160165b 100644 --- a/src/crypto/backup.ts +++ b/src/crypto/backup.ts @@ -120,7 +120,7 @@ export class BackupManager { private sendingBackups: boolean; // Are we currently sending backups? private sessionLastCheckAttemptedTime: Record = {}; // When did we last try to check the server for a given session id? - constructor(private readonly baseApis: MatrixClient, public readonly getKey: GetKey) { + public constructor(private readonly baseApis: MatrixClient, public readonly getKey: GetKey) { this.checkedForBackup = false; this.sendingBackups = false; } @@ -609,7 +609,7 @@ export class BackupManager { export class Curve25519 implements BackupAlgorithm { public static algorithmName = "m.megolm_backup.v1.curve25519-aes-sha2"; - constructor( + public constructor( public authData: ICurve25519AuthData, private publicKey: any, // FIXME: PkEncryption private getKey: () => Promise, @@ -661,7 +661,7 @@ export class Curve25519 implements BackupAlgorithm { } } - public get untrusted() { return true; } + public get untrusted(): boolean { return true; } public async encryptSession(data: Record): Promise { const plainText: Record = Object.assign({}, data); @@ -735,7 +735,7 @@ const UNSTABLE_MSC3270_NAME = new UnstableValue( export class Aes256 implements BackupAlgorithm { public static algorithmName = UNSTABLE_MSC3270_NAME.name; - constructor( + public constructor( public readonly authData: IAes256AuthData, private readonly key: Uint8Array, ) {} @@ -786,7 +786,7 @@ export class Aes256 implements BackupAlgorithm { } } - public get untrusted() { return false; } + public get untrusted(): boolean { return false; } public encryptSession(data: Record): Promise { const plainText: Record = Object.assign({}, data); diff --git a/src/crypto/dehydration.ts b/src/crypto/dehydration.ts index 5b12159ae..cc6b252da 100644 --- a/src/crypto/dehydration.ts +++ b/src/crypto/dehydration.ts @@ -62,7 +62,7 @@ export class DehydrationManager { private keyInfo?: {[props: string]: any}; private deviceDisplayName?: string; - constructor(private readonly crypto: Crypto) { + public constructor(private readonly crypto: Crypto) { this.getDehydrationKeyFromCache(); } @@ -294,7 +294,7 @@ export class DehydrationManager { } } - public stop() { + public stop(): void { if (this.timeoutId) { global.clearTimeout(this.timeoutId); this.timeoutId = undefined; diff --git a/src/crypto/deviceinfo.ts b/src/crypto/deviceinfo.ts index 00ebf7c38..3b4d53f68 100644 --- a/src/crypto/deviceinfo.ts +++ b/src/crypto/deviceinfo.ts @@ -94,7 +94,7 @@ export class DeviceInfo { public unsigned: Record = {}; public signatures: ISignatures = {}; - constructor(public readonly deviceId: string) {} + public constructor(public readonly deviceId: string) {} /** * Prepare a DeviceInfo for JSON serialisation in the session store diff --git a/src/crypto/index.ts b/src/crypto/index.ts index 2a55d75fe..04a6e5e1a 100644 --- a/src/crypto/index.ts +++ b/src/crypto/index.ts @@ -278,7 +278,7 @@ export class Crypto extends TypedEventEmitter { + cryptoCallbacks.getCrossSigningKey = async (type): Promise => { return CrossSigningInfo.getFromSecretStorage(type, this.secretStorage); }; } @@ -709,7 +709,7 @@ export class Crypto extends TypedEventEmitter { + const resetCrossSigning = async (): Promise => { crossSigningInfo.resetKeys(); // Sign master key with device key await this.signObject(crossSigningInfo.keys.master); @@ -846,12 +846,12 @@ export class Crypto extends TypedEventEmitter ({} as IRecoveryKey), + createSecretStorageKey = async (): Promise => ({} as IRecoveryKey), keyBackupInfo, setupNewKeyBackup, setupNewSecretStorage, getKeyBackupPassphrase, - }: ICreateSecretStorageOpts = {}) { + }: ICreateSecretStorageOpts = {}): Promise { logger.log("Bootstrapping Secure Secret Storage"); const delegateCryptoCallbacks = this.baseApis.cryptoCallbacks; const builder = new EncryptionSetupBuilder( @@ -868,7 +868,7 @@ export class Crypto extends TypedEventEmitter { + const createSSSS = async (opts: IAddSecretStorageKeyOpts, privateKey?: Uint8Array): Promise => { if (privateKey) { opts.key = privateKey; } @@ -884,7 +884,7 @@ export class Crypto extends TypedEventEmitter { + const ensureCanCheckPassphrase = async (keyId: string, keyInfo: ISecretStorageKeyInfo): Promise => { if (!keyInfo.mac) { const key = await this.baseApis.cryptoCallbacks.getSecretStorageKey?.( { keys: { [keyId]: keyInfo } }, "", @@ -903,7 +903,7 @@ export class Crypto extends TypedEventEmitter { + const signKeyBackupWithCrossSigning = async (keyBackupAuthData: IKeyBackupInfo["auth_data"]): Promise => { if ( this.crossSigningInfo.getId() && await this.crossSigningInfo.isStoredInKeyCache("master") @@ -1241,7 +1241,7 @@ export class Crypto extends TypedEventEmitter { + const upload = ({ shouldEmit = false }): Promise => { return this.baseApis.uploadKeySignatures({ [this.userId]: { [this.deviceId]: signedDevice!, @@ -1475,7 +1475,7 @@ export class Crypto extends TypedEventEmitter { + private onDeviceListUserCrossSigningUpdated = async (userId: string): Promise => { if (userId === this.userId) { // An update to our own cross-signing key. // Get the new key first: @@ -1657,7 +1657,7 @@ export class Crypto extends TypedEventEmitter { + const upload = ({ shouldEmit = false }): Promise => { logger.info(`Starting background key sig upload for ${keysToUpload}`); return this.baseApis.uploadKeySignatures({ [this.userId]: keySignatures }) .then((response) => { @@ -1864,7 +1864,7 @@ export class Crypto extends TypedEventEmitter { + const uploadLoop = async (keyCount: number): Promise => { while (keyLimit > keyCount || this.getNeedsNewFallback()) { // Ask olm to generate new one time keys, then upload them to synapse. if (keyLimit > keyCount) { @@ -2155,7 +2155,7 @@ export class Crypto extends TypedEventEmitter { + const upload = async ({ shouldEmit = false }): Promise => { logger.info("Uploading signature for " + userId + "..."); const response = await this.baseApis.uploadKeySignatures({ [userId]: { @@ -2246,7 +2246,7 @@ export class Crypto extends TypedEventEmitter { + const upload = async ({ shouldEmit = false }): Promise => { logger.info("Uploading signature for " + deviceId); const response = await this.baseApis.uploadKeySignatures({ [userId]: { @@ -2645,7 +2645,7 @@ export class Crypto extends TypedEventEmitter { - const trackMembers = async () => { + const trackMembers = async (): Promise => { // not an encrypted room if (!this.roomEncryptors.has(roomId)) { return; @@ -2747,7 +2747,7 @@ export class Crypto extends TypedEventEmitter { + private onMembership = (event: MatrixEvent, member: RoomMember, oldMembership?: string): void => { try { this.onRoomMembership(event, member, oldMembership); } catch (e) { @@ -3340,7 +3340,7 @@ export class Crypto extends TypedEventEmitter { + const createRequest = (event: MatrixEvent): VerificationRequest => { const channel = new InRoomChannel(this.baseApis, event.getRoomId()!); return new VerificationRequest( channel, this.verificationMethods, this.baseApis); @@ -3361,7 +3361,7 @@ export class Crypto extends TypedEventEmitter((resolve, reject) => { eventIdListener = resolve; - statusListener = () => { + statusListener = (): void => { if (event.status == EventStatus.CANCELLED) { reject(new Error("Event status set to CANCELLED.")); } @@ -3420,7 +3420,7 @@ export class Crypto extends TypedEventEmitter { + const retryDecryption = (): void => { const roomDecryptors = this.getRoomDecryptors(olmlib.MEGOLM_ALGORITHM); for (const decryptor of roomDecryptors) { decryptor.retryDecryptionFromSender(deviceKey); @@ -3692,7 +3692,7 @@ export class Crypto extends TypedEventEmitter { + req.share = (): void => { decryptor.shareKeysWithDevice(req); }; @@ -3863,14 +3863,14 @@ export class IncomingRoomKeyRequest { public readonly requestBody: IRoomKeyRequestBody; public share: () => void; - constructor(event: MatrixEvent) { + public constructor(event: MatrixEvent) { const content = event.getContent(); this.userId = event.getSender()!; this.deviceId = content.requesting_device_id; this.requestId = content.request_id; this.requestBody = content.body || {}; - this.share = () => { + this.share = (): void => { throw new Error("don't know how to share keys for this request yet"); }; } @@ -3888,7 +3888,7 @@ class IncomingRoomKeyRequestCancellation { public readonly deviceId: string; public readonly requestId: string; - constructor(event: MatrixEvent) { + public constructor(event: MatrixEvent) { const content = event.getContent(); this.userId = event.getSender()!; diff --git a/src/crypto/olmlib.ts b/src/crypto/olmlib.ts index b77c0b16f..111e4c16d 100644 --- a/src/crypto/olmlib.ts +++ b/src/crypto/olmlib.ts @@ -82,7 +82,7 @@ export async function encryptMessageForDevice( recipientUserId: string, recipientDevice: DeviceInfo, payloadFields: Record, -) { +): Promise { const deviceKey = recipientDevice.getIdentityKey(); const sessionId = await olmDevice.getSessionIdForDevice(deviceKey); if (sessionId === null) { @@ -173,7 +173,7 @@ export async function getExistingOlmSessions( for (const deviceInfo of devices) { const deviceId = deviceInfo.deviceId; const key = deviceInfo.getIdentityKey(); - promises.push((async () => { + promises.push((async (): Promise => { const sessionId = await olmDevice.getSessionIdForDevice( key, true, ); @@ -256,7 +256,7 @@ export async function ensureOlmSessionsForDevices( // conditions. If we find that we already have a session, then // we'll resolve olmDevice.sessionsInProgress[key] = new Promise(resolve => { - resolveSession[key] = (v: any) => { + resolveSession[key] = (v: any): void => { delete olmDevice.sessionsInProgress[key]; resolve(v); }; @@ -463,7 +463,7 @@ export async function verifySignature( signingUserId: string, signingDeviceId: string, signingKey: string, -) { +): Promise { const signKeyId = "ed25519:" + signingDeviceId; const signatures = obj.signatures || {}; const userSigs = signatures[signingUserId] || {}; @@ -527,7 +527,7 @@ export function pkSign(obj: IObject, key: PkSigning, userId: string, pubKey: str * @param {string} pubKey The public key to use to verify * @param {string} userId The user ID who signed the object */ -export function pkVerify(obj: IObject, pubKey: string, userId: string) { +export function pkVerify(obj: IObject, pubKey: string, userId: string): void { const keyId = "ed25519:" + pubKey; if (!(obj.signatures && obj.signatures[userId] && obj.signatures[userId][keyId])) { throw new Error("No signature"); diff --git a/src/crypto/store/indexeddb-crypto-store-backend.ts b/src/crypto/store/indexeddb-crypto-store-backend.ts index f525c0c95..cdf35e787 100644 --- a/src/crypto/store/indexeddb-crypto-store-backend.ts +++ b/src/crypto/store/indexeddb-crypto-store-backend.ts @@ -48,11 +48,11 @@ export class Backend implements CryptoStore { /** * @param {IDBDatabase} db */ - constructor(private db: IDBDatabase) { + public constructor(private db: IDBDatabase) { // make sure we close the db on `onversionchange` - otherwise // attempts to delete the database will block (and subsequent // attempts to re-create it will also block). - db.onversionchange = () => { + db.onversionchange = (): void => { logger.log(`versionchange for indexeddb ${this.db.name}: closing`); db.close(); }; @@ -103,7 +103,7 @@ export class Backend implements CryptoStore { `enqueueing key request for ${requestBody.room_id} / ` + requestBody.session_id, ); - txn.oncomplete = () => {resolve(request);}; + txn.oncomplete = (): void => {resolve(request);}; const store = txn.objectStore("outgoingRoomKeyRequests"); store.add(request); }); @@ -157,7 +157,7 @@ export class Backend implements CryptoStore { requestBody.session_id, ]); - cursorReq.onsuccess = () => { + cursorReq.onsuccess = (): void => { const cursor = cursorReq.result; if (!cursor) { // no match found @@ -201,7 +201,7 @@ export class Backend implements CryptoStore { let stateIndex = 0; let result: OutgoingRoomKeyRequest; - function onsuccess(this: IDBRequest) { + function onsuccess(this: IDBRequest): void { const cursor = this.result; if (cursor) { // got a match @@ -243,8 +243,8 @@ export class Backend implements CryptoStore { const index = store.index("state"); const request = index.getAll(wantedState); - request.onsuccess = () => resolve(request.result); - request.onerror = () => reject(request.error); + request.onsuccess = (): void => resolve(request.result); + request.onerror = (): void => reject(request.error); }); } @@ -256,7 +256,7 @@ export class Backend implements CryptoStore { let stateIndex = 0; const results: OutgoingRoomKeyRequest[] = []; - function onsuccess(this: IDBRequest) { + function onsuccess(this: IDBRequest): void { const cursor = this.result; if (cursor) { const keyReq = cursor.value; @@ -309,7 +309,7 @@ export class Backend implements CryptoStore { ): Promise { let result: OutgoingRoomKeyRequest | null = null; - function onsuccess(this: IDBRequest) { + function onsuccess(this: IDBRequest): void { const cursor = this.result; if (!cursor) { return; @@ -348,7 +348,7 @@ export class Backend implements CryptoStore { ): Promise { const txn = this.db.transaction("outgoingRoomKeyRequests", "readwrite"); const cursorReq = txn.objectStore("outgoingRoomKeyRequests").openCursor(requestId); - cursorReq.onsuccess = () => { + cursorReq.onsuccess = (): void => { const cursor = cursorReq.result; if (!cursor) { return; @@ -371,7 +371,7 @@ export class Backend implements CryptoStore { public getAccount(txn: IDBTransaction, func: (accountPickle: string | null) => void): void { const objectStore = txn.objectStore("account"); const getReq = objectStore.get("-"); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { try { func(getReq.result || null); } catch (e) { @@ -391,7 +391,7 @@ export class Backend implements CryptoStore { ): void { const objectStore = txn.objectStore("account"); const getReq = objectStore.get("crossSigningKeys"); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { try { func(getReq.result || null); } catch (e) { @@ -407,7 +407,7 @@ export class Backend implements CryptoStore { ): void { const objectStore = txn.objectStore("account"); const getReq = objectStore.get(`ssss_cache:${type}`); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { try { func(getReq.result || null); } catch (e) { @@ -435,7 +435,7 @@ export class Backend implements CryptoStore { public countEndToEndSessions(txn: IDBTransaction, func: (count: number) => void): void { const objectStore = txn.objectStore("sessions"); const countReq = objectStore.count(); - countReq.onsuccess = function() { + countReq.onsuccess = function(): void { try { func(countReq.result); } catch (e) { @@ -453,7 +453,7 @@ export class Backend implements CryptoStore { const idx = objectStore.index("deviceKey"); const getReq = idx.openCursor(deviceKey); const results: Parameters[2]>[0] = {}; - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { const cursor = getReq.result; if (cursor) { results[cursor.value.sessionId] = { @@ -479,7 +479,7 @@ export class Backend implements CryptoStore { ): void { const objectStore = txn.objectStore("sessions"); const getReq = objectStore.get([deviceKey, sessionId]); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { try { if (getReq.result) { func({ @@ -498,7 +498,7 @@ export class Backend implements CryptoStore { public getAllEndToEndSessions(txn: IDBTransaction, func: (session: ISessionInfo | null) => void): void { const objectStore = txn.objectStore("sessions"); const getReq = objectStore.openCursor(); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { try { const cursor = getReq.result; if (cursor) { @@ -546,7 +546,7 @@ export class Backend implements CryptoStore { const objectStore = txn.objectStore("session_problems"); const index = objectStore.index("deviceKey"); const req = index.getAll(deviceKey); - req.onsuccess = () => { + req.onsuccess = (): void => { const problems = req.result; if (!problems.length) { result = null; @@ -583,7 +583,7 @@ export class Backend implements CryptoStore { return new Promise((resolve) => { const { userId, deviceInfo } = device; const getReq = objectStore.get([userId, deviceInfo.deviceId]); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { if (!getReq.result) { objectStore.put({ userId, deviceId: deviceInfo.deviceId }); ret.push(device); @@ -608,7 +608,7 @@ export class Backend implements CryptoStore { let withheld: IWithheld | null | boolean = false; const objectStore = txn.objectStore("inbound_group_sessions"); const getReq = objectStore.get([senderCurve25519Key, sessionId]); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { try { if (getReq.result) { session = getReq.result.session; @@ -625,7 +625,7 @@ export class Backend implements CryptoStore { const withheldObjectStore = txn.objectStore("inbound_group_sessions_withheld"); const withheldGetReq = withheldObjectStore.get([senderCurve25519Key, sessionId]); - withheldGetReq.onsuccess = function() { + withheldGetReq.onsuccess = function(): void { try { if (withheldGetReq.result) { withheld = withheldGetReq.result.session; @@ -644,7 +644,7 @@ export class Backend implements CryptoStore { public getAllEndToEndInboundGroupSessions(txn: IDBTransaction, func: (session: ISession | null) => void): void { const objectStore = txn.objectStore("inbound_group_sessions"); const getReq = objectStore.openCursor(); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { const cursor = getReq.result; if (cursor) { try { @@ -677,7 +677,7 @@ export class Backend implements CryptoStore { const addReq = objectStore.add({ senderCurve25519Key, sessionId, session: sessionData, }); - addReq.onerror = (ev) => { + addReq.onerror = (ev): void => { if (addReq.error?.name === 'ConstraintError') { // This stops the error from triggering the txn's onerror ev.stopPropagation(); @@ -722,7 +722,7 @@ export class Backend implements CryptoStore { public getEndToEndDeviceData(txn: IDBTransaction, func: (deviceData: IDeviceData | null) => void): void { const objectStore = txn.objectStore("device_data"); const getReq = objectStore.get("-"); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { try { func(getReq.result || null); } catch (e) { @@ -745,7 +745,7 @@ export class Backend implements CryptoStore { const rooms: Parameters[1]>[0] = {}; const objectStore = txn.objectStore("rooms"); const getReq = objectStore.openCursor(); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { const cursor = getReq.result; if (cursor) { rooms[cursor.key as string] = cursor.value; @@ -771,17 +771,17 @@ export class Backend implements CryptoStore { "readonly", ); txn.onerror = reject; - txn.oncomplete = function() { + txn.oncomplete = function(): void { resolve(sessions); }; const objectStore = txn.objectStore("sessions_needing_backup"); const sessionStore = txn.objectStore("inbound_group_sessions"); const getReq = objectStore.openCursor(); - getReq.onsuccess = function() { + getReq.onsuccess = function(): void { const cursor = getReq.result; if (cursor) { const sessionGetReq = sessionStore.get(cursor.key); - sessionGetReq.onsuccess = function() { + sessionGetReq.onsuccess = function(): void { sessions.push({ senderKey: sessionGetReq.result.senderCurve25519Key, sessionId: sessionGetReq.result.sessionId, @@ -804,7 +804,7 @@ export class Backend implements CryptoStore { return new Promise((resolve, reject) => { const req = objectStore.count(); req.onerror = reject; - req.onsuccess = () => resolve(req.result); + req.onsuccess = (): void => resolve(req.result); }); } @@ -852,7 +852,7 @@ export class Backend implements CryptoStore { } const objectStore = txn.objectStore("shared_history_inbound_group_sessions"); const req = objectStore.get([roomId]); - req.onsuccess = () => { + req.onsuccess = (): void => { const { sessions } = req.result || { sessions: [] }; sessions.push([senderKey, sessionId]); objectStore.put({ roomId, sessions }); @@ -871,7 +871,7 @@ export class Backend implements CryptoStore { const objectStore = txn.objectStore("shared_history_inbound_group_sessions"); const req = objectStore.get([roomId]); return new Promise((resolve, reject) => { - req.onsuccess = () => { + req.onsuccess = (): void => { const { sessions } = req.result || { sessions: [] }; resolve(sessions); }; @@ -891,7 +891,7 @@ export class Backend implements CryptoStore { } const objectStore = txn.objectStore("parked_shared_history"); const req = objectStore.get([roomId]); - req.onsuccess = () => { + req.onsuccess = (): void => { const { parked } = req.result || { parked: [] }; parked.push(parkedData); objectStore.put({ roomId, parked }); @@ -909,7 +909,7 @@ export class Backend implements CryptoStore { } const cursorReq = txn.objectStore("parked_shared_history").openCursor(roomId); return new Promise((resolve, reject) => { - cursorReq.onsuccess = () => { + cursorReq.onsuccess = (): void => { const cursor = cursorReq.result; if (!cursor) { resolve([]); @@ -957,32 +957,32 @@ export class Backend implements CryptoStore { type DbMigration = (db: IDBDatabase) => void; const DB_MIGRATIONS: DbMigration[] = [ - (db) => { createDatabase(db); }, - (db) => { db.createObjectStore("account"); }, - (db) => { + (db): void => { createDatabase(db); }, + (db): void => { db.createObjectStore("account"); }, + (db): void => { const sessionsStore = db.createObjectStore("sessions", { keyPath: ["deviceKey", "sessionId"], }); sessionsStore.createIndex("deviceKey", "deviceKey"); }, - (db) => { + (db): void => { db.createObjectStore("inbound_group_sessions", { keyPath: ["senderCurve25519Key", "sessionId"], }); }, - (db) => { db.createObjectStore("device_data"); }, - (db) => { db.createObjectStore("rooms"); }, - (db) => { + (db): void => { db.createObjectStore("device_data"); }, + (db): void => { db.createObjectStore("rooms"); }, + (db): void => { db.createObjectStore("sessions_needing_backup", { keyPath: ["senderCurve25519Key", "sessionId"], }); }, - (db) => { + (db): void => { db.createObjectStore("inbound_group_sessions_withheld", { keyPath: ["senderCurve25519Key", "sessionId"], }); }, - (db) => { + (db): void => { const problemsStore = db.createObjectStore("session_problems", { keyPath: ["deviceKey", "time"], }); @@ -992,12 +992,12 @@ const DB_MIGRATIONS: DbMigration[] = [ keyPath: ["userId", "deviceId"], }); }, - (db) => { + (db): void => { db.createObjectStore("shared_history_inbound_group_sessions", { keyPath: ["roomId"], }); }, - (db) => { + (db): void => { db.createObjectStore("parked_shared_history", { keyPath: ["roomId"], }); @@ -1037,7 +1037,7 @@ interface IWrappedIDBTransaction extends IDBTransaction { * Aborts a transaction with a given exception * The transaction promise will be rejected with this exception. */ -function abortWithException(txn: IDBTransaction, e: Error) { +function abortWithException(txn: IDBTransaction, e: Error): void { // We cheekily stick our exception onto the transaction object here // We could alternatively make the thing we pass back to the app // an object containing the transaction and exception. @@ -1052,13 +1052,13 @@ function abortWithException(txn: IDBTransaction, e: Error) { function promiseifyTxn(txn: IDBTransaction): Promise { return new Promise((resolve, reject) => { - txn.oncomplete = () => { + txn.oncomplete = (): void => { if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) { reject((txn as IWrappedIDBTransaction)._mx_abortexception); } resolve(null); }; - txn.onerror = (event) => { + txn.onerror = (event): void => { if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) { reject((txn as IWrappedIDBTransaction)._mx_abortexception); } else { @@ -1066,7 +1066,7 @@ function promiseifyTxn(txn: IDBTransaction): Promise { reject(txn.error); } }; - txn.onabort = (event) => { + txn.onabort = (event): void => { if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) { reject((txn as IWrappedIDBTransaction)._mx_abortexception); } else { diff --git a/src/crypto/store/indexeddb-crypto-store.ts b/src/crypto/store/indexeddb-crypto-store.ts index 4fbeafe19..d743a95de 100644 --- a/src/crypto/store/indexeddb-crypto-store.ts +++ b/src/crypto/store/indexeddb-crypto-store.ts @@ -73,7 +73,7 @@ export class IndexedDBCryptoStore implements CryptoStore { * @param {IDBFactory} indexedDB global indexedDB instance * @param {string} dbName name of db to connect to */ - constructor(private readonly indexedDB: IDBFactory, private readonly dbName: string) {} + public constructor(private readonly indexedDB: IDBFactory, private readonly dbName: string) {} /** * Ensure the database exists and is up-to-date, or fall back to @@ -99,24 +99,24 @@ export class IndexedDBCryptoStore implements CryptoStore { const req = this.indexedDB.open(this.dbName, IndexedDBCryptoStoreBackend.VERSION); - req.onupgradeneeded = (ev) => { + req.onupgradeneeded = (ev): void => { const db = req.result; const oldVersion = ev.oldVersion; IndexedDBCryptoStoreBackend.upgradeDatabase(db, oldVersion); }; - req.onblocked = () => { + req.onblocked = (): void => { logger.log( `can't yet open IndexedDBCryptoStore because it is open elsewhere`, ); }; - req.onerror = (ev) => { + req.onerror = (ev): void => { logger.log("Error connecting to indexeddb", ev); reject(req.error); }; - req.onsuccess = () => { + req.onsuccess = (): void => { const db = req.result; logger.log(`connected to indexeddb ${this.dbName}`); @@ -179,18 +179,18 @@ export class IndexedDBCryptoStore implements CryptoStore { logger.log(`Removing indexeddb instance: ${this.dbName}`); const req = this.indexedDB.deleteDatabase(this.dbName); - req.onblocked = () => { + req.onblocked = (): void => { logger.log( `can't yet delete IndexedDBCryptoStore because it is open elsewhere`, ); }; - req.onerror = (ev) => { + req.onerror = (ev): void => { logger.log("Error deleting data from indexeddb", ev); reject(req.error); }; - req.onsuccess = () => { + req.onsuccess = (): void => { logger.log(`Removed indexeddb instance: ${this.dbName}`); resolve(); }; @@ -322,7 +322,7 @@ export class IndexedDBCryptoStore implements CryptoStore { * @param {*} txn An active transaction. See doTxn(). * @param {function(string)} func Called with the account pickle */ - public getAccount(txn: IDBTransaction, func: (accountPickle: string | null) => void) { + public getAccount(txn: IDBTransaction, func: (accountPickle: string | null) => void): void { this.backend!.getAccount(txn, func); } diff --git a/src/crypto/store/localStorage-crypto-store.ts b/src/crypto/store/localStorage-crypto-store.ts index 4bc8b45ef..977236ef9 100644 --- a/src/crypto/store/localStorage-crypto-store.ts +++ b/src/crypto/store/localStorage-crypto-store.ts @@ -76,7 +76,7 @@ export class LocalStorageCryptoStore extends MemoryCryptoStore { return false; } - constructor(private readonly store: Storage) { + public constructor(private readonly store: Storage) { super(); } @@ -154,7 +154,7 @@ export class LocalStorageCryptoStore extends MemoryCryptoStore { setJsonItem(this.store, key, problems); } - async getEndToEndSessionProblem(deviceKey: string, timestamp: number): Promise { + public async getEndToEndSessionProblem(deviceKey: string, timestamp: number): Promise { const key = keyEndToEndSessionProblems(deviceKey); const problems = getJsonItem(this.store, key) || []; if (!problems.length) { @@ -408,7 +408,7 @@ export class LocalStorageCryptoStore extends MemoryCryptoStore { setJsonItem(this.store, E2E_PREFIX + `ssss_cache.${type}`, key); } - doTxn(mode: Mode, stores: Iterable, func: (txn: unknown) => T): Promise { + public doTxn(mode: Mode, stores: Iterable, func: (txn: unknown) => T): Promise { return Promise.resolve(func(null)); } } diff --git a/src/crypto/store/memory-crypto-store.ts b/src/crypto/store/memory-crypto-store.ts index 8b0206eef..f22379ee8 100644 --- a/src/crypto/store/memory-crypto-store.ts +++ b/src/crypto/store/memory-crypto-store.ts @@ -279,7 +279,7 @@ export class MemoryCryptoStore implements CryptoStore { // Olm Account - public getAccount(txn: unknown, func: (accountPickle: string | null) => void) { + public getAccount(txn: unknown, func: (accountPickle: string | null) => void): void { func(this.account); } diff --git a/src/crypto/verification/Base.ts b/src/crypto/verification/Base.ts index f2fc1d5f9..55b349e99 100644 --- a/src/crypto/verification/Base.ts +++ b/src/crypto/verification/Base.ts @@ -34,7 +34,7 @@ import { ListenerMap, TypedEventEmitter } from "../../models/typed-event-emitter const timeoutException = new Error("Verification timed out"); export class SwitchStartEventError extends Error { - constructor(public readonly startEvent: MatrixEvent | null) { + public constructor(public readonly startEvent: MatrixEvent | null) { super(); } } @@ -91,7 +91,7 @@ export class VerificationBase< * @param {object} [request] the key verification request object related to * this verification, if any */ - constructor( + public constructor( public readonly channel: IVerificationChannel, public readonly baseApis: MatrixClient, public readonly userId: string, @@ -286,12 +286,12 @@ export class VerificationBase< if (this.promise) return this.promise; this.promise = new Promise((resolve, reject) => { - this.resolve = (...args) => { + this.resolve = (...args): void => { this._done = true; this.endTimer(); resolve(...args); }; - this.reject = (e: Error | MatrixEvent) => { + this.reject = (e: Error | MatrixEvent): void => { this._done = true; this.endTimer(); reject(e); diff --git a/src/crypto/verification/QRCode.ts b/src/crypto/verification/QRCode.ts index 9ff9315a9..f6bdda17e 100644 --- a/src/crypto/verification/QRCode.ts +++ b/src/crypto/verification/QRCode.ts @@ -154,7 +154,7 @@ interface IQrData { } export class QRCodeData { - constructor( + public constructor( public readonly mode: Mode, private readonly sharedSecret: string, // only set when mode is MODE_VERIFY_OTHER_USER, master key of other party at time of generating QR code @@ -283,21 +283,21 @@ export class QRCodeData { private static generateBuffer(qrData: IQrData): Buffer { let buf = Buffer.alloc(0); // we'll concat our way through life - const appendByte = (b) => { + const appendByte = (b): void => { const tmpBuf = Buffer.from([b]); buf = Buffer.concat([buf, tmpBuf]); }; - const appendInt = (i) => { + const appendInt = (i): void => { const tmpBuf = Buffer.alloc(2); tmpBuf.writeInt16BE(i, 0); buf = Buffer.concat([buf, tmpBuf]); }; - const appendStr = (s, enc, withLengthPrefix = true) => { + const appendStr = (s, enc, withLengthPrefix = true): void => { const tmpBuf = Buffer.from(s, enc); if (withLengthPrefix) appendInt(tmpBuf.byteLength); buf = Buffer.concat([buf, tmpBuf]); }; - const appendEncBase64 = (b64) => { + const appendEncBase64 = (b64): void => { const b = decodeBase64(b64); const tmpBuf = Buffer.from(b); buf = Buffer.concat([buf, tmpBuf]); diff --git a/src/crypto/verification/SAS.ts b/src/crypto/verification/SAS.ts index 806b4bf5e..5df6d48f6 100644 --- a/src/crypto/verification/SAS.ts +++ b/src/crypto/verification/SAS.ts @@ -170,10 +170,12 @@ const macMethods = { "hmac-sha256": "calculate_mac_long_kdf", }; -function calculateMAC(olmSAS: OlmSAS, method: string) { - return function(...args) { +type Method = keyof typeof macMethods; + +function calculateMAC(olmSAS: OlmSAS, method: Method) { + return function(...args): string { const macFunction = olmSAS[macMethods[method]]; - const mac = macFunction.apply(olmSAS, args); + const mac: string = macFunction.apply(olmSAS, args); logger.log("SAS calculateMAC:", method, args, mac); return mac; }; @@ -208,7 +210,7 @@ const calculateKeyAgreement = { */ const KEY_AGREEMENT_LIST = ["curve25519-hkdf-sha256", "curve25519"]; const HASHES_LIST = ["sha256"]; -const MAC_LIST = ["org.matrix.msc3783.hkdf-hmac-sha256", "hkdf-hmac-sha256", "hmac-sha256"]; +const MAC_LIST: Method[] = ["org.matrix.msc3783.hkdf-hmac-sha256", "hkdf-hmac-sha256", "hmac-sha256"]; const SAS_LIST = Object.keys(sasGenerators); const KEY_AGREEMENT_SET = new Set(KEY_AGREEMENT_LIST); @@ -300,13 +302,13 @@ export class SAS extends Base { keyAgreement: string, sasMethods: string[], olmSAS: OlmSAS, - macMethod: string, + macMethod: Method, ): Promise { const sasBytes = calculateKeyAgreement[keyAgreement](this, olmSAS, 6); const verifySAS = new Promise((resolve, reject) => { this.sasEvent = { sas: generateSas(sasBytes, sasMethods), - confirm: async () => { + confirm: async (): Promise => { try { await this.sendMAC(olmSAS, macMethod); resolve(); @@ -443,7 +445,7 @@ export class SAS extends Base { } } - private sendMAC(olmSAS: OlmSAS, method: string): Promise { + private sendMAC(olmSAS: OlmSAS, method: Method): Promise { const mac = {}; const keyList: string[] = []; const baseInfo = "MATRIX_KEY_VERIFICATION_MAC" @@ -475,7 +477,7 @@ export class SAS extends Base { return this.send(EventType.KeyVerificationMac, { mac, keys }); } - private async checkMAC(olmSAS: OlmSAS, content: IContent, method: string): Promise { + private async checkMAC(olmSAS: OlmSAS, content: IContent, method: Method): Promise { const baseInfo = "MATRIX_KEY_VERIFICATION_MAC" + this.userId + this.deviceId + this.baseApis.getUserId() + this.baseApis.deviceId diff --git a/src/crypto/verification/request/InRoomChannel.ts b/src/crypto/verification/request/InRoomChannel.ts index 2a4fb8d81..664a2dad6 100644 --- a/src/crypto/verification/request/InRoomChannel.ts +++ b/src/crypto/verification/request/InRoomChannel.ts @@ -44,7 +44,7 @@ export class InRoomChannel implements IVerificationChannel { * @param {string} roomId id of the room where verification events should be posted in, should be a DM with the given user. * @param {string} userId id of user that the verification request is directed at, should be present in the room. */ - constructor( + public constructor( private readonly client: MatrixClient, public readonly roomId: string, public userId?: string, diff --git a/src/crypto/verification/request/ToDeviceChannel.ts b/src/crypto/verification/request/ToDeviceChannel.ts index 112272914..30d615251 100644 --- a/src/crypto/verification/request/ToDeviceChannel.ts +++ b/src/crypto/verification/request/ToDeviceChannel.ts @@ -42,7 +42,7 @@ export class ToDeviceChannel implements IVerificationChannel { public request?: VerificationRequest; // userId and devices of user we're about to verify - constructor( + public constructor( private readonly client: MatrixClient, public readonly userId: string, private readonly devices: string[], diff --git a/src/crypto/verification/request/VerificationRequest.ts b/src/crypto/verification/request/VerificationRequest.ts index 2ff71d62c..58de4b9a2 100644 --- a/src/crypto/verification/request/VerificationRequest.ts +++ b/src/crypto/verification/request/VerificationRequest.ts @@ -116,7 +116,7 @@ export class VerificationRequest< public _cancellingUserId?: string; // Used in tests only private _verifier?: VerificationBase; - constructor( + public constructor( public readonly channel: C, private readonly verificationMethods: Map, private readonly client: MatrixClient, @@ -498,7 +498,7 @@ export class VerificationRequest< */ public waitFor(fn: (request: VerificationRequest) => boolean): Promise { return new Promise((resolve, reject) => { - const check = () => { + const check = (): boolean => { let handled = false; if (fn(this)) { resolve(this); @@ -539,7 +539,7 @@ export class VerificationRequest< private calculatePhaseTransitions(): ITransition[] { const transitions: ITransition[] = [{ phase: PHASE_UNSENT }]; - const phase = () => transitions[transitions.length - 1].phase; + const phase = (): Phase => transitions[transitions.length - 1].phase; // always pass by .request first to be sure channel.userId has been set const hasRequestByThem = this.eventsByThem.has(REQUEST_TYPE); @@ -816,7 +816,7 @@ export class VerificationRequest< } } - private cancelOnTimeout = async () => { + private cancelOnTimeout = async (): Promise => { try { if (this.initiatedByMe) { await this.cancel({ diff --git a/src/embedded.ts b/src/embedded.ts index d1dfb50bf..27cf564a6 100644 --- a/src/embedded.ts +++ b/src/embedded.ts @@ -101,7 +101,7 @@ export class RoomWidgetClient extends MatrixClient { private lifecycle?: AbortController; private syncState: SyncState | null = null; - constructor( + public constructor( private readonly widgetApi: WidgetApi, private readonly capabilities: ICapabilities, private readonly roomId: string, @@ -211,7 +211,7 @@ export class RoomWidgetClient extends MatrixClient { if (this.capabilities.turnServers) this.watchTurnServers(); } - public stopClient() { + public stopClient(): void { this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent); this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice); @@ -288,7 +288,7 @@ export class RoomWidgetClient extends MatrixClient { return this.syncState; } - private setSyncState(state: SyncState) { + private setSyncState(state: SyncState): void { const oldState = this.syncState; this.syncState = state; this.emit(ClientEvent.Sync, state, oldState); @@ -298,7 +298,7 @@ export class RoomWidgetClient extends MatrixClient { await this.widgetApi.transport.reply(ev.detail, {}); } - private onEvent = async (ev: CustomEvent) => { + private onEvent = async (ev: CustomEvent): Promise => { ev.preventDefault(); // Verify the room ID matches, since it's possible for the client to @@ -317,7 +317,7 @@ export class RoomWidgetClient extends MatrixClient { await this.ack(ev); }; - private onToDevice = async (ev: CustomEvent) => { + private onToDevice = async (ev: CustomEvent): Promise => { ev.preventDefault(); const event = new MatrixEvent({ @@ -333,9 +333,11 @@ export class RoomWidgetClient extends MatrixClient { await this.ack(ev); }; - private async watchTurnServers() { + private async watchTurnServers(): Promise { const servers = this.widgetApi.getTurnServers(); - const onClientStopped = () => servers.return(undefined); + const onClientStopped = (): void => { + servers.return(undefined); + }; this.lifecycle!.signal.addEventListener("abort", onClientStopped); try { diff --git a/src/event-mapper.ts b/src/event-mapper.ts index 57d36c9f6..6f2e25c1b 100644 --- a/src/event-mapper.ts +++ b/src/event-mapper.ts @@ -29,7 +29,7 @@ export function eventMapperFor(client: MatrixClient, options: MapperOpts): Event let preventReEmit = Boolean(options.preventReEmit); const decrypt = options.decrypt !== false; - function mapper(plainOldJsObject: Partial) { + function mapper(plainOldJsObject: Partial): MatrixEvent { if (options.toDevice) { delete plainOldJsObject.room_id; } diff --git a/src/filter-component.ts b/src/filter-component.ts index 759c97921..85afb0ea7 100644 --- a/src/filter-component.ts +++ b/src/filter-component.ts @@ -73,7 +73,7 @@ export interface IFilterComponent { * @param {Object} filterJson the definition of this filter JSON, e.g. { 'contains_url': true } */ export class FilterComponent { - constructor(private filterJson: IFilterComponent, public readonly userId?: string | undefined | null) {} + public constructor(private filterJson: IFilterComponent, public readonly userId?: string | undefined | null) {} /** * Checks with the filter component matches the given event diff --git a/src/filter.ts b/src/filter.ts index fb499c4da..57bd0540d 100644 --- a/src/filter.ts +++ b/src/filter.ts @@ -31,7 +31,7 @@ import { MatrixEvent } from "./models/event"; * @param {string} keyNesting * @param {*} val */ -function setProp(obj: object, keyNesting: string, val: any) { +function setProp(obj: object, keyNesting: string, val: any): void { const nestedKeys = keyNesting.split("."); let currentObj = obj; for (let i = 0; i < (nestedKeys.length - 1); i++) { @@ -88,7 +88,7 @@ interface IRoomFilter { * @prop {?string} filterId The filter ID */ export class Filter { - static LAZY_LOADING_MESSAGES_FILTER = { + public static LAZY_LOADING_MESSAGES_FILTER = { lazy_load_members: true, }; @@ -110,7 +110,7 @@ export class Filter { private roomFilter?: FilterComponent; private roomTimelineFilter?: FilterComponent; - constructor(public readonly userId: string | undefined | null, public filterId?: string) {} + public constructor(public readonly userId: string | undefined | null, public filterId?: string) {} /** * Get the ID of this filter on your homeserver (if known) @@ -132,7 +132,7 @@ export class Filter { * Set the JSON body of the filter * @param {Object} definition The filter definition */ - public setDefinition(definition: IFilterDefinition) { + public setDefinition(definition: IFilterDefinition): void { this.definition = definition; // This is all ported from synapse's FilterCollection() @@ -225,7 +225,7 @@ export class Filter { * Set the max number of events to return for each room's timeline. * @param {Number} limit The max number of events to return for each room. */ - public setTimelineLimit(limit: number) { + public setTimelineLimit(limit: number): void { setProp(this.definition, "room.timeline.limit", limit); } @@ -255,7 +255,7 @@ export class Filter { * @param {boolean} includeLeave True to make rooms the user has left appear * in responses. */ - public setIncludeLeaveRooms(includeLeave: boolean) { + public setIncludeLeaveRooms(includeLeave: boolean): void { setProp(this.definition, "room.include_leave", includeLeave); } } diff --git a/src/http-api/errors.ts b/src/http-api/errors.ts index be63c94fd..5ae0a0f50 100644 --- a/src/http-api/errors.ts +++ b/src/http-api/errors.ts @@ -31,7 +31,7 @@ interface IErrorJson extends Partial { * @param {number} httpStatus The HTTP response status code. */ export class HTTPError extends Error { - constructor(msg: string, public readonly httpStatus?: number) { + public constructor(msg: string, public readonly httpStatus?: number) { super(msg); } } @@ -51,7 +51,7 @@ export class MatrixError extends HTTPError { public readonly errcode?: string; public data: IErrorJson; - constructor( + public constructor( errorJson: IErrorJson = {}, public readonly httpStatus?: number, public url?: string, @@ -79,11 +79,11 @@ export class MatrixError extends HTTPError { * @constructor */ export class ConnectionError extends Error { - constructor(message: string, cause?: Error) { + public constructor(message: string, cause?: Error) { super(message + (cause ? `: ${cause.message}` : "")); } - get name() { + public get name(): string { return "ConnectionError"; } } diff --git a/src/http-api/fetch.ts b/src/http-api/fetch.ts index 92413c094..71ba098e3 100644 --- a/src/http-api/fetch.ts +++ b/src/http-api/fetch.ts @@ -41,7 +41,7 @@ export type ResponseType = export class FetchHttpApi { private abortController = new AbortController(); - constructor( + public constructor( private eventEmitter: TypedEventEmitter, public readonly opts: O, ) { diff --git a/src/http-api/index.ts b/src/http-api/index.ts index 0c9b0b623..c7f782d89 100644 --- a/src/http-api/index.ts +++ b/src/http-api/index.ts @@ -77,7 +77,7 @@ export class MatrixHttpApi extends FetchHttpApi { if (global.XMLHttpRequest) { const xhr = new global.XMLHttpRequest(); - const timeoutFn = function() { + const timeoutFn = function(): void { xhr.abort(); defer.reject(new Error("Timeout")); }; @@ -85,7 +85,7 @@ export class MatrixHttpApi extends FetchHttpApi { // set an initial timeout of 30s; we'll advance it each time we get a progress notification let timeoutTimer = callbacks.setTimeout(timeoutFn, 30000); - xhr.onreadystatechange = function() { + xhr.onreadystatechange = function(): void { switch (xhr.readyState) { case global.XMLHttpRequest.DONE: callbacks.clearTimeout(timeoutTimer); @@ -113,7 +113,7 @@ export class MatrixHttpApi extends FetchHttpApi { } }; - xhr.upload.onprogress = (ev: ProgressEvent) => { + xhr.upload.onprogress = (ev: ProgressEvent): void => { callbacks.clearTimeout(timeoutTimer); upload.loaded = ev.loaded; upload.total = ev.total; diff --git a/src/http-api/utils.ts b/src/http-api/utils.ts index c7e394770..504660950 100644 --- a/src/http-api/utils.ts +++ b/src/http-api/utils.ts @@ -36,13 +36,13 @@ export function anySignal(signals: AbortSignal[]): { } { const controller = new AbortController(); - function cleanup() { + function cleanup(): void { for (const signal of signals) { signal.removeEventListener("abort", onAbort); } } - function onAbort() { + function onAbort(): void { controller.abort(); cleanup(); } diff --git a/src/indexeddb-helpers.ts b/src/indexeddb-helpers.ts index 84de7c0e9..695a3145f 100644 --- a/src/indexeddb-helpers.ts +++ b/src/indexeddb-helpers.ts @@ -26,13 +26,13 @@ export function exists(indexedDB: IDBFactory, dbName: string): Promise return new Promise((resolve, reject) => { let exists = true; const req = indexedDB.open(dbName); - req.onupgradeneeded = () => { + req.onupgradeneeded = (): void => { // Since we did not provide an explicit version when opening, this event // should only fire if the DB did not exist before at any version. exists = false; }; - req.onblocked = () => reject(req.error); - req.onsuccess = () => { + req.onblocked = (): void => reject(req.error); + req.onsuccess = (): void => { const db = req.result; db.close(); if (!exists) { @@ -45,6 +45,6 @@ export function exists(indexedDB: IDBFactory, dbName: string): Promise } resolve(exists); }; - req.onerror = ev => reject(req.error); + req.onerror = (): void => reject(req.error); }); } diff --git a/src/interactive-auth.ts b/src/interactive-auth.ts index 80f3e95cf..df4a42c27 100644 --- a/src/interactive-auth.ts +++ b/src/interactive-auth.ts @@ -100,7 +100,7 @@ class NoAuthFlowFoundError extends Error { public name = "NoAuthFlowFoundError"; // eslint-disable-next-line @typescript-eslint/naming-convention, camelcase - constructor(m: string, public readonly required_stages: string[], public readonly flows: IFlow[]) { + public constructor(m: string, public readonly required_stages: string[], public readonly flows: IFlow[]) { super(m); } } @@ -218,7 +218,7 @@ export class InteractiveAuth { // the promise the will resolve/reject when it completes private submitPromise: Promise | null = null; - constructor(opts: IOpts) { + public constructor(opts: IOpts) { this.matrixClient = opts.matrixClient; this.data = opts.authData || {}; this.requestCallback = opts.doRequest; @@ -419,7 +419,7 @@ export class InteractiveAuth { /** * Requests a new email token and sets the email sid for the validation session */ - public requestEmailToken = async () => { + public requestEmailToken = async (): Promise => { if (!this.requestingEmailToken) { logger.trace("Requesting email token. Attempt: " + this.emailAttempt); // If we've picked a flow with email auth, we send the email diff --git a/src/logger.ts b/src/logger.ts index f2fb82167..de1ca6619 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -35,7 +35,7 @@ const DEFAULT_NAMESPACE = "matrix"; // console methods at initialization time by a factory that looks up the console methods // when logging so we always get the current value of console methods. log.methodFactory = function(methodName, logLevel, loggerName) { - return function(this: PrefixedLogger, ...args) { + return function(this: PrefixedLogger, ...args): void { /* eslint-disable @typescript-eslint/no-invalid-this */ if (this.prefix) { args.unshift(this.prefix); @@ -67,7 +67,7 @@ export interface PrefixedLogger extends Logger { prefix: string; } -function extendLogger(logger: Logger) { +function extendLogger(logger: Logger): void { (logger).withPrefix = function(prefix: string): PrefixedLogger { const existingPrefix = this.prefix || ""; return getPrefixedLogger(existingPrefix + prefix); diff --git a/src/matrix.ts b/src/matrix.ts index e89feddeb..421e0e6ed 100644 --- a/src/matrix.ts +++ b/src/matrix.ts @@ -21,6 +21,7 @@ import { MemoryStore } from "./store/memory"; import { MatrixScheduler } from "./scheduler"; import { MatrixClient, ICreateClientOpts } from "./client"; import { RoomWidgetClient, ICapabilities } from "./embedded"; +import { CryptoStore } from "./crypto/store/base"; export * from "./client"; export * from "./embedded"; @@ -64,7 +65,7 @@ export { } from "./webrtc/groupCall"; export type { GroupCall } from "./webrtc/groupCall"; -let cryptoStoreFactory = () => new MemoryCryptoStore; +let cryptoStoreFactory = (): CryptoStore => new MemoryCryptoStore; /** * Configure a different factory to be used for creating crypto stores @@ -72,7 +73,7 @@ let cryptoStoreFactory = () => new MemoryCryptoStore; * @param {Function} fac a function which will return a new * {@link module:crypto.store.base~CryptoStore}. */ -export function setCryptoStoreFactory(fac) { +export function setCryptoStoreFactory(fac: () => CryptoStore): void { cryptoStoreFactory = fac; } diff --git a/src/models/MSC3089TreeSpace.ts b/src/models/MSC3089TreeSpace.ts index 762ef586a..f437eab84 100644 --- a/src/models/MSC3089TreeSpace.ts +++ b/src/models/MSC3089TreeSpace.ts @@ -172,7 +172,7 @@ export class MSC3089TreeSpace { const currentPls = this.room.currentState.getStateEvents(EventType.RoomPowerLevels, ""); if (Array.isArray(currentPls)) throw new Error("Unexpected return type for power levels"); - const pls = currentPls.getContent() || {}; + const pls = currentPls?.getContent() || {}; const viewLevel = pls['users_default'] || 0; const editLevel = pls['events_default'] || 50; const adminLevel = pls['events']?.[EventType.RoomPowerLevels] || 100; @@ -207,7 +207,7 @@ export class MSC3089TreeSpace { const currentPls = this.room.currentState.getStateEvents(EventType.RoomPowerLevels, ""); if (Array.isArray(currentPls)) throw new Error("Unexpected return type for power levels"); - const pls = currentPls.getContent() || {}; + const pls = currentPls?.getContent() || {}; const viewLevel = pls['users_default'] || 0; const editLevel = pls['events_default'] || 50; const adminLevel = pls['events']?.[EventType.RoomPowerLevels] || 100; diff --git a/src/models/beacon.ts b/src/models/beacon.ts index fc817b05e..6e20b229b 100644 --- a/src/models/beacon.ts +++ b/src/models/beacon.ts @@ -56,7 +56,7 @@ export class Beacon extends TypedEventEmitter; private _latestLocationEvent?: MatrixEvent; - constructor( + public constructor( private rootEvent: MatrixEvent, ) { super(); @@ -180,7 +180,7 @@ export class Beacon extends TypedEventEmitter { + private clearLatestLocation = (): void => { this._latestLocationEvent = undefined; this.emit(BeaconEvent.LocationUpdate, this.latestLocationState!); }; diff --git a/src/models/event-context.ts b/src/models/event-context.ts index a1a43e98f..60252627b 100644 --- a/src/models/event-context.ts +++ b/src/models/event-context.ts @@ -42,7 +42,7 @@ export class EventContext { * * @constructor */ - constructor(public readonly ourEvent: MatrixEvent) { + public constructor(public readonly ourEvent: MatrixEvent) { this.timeline = [ourEvent]; } diff --git a/src/models/event-timeline-set.ts b/src/models/event-timeline-set.ts index a69715dc3..6dd2a0e77 100644 --- a/src/models/event-timeline-set.ts +++ b/src/models/event-timeline-set.ts @@ -36,7 +36,7 @@ if (DEBUG) { // using bind means that we get to keep useful line numbers in the console debuglog = logger.log.bind(logger); } else { - debuglog = function() {}; + debuglog = function(): void {}; } interface IOpts { @@ -135,7 +135,7 @@ export class EventTimelineSet extends TypedEventEmitterThis property is experimental and may change. */ - constructor(public event: Partial = {}) { + public constructor(public event: Partial = {}) { super(); // intern the values of matrix events to force share strings and reduce the @@ -352,7 +352,7 @@ export class MatrixEvent extends TypedEventEmitter { await this.client.redactEvent(event.getRoomId()!, event.getId()!); } @@ -314,7 +314,7 @@ export class IgnoredInvites { /** * Modify in place the `IGNORE_INVITES_POLICIES` object from account data. */ - private async withIgnoreInvitesPolicies(cb: (ignoreInvitesPolicies: {[key: string]: any}) => void) { + private async withIgnoreInvitesPolicies(cb: (ignoreInvitesPolicies: {[key: string]: any}) => void): Promise { const { policies, ignoreInvitesPolicies } = this.getPoliciesAndIgnoreInvitesPolicies(); cb(ignoreInvitesPolicies); policies[IGNORE_INVITES_ACCOUNT_EVENT_KEY.name] = ignoreInvitesPolicies; diff --git a/src/models/related-relations.ts b/src/models/related-relations.ts index 09c618ae8..f619ea059 100644 --- a/src/models/related-relations.ts +++ b/src/models/related-relations.ts @@ -29,11 +29,11 @@ export class RelatedRelations { return this.relations.reduce((c, p) => [...c, ...p.getRelations()], []); } - public on(ev: T, fn: Listener) { + public on(ev: T, fn: Listener): void { this.relations.forEach(r => r.on(ev, fn)); } - public off(ev: T, fn: Listener) { + public off(ev: T, fn: Listener): void { this.relations.forEach(r => r.off(ev, fn)); } } diff --git a/src/models/relations-container.ts b/src/models/relations-container.ts index edb261610..55e098a3f 100644 --- a/src/models/relations-container.ts +++ b/src/models/relations-container.ts @@ -26,7 +26,7 @@ export class RelationsContainer { // this.relations.get(parentEventId).get(relationType).get(relationEventType) private relations = new Map>>(); - constructor(private readonly client: MatrixClient, private readonly room?: Room) { + public constructor(private readonly client: MatrixClient, private readonly room?: Room) { } /** @@ -98,7 +98,7 @@ export class RelationsContainer { const relation = event.getRelation(); if (!relation) return; - const onEventDecrypted = () => { + const onEventDecrypted = (): void => { if (event.isDecryptionFailure()) { // This could for example happen if the encryption keys are not yet available. // The event may still be decrypted later. Register the listener again. diff --git a/src/models/relations.ts b/src/models/relations.ts index a384c9b7f..00fb7f6e9 100644 --- a/src/models/relations.ts +++ b/src/models/relations.ts @@ -60,7 +60,7 @@ export class Relations extends TypedEventEmitter { if (this.relationEventIds.has(event.getId()!)) { return; } @@ -123,7 +123,7 @@ export class Relations extends TypedEventEmitter { if (!this.relations.has(event)) { return; } @@ -160,7 +160,7 @@ export class Relations extends TypedEventEmitter { + private onEventStatus = (event: MatrixEvent, status: EventStatus | null): void => { if (!event.isSending()) { // Sending is done, so we don't need to listen anymore event.removeListener(MatrixEventEvent.Status, this.onEventStatus); @@ -356,7 +356,7 @@ export class Relations extends TypedEventEmitter { if (this.targetEvent) { return; } @@ -374,7 +374,7 @@ export class Relations extends TypedEventEmitter * events dictionary, keyed on the event type and then the state_key value. * @prop {string} paginationToken The pagination token for this state. */ - constructor(public readonly roomId: string, private oobMemberFlags = { status: OobStatus.NotStarted }) { + public constructor(public readonly roomId: string, private oobMemberFlags = { status: OobStatus.NotStarted }) { super(); this.updateModifiedTime(); } @@ -250,8 +250,8 @@ export class RoomState extends TypedEventEmitter * undefined, else a single event (or null if no match found). */ public getStateEvents(eventType: EventType | string): MatrixEvent[]; - public getStateEvents(eventType: EventType | string, stateKey: string): MatrixEvent; - public getStateEvents(eventType: EventType | string, stateKey?: string) { + public getStateEvents(eventType: EventType | string, stateKey: string): MatrixEvent | null; + public getStateEvents(eventType: EventType | string, stateKey?: string): MatrixEvent[] | MatrixEvent | null { if (!this.events.has(eventType)) { // no match return stateKey === undefined ? [] : null; @@ -342,7 +342,7 @@ export class RoomState extends TypedEventEmitter * @fires module:client~MatrixClient#event:"RoomState.events" * @fires module:client~MatrixClient#event:"RoomStateEvent.Marker" */ - public setStateEvents(stateEvents: MatrixEvent[], markerFoundOptions?: IMarkerFoundOptions) { + public setStateEvents(stateEvents: MatrixEvent[], markerFoundOptions?: IMarkerFoundOptions): void { this.updateModifiedTime(); // update the core event dict diff --git a/src/models/room-summary.ts b/src/models/room-summary.ts index d01b470ae..ba279d2d4 100644 --- a/src/models/room-summary.ts +++ b/src/models/room-summary.ts @@ -46,6 +46,6 @@ interface IInfo { * @param {Number} info.timestamp The timestamp for this room. */ export class RoomSummary { - constructor(public readonly roomId: string, info?: IInfo) {} + public constructor(public readonly roomId: string, info?: IInfo) {} } diff --git a/src/models/room.ts b/src/models/room.ts index 21b06a6ce..0d1694027 100644 --- a/src/models/room.ts +++ b/src/models/room.ts @@ -317,7 +317,7 @@ export class Room extends ReadReceipt { * @param {boolean} [opts.timelineSupport = false] Set to true to enable improved * timeline support. */ - constructor( + public constructor( public readonly roomId: string, public readonly client: MatrixClient, public readonly myUserId: string, @@ -1950,7 +1950,7 @@ export class Room extends ReadReceipt { )); } - private updateThreadRootEvents = (thread: Thread, toStartOfTimeline: boolean) => { + private updateThreadRootEvents = (thread: Thread, toStartOfTimeline: boolean): void => { if (thread.length) { this.updateThreadRootEvent(this.threadsTimelineSets?.[0], thread, toStartOfTimeline); if (thread.hasCurrentUserParticipated) { @@ -1963,7 +1963,7 @@ export class Room extends ReadReceipt { timelineSet: Optional, thread: Thread, toStartOfTimeline: boolean, - ) => { + ): void => { if (timelineSet && thread.rootEvent) { if (Thread.hasServerSideSupport) { timelineSet.addLiveEvent(thread.rootEvent, { @@ -2050,7 +2050,7 @@ export class Room extends ReadReceipt { redactedEvent.getType(), redactedEvent.getStateKey()!, ); - if (currentStateEvent.getId() === redactedEvent.getId()) { + if (currentStateEvent?.getId() === redactedEvent.getId()) { this.currentState.setStateEvents([redactedEvent]); } } @@ -2913,7 +2913,7 @@ export class Room extends ReadReceipt { let excludedUserIds: string[] = []; const mFunctionalMembers = this.currentState.getStateEvents(UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, ""); if (Array.isArray(mFunctionalMembers?.getContent().service_members)) { - excludedUserIds = mFunctionalMembers.getContent().service_members; + excludedUserIds = mFunctionalMembers!.getContent().service_members; } // get members that are NOT ourselves and are actually in the room. @@ -3077,7 +3077,7 @@ export class Room extends ReadReceipt { originalEvent.applyVisibilityEvent(visibilityChange); } - private redactVisibilityChangeEvent(event: MatrixEvent) { + private redactVisibilityChangeEvent(event: MatrixEvent): void { // Sanity checks. if (!event.isVisibilityEvent) { throw new Error("expected a visibility change event"); diff --git a/src/models/search-result.ts b/src/models/search-result.ts index 99f9c5dda..f598301d7 100644 --- a/src/models/search-result.ts +++ b/src/models/search-result.ts @@ -60,5 +60,5 @@ export class SearchResult { * * @constructor */ - constructor(public readonly rank: number, public readonly context: EventContext) {} + public constructor(public readonly rank: number, public readonly context: EventContext) {} } diff --git a/src/models/thread.ts b/src/models/thread.ts index 3c02558bf..5abe63d6c 100644 --- a/src/models/thread.ts +++ b/src/models/thread.ts @@ -94,7 +94,7 @@ export class Thread extends ReadReceipt { public initialEventsFetched = !Thread.hasServerSideSupport; - constructor( + public constructor( public readonly id: string, public rootEvent: MatrixEvent | undefined, opts: IThreadOpts, @@ -167,7 +167,7 @@ export class Thread extends ReadReceipt { Thread.hasServerSideFwdPaginationSupport = status; } - private onBeforeRedaction = (event: MatrixEvent, redaction: MatrixEvent) => { + private onBeforeRedaction = (event: MatrixEvent, redaction: MatrixEvent): void => { if (event?.isRelation(THREAD_RELATION_TYPE.name) && this.room.eventShouldLiveIn(event).threadId === this.id && event.getId() !== this.id && // the root event isn't counted in the length so ignore this redaction @@ -178,7 +178,7 @@ export class Thread extends ReadReceipt { } }; - private onRedaction = async (event: MatrixEvent) => { + private onRedaction = async (event: MatrixEvent): Promise => { if (event.threadRootId !== this.id) return; // ignore redactions for other timelines if (this.replyCount <= 0) { for (const threadEvent of this.events) { @@ -192,7 +192,7 @@ export class Thread extends ReadReceipt { } }; - private onEcho = async (event: MatrixEvent) => { + private onEcho = async (event: MatrixEvent): Promise => { if (event.threadRootId !== this.id) return; // ignore echoes for other timelines if (this.lastEvent === event) return; if (!event.isRelation(THREAD_RELATION_TYPE.name)) return; @@ -349,7 +349,7 @@ export class Thread extends ReadReceipt { /** * Finds an event by ID in the current thread */ - public findEventById(eventId: string) { + public findEventById(eventId: string): MatrixEvent | undefined { // Check the lastEvent as it may have been created based on a bundled relationship and not in a timeline if (this.lastEvent?.getId() === eventId) { return this.lastEvent; @@ -361,7 +361,7 @@ export class Thread extends ReadReceipt { /** * Return last reply to the thread, if known. */ - public lastReply(matches: (ev: MatrixEvent) => boolean = () => true): MatrixEvent | null { + public lastReply(matches: (ev: MatrixEvent) => boolean = (): boolean => true): MatrixEvent | null { for (let i = this.events.length - 1; i >= 0; i--) { const event = this.events[i]; if (matches(event)) { diff --git a/src/models/user.ts b/src/models/user.ts index 31d113dbe..5d92ca494 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -76,7 +76,7 @@ export class User extends TypedEventEmitter { * @prop {Object} events The events describing this user. * @prop {MatrixEvent} events.presence The m.presence event for this user. */ - constructor(public readonly userId: string) { + public constructor(public readonly userId: string) { super(); this.displayName = userId; this.rawDisplayName = userId; diff --git a/src/pushprocessor.ts b/src/pushprocessor.ts index 7c127d4c7..4538b9721 100644 --- a/src/pushprocessor.ts +++ b/src/pushprocessor.ts @@ -126,7 +126,7 @@ export class PushProcessor { * @constructor * @param {Object} client The Matrix client object to use */ - constructor(private readonly client: MatrixClient) {} + public constructor(private readonly client: MatrixClient) {} /** * Convert a list of actions into a object with the actions as keys and their values diff --git a/src/realtime-callbacks.ts b/src/realtime-callbacks.ts index 222c94763..4677b0c1e 100644 --- a/src/realtime-callbacks.ts +++ b/src/realtime-callbacks.ts @@ -48,7 +48,7 @@ type Callback = { const callbackList: Callback[] = []; // var debuglog = logger.log.bind(logger); -const debuglog = function(...params: any[]) {}; +const debuglog = function(...params: any[]): void {}; /** * reimplementation of window.setTimeout, which will call the callback if diff --git a/src/rendezvous/MSC3906Rendezvous.ts b/src/rendezvous/MSC3906Rendezvous.ts index c18af5912..a93d4c476 100644 --- a/src/rendezvous/MSC3906Rendezvous.ts +++ b/src/rendezvous/MSC3906Rendezvous.ts @@ -143,11 +143,11 @@ export class MSC3906Rendezvous { return await this.channel.receive() as MSC3906RendezvousPayload; } - private async send(payload: MSC3906RendezvousPayload) { + private async send(payload: MSC3906RendezvousPayload): Promise { await this.channel.send(payload); } - public async declineLoginOnExistingDevice() { + public async declineLoginOnExistingDevice(): Promise { logger.info('User declined sign in'); await this.send({ type: PayloadType.Finish, outcome: Outcome.Declined }); } diff --git a/src/rendezvous/RendezvousError.ts b/src/rendezvous/RendezvousError.ts index 1c1f6af9c..8b76fc118 100644 --- a/src/rendezvous/RendezvousError.ts +++ b/src/rendezvous/RendezvousError.ts @@ -17,7 +17,7 @@ limitations under the License. import { RendezvousFailureReason } from "."; export class RendezvousError extends Error { - constructor(message: string, public readonly code: RendezvousFailureReason) { + public constructor(message: string, public readonly code: RendezvousFailureReason) { super(message); } } diff --git a/src/room-hierarchy.ts b/src/room-hierarchy.ts index 6d95db2a5..c15f2ac56 100644 --- a/src/room-hierarchy.ts +++ b/src/room-hierarchy.ts @@ -47,7 +47,7 @@ export class RoomHierarchy { * @param {boolean} suggestedOnly whether to only return rooms with suggested=true. * @constructor */ - constructor( + public constructor( public readonly root: Room, private readonly pageSize?: number, private readonly maxDepth?: number, diff --git a/src/scheduler.ts b/src/scheduler.ts index 7a1a99ded..f6d66198a 100644 --- a/src/scheduler.ts +++ b/src/scheduler.ts @@ -97,7 +97,7 @@ export class MatrixScheduler { * @see module:scheduler~queueAlgorithm */ // eslint-disable-next-line @typescript-eslint/naming-convention - public static QUEUE_MESSAGES(event: MatrixEvent) { + public static QUEUE_MESSAGES(event: MatrixEvent): "message" | null { // enqueue messages or events that associate with another event (redactions and relations) if (event.getType() === EventType.RoomMessage || event.hasAssocation()) { // put these events in the 'message' queue. @@ -116,7 +116,7 @@ export class MatrixScheduler { private activeQueues: string[] = []; private procFn: ProcessFunction | null = null; - constructor( + public constructor( public readonly retryAlgorithm = MatrixScheduler.RETRY_BACKOFF_RATELIMIT, public readonly queueAlgorithm = MatrixScheduler.QUEUE_MESSAGES, ) {} @@ -283,7 +283,7 @@ export class MatrixScheduler { } } -function debuglog(...args: any[]) { +function debuglog(...args: any[]): void { if (DEBUG) { logger.log(...args); } diff --git a/src/sliding-sync-sdk.ts b/src/sliding-sync-sdk.ts index 962d824a8..4f3867f54 100644 --- a/src/sliding-sync-sdk.ts +++ b/src/sliding-sync-sdk.ts @@ -45,7 +45,7 @@ import { RoomMemberEvent } from "./models/room-member"; const FAILED_SYNC_ERROR_THRESHOLD = 3; class ExtensionE2EE implements Extension { - constructor(private readonly crypto: Crypto) {} + public constructor(private readonly crypto: Crypto) {} public name(): string { return "e2ee"; @@ -95,7 +95,7 @@ class ExtensionE2EE implements Extension { class ExtensionToDevice implements Extension { private nextBatch: string | null = null; - constructor(private readonly client: MatrixClient) {} + public constructor(private readonly client: MatrixClient) {} public name(): string { return "to_device"; @@ -170,7 +170,7 @@ class ExtensionToDevice implements Extension { } class ExtensionAccountData implements Extension { - constructor(private readonly client: MatrixClient) {} + public constructor(private readonly client: MatrixClient) {} public name(): string { return "account_data"; @@ -244,7 +244,7 @@ export class SlidingSyncSdk { private failCount = 0; private notifEvents: MatrixEvent[] = []; // accumulator of sync events in the current sync response - constructor( + public constructor( private readonly slidingSync: SlidingSync, private readonly client: MatrixClient, private readonly opts: Partial = {}, @@ -256,7 +256,7 @@ export class SlidingSyncSdk { this.opts.experimentalThreadSupport = this.opts.experimentalThreadSupport === true; if (!opts.canResetEntireTimeline) { - opts.canResetEntireTimeline = (_roomId: string) => { + opts.canResetEntireTimeline = (_roomId: string): boolean => { return false; }; } @@ -348,7 +348,7 @@ export class SlidingSyncSdk { * Sync rooms the user has left. * @return {Promise} Resolved when they've been added to the store. */ - public async syncLeftRooms() { + public async syncLeftRooms(): Promise { return []; // TODO } @@ -457,7 +457,7 @@ export class SlidingSyncSdk { return false; } - private async processRoomData(client: MatrixClient, room: Room, roomData: MSC3575RoomData) { + private async processRoomData(client: MatrixClient, room: Room, roomData: MSC3575RoomData): Promise { roomData = ensureNameEvent(client, room.roomId, roomData); const stateEvents = mapEvents(this.client, room.roomId, roomData.required_state); // Prevent events from being decrypted ahead of time @@ -632,7 +632,7 @@ export class SlidingSyncSdk { // we'll purge this once we've fully processed the sync response this.addNotifications(timelineEvents); - const processRoomEvent = async (e: MatrixEvent) => { + const processRoomEvent = async (e: MatrixEvent): Promise => { client.emit(ClientEvent.Event, e); if (e.isState() && e.getType() == EventType.RoomEncryption && this.opts.crypto) { await this.opts.crypto.onCryptoEvent(e); @@ -767,7 +767,7 @@ export class SlidingSyncSdk { /** * Main entry point. Blocks until stop() is called. */ - public async sync() { + public async sync(): Promise { logger.debug("Sliding sync init loop"); // 1) We need to get push rules so we can check if events should bing as we get diff --git a/src/sliding-sync.ts b/src/sliding-sync.ts index e091c9883..171bf55c3 100644 --- a/src/sliding-sync.ts +++ b/src/sliding-sync.ts @@ -169,7 +169,7 @@ class SlidingList { * Construct a new sliding list. * @param {MSC3575List} list The range, sort and filter values to use for this list. */ - constructor(list: MSC3575List) { + public constructor(list: MSC3575List) { this.replaceList(list); } @@ -373,7 +373,7 @@ export class SlidingSync extends TypedEventEmitter { this.abortController = new AbortController(); let currentPos: string | undefined; diff --git a/src/store/indexeddb-local-backend.ts b/src/store/indexeddb-local-backend.ts index 597ed5117..af4b5fc65 100644 --- a/src/store/indexeddb-local-backend.ts +++ b/src/store/indexeddb-local-backend.ts @@ -25,7 +25,7 @@ import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDevice type DbMigration = (db: IDBDatabase) => void; const DB_MIGRATIONS: DbMigration[] = [ - (db) => { + (db): void => { // Make user store, clobber based on user ID. (userId property of User objects) db.createObjectStore("users", { keyPath: ["userId"] }); @@ -36,15 +36,15 @@ const DB_MIGRATIONS: DbMigration[] = [ // Make /sync store (sync tokens, room data, etc), always clobber (const key). db.createObjectStore("sync", { keyPath: ["clobber"] }); }, - (db) => { + (db): void => { const oobMembersStore = db.createObjectStore( "oob_membership_events", { keyPath: ["room_id", "state_key"], }); oobMembersStore.createIndex("room", "room_id"); }, - (db) => { db.createObjectStore("client_options", { keyPath: ["clobber"] }); }, - (db) => { db.createObjectStore("to_device_queue", { autoIncrement: true }); }, + (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; @@ -67,11 +67,11 @@ function selectQuery( const query = store.openCursor(keyRange); return new Promise((resolve, reject) => { const results: T[] = []; - query.onerror = () => { + query.onerror = (): void => { reject(new Error("Query failed: " + query.error)); }; // collect results - query.onsuccess = () => { + query.onsuccess = (): void => { const cursor = query.result; if (!cursor) { resolve(results); @@ -85,10 +85,10 @@ function selectQuery( function txnAsPromise(txn: IDBTransaction): Promise { return new Promise((resolve, reject) => { - txn.oncomplete = function(event) { + txn.oncomplete = function(event): void { resolve(event); }; - txn.onerror = function() { + txn.onerror = function(): void { reject(txn.error); }; }); @@ -96,10 +96,10 @@ function txnAsPromise(txn: IDBTransaction): Promise { function reqAsEventPromise(req: IDBRequest): Promise { return new Promise((resolve, reject) => { - req.onsuccess = function(event) { + req.onsuccess = function(event): void { resolve(event); }; - req.onerror = function() { + req.onerror = function(): void { reject(req.error); }; }); @@ -107,8 +107,8 @@ function reqAsEventPromise(req: IDBRequest): Promise { function reqAsPromise(req: IDBRequest): Promise { return new Promise((resolve, reject) => { - req.onsuccess = () => resolve(req); - req.onerror = (err) => reject(err); + req.onsuccess = (): void => resolve(req); + req.onerror = (err): void => reject(err); }); } @@ -141,7 +141,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { * @param {string=} dbName Optional database name. The same name must be used * to open the same database. */ - constructor(private readonly indexedDB: IDBFactory, dbName = "default") { + public constructor(private readonly indexedDB: IDBFactory, dbName = "default") { this.dbName = "matrix-js-sdk:" + dbName; this.syncAccumulator = new SyncAccumulator(); } @@ -161,7 +161,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`); const req = this.indexedDB.open(this.dbName, VERSION); - req.onupgradeneeded = (ev) => { + req.onupgradeneeded = (ev): void => { const db = req.result; const oldVersion = ev.oldVersion; logger.log( @@ -176,22 +176,22 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { }); }; - req.onblocked = () => { + 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(() => { + 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 = () => { + this.db.onversionchange = (): void => { this.db?.close(); }; - return this.init(); + await this.init(); }); } @@ -204,7 +204,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { * Having connected, load initial data from the database and prepare for use * @return {Promise} Resolves on success */ - private init() { + private init(): Promise { return Promise.all([ this.loadAccountData(), this.loadSyncData(), @@ -243,7 +243,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { // were all known already let oobWritten = false; - request.onsuccess = () => { + request.onsuccess = (): void => { const cursor = request.result; if (!cursor) { // Unknown room @@ -260,7 +260,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { } cursor.continue(); }; - request.onerror = (err) => { + request.onerror = (err): void => { reject(err); }; }).then((events) => { @@ -346,11 +346,11 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { logger.log(`Removing indexeddb instance: ${this.dbName}`); const req = this.indexedDB.deleteDatabase(this.dbName); - req.onblocked = () => { + req.onblocked = (): void => { logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`); }; - req.onerror = () => { + 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. @@ -358,7 +358,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend { resolve(); }; - req.onsuccess = () => { + req.onsuccess = (): void => { logger.log(`Removed indexeddb instance: ${this.dbName}`); resolve(); }; diff --git a/src/store/indexeddb-remote-backend.ts b/src/store/indexeddb-remote-backend.ts index 39486fe23..1ca6fc03a 100644 --- a/src/store/indexeddb-remote-backend.ts +++ b/src/store/indexeddb-remote-backend.ts @@ -42,7 +42,7 @@ export class RemoteIndexedDBStoreBackend implements IIndexedDBBackend { * @param {string=} dbName Optional database name. The same name must be used * to open the same database. */ - constructor( + public constructor( private readonly workerFactory: () => Worker, private readonly dbName?: string, ) {} diff --git a/src/store/indexeddb-store-worker.ts b/src/store/indexeddb-store-worker.ts index 691a21f86..57e7da983 100644 --- a/src/store/indexeddb-store-worker.ts +++ b/src/store/indexeddb-store-worker.ts @@ -45,7 +45,7 @@ export class IndexedDBStoreWorker { * @param {function} postMessage The web worker postMessage function that * should be used to communicate back to the main script. */ - constructor(private readonly postMessage: InstanceType["postMessage"]) {} + public constructor(private readonly postMessage: InstanceType["postMessage"]) {} /** * Passes a message event from the main script into the class. This method diff --git a/src/store/indexeddb.ts b/src/store/indexeddb.ts index 961e66fd3..55f8261fa 100644 --- a/src/store/indexeddb.ts +++ b/src/store/indexeddb.ts @@ -53,7 +53,7 @@ type EventHandlerMap = { }; export class IndexedDBStore extends MemoryStore { - static exists(indexedDB: IDBFactory, dbName: string): Promise { + public static exists(indexedDB: IDBFactory, dbName: string): Promise { return LocalIndexedDBStoreBackend.exists(indexedDB, dbName); } @@ -109,7 +109,7 @@ export class IndexedDBStore extends MemoryStore { * this API if you need to perform specific indexeddb actions like deleting the * database. */ - constructor(opts: IOpts) { + public constructor(opts: IOpts) { super(opts); if (!opts.indexedDB) { diff --git a/src/store/memory.ts b/src/store/memory.ts index 24b79fccb..f24ab2d97 100644 --- a/src/store/memory.ts +++ b/src/store/memory.ts @@ -69,7 +69,7 @@ export class MemoryStore implements IStore { private pendingToDeviceBatches: IndexedToDeviceBatch[] = []; private nextToDeviceBatchId = 0; - constructor(opts: IOpts = {}) { + public constructor(opts: IOpts = {}) { this.localStorage = opts.localStorage; } @@ -90,7 +90,7 @@ export class MemoryStore implements IStore { * Set the token to stream from. * @param {string} token The token to stream from. */ - public setSyncToken(token: string) { + public setSyncToken(token: string): void { this.syncToken = token; } @@ -98,7 +98,7 @@ export class MemoryStore implements IStore { * Store the given room. * @param {Room} room The room to be stored. All properties must be stored. */ - public storeRoom(room: Room) { + 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. @@ -116,7 +116,7 @@ export class MemoryStore implements IStore { * @param {RoomState} state * @param {RoomMember} member */ - private onRoomMember = (event: MatrixEvent | null, state: RoomState, member: RoomMember) => { + 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 (!) @@ -217,7 +217,7 @@ export class MemoryStore implements IStore { * @param {string} token The token associated with these events. * @param {boolean} toStart True if these are paginated results. */ - public storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean) { + public storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean): void { // no-op because they've already been added to the room instance. } @@ -275,7 +275,7 @@ export class MemoryStore implements IStore { * @param {string} filterName * @param {string} filterId */ - public setFilterIdByName(filterName: string, filterId?: string) { + public setFilterIdByName(filterName: string, filterId?: string): void { if (!this.localStorage) { return; } diff --git a/src/store/stub.ts b/src/store/stub.ts index 64a35d513..746bc521f 100644 --- a/src/store/stub.ts +++ b/src/store/stub.ts @@ -56,7 +56,7 @@ export class StubStore implements IStore { * Set the sync token. * @param {string} token */ - public setSyncToken(token: string) { + public setSyncToken(token: string): void { this.fromToken = token; } @@ -64,7 +64,7 @@ export class StubStore implements IStore { * No-op. * @param {Room} room */ - public storeRoom(room: Room) {} + public storeRoom(room: Room): void {} /** * No-op. @@ -87,7 +87,7 @@ export class StubStore implements IStore { * Permanently delete a room. * @param {string} roomId */ - public removeRoom(roomId: string) { + public removeRoom(roomId: string): void { return; } @@ -103,7 +103,7 @@ export class StubStore implements IStore { * No-op. * @param {User} user */ - public storeUser(user: User) {} + public storeUser(user: User): void {} /** * No-op. @@ -139,13 +139,13 @@ export class StubStore implements IStore { * @param {string} token The token associated with these events. * @param {boolean} toStart True if these are paginated results. */ - public storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean) {} + public storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean): void {} /** * Store a filter. * @param {Filter} filter */ - public storeFilter(filter: Filter) {} + public storeFilter(filter: Filter): void {} /** * Retrieve a filter. @@ -171,13 +171,13 @@ export class StubStore implements IStore { * @param {string} filterName * @param {string} filterId */ - public setFilterIdByName(filterName: string, filterId?: string) {} + public setFilterIdByName(filterName: string, filterId?: string): void {} /** * Store user-scoped account data events * @param {Array} events The events to store. */ - public storeAccountDataEvents(events: MatrixEvent[]) {} + public storeAccountDataEvents(events: MatrixEvent[]): void {} /** * Get account data event by event type @@ -209,7 +209,7 @@ export class StubStore implements IStore { /** * Save does nothing as there is no backing data store. */ - public save() {} + public save(): void {} /** * Startup does nothing. diff --git a/src/sync-accumulator.ts b/src/sync-accumulator.ts index 484e96e4f..19d5cf131 100644 --- a/src/sync-accumulator.ts +++ b/src/sync-accumulator.ts @@ -211,7 +211,7 @@ export class SyncAccumulator { * never be more. This cannot be 0 or else it makes it impossible to scroll * back in a room. Default: 50. */ - constructor(private readonly opts: IOpts = {}) { + public constructor(private readonly opts: IOpts = {}) { this.opts.maxTimelineEntries = this.opts.maxTimelineEntries || 50; } diff --git a/src/sync.ts b/src/sync.ts index d85bfc4cb..f32ccf7d2 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -106,7 +106,7 @@ function getFilterName(userId: string, suffix?: string): string { return `FILTER_SYNC_${userId}` + (suffix ? "_" + suffix : ""); } -function debuglog(...params) { +function debuglog(...params): void { if (!DEBUG) return; logger.log(...params); } @@ -175,7 +175,7 @@ export class SyncApi { private failedSyncCount = 0; // Number of consecutive failed /sync requests private storeIsInvalid = false; // flag set if the store needs to be cleared before we can start - constructor(private readonly client: MatrixClient, private readonly opts: Partial = {}) { + public constructor(private readonly client: MatrixClient, private readonly opts: Partial = {}) { this.opts.initialSyncLimit = this.opts.initialSyncLimit ?? 8; this.opts.resolveInvitesToProfiles = this.opts.resolveInvitesToProfiles || false; this.opts.pollTimeout = this.opts.pollTimeout || (30 * 1000); @@ -183,7 +183,7 @@ export class SyncApi { this.opts.experimentalThreadSupport = this.opts.experimentalThreadSupport === true; if (!opts.canResetEntireTimeline) { - opts.canResetEntireTimeline = (roomId: string) => { + opts.canResetEntireTimeline = (roomId: string): boolean => { return false; }; } @@ -554,7 +554,7 @@ export class SyncApi { return false; } - private getPushRules = async () => { + private getPushRules = async (): Promise => { try { debuglog("Getting push rules..."); const result = await this.client.getPushRules(); @@ -572,7 +572,7 @@ export class SyncApi { } }; - private buildDefaultFilter = () => { + private buildDefaultFilter = (): Filter => { const filter = new Filter(this.client.credentials.userId); if (this.client.canSupport.get(Feature.ThreadUnreadNotifications) !== ServerSupport.Unsupported) { filter.setUnreadThreadNotifications(true); @@ -580,7 +580,7 @@ export class SyncApi { return filter; }; - private checkLazyLoadStatus = async () => { + private checkLazyLoadStatus = async (): Promise => { debuglog("Checking lazy load status..."); if (this.opts.lazyLoadMembers && this.client.isGuest()) { this.opts.lazyLoadMembers = false; @@ -1389,7 +1389,7 @@ export class SyncApi { this.processEventsForNotifs(room, events); - const processRoomEvent = async (e) => { + const processRoomEvent = async (e): Promise => { client.emit(ClientEvent.Event, e); if (e.isState() && e.getType() == "m.room.encryption" && this.opts.crypto) { await this.opts.crypto.onCryptoEvent(e); @@ -1521,7 +1521,7 @@ export class SyncApi { * @param {boolean} connDidFail True if a connectivity failure has been detected. Optional. */ private pokeKeepAlive(connDidFail = false): void { - const success = () => { + const success = (): void => { clearTimeout(this.keepAliveTimer); if (this.connectionReturnedDefer) { this.connectionReturnedDefer.resolve(connDidFail); diff --git a/src/timeline-window.ts b/src/timeline-window.ts index c5560bdf4..5498600a9 100644 --- a/src/timeline-window.ts +++ b/src/timeline-window.ts @@ -32,7 +32,7 @@ const DEBUG = false; /** * @private */ -const debuglog = DEBUG ? logger.log.bind(logger) : function() {}; +const debuglog = DEBUG ? logger.log.bind(logger) : function(): void {}; /** * the number of times we ask the server for more events before giving up @@ -84,7 +84,7 @@ export class TimelineWindow { * * @constructor */ - constructor( + public constructor( private readonly client: MatrixClient, private readonly timelineSet: EventTimelineSet, opts: IOpts = {}, @@ -104,7 +104,7 @@ export class TimelineWindow { public load(initialEventId?: string, initialWindowSize = 20): Promise { // given an EventTimeline, find the event we were looking for, and initialise our // fields so that the event in question is in the middle of the window. - const initFields = (timeline: Optional) => { + const initFields = (timeline: Optional): void => { if (!timeline) { throw new Error("No timeline given to initFields"); } @@ -430,7 +430,7 @@ export class TimelineIndex { public pendingPaginate?: Promise; // index: the indexes are relative to BaseIndex, so could well be negative. - constructor(public timeline: EventTimeline, public index: number) {} + public constructor(public timeline: EventTimeline, public index: number) {} /** * @return {number} the minimum possible value for the index in the current diff --git a/src/utils.ts b/src/utils.ts index d4364f18a..201be5b3e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -178,7 +178,7 @@ export function removeElement( * @param {*} value The thing to check. * @return {boolean} True if it is a function. */ -export function isFunction(value: any) { +export function isFunction(value: any): boolean { return Object.prototype.toString.call(value) === "[object Function]"; } @@ -189,7 +189,7 @@ export function isFunction(value: any) { * @throws If the object is missing keys. */ // note using 'keys' here would shadow the 'keys' function defined above -export function checkObjectHasKeys(obj: object, keys: string[]) { +export function checkObjectHasKeys(obj: object, keys: string[]): void { for (const key of keys) { if (!obj.hasOwnProperty(key)) { throw new Error("Missing required key: " + key); @@ -383,7 +383,7 @@ export function globToRegexp(glob: string, extended = false): string { if (!extended) { replacements.push([ /\\\[(!|)(.*)\\]/g, - (_match: string, neg: string, pat: string) => [ + (_match: string, neg: string, pat: string): string => [ '[', neg ? '^' : '', pat.replace(/\\-/, '-'), @@ -490,7 +490,7 @@ export function simpleRetryOperation(promiseFn: (attempt: number) => Promise< * The default alphabet used by string averaging in this SDK. This matches * all usefully printable ASCII characters (0x20-0x7E, inclusive). */ -export const DEFAULT_ALPHABET = (() => { +export const DEFAULT_ALPHABET = ((): string => { let str = ""; for (let c = 0x20; c <= 0x7E; c++) { str += String.fromCharCode(c); diff --git a/src/webrtc/audioContext.ts b/src/webrtc/audioContext.ts index 8a9ceb15d..0e08574b8 100644 --- a/src/webrtc/audioContext.ts +++ b/src/webrtc/audioContext.ts @@ -35,7 +35,7 @@ export const acquireContext = (): AudioContext => { * released, allowing the context and associated hardware resources to be * cleaned up if nothing else is using it. */ -export const releaseContext = () => { +export const releaseContext = (): void => { refCount--; if (refCount === 0) { audioContext?.close(); diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index 22a6d8ec1..0e4a664fb 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -268,7 +268,7 @@ const CALL_TIMEOUT_MS = 60000; export class CallError extends Error { public readonly code: string; - constructor(code: CallErrorCode, msg: string, err: Error) { + public constructor(code: CallErrorCode, msg: string, err: Error) { // Still don't think there's any way to have proper nested errors super(msg + ": " + err); @@ -404,7 +404,7 @@ export class MatrixCall extends TypedEventEmitter !feed.isLocal()); } - private async initOpponentCrypto() { + private async initOpponentCrypto(): Promise { if (!this.opponentDeviceId) return; if (!this.client.getUseE2eForGroupCall()) return; // It's possible to want E2EE and yet not have the means to manage E2EE @@ -938,7 +938,7 @@ export class MatrixCall extends TypedEventEmitter { + const onState = (state: CallState): void => { if (state !== CallState.Ringing) { clearTimeout(ringingTimer); this.off(CallEvent.State, onState); @@ -2132,7 +2132,7 @@ export class MatrixCall extends TypedEventEmitter { + const onRemoveTrack = (): void => { if (stream.getTracks().length === 0) { logger.info(`Call ${this.callId} removing track streamId: ${stream.id}`); this.deleteFeedByStream(stream); diff --git a/src/webrtc/callEventHandler.ts b/src/webrtc/callEventHandler.ts index c4c48cf50..7cbefd46e 100644 --- a/src/webrtc/callEventHandler.ts +++ b/src/webrtc/callEventHandler.ts @@ -46,7 +46,7 @@ export class CallEventHandler { private candidateEventsByCall: Map>; private eventBufferPromiseChain?: Promise; - constructor(client: MatrixClient) { + public constructor(client: MatrixClient) { this.client = client; this.calls = new Map(); // The sync code always emits one event at a time, so it will patiently @@ -61,13 +61,13 @@ export class CallEventHandler { this.candidateEventsByCall = new Map>(); } - public start() { + public start(): void { this.client.on(ClientEvent.Sync, this.onSync); this.client.on(RoomEvent.Timeline, this.onRoomTimeline); this.client.on(ClientEvent.ToDeviceEvent, this.onToDeviceEvent); } - public stop() { + public stop(): void { this.client.removeListener(ClientEvent.Sync, this.onSync); this.client.removeListener(RoomEvent.Timeline, this.onRoomTimeline); this.client.removeListener(ClientEvent.ToDeviceEvent, this.onToDeviceEvent); @@ -87,7 +87,7 @@ export class CallEventHandler { } }; - private async evaluateEventBuffer(eventBuffer: MatrixEvent[]) { + private async evaluateEventBuffer(eventBuffer: MatrixEvent[]): Promise { await Promise.all(eventBuffer.map((event) => this.client.decryptEventIfNeeded(event))); const callEvents = eventBuffer.filter((event) => { @@ -125,7 +125,7 @@ export class CallEventHandler { } } - private onRoomTimeline = (event: MatrixEvent) => { + private onRoomTimeline = (event: MatrixEvent): void => { this.callEventBuffer.push(event); }; @@ -178,7 +178,7 @@ export class CallEventHandler { } }; - private async handleCallEvent(event: MatrixEvent) { + private async handleCallEvent(event: MatrixEvent): Promise { this.client.emit(ClientEvent.ReceivedVoipEvent, event); const content = event.getContent(); diff --git a/src/webrtc/callFeed.ts b/src/webrtc/callFeed.ts index 965a04441..6f71b5040 100644 --- a/src/webrtc/callFeed.ts +++ b/src/webrtc/callFeed.ts @@ -80,7 +80,7 @@ export class CallFeed extends TypedEventEmitter private volumeLooperTimeout?: ReturnType; private _disposed = false; - constructor(opts: ICallFeedOpts) { + public constructor(opts: ICallFeedOpts) { super(); this.client = opts.client; @@ -227,11 +227,11 @@ export class CallFeed extends TypedEventEmitter } } - public setSpeakingThreshold(threshold: number) { + public setSpeakingThreshold(threshold: number): void { this.speakingThreshold = threshold; } - private volumeLooper = () => { + private volumeLooper = (): void => { if (!this.analyser) return; if (!this.measuringVolumeActivity) return; diff --git a/src/webrtc/groupCall.ts b/src/webrtc/groupCall.ts index 737528253..cafcadb10 100644 --- a/src/webrtc/groupCall.ts +++ b/src/webrtc/groupCall.ts @@ -73,7 +73,7 @@ export enum GroupCallErrorCode { export class GroupCallError extends Error { public code: string; - constructor(code: GroupCallErrorCode, msg: string, err?: Error) { + public constructor(code: GroupCallErrorCode, msg: string, err?: Error) { // Still don't think there's any way to have proper nested errors if (err) { super(msg + ": " + err); @@ -86,13 +86,13 @@ export class GroupCallError extends Error { } export class GroupCallUnknownDeviceError extends GroupCallError { - constructor(public userId: string) { + public constructor(public userId: string) { super(GroupCallErrorCode.UnknownDevice, "No device found for " + userId); } } export class OtherUserSpeakingError extends Error { - constructor() { + public constructor() { super("Cannot unmute: another user is speaking"); } } @@ -187,7 +187,7 @@ export class GroupCall extends TypedEventEmitter< private initWithAudioMuted = false; private initWithVideoMuted = false; - constructor( + public constructor( private client: MatrixClient, public room: Room, public type: GroupCallType, @@ -206,7 +206,7 @@ export class GroupCall extends TypedEventEmitter< } } - public async create() { + public async create(): Promise { this.client.groupCallEventHandler!.groupCalls.set(this.room.roomId, this); await this.client.sendStateEvent( @@ -258,7 +258,7 @@ export class GroupCall extends TypedEventEmitter< let stream: MediaStream; let disposed = false; - const onState = (state: GroupCallState) => { + const onState = (state: GroupCallState): void => { if (state === GroupCallState.LocalCallFeedUninitialized) { disposed = true; } @@ -300,7 +300,7 @@ export class GroupCall extends TypedEventEmitter< return callFeed; } - public async updateLocalUsermediaStream(stream: MediaStream) { + public async updateLocalUsermediaStream(stream: MediaStream): Promise { if (this.localCallFeed) { const oldStream = this.localCallFeed.stream; this.localCallFeed.setNewStream(stream); @@ -315,7 +315,7 @@ export class GroupCall extends TypedEventEmitter< } } - public async enter() { + public async enter(): Promise { if (!(this.state === GroupCallState.LocalCallFeedUninitialized || this.state === GroupCallState.LocalCallFeedInitialized)) { throw new Error(`Cannot enter call in the "${this.state}" state`); @@ -354,7 +354,7 @@ export class GroupCall extends TypedEventEmitter< this.onActiveSpeakerLoop(); } - private dispose() { + private dispose(): void { if (this.localCallFeed) { this.removeUserMediaFeed(this.localCallFeed); this.localCallFeed = undefined; @@ -400,7 +400,7 @@ export class GroupCall extends TypedEventEmitter< this.client.removeListener(CallEventHandlerEvent.Incoming, this.onIncomingCall); } - public leave() { + public leave(): void { if (this.transmitTimer !== null) { clearTimeout(this.transmitTimer); this.transmitTimer = null; @@ -410,7 +410,7 @@ export class GroupCall extends TypedEventEmitter< this.setState(GroupCallState.LocalCallFeedUninitialized); } - public async terminate(emitStateEvent = true) { + public async terminate(emitStateEvent = true): Promise { this.dispose(); if (this.transmitTimer !== null) { @@ -430,7 +430,7 @@ export class GroupCall extends TypedEventEmitter< this.room.roomId, EventType.GroupCallPrefix, { - ...existingStateEvent.getContent(), + ...existingStateEvent!.getContent(), ["m.terminated"]: GroupCallTerminationReason.CallEnded, }, this.groupCallId, @@ -445,7 +445,7 @@ export class GroupCall extends TypedEventEmitter< * Local Usermedia */ - public isLocalVideoMuted() { + public isLocalVideoMuted(): boolean { if (this.localCallFeed) { return this.localCallFeed.isVideoMuted(); } @@ -453,7 +453,7 @@ export class GroupCall extends TypedEventEmitter< return true; } - public isMicrophoneMuted() { + public isMicrophoneMuted(): boolean { if (this.localCallFeed) { return this.localCallFeed.isAudioMuted(); } @@ -576,7 +576,7 @@ export class GroupCall extends TypedEventEmitter< const stream = await this.client.getMediaHandler().getScreensharingStream(opts); for (const track of stream.getTracks()) { - const onTrackEnded = () => { + const onTrackEnded = (): void => { this.setScreensharingEnabled(false); track.removeEventListener("ended", onTrackEnded); }; @@ -651,7 +651,7 @@ export class GroupCall extends TypedEventEmitter< * as they are observed by the RoomState.members event. */ - private onIncomingCall = (newCall: MatrixCall) => { + private onIncomingCall = (newCall: MatrixCall): void => { // The incoming calls may be for another room, which we will ignore. if (newCall.roomId !== this.room.roomId) { return; @@ -700,7 +700,7 @@ export class GroupCall extends TypedEventEmitter< private getMemberStateEvents(userId?: string): MatrixEvent[] | MatrixEvent | null { if (userId != null) { const event = this.room.currentState.getStateEvents(EventType.GroupCallMemberPrefix, userId); - return callMemberStateIsExpired(event) ? null : event; + return callMemberStateIsExpired(event!) ? null : event; } else { return this.room.currentState.getStateEvents(EventType.GroupCallMemberPrefix) .filter(event => !callMemberStateIsExpired(event)); @@ -708,7 +708,7 @@ export class GroupCall extends TypedEventEmitter< } private async sendMemberStateEvent(): Promise { - const send = () => this.updateMemberCallState({ + const send = (): Promise => this.updateMemberCallState({ "m.call_id": this.groupCallId, "m.devices": [ { @@ -779,7 +779,7 @@ export class GroupCall extends TypedEventEmitter< ); } - public onMemberStateChanged = async (event: MatrixEvent) => { + public onMemberStateChanged = async (event: MatrixEvent): Promise => { // If we haven't entered the call yet, we don't care if (this.state !== GroupCallState.Entered) { return; @@ -800,7 +800,7 @@ export class GroupCall extends TypedEventEmitter< logger.debug(`Processing member state event for ${member.userId}`); - const ignore = () => { + const ignore = (): void => { this.removeParticipant(member); clearTimeout(this.memberStateExpirationTimers.get(member.userId)); this.memberStateExpirationTimers.delete(member.userId); @@ -953,7 +953,7 @@ export class GroupCall extends TypedEventEmitter< return memberDevices[0]; } - private onRetryCallLoop = () => { + private onRetryCallLoop = (): void => { for (const event of this.getMemberStateEvents()) { const memberId = event.getStateKey()!; const existingCall = this.calls.find((call) => getCallUserId(call) === memberId); @@ -976,13 +976,17 @@ export class GroupCall extends TypedEventEmitter< return this.calls.find((call) => getCallUserId(call) === userId); } - private addCall(call: MatrixCall) { + private addCall(call: MatrixCall): void { this.calls.push(call); this.initCall(call); this.emit(GroupCallEvent.CallsChanged, this.calls); } - private replaceCall(existingCall: MatrixCall, replacementCall: MatrixCall, hangupReason = CallErrorCode.Replaced) { + private replaceCall( + existingCall: MatrixCall, + replacementCall: MatrixCall, + hangupReason = CallErrorCode.Replaced, + ): void { const existingCallIndex = this.calls.indexOf(existingCall); if (existingCallIndex === -1) { @@ -997,7 +1001,7 @@ export class GroupCall extends TypedEventEmitter< this.emit(GroupCallEvent.CallsChanged, this.calls); } - private removeCall(call: MatrixCall, hangupReason: CallErrorCode) { + private removeCall(call: MatrixCall, hangupReason: CallErrorCode): void { this.disposeCall(call, hangupReason); const callIndex = this.calls.indexOf(call); @@ -1011,18 +1015,20 @@ export class GroupCall extends TypedEventEmitter< this.emit(GroupCallEvent.CallsChanged, this.calls); } - private initCall(call: MatrixCall) { + private initCall(call: MatrixCall): void { const opponentMemberId = getCallUserId(call); if (!opponentMemberId) { throw new Error("Cannot init call without user id"); } - const onCallFeedsChanged = () => this.onCallFeedsChanged(call); - const onCallStateChanged = - (state: CallState, oldState: CallState | undefined) => this.onCallStateChanged(call, state, oldState); + const onCallFeedsChanged = (): void => this.onCallFeedsChanged(call); + const onCallStateChanged = ( + state: CallState, + oldState?: CallState, + ): void => this.onCallStateChanged(call, state, oldState); const onCallHangup = this.onCallHangup; - const onCallReplaced = (newCall: MatrixCall) => this.replaceCall(call, newCall); + const onCallReplaced = (newCall: MatrixCall): void => this.replaceCall(call, newCall); this.callHandlers.set(opponentMemberId, { onCallFeedsChanged, @@ -1041,7 +1047,7 @@ export class GroupCall extends TypedEventEmitter< onCallFeedsChanged(); } - private disposeCall(call: MatrixCall, hangupReason: CallErrorCode) { + private disposeCall(call: MatrixCall, hangupReason: CallErrorCode): void { const opponentMemberId = getCallUserId(call); if (!opponentMemberId) { @@ -1083,7 +1089,7 @@ export class GroupCall extends TypedEventEmitter< } } - private onCallFeedsChanged = (call: MatrixCall) => { + private onCallFeedsChanged = (call: MatrixCall): void => { const opponentMemberId = getCallUserId(call); if (!opponentMemberId) { @@ -1119,7 +1125,7 @@ export class GroupCall extends TypedEventEmitter< } }; - private onCallStateChanged = (call: MatrixCall, state: CallState, _oldState: CallState | undefined) => { + private onCallStateChanged = (call: MatrixCall, state: CallState, _oldState: CallState | undefined): void => { const audioMuted = this.localCallFeed!.isAudioMuted(); if ( @@ -1143,7 +1149,7 @@ export class GroupCall extends TypedEventEmitter< } }; - private onCallHangup = (call: MatrixCall) => { + private onCallHangup = (call: MatrixCall): void => { if (call.hangupReason === CallErrorCode.Replaced) { return; } @@ -1155,17 +1161,17 @@ export class GroupCall extends TypedEventEmitter< * UserMedia CallFeed Event Handlers */ - public getUserMediaFeedByUserId(userId: string) { + public getUserMediaFeedByUserId(userId: string): CallFeed | undefined { return this.userMediaFeeds.find((feed) => feed.userId === userId); } - private addUserMediaFeed(callFeed: CallFeed) { + private addUserMediaFeed(callFeed: CallFeed): void { this.userMediaFeeds.push(callFeed); callFeed.measureVolumeActivity(true); this.emit(GroupCallEvent.UserMediaFeedsChanged, this.userMediaFeeds); } - private replaceUserMediaFeed(existingFeed: CallFeed, replacementFeed: CallFeed) { + private replaceUserMediaFeed(existingFeed: CallFeed, replacementFeed: CallFeed): void { const feedIndex = this.userMediaFeeds.findIndex((feed) => feed.userId === existingFeed.userId); if (feedIndex === -1) { @@ -1179,7 +1185,7 @@ export class GroupCall extends TypedEventEmitter< this.emit(GroupCallEvent.UserMediaFeedsChanged, this.userMediaFeeds); } - private removeUserMediaFeed(callFeed: CallFeed) { + private removeUserMediaFeed(callFeed: CallFeed): void { const feedIndex = this.userMediaFeeds.findIndex((feed) => feed.userId === callFeed.userId); if (feedIndex === -1) { @@ -1200,7 +1206,7 @@ export class GroupCall extends TypedEventEmitter< } } - private onActiveSpeakerLoop = () => { + private onActiveSpeakerLoop = (): void => { let topAvg: number | undefined = undefined; let nextActiveSpeaker: string | undefined = undefined; @@ -1239,16 +1245,16 @@ export class GroupCall extends TypedEventEmitter< * Screenshare Call Feed Event Handlers */ - public getScreenshareFeedByUserId(userId: string) { + public getScreenshareFeedByUserId(userId: string): CallFeed | undefined { return this.screenshareFeeds.find((feed) => feed.userId === userId); } - private addScreenshareFeed(callFeed: CallFeed) { + private addScreenshareFeed(callFeed: CallFeed): void { this.screenshareFeeds.push(callFeed); this.emit(GroupCallEvent.ScreenshareFeedsChanged, this.screenshareFeeds); } - private replaceScreenshareFeed(existingFeed: CallFeed, replacementFeed: CallFeed) { + private replaceScreenshareFeed(existingFeed: CallFeed, replacementFeed: CallFeed): void { const feedIndex = this.screenshareFeeds.findIndex((feed) => feed.userId === existingFeed.userId); if (feedIndex === -1) { @@ -1261,7 +1267,7 @@ export class GroupCall extends TypedEventEmitter< this.emit(GroupCallEvent.ScreenshareFeedsChanged, this.screenshareFeeds); } - private removeScreenshareFeed(callFeed: CallFeed) { + private removeScreenshareFeed(callFeed: CallFeed): void { const feedIndex = this.screenshareFeeds.findIndex((feed) => feed.userId === callFeed.userId); if (feedIndex === -1) { @@ -1278,7 +1284,7 @@ export class GroupCall extends TypedEventEmitter< * Participant Management */ - private addParticipant(member: RoomMember) { + private addParticipant(member: RoomMember): void { if (this.participants.find((m) => m.userId === member.userId)) { return; } @@ -1289,7 +1295,7 @@ export class GroupCall extends TypedEventEmitter< this.client.emit(GroupCallEventHandlerEvent.Participants, this.participants, this); } - private removeParticipant(member: RoomMember) { + private removeParticipant(member: RoomMember): void { const index = this.participants.findIndex((m) => m.userId === member.userId); if (index === -1) { diff --git a/src/webrtc/groupCallEventHandler.ts b/src/webrtc/groupCallEventHandler.ts index 86df72289..6a1084152 100644 --- a/src/webrtc/groupCallEventHandler.ts +++ b/src/webrtc/groupCallEventHandler.ts @@ -55,7 +55,7 @@ export class GroupCallEventHandler { // and get private roomDeferreds = new Map(); - constructor(private client: MatrixClient) { } + public constructor(private client: MatrixClient) { } public async start(): Promise { // We wait until the client has started syncing for real. @@ -66,7 +66,7 @@ export class GroupCallEventHandler { if (this.client.getSyncState() !== SyncState.Syncing) { logger.debug("Waiting for client to start syncing..."); await new Promise(resolve => { - const onSync = () => { + const onSync = (): void => { if (this.client.getSyncState() === SyncState.Syncing) { this.client.off(ClientEvent.Sync, onSync); return resolve(); @@ -192,7 +192,7 @@ export class GroupCallEventHandler { return groupCall; } - private onRoomsChanged = (room: Room) => { + private onRoomsChanged = (room: Room): void => { this.createGroupCallForRoom(room); }; diff --git a/src/webrtc/mediaHandler.ts b/src/webrtc/mediaHandler.ts index c4b912ef3..c7c84876b 100644 --- a/src/webrtc/mediaHandler.ts +++ b/src/webrtc/mediaHandler.ts @@ -56,11 +56,11 @@ export class MediaHandler extends TypedEventEmitter< public userMediaStreams: MediaStream[] = []; public screensharingStreams: MediaStream[] = []; - constructor(private client: MatrixClient) { + public constructor(private client: MatrixClient) { super(); } - public restoreMediaSettings(audioInput: string, videoInput: string) { + public restoreMediaSettings(audioInput: string, videoInput: string): void { this.audioInput = audioInput; this.videoInput = videoInput; } @@ -275,7 +275,7 @@ export class MediaHandler extends TypedEventEmitter< /** * Stops all tracks on the provided usermedia stream */ - public stopUserMediaStream(mediaStream: MediaStream) { + public stopUserMediaStream(mediaStream: MediaStream): void { logger.log(`mediaHandler stopUserMediaStream stopping stream ${mediaStream.id}`); for (const track of mediaStream.getTracks()) { track.stop(); @@ -333,7 +333,7 @@ export class MediaHandler extends TypedEventEmitter< /** * Stops all tracks on the provided screensharing stream */ - public stopScreensharingStream(mediaStream: MediaStream) { + public stopScreensharingStream(mediaStream: MediaStream): void { logger.debug("Stopping screensharing stream", mediaStream.id); for (const track of mediaStream.getTracks()) { track.stop(); @@ -352,7 +352,7 @@ export class MediaHandler extends TypedEventEmitter< /** * Stops all local media tracks */ - public stopAllStreams() { + public stopAllStreams(): void { for (const stream of this.userMediaStreams) { logger.log(`mediaHandler stopAllStreams stopping stream ${stream.id}`); for (const track of stream.getTracks()) { diff --git a/yarn.lock b/yarn.lock index 24a08eb42..56821e35f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3278,10 +3278,10 @@ eslint-plugin-import@^2.26.0: resolve "^1.22.0" tsconfig-paths "^3.14.1" -eslint-plugin-matrix-org@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-matrix-org/-/eslint-plugin-matrix-org-0.7.0.tgz#4b7456b31e30e7575b62c2aada91915478829f88" - integrity sha512-FLmwE4/cRalB7J+J1BBuTccaXvKtRgAoHlbqSCbdsRqhh27xpxEWXe08KlNiET7drEnnz+xMHXdmvW469gch7g== +eslint-plugin-matrix-org@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-matrix-org/-/eslint-plugin-matrix-org-0.8.0.tgz#daa1396900a8cb1c1d88f1a370e45fc32482cd9e" + integrity sha512-/Poz/F8lXYDsmQa29iPSt+kO+Jn7ArvRdq10g0CCk8wbRS0sb2zb6fvd9xL1BgR5UDQL771V0l8X32etvY5yKA== eslint-plugin-unicorn@^44.0.2: version "44.0.2"