1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-07-31 15:24:23 +03:00

Improve typing (#2055)

This commit is contained in:
Michael Telatynski
2021-12-09 14:22:58 +00:00
committed by GitHub
parent 95e7a76ba9
commit f8097221e6
28 changed files with 189 additions and 284 deletions

View File

@ -15,7 +15,7 @@
"build:minify-browser": "terser dist/browser-matrix.js --compress --mangle --source-map --output dist/browser-matrix.min.js", "build:minify-browser": "terser dist/browser-matrix.js --compress --mangle --source-map --output dist/browser-matrix.min.js",
"gendoc": "jsdoc -c jsdoc.json -P package.json", "gendoc": "jsdoc -c jsdoc.json -P package.json",
"lint": "yarn lint:types && yarn lint:js", "lint": "yarn lint:types && yarn lint:js",
"lint:js": "eslint --max-warnings 7 src spec", "lint:js": "eslint --max-warnings 4 src spec",
"lint:js-fix": "eslint --fix src spec", "lint:js-fix": "eslint --fix src spec",
"lint:types": "tsc --noEmit", "lint:types": "tsc --noEmit",
"test": "jest", "test": "jest",

View File

@ -4,13 +4,13 @@ import { Room } from "../../src/models/room";
import { TestClient } from "../TestClient"; import { TestClient } from "../TestClient";
describe("MatrixClient retrying", function() { describe("MatrixClient retrying", function() {
let client = null; let client: TestClient = null;
let httpBackend = null; let httpBackend: TestClient["httpBackend"] = null;
let scheduler; let scheduler;
const userId = "@alice:localhost"; const userId = "@alice:localhost";
const accessToken = "aseukfgwef"; const accessToken = "aseukfgwef";
const roomId = "!room:here"; const roomId = "!room:here";
let room; let room: Room;
beforeEach(function() { beforeEach(function() {
scheduler = new MatrixScheduler(); scheduler = new MatrixScheduler();
@ -53,10 +53,10 @@ describe("MatrixClient retrying", function() {
const p1 = client.sendMessage(roomId, { const p1 = client.sendMessage(roomId, {
"msgtype": "m.text", "msgtype": "m.text",
"body": "m1", "body": "m1",
}).then(function(ev) { }).then(function() {
// we expect the first message to fail // we expect the first message to fail
throw new Error('Message 1 unexpectedly sent successfully'); throw new Error('Message 1 unexpectedly sent successfully');
}, (e) => { }, () => {
// this is expected // this is expected
}); });
@ -78,7 +78,7 @@ describe("MatrixClient retrying", function() {
expect(ev2.status).toEqual(EventStatus.SENDING); expect(ev2.status).toEqual(EventStatus.SENDING);
// the first message should get sent, and the second should get queued // the first message should get sent, and the second should get queued
httpBackend.when("PUT", "/send/m.room.message/").check(function(rq) { httpBackend.when("PUT", "/send/m.room.message/").check(function() {
// ev2 should now have been queued // ev2 should now have been queued
expect(ev2.status).toEqual(EventStatus.QUEUED); expect(ev2.status).toEqual(EventStatus.QUEUED);

View File

@ -1018,7 +1018,7 @@ describe("MSC3089TreeSpace", () => {
it('should return falsy for unknown files', () => { it('should return falsy for unknown files', () => {
const fileEventId = "$file"; const fileEventId = "$file";
room.currentState = { room.currentState = {
getStateEvents: (eventType: string, stateKey?: string) => { getStateEvents: (eventType: string, stateKey?: string): MatrixEvent[] | MatrixEvent | null => {
expect(eventType).toEqual(UNSTABLE_MSC3089_BRANCH.unstable); // test to ensure we're definitely using unstable expect(eventType).toEqual(UNSTABLE_MSC3089_BRANCH.unstable); // test to ensure we're definitely using unstable
expect(stateKey).toEqual(fileEventId); expect(stateKey).toEqual(fileEventId);
return null; return null;

View File

@ -111,10 +111,10 @@ describe("utils", function() {
describe("deepCompare", function() { describe("deepCompare", function() {
const assert = { const assert = {
isTrue: function(x) { isTrue: function(x: any) {
expect(x).toBe(true); expect(x).toBe(true);
}, },
isFalse: function(x) { isFalse: function(x: any) {
expect(x).toBe(false); expect(x).toBe(false);
}, },
}; };
@ -176,10 +176,10 @@ describe("utils", function() {
// no two different function is equal really, they capture their // no two different function is equal really, they capture their
// context variables so even if they have same toString(), they // context variables so even if they have same toString(), they
// won't have same functionality // won't have same functionality
const func = function(x) { const func = function() {
return true; return true;
}; };
const func2 = function(x) { const func2 = function() {
return true; return true;
}; };
assert.isTrue(utils.deepCompare(func, func)); assert.isTrue(utils.deepCompare(func, func));
@ -189,66 +189,6 @@ describe("utils", function() {
}); });
}); });
describe("extend", function() {
const SOURCE = { "prop2": 1, "string2": "x", "newprop": "new" };
it("should extend", function() {
const target = {
"prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo",
};
const merged = {
"prop1": 5, "prop2": 1, "string1": "baz", "string2": "x",
"newprop": "new",
};
const sourceOrig = JSON.stringify(SOURCE);
utils.extend(target, SOURCE);
expect(JSON.stringify(target)).toEqual(JSON.stringify(merged));
// check the originial wasn't modified
expect(JSON.stringify(SOURCE)).toEqual(sourceOrig);
});
it("should ignore null", function() {
const target = {
"prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo",
};
const merged = {
"prop1": 5, "prop2": 1, "string1": "baz", "string2": "x",
"newprop": "new",
};
const sourceOrig = JSON.stringify(SOURCE);
utils.extend(target, null, SOURCE);
expect(JSON.stringify(target)).toEqual(JSON.stringify(merged));
// check the originial wasn't modified
expect(JSON.stringify(SOURCE)).toEqual(sourceOrig);
});
it("should handle properties created with defineProperties", function() {
const source = Object.defineProperties({}, {
"enumerableProp": {
get: function() {
return true;
},
enumerable: true,
},
"nonenumerableProp": {
get: function() {
return true;
},
},
});
// TODO: Fix type
const target: any = {};
utils.extend(target, source);
expect(target.enumerableProp).toBe(true);
expect(target.nonenumerableProp).toBe(undefined);
});
});
describe("chunkPromises", function() { describe("chunkPromises", function() {
it("should execute promises in chunks", async function() { it("should execute promises in chunks", async function() {
let promiseCount = 0; let promiseCount = 0;
@ -273,7 +213,7 @@ describe("utils", function() {
it('should retry', async () => { it('should retry', async () => {
let count = 0; let count = 0;
const val = {}; const val = {};
const fn = (attempt) => { const fn = (attempt: any) => {
count++; count++;
// If this expectation fails then it can appear as a Jest Timeout due to // If this expectation fails then it can appear as a Jest Timeout due to
@ -480,7 +420,7 @@ describe("utils", function() {
}, },
[72]: "test", [72]: "test",
}; };
const output = [ const output: any = [
["72", "test"], ["72", "test"],
["a", 42], ["a", 42],
["b", [ ["b", [

View File

@ -17,6 +17,7 @@ limitations under the License.
import { TestClient } from '../../TestClient'; import { TestClient } from '../../TestClient';
import { MatrixCall, CallErrorCode, CallEvent } from '../../../src/webrtc/call'; import { MatrixCall, CallErrorCode, CallEvent } from '../../../src/webrtc/call';
import { SDPStreamMetadataKey, SDPStreamMetadataPurpose } from '../../../src/webrtc/callEventTypes'; import { SDPStreamMetadataKey, SDPStreamMetadataPurpose } from '../../../src/webrtc/callEventTypes';
import { RoomMember } from "../../../src";
const DUMMY_SDP = ( const DUMMY_SDP = (
"v=0\r\n" + "v=0\r\n" +
@ -85,7 +86,7 @@ class MockRTCPeerConnection {
class MockMediaStream { class MockMediaStream {
constructor( constructor(
public id, public id: string,
) {} ) {}
getTracks() { return []; } getTracks() { return []; }
@ -362,7 +363,7 @@ describe('Call', function() {
await callPromise; await callPromise;
call.getOpponentMember = () => { call.getOpponentMember = () => {
return { userId: "@bob:bar.uk" }; return { userId: "@bob:bar.uk" } as RoomMember;
}; };
await call.onAnswerReceived({ await call.onAnswerReceived({

View File

@ -30,7 +30,7 @@ export class ReEmitter {
// We include the source as the last argument for event handlers which may need it, // 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 // such as read receipt listeners on the client class which won't have the context
// of the room. // of the room.
const forSource = (...args) => { const forSource = (...args: any[]) => {
// EventEmitter special cases 'error' to make the emit function throw if no // 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 // 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 // handles an error, but for re-emitting, there could be a listener on the original

View File

@ -1423,7 +1423,7 @@ export class MatrixClient extends EventEmitter {
// We swallow errors because we need a default object anyhow // We swallow errors because we need a default object anyhow
return this.http.authedRequest( return this.http.authedRequest(
undefined, "GET", "/capabilities", undefined, "GET", "/capabilities",
).catch((e) => { ).catch((e: Error) => {
logger.error(e); logger.error(e);
return null; // otherwise consume the error return null; // otherwise consume the error
}).then((r) => { }).then((r) => {
@ -3106,7 +3106,7 @@ export class MatrixClient extends EventEmitter {
* data event. * data event.
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
public async getAccountDataFromServer(eventType: string): Promise<Record<string, any>> { public async getAccountDataFromServer<T>(eventType: string): Promise<T> {
if (this.isInitialSyncComplete()) { if (this.isInitialSyncComplete()) {
const event = this.store.getAccountData(eventType); const event = this.store.getAccountData(eventType);
if (!event) { if (!event) {
@ -3201,7 +3201,7 @@ export class MatrixClient extends EventEmitter {
); );
} }
const queryString = {}; const queryString: Record<string, string | string[]> = {};
if (opts.viaServers) { if (opts.viaServers) {
queryString["server_name"] = opts.viaServers; queryString["server_name"] = opts.viaServers;
} }
@ -3411,7 +3411,7 @@ export class MatrixClient extends EventEmitter {
content: IContent, content: IContent,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendEvent( public sendEvent(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3419,7 +3419,7 @@ export class MatrixClient extends EventEmitter {
content: IContent, content: IContent,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendEvent( public sendEvent(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3699,14 +3699,14 @@ export class MatrixClient extends EventEmitter {
eventId: string, eventId: string,
txnId?: string | undefined, txnId?: string | undefined,
cbOrOpts?: Callback | IRedactOpts, cbOrOpts?: Callback | IRedactOpts,
); ): Promise<ISendEventResponse>;
public redactEvent( public redactEvent(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
eventId: string, eventId: string,
txnId?: string | undefined, txnId?: string | undefined,
cbOrOpts?: Callback | IRedactOpts, cbOrOpts?: Callback | IRedactOpts,
); ): Promise<ISendEventResponse>;
public redactEvent( public redactEvent(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3744,14 +3744,14 @@ export class MatrixClient extends EventEmitter {
content: IContent, content: IContent,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendMessage( public sendMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
content: IContent, content: IContent,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendMessage( public sendMessage(
roomId: string, roomId: string,
threadId: string | null | IContent, threadId: string | null | IContent,
@ -3793,14 +3793,14 @@ export class MatrixClient extends EventEmitter {
body: string, body: string,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendTextMessage( public sendTextMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
body: string, body: string,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendTextMessage( public sendTextMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3832,14 +3832,14 @@ export class MatrixClient extends EventEmitter {
body: string, body: string,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendNotice( public sendNotice(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
body: string, body: string,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendNotice( public sendNotice(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3871,14 +3871,14 @@ export class MatrixClient extends EventEmitter {
body: string, body: string,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendEmoteMessage( public sendEmoteMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
body: string, body: string,
txnId?: string, txnId?: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendEmoteMessage( public sendEmoteMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3912,7 +3912,7 @@ export class MatrixClient extends EventEmitter {
info?: IImageInfo, info?: IImageInfo,
text?: string, text?: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendImageMessage( public sendImageMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3920,7 +3920,7 @@ export class MatrixClient extends EventEmitter {
info?: IImageInfo, info?: IImageInfo,
text?: string, text?: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendImageMessage( public sendImageMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3965,7 +3965,7 @@ export class MatrixClient extends EventEmitter {
info?: IImageInfo, info?: IImageInfo,
text?: string, text?: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendStickerMessage( public sendStickerMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -3973,7 +3973,7 @@ export class MatrixClient extends EventEmitter {
info?: IImageInfo, info?: IImageInfo,
text?: string, text?: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendStickerMessage( public sendStickerMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -4015,14 +4015,14 @@ export class MatrixClient extends EventEmitter {
body: string, body: string,
htmlBody: string, htmlBody: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendHtmlMessage( public sendHtmlMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
body: string, body: string,
htmlBody: string, htmlBody: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendHtmlMessage( public sendHtmlMessage(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -4053,14 +4053,14 @@ export class MatrixClient extends EventEmitter {
body: string, body: string,
htmlBody: string, htmlBody: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendHtmlNotice( public sendHtmlNotice(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
body: string, body: string,
htmlBody: string, htmlBody: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendHtmlNotice( public sendHtmlNotice(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -4092,14 +4092,14 @@ export class MatrixClient extends EventEmitter {
body: string, body: string,
htmlBody: string, htmlBody: string,
callback?: Callback, callback?: Callback,
); ): Promise<ISendEventResponse>;
public sendHtmlEmote( public sendHtmlEmote(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
body: string, body: string,
htmlBody: string, htmlBody: string,
callback?: Callback, callback?: Callback,
) ): Promise<ISendEventResponse>;
public sendHtmlEmote( public sendHtmlEmote(
roomId: string, roomId: string,
threadId: string | null, threadId: string | null,
@ -4420,7 +4420,7 @@ export class MatrixClient extends EventEmitter {
errcode: "ORG.MATRIX.JSSDK_MISSING_PARAM", errcode: "ORG.MATRIX.JSSDK_MISSING_PARAM",
})); }));
} }
const params = { const params: Record<string, string> = {
id_server: identityServerUrl, id_server: identityServerUrl,
medium: medium, medium: medium,
address: address, address: address,
@ -4478,10 +4478,10 @@ export class MatrixClient extends EventEmitter {
} }
} }
const populationResults = {}; // {roomId: Error} const populationResults: Record<string, Error> = {}; // {roomId: Error}
const promises = []; const promises = [];
const doLeave = (roomId) => { const doLeave = (roomId: string) => {
return this.leave(roomId).then(() => { return this.leave(roomId).then(() => {
populationResults[roomId] = null; populationResults[roomId] = null;
}).catch((err) => { }).catch((err) => {
@ -5065,14 +5065,14 @@ export class MatrixClient extends EventEmitter {
return pendingRequest; return pendingRequest;
} }
let path; let path: string;
let params; let params: Record<string, string>;
let promise; let promise;
if (isNotifTimeline) { if (isNotifTimeline) {
path = "/notifications"; path = "/notifications";
params = { params = {
limit: ('limit' in opts) ? opts.limit : 30, limit: (opts.limit ?? 30).toString(),
only: 'highlight', only: 'highlight',
}; };
@ -5509,7 +5509,7 @@ export class MatrixClient extends EventEmitter {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
public setRoomMutePushRule(scope: string, roomId: string, mute: boolean): Promise<void> | void { public setRoomMutePushRule(scope: string, roomId: string, mute: boolean): Promise<void> | void {
let deferred; let promise: Promise<void>;
let hasDontNotifyRule; let hasDontNotifyRule;
// Get the existing room-kind push rule if any // Get the existing room-kind push rule if any
@ -5523,17 +5523,17 @@ export class MatrixClient extends EventEmitter {
if (!mute) { if (!mute) {
// Remove the rule only if it is a muting rule // Remove the rule only if it is a muting rule
if (hasDontNotifyRule) { if (hasDontNotifyRule) {
deferred = this.deletePushRule(scope, PushRuleKind.RoomSpecific, roomPushRule.rule_id); promise = this.deletePushRule(scope, PushRuleKind.RoomSpecific, roomPushRule.rule_id);
} }
} else { } else {
if (!roomPushRule) { if (!roomPushRule) {
deferred = this.addPushRule(scope, PushRuleKind.RoomSpecific, roomId, { promise = this.addPushRule(scope, PushRuleKind.RoomSpecific, roomId, {
actions: ["dont_notify"], actions: ["dont_notify"],
}); });
} else if (!hasDontNotifyRule) { } else if (!hasDontNotifyRule) {
// Remove the existing one before setting the mute push rule // Remove the existing one before setting the mute push rule
// This is a workaround to SYN-590 (Push rule update fails) // This is a workaround to SYN-590 (Push rule update fails)
deferred = utils.defer(); const deferred = utils.defer();
this.deletePushRule(scope, PushRuleKind.RoomSpecific, roomPushRule.rule_id) this.deletePushRule(scope, PushRuleKind.RoomSpecific, roomPushRule.rule_id)
.then(() => { .then(() => {
this.addPushRule(scope, PushRuleKind.RoomSpecific, roomId, { this.addPushRule(scope, PushRuleKind.RoomSpecific, roomId, {
@ -5547,21 +5547,21 @@ export class MatrixClient extends EventEmitter {
deferred.reject(err); deferred.reject(err);
}); });
deferred = deferred.promise; promise = deferred.promise;
} }
} }
if (deferred) { if (promise) {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
// Update this.pushRules when the operation completes // Update this.pushRules when the operation completes
deferred.then(() => { promise.then(() => {
this.getPushRules().then((result) => { this.getPushRules().then((result) => {
this.pushRules = result; this.pushRules = result;
resolve(); resolve();
}).catch((err) => { }).catch((err) => {
reject(err); reject(err);
}); });
}).catch((err) => { }).catch((err: Error) => {
// Update it even if the previous operation fails. This can help the // Update it even if the previous operation fails. This can help the
// app to recover when push settings has been modifed from another client // app to recover when push settings has been modifed from another client
this.getPushRules().then((result) => { this.getPushRules().then((result) => {
@ -6281,7 +6281,7 @@ export class MatrixClient extends EventEmitter {
fetchedEventType, fetchedEventType,
opts); opts);
const mapper = this.getEventMapper(); const mapper = this.getEventMapper();
let originalEvent; let originalEvent: MatrixEvent;
if (result.original_event) { if (result.original_event) {
originalEvent = mapper(result.original_event); originalEvent = mapper(result.original_event);
} }
@ -6564,7 +6564,7 @@ export class MatrixClient extends EventEmitter {
}; };
// merge data into loginData // merge data into loginData
utils.extend(loginData, data); Object.assign(loginData, data);
return this.http.authedRequest( return this.http.authedRequest(
(error, response) => { (error, response) => {
@ -7544,7 +7544,7 @@ export class MatrixClient extends EventEmitter {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
public getPushRules(callback?: Callback): Promise<IPushRules> { public getPushRules(callback?: Callback): Promise<IPushRules> {
return this.http.authedRequest(callback, "GET", "/pushrules/").then(rules => { return this.http.authedRequest(callback, "GET", "/pushrules/").then((rules: IPushRules) => {
return PushProcessor.rewriteDefaultRules(rules); return PushProcessor.rewriteDefaultRules(rules);
}); });
} }
@ -8018,7 +8018,7 @@ export class MatrixClient extends EventEmitter {
addressPairs: [string, string][], addressPairs: [string, string][],
identityAccessToken: string, identityAccessToken: string,
): Promise<{ address: string, mxid: string }[]> { ): Promise<{ address: string, mxid: string }[]> {
const params = { const params: Record<string, string | string[]> = {
// addresses: ["email@example.org", "10005550000"], // addresses: ["email@example.org", "10005550000"],
// algorithm: "sha256", // algorithm: "sha256",
// pepper: "abc123" // pepper: "abc123"
@ -8032,7 +8032,7 @@ export class MatrixClient extends EventEmitter {
params['pepper'] = hashes['lookup_pepper']; params['pepper'] = hashes['lookup_pepper'];
const localMapping = { const localMapping: Record<string, string> = {
// hashed identifier => plain text address // hashed identifier => plain text address
// For use in this function's return format // For use in this function's return format
}; };

View File

@ -53,13 +53,13 @@ export function getHttpUriForMxc(
} }
let serverAndMediaId = mxc.slice(6); // strips mxc:// let serverAndMediaId = mxc.slice(6); // strips mxc://
let prefix = "/_matrix/media/r0/download/"; let prefix = "/_matrix/media/r0/download/";
const params = {}; const params: Record<string, string> = {};
if (width) { if (width) {
params["width"] = Math.round(width); params["width"] = Math.round(width).toString();
} }
if (height) { if (height) {
params["height"] = Math.round(height); params["height"] = Math.round(height).toString();
} }
if (resizeMethod) { if (resizeMethod) {
params["method"] = resizeMethod; params["method"] = resizeMethod;

View File

@ -265,8 +265,8 @@ export class DeviceList extends EventEmitter {
* module:crypto/deviceinfo|DeviceInfo}. * module:crypto/deviceinfo|DeviceInfo}.
*/ */
public downloadKeys(userIds: string[], forceDownload: boolean): Promise<DeviceInfoMap> { public downloadKeys(userIds: string[], forceDownload: boolean): Promise<DeviceInfoMap> {
const usersToDownload = []; const usersToDownload: string[] = [];
const promises = []; const promises: Promise<unknown>[] = [];
userIds.forEach((u) => { userIds.forEach((u) => {
const trackingStatus = this.deviceTrackingStatus[u]; const trackingStatus = this.deviceTrackingStatus[u];
@ -633,7 +633,7 @@ export class DeviceList extends EventEmitter {
} }
}); });
const finished = (success) => { const finished = (success: boolean): void => {
this.emit("crypto.willUpdateDevices", users, !this.hasFetched); this.emit("crypto.willUpdateDevices", users, !this.hasFetched);
users.forEach((u) => { users.forEach((u) => {
this.dirty = true; this.dirty = true;

View File

@ -37,7 +37,7 @@ export interface ISecretRequest {
export interface IAccountDataClient extends EventEmitter { export interface IAccountDataClient extends EventEmitter {
// Subset of MatrixClient (which also uses any for the event content) // Subset of MatrixClient (which also uses any for the event content)
getAccountDataFromServer: (eventType: string) => Promise<Record<string, any>>; getAccountDataFromServer: <T>(eventType: string) => Promise<T>;
getAccountData: (eventType: string) => MatrixEvent; getAccountData: (eventType: string) => MatrixEvent;
setAccountData: (eventType: string, content: any) => Promise<{}>; setAccountData: (eventType: string, content: any) => Promise<{}>;
} }
@ -76,7 +76,7 @@ export class SecretStorage {
) {} ) {}
public async getDefaultKeyId(): Promise<string> { public async getDefaultKeyId(): Promise<string> {
const defaultKey = await this.accountDataAdapter.getAccountDataFromServer( const defaultKey = await this.accountDataAdapter.getAccountDataFromServer<{ key: string }>(
'm.secret_storage.default_key', 'm.secret_storage.default_key',
); );
if (!defaultKey) return null; if (!defaultKey) return null;
@ -230,7 +230,7 @@ export class SecretStorage {
* or null/undefined to use the default key. * or null/undefined to use the default key.
*/ */
public async store(name: string, secret: string, keys?: string[]): Promise<void> { public async store(name: string, secret: string, keys?: string[]): Promise<void> {
const encrypted = {}; const encrypted: Record<string, IEncryptedPayload> = {};
if (!keys) { if (!keys) {
const defaultKeyId = await this.getDefaultKeyId(); const defaultKeyId = await this.getDefaultKeyId();
@ -246,9 +246,9 @@ export class SecretStorage {
for (const keyId of keys) { for (const keyId of keys) {
// get key information from key storage // get key information from key storage
const keyInfo = await this.accountDataAdapter.getAccountDataFromServer( const keyInfo = await this.accountDataAdapter.getAccountDataFromServer<ISecretStorageKeyInfo>(
"m.secret_storage.key." + keyId, "m.secret_storage.key." + keyId,
) as ISecretStorageKeyInfo; );
if (!keyInfo) { if (!keyInfo) {
throw new Error("Unknown key: " + keyId); throw new Error("Unknown key: " + keyId);
} }
@ -277,7 +277,7 @@ export class SecretStorage {
* @return {string} the contents of the secret * @return {string} the contents of the secret
*/ */
public async get(name: string): Promise<string> { public async get(name: string): Promise<string> {
const secretInfo = await this.accountDataAdapter.getAccountDataFromServer(name); const secretInfo = await this.accountDataAdapter.getAccountDataFromServer<any>(name); // TODO types
if (!secretInfo) { if (!secretInfo) {
return; return;
} }
@ -286,11 +286,13 @@ export class SecretStorage {
} }
// get possible keys to decrypt // get possible keys to decrypt
const keys = {}; const keys: Record<string, ISecretStorageKeyInfo> = {};
for (const keyId of Object.keys(secretInfo.encrypted)) { for (const keyId of Object.keys(secretInfo.encrypted)) {
// get key information from key storage // get key information from key storage
const keyInfo = await this.accountDataAdapter.getAccountDataFromServer( const keyInfo = (
"m.secret_storage.key." + keyId, await this.accountDataAdapter.getAccountDataFromServer<ISecretStorageKeyInfo>(
"m.secret_storage.key." + keyId,
)
); );
const encInfo = secretInfo.encrypted[keyId]; const encInfo = secretInfo.encrypted[keyId];
// only use keys we understand the encryption algorithm of // only use keys we understand the encryption algorithm of
@ -306,7 +308,7 @@ export class SecretStorage {
`the keys it is encrypted with are for a supported algorithm`); `the keys it is encrypted with are for a supported algorithm`);
} }
let keyId; let keyId: string;
let decryption; let decryption;
try { try {
// fetch private key from app // fetch private key from app
@ -337,7 +339,7 @@ export class SecretStorage {
*/ */
public async isStored(name: string, checkKey: boolean): Promise<Record<string, ISecretStorageKeyInfo>> { public async isStored(name: string, checkKey: boolean): Promise<Record<string, ISecretStorageKeyInfo>> {
// check if secret exists // check if secret exists
const secretInfo = await this.accountDataAdapter.getAccountDataFromServer(name); const secretInfo = await this.accountDataAdapter.getAccountDataFromServer<any>(name); // TODO types
if (!secretInfo) return null; if (!secretInfo) return null;
if (!secretInfo.encrypted) { if (!secretInfo.encrypted) {
return null; return null;
@ -350,7 +352,7 @@ export class SecretStorage {
// filter secret encryption keys with supported algorithm // filter secret encryption keys with supported algorithm
for (const keyId of Object.keys(secretInfo.encrypted)) { for (const keyId of Object.keys(secretInfo.encrypted)) {
// get key information from key storage // get key information from key storage
const keyInfo = await this.accountDataAdapter.getAccountDataFromServer( const keyInfo = await this.accountDataAdapter.getAccountDataFromServer<any>( // TODO types
"m.secret_storage.key." + keyId, "m.secret_storage.key." + keyId,
); );
if (!keyInfo) continue; if (!keyInfo) continue;
@ -375,8 +377,8 @@ export class SecretStorage {
public request(name: string, devices: string[]): ISecretRequest { public request(name: string, devices: string[]): ISecretRequest {
const requestId = this.baseApis.makeTxnId(); const requestId = this.baseApis.makeTxnId();
let resolve: (string) => void; let resolve: (s: string) => void;
let reject: (Error) => void; let reject: (e: Error) => void;
const promise = new Promise<string>((res, rej) => { const promise = new Promise<string>((res, rej) => {
resolve = res; resolve = res;
reject = rej; reject = rej;

View File

@ -46,7 +46,7 @@ type DecryptionClassParams = Omit<IParams, "deviceId" | "config">;
*/ */
export const DECRYPTION_CLASSES: Record<string, new (params: DecryptionClassParams) => DecryptionAlgorithm> = {}; export const DECRYPTION_CLASSES: Record<string, new (params: DecryptionClassParams) => DecryptionAlgorithm> = {};
interface IParams { export interface IParams {
userId: string; userId: string;
deviceId: string; deviceId: string;
crypto: Crypto; crypto: Crypto;

View File

@ -26,6 +26,7 @@ import {
DecryptionAlgorithm, DecryptionAlgorithm,
DecryptionError, DecryptionError,
EncryptionAlgorithm, EncryptionAlgorithm,
IParams,
registerAlgorithm, registerAlgorithm,
UnknownDeviceError, UnknownDeviceError,
} from "./base"; } from "./base";
@ -99,6 +100,12 @@ interface IPayload extends Partial<IMessage> {
algorithm?: string; algorithm?: string;
sender_key?: string; sender_key?: string;
} }
interface IEncryptedContent {
algorithm: string;
sender_key: string;
ciphertext: Record<string, string>;
}
/* eslint-enable camelcase */ /* eslint-enable camelcase */
interface SharedWithData { interface SharedWithData {
@ -238,7 +245,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
startTime: number; startTime: number;
}; };
constructor(params) { constructor(params: IParams) {
super(params); super(params);
this.sessionRotationPeriodMsgs = params.config?.rotation_period_msgs ?? 100; this.sessionRotationPeriodMsgs = params.config?.rotation_period_msgs ?? 100;
@ -263,7 +270,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
blocked: IBlockedMap, blocked: IBlockedMap,
singleOlmCreationPhase = false, singleOlmCreationPhase = false,
): Promise<OutboundSessionInfo> { ): Promise<OutboundSessionInfo> {
let session; let session: OutboundSessionInfo;
// takes the previous OutboundSessionInfo, and considers whether to create // takes the previous OutboundSessionInfo, and considers whether to create
// a new one. Also shares the key with any (new) devices in the room. // a new one. Also shares the key with any (new) devices in the room.
@ -302,7 +309,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
} }
// now check if we need to share with any devices // now check if we need to share with any devices
const shareMap = {}; const shareMap: Record<string, DeviceInfo[]> = {};
for (const [userId, userDevices] of Object.entries(devicesInRoom)) { for (const [userId, userDevices] of Object.entries(devicesInRoom)) {
for (const [deviceId, deviceInfo] of Object.entries(userDevices)) { for (const [deviceId, deviceInfo] of Object.entries(userDevices)) {
@ -350,7 +357,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
`Sharing keys (start phase 1) with new Olm sessions in ${this.roomId}`, `Sharing keys (start phase 1) with new Olm sessions in ${this.roomId}`,
devicesWithoutSession, devicesWithoutSession,
); );
const errorDevices = []; const errorDevices: IOlmDevice[] = [];
// meanwhile, establish olm sessions for devices that we don't // meanwhile, establish olm sessions for devices that we don't
// already have a session for, and share keys with them. If // already have a session for, and share keys with them. If
@ -358,7 +365,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
// shorter timeout when fetching one-time keys for the first // shorter timeout when fetching one-time keys for the first
// phase. // phase.
const start = Date.now(); const start = Date.now();
const failedServers = []; const failedServers: string[] = [];
await this.shareKeyWithDevices( await this.shareKeyWithDevices(
session, key, payload, devicesWithoutSession, errorDevices, session, key, payload, devicesWithoutSession, errorDevices,
singleOlmCreationPhase ? 10000 : 2000, failedServers, singleOlmCreationPhase ? 10000 : 2000, failedServers,
@ -374,7 +381,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
// do this in the background and don't block anything else while we // do this in the background and don't block anything else while we
// do this. We only need to retry users from servers that didn't // do this. We only need to retry users from servers that didn't
// respond the first time. // respond the first time.
const retryDevices = {}; const retryDevices: Record<string, DeviceInfo[]> = {};
const failedServerMap = new Set; const failedServerMap = new Set;
for (const server of failedServers) { for (const server of failedServers) {
failedServerMap.add(server); failedServerMap.add(server);
@ -584,12 +591,12 @@ class MegolmEncryption extends EncryptionAlgorithm {
userDeviceMap: IOlmDevice[], userDeviceMap: IOlmDevice[],
payload: IPayload, payload: IPayload,
): Promise<void> { ): Promise<void> {
const contentMap = {}; const contentMap: Record<string, Record<string, IEncryptedContent>> = {};
const deviceInfoByDeviceId = new Map<string, DeviceInfo>(); const deviceInfoByDeviceId = new Map<string, DeviceInfo>();
const promises = []; const promises: Promise<unknown>[] = [];
for (let i = 0; i < userDeviceMap.length; i++) { for (let i = 0; i < userDeviceMap.length; i++) {
const encryptedContent = { const encryptedContent: IEncryptedContent = {
algorithm: olmlib.OLM_ALGORITHM, algorithm: olmlib.OLM_ALGORITHM,
sender_key: this.olmDevice.deviceCurve25519Key, sender_key: this.olmDevice.deviceCurve25519Key,
ciphertext: {}, ciphertext: {},
@ -679,7 +686,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
userDeviceMap: IOlmDevice<IBlockedDevice>[], userDeviceMap: IOlmDevice<IBlockedDevice>[],
payload: IPayload, payload: IPayload,
): Promise<void> { ): Promise<void> {
const contentMap = {}; const contentMap: Record<string, Record<string, IPayload>> = {};
for (const val of userDeviceMap) { for (const val of userDeviceMap) {
const userId = val.userId; const userId = val.userId;
@ -1105,7 +1112,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
* devices we should shared the session with. * devices we should shared the session with.
*/ */
private checkForUnknownDevices(devicesInRoom: DeviceInfoMap): void { private checkForUnknownDevices(devicesInRoom: DeviceInfoMap): void {
const unknownDevices = {}; const unknownDevices: Record<string, Record<string, DeviceInfo>> = {};
Object.keys(devicesInRoom).forEach((userId)=>{ Object.keys(devicesInRoom).forEach((userId)=>{
Object.keys(devicesInRoom[userId]).forEach((deviceId)=>{ Object.keys(devicesInRoom[userId]).forEach((deviceId)=>{
@ -1304,8 +1311,7 @@ class MegolmDecryption extends DecryptionAlgorithm {
content.sender_key, event.getTs() - 120000, content.sender_key, event.getTs() - 120000,
); );
if (problem) { if (problem) {
let problemDescription = PROBLEM_DESCRIPTIONS[problem.type] let problemDescription = PROBLEM_DESCRIPTIONS[problem.type as "no_olm"] || PROBLEM_DESCRIPTIONS.unknown;
|| PROBLEM_DESCRIPTIONS.unknown;
if (problem.fixed) { if (problem.fixed) {
problemDescription += problemDescription +=
" Trying to create a new secure channel and re-requesting the keys."; " Trying to create a new secure channel and re-requesting the keys.";
@ -1399,14 +1405,14 @@ class MegolmDecryption extends DecryptionAlgorithm {
const senderKey = content.sender_key; const senderKey = content.sender_key;
const sessionId = content.session_id; const sessionId = content.session_id;
const senderPendingEvents = this.pendingEvents[senderKey]; const senderPendingEvents = this.pendingEvents[senderKey];
const pendingEvents = senderPendingEvents && senderPendingEvents.get(sessionId); const pendingEvents = senderPendingEvents?.get(sessionId);
if (!pendingEvents) { if (!pendingEvents) {
return; return;
} }
pendingEvents.delete(event); pendingEvents.delete(event);
if (pendingEvents.size === 0) { if (pendingEvents.size === 0) {
senderPendingEvents.delete(senderKey); senderPendingEvents.delete(sessionId);
} }
if (senderPendingEvents.size === 0) { if (senderPendingEvents.size === 0) {
delete this.pendingEvents[senderKey]; delete this.pendingEvents[senderKey];
@ -1760,7 +1766,7 @@ class MegolmDecryption extends DecryptionAlgorithm {
})); }));
// If decrypted successfully, they'll have been removed from pendingEvents // If decrypted successfully, they'll have been removed from pendingEvents
return !((this.pendingEvents[senderKey] || {})[sessionId]); return !this.pendingEvents[senderKey]?.has(sessionId);
} }
public async retryDecryptionFromSender(senderKey: string): Promise<boolean> { public async retryDecryptionFromSender(senderKey: string): Promise<boolean> {
@ -1794,12 +1800,12 @@ class MegolmDecryption extends DecryptionAlgorithm {
for (const [senderKey, sessionId] of sharedHistorySessions) { for (const [senderKey, sessionId] of sharedHistorySessions) {
const payload = await this.buildKeyForwardingMessage(this.roomId, senderKey, sessionId); const payload = await this.buildKeyForwardingMessage(this.roomId, senderKey, sessionId);
const promises = []; const promises: Promise<unknown>[] = [];
const contentMap = {}; const contentMap: Record<string, Record<string, IEncryptedContent>> = {};
for (const [userId, devices] of Object.entries(devicesByUser)) { for (const [userId, devices] of Object.entries(devicesByUser)) {
contentMap[userId] = {}; contentMap[userId] = {};
for (const deviceInfo of devices) { for (const deviceInfo of devices) {
const encryptedContent = { const encryptedContent: IEncryptedContent = {
algorithm: olmlib.OLM_ALGORITHM, algorithm: olmlib.OLM_ALGORITHM,
sender_key: this.olmDevice.deviceCurve25519Key, sender_key: this.olmDevice.deviceCurve25519Key,
ciphertext: {}, ciphertext: {},

View File

@ -282,7 +282,7 @@ class OlmDecryption extends DecryptionAlgorithm {
const sessionIds = await this.olmDevice.getSessionIdsForDevice(theirDeviceIdentityKey); const sessionIds = await this.olmDevice.getSessionIdsForDevice(theirDeviceIdentityKey);
// try each session in turn. // try each session in turn.
const decryptionErrors = {}; const decryptionErrors: Record<string, string> = {};
for (let i = 0; i < sessionIds.length; i++) { for (let i = 0; i < sessionIds.length; i++) {
const sessionId = sessionIds[i]; const sessionId = sessionIds[i];
try { try {

View File

@ -58,7 +58,7 @@ import { BackupManager } from "./backup";
import { IStore } from "../store"; import { IStore } from "../store";
import { Room } from "../models/room"; import { Room } from "../models/room";
import { RoomMember } from "../models/room-member"; import { RoomMember } from "../models/room-member";
import { MatrixEvent, EventStatus } from "../models/event"; import { MatrixEvent, EventStatus, IClearEvent } from "../models/event";
import { MatrixClient, IKeysUploadResponse, SessionStore, ISignedKey, ICrossSigningKey } from "../client"; import { MatrixClient, IKeysUploadResponse, SessionStore, ISignedKey, ICrossSigningKey } from "../client";
import type { EncryptionAlgorithm, DecryptionAlgorithm } from "./algorithms/base"; import type { EncryptionAlgorithm, DecryptionAlgorithm } from "./algorithms/base";
import type { IRoomEncryption, RoomList } from "./RoomList"; import type { IRoomEncryption, RoomList } from "./RoomList";
@ -172,10 +172,10 @@ interface ISignableObject {
} }
export interface IEventDecryptionResult { export interface IEventDecryptionResult {
clearEvent: object; clearEvent: IClearEvent;
forwardingCurve25519KeyChain?: string[];
senderCurve25519Key?: string; senderCurve25519Key?: string;
claimedEd25519Key?: string; claimedEd25519Key?: string;
forwardingCurve25519KeyChain?: string[];
untrusted?: boolean; untrusted?: boolean;
} }

View File

@ -67,5 +67,5 @@ export interface IKeyBackupRestoreResult {
export interface IKeyBackupRestoreOpts { export interface IKeyBackupRestoreOpts {
cacheCompleteCallback?: () => void; cacheCompleteCallback?: () => void;
progressCallback?: ({ stage: string }) => void; progressCallback?: (progress: { stage: string }) => void;
} }

View File

@ -27,7 +27,6 @@ import { Logger } from "loglevel";
import { OlmDevice } from "./OlmDevice"; import { OlmDevice } from "./OlmDevice";
import { DeviceInfo } from "./deviceinfo"; import { DeviceInfo } from "./deviceinfo";
import { logger } from '../logger'; import { logger } from '../logger';
import * as utils from "../utils";
import { IOneTimeKey } from "./dehydration"; import { IOneTimeKey } from "./dehydration";
import { MatrixClient } from "../client"; import { MatrixClient } from "../client";
@ -126,7 +125,7 @@ export async function encryptMessageForDevice(
// involved in the session. If we're looking to reduce data transfer in the // involved in the session. If we're looking to reduce data transfer in the
// future, we could elide them for subsequent messages. // future, we could elide them for subsequent messages.
utils.extend(payload, payloadFields); Object.assign(payload, payloadFields);
resultsObject[deviceKey] = await olmDevice.encryptMessage( resultsObject[deviceKey] = await olmDevice.encryptMessage(
deviceKey, sessionId, JSON.stringify(payload), deviceKey, sessionId, JSON.stringify(payload),

View File

@ -36,7 +36,7 @@ const M_RELATES_TO = "m.relates_to";
* Uses the event id of the initial m.key.verification.request event as a transaction id. * Uses the event id of the initial m.key.verification.request event as a transaction id.
*/ */
export class InRoomChannel implements IVerificationChannel { export class InRoomChannel implements IVerificationChannel {
private requestEventId = null; private requestEventId: string = null;
/** /**
* @param {MatrixClient} client the matrix client, to send messages with and get current user & device from. * @param {MatrixClient} client the matrix client, to send messages with and get current user & device from.

View File

@ -657,7 +657,7 @@ MatrixHttpApi.prototype = {
}; };
} }
const headers = utils.extend({}, opts.headers || {}); const headers = Object.assign({}, opts.headers || {});
const json = opts.json === undefined ? true : opts.json; const json = opts.json === undefined ? true : opts.json;
let bodyParser = opts.bodyParser; let bodyParser = opts.bodyParser;

View File

@ -18,7 +18,6 @@ limitations under the License.
/** @module interactive-auth */ /** @module interactive-auth */
import * as utils from "./utils";
import { logger } from './logger'; import { logger } from './logger';
import { MatrixClient } from "./client"; import { MatrixClient } from "./client";
import { defer, IDeferred } from "./utils"; import { defer, IDeferred } from "./utils";
@ -68,7 +67,7 @@ export enum AuthType {
export interface IAuthDict { export interface IAuthDict {
// [key: string]: any; // [key: string]: any;
type?: string; type?: string;
// session?: string; // TODO session?: string;
// TODO: Remove `user` once servers support proper UIA // TODO: Remove `user` once servers support proper UIA
// See https://github.com/vector-im/element-web/issues/10312 // See https://github.com/vector-im/element-web/issues/10312
user?: string; user?: string;
@ -360,12 +359,12 @@ export class InteractiveAuth {
} }
// use the sessionid from the last request, if one is present. // use the sessionid from the last request, if one is present.
let auth; let auth: IAuthDict;
if (this.data.session) { if (this.data.session) {
auth = { auth = {
session: this.data.session, session: this.data.session,
}; };
utils.extend(auth, authData); Object.assign(auth, authData);
} else { } else {
auth = authData; auth = authData;
} }

View File

@ -76,7 +76,7 @@ function extendLogger(logger: PrefixedLogger) {
extendLogger(logger); extendLogger(logger);
function getPrefixedLogger(prefix): PrefixedLogger { function getPrefixedLogger(prefix: string): PrefixedLogger {
const prefixLogger: PrefixedLogger = log.getLogger(`${DEFAULT_NAMESPACE}-${prefix}`); const prefixLogger: PrefixedLogger = log.getLogger(`${DEFAULT_NAMESPACE}-${prefix}`);
if (prefixLogger.prefix !== prefix) { if (prefixLogger.prefix !== prefix) {
// Only do this setup work the first time through, as loggers are saved by name. // Only do this setup work the first time through, as loggers are saved by name.

View File

@ -121,7 +121,7 @@ export interface ICryptoCallbacks {
) => Promise<string>; ) => Promise<string>;
getDehydrationKey?: ( getDehydrationKey?: (
keyInfo: ISecretStorageKeyInfo, keyInfo: ISecretStorageKeyInfo,
checkFunc: (Uint8Array) => void, checkFunc: (key: Uint8Array) => void,
) => Promise<Uint8Array>; ) => Promise<Uint8Array>;
getBackupKey?: () => Promise<Uint8Array>; getBackupKey?: () => Promise<Uint8Array>;
} }

View File

@ -33,7 +33,7 @@ import { Thread } from "./thread";
// var DEBUG = false; // var DEBUG = false;
const DEBUG = true; const DEBUG = true;
let debuglog; let debuglog: (...args: any[]) => void;
if (DEBUG) { if (DEBUG) {
// using bind means that we get to keep useful line numbers in the console // using bind means that we get to keep useful line numbers in the console
debuglog = logger.log.bind(logger); debuglog = logger.log.bind(logger);

View File

@ -29,7 +29,7 @@ import {
MsgType, MsgType,
RelationType, RelationType,
} from "../@types/event"; } from "../@types/event";
import { Crypto } from "../crypto"; import { Crypto, IEventDecryptionResult } from "../crypto";
import { deepSortedObjectEntries } from "../utils"; import { deepSortedObjectEntries } from "../utils";
import { RoomMember } from "./room-member"; import { RoomMember } from "./room-member";
import { Thread, ThreadEvent } from "./thread"; import { Thread, ThreadEvent } from "./thread";
@ -85,7 +85,7 @@ export interface IUnsigned {
age?: number; age?: number;
prev_sender?: string; prev_sender?: string;
prev_content?: IContent; prev_content?: IContent;
redacted_because?: IEvent; redacted_because?: IClearEvent;
transaction_id?: string; transaction_id?: string;
invite_room_state?: StrippedState[]; invite_room_state?: StrippedState[];
} }
@ -124,25 +124,13 @@ export interface IEventRelation {
key?: string; key?: string;
} }
interface IDecryptionResult {
clearEvent: {
room_id?: string;
type: string;
content: IContent;
unsigned?: IUnsigned;
};
forwardingCurve25519KeyChain?: string[];
senderCurve25519Key?: string;
claimedEd25519Key?: string;
untrusted?: boolean;
}
/* eslint-enable camelcase */
export interface IClearEvent { export interface IClearEvent {
room_id?: string;
type: string; type: string;
content: Omit<IContent, "membership" | "avatar_url" | "displayname" | "m.relates_to">; content: Omit<IContent, "membership" | "avatar_url" | "displayname" | "m.relates_to">;
unsigned?: IUnsigned; unsigned?: IUnsigned;
} }
/* eslint-enable camelcase */
interface IKeyRequestRecipient { interface IKeyRequestRecipient {
userId: string; userId: string;
@ -215,14 +203,14 @@ export class MatrixEvent extends EventEmitter {
public sender: RoomMember = null; public sender: RoomMember = null;
public target: RoomMember = null; public target: RoomMember = null;
public status: EventStatus = null; public status: EventStatus = null;
public error = null; public error: Error = null;
public forwardLooking = true; public forwardLooking = true;
/* If the event is a `m.key.verification.request` (or to_device `m.key.verification.start`) event, /* If the event is a `m.key.verification.request` (or to_device `m.key.verification.start`) event,
* `Crypto` will set this the `VerificationRequest` for the event * `Crypto` will set this the `VerificationRequest` for the event
* so it can be easily accessed from the timeline. * so it can be easily accessed from the timeline.
*/ */
public verificationRequest = null; public verificationRequest: VerificationRequest = null;
private readonly reEmitter: ReEmitter; private readonly reEmitter: ReEmitter;
@ -690,8 +678,8 @@ export class MatrixEvent extends EventEmitter {
while (true) { while (true) {
this.retryDecryption = false; this.retryDecryption = false;
let res; let res: IEventDecryptionResult;
let err; let err: Error;
try { try {
if (!crypto) { if (!crypto) {
res = this.badEncryptedMessage("Encryption not enabled"); res = this.badEncryptedMessage("Encryption not enabled");
@ -779,7 +767,7 @@ export class MatrixEvent extends EventEmitter {
} }
} }
private badEncryptedMessage(reason: string): IDecryptionResult { private badEncryptedMessage(reason: string): IEventDecryptionResult {
return { return {
clearEvent: { clearEvent: {
type: "m.room.message", type: "m.room.message",
@ -803,7 +791,7 @@ export class MatrixEvent extends EventEmitter {
* @param {module:crypto~EventDecryptionResult} decryptionResult * @param {module:crypto~EventDecryptionResult} decryptionResult
* the decryption result, including the plaintext and some key info * the decryption result, including the plaintext and some key info
*/ */
private setClearData(decryptionResult: IDecryptionResult): void { private setClearData(decryptionResult: IEventDecryptionResult): void {
this.clearEvent = decryptionResult.clearEvent; this.clearEvent = decryptionResult.clearEvent;
this.senderCurve25519Key = this.senderCurve25519Key =
decryptionResult.senderCurve25519Key || null; decryptionResult.senderCurve25519Key || null;

View File

@ -48,19 +48,19 @@ const SAFE_ROOM_VERSIONS = ['1', '2', '3', '4', '5', '6'];
function synthesizeReceipt(userId: string, event: MatrixEvent, receiptType: string): MatrixEvent { function synthesizeReceipt(userId: string, event: MatrixEvent, receiptType: string): MatrixEvent {
// console.log("synthesizing receipt for "+event.getId()); // console.log("synthesizing receipt for "+event.getId());
// This is really ugly because JS has no way to express an object literal return new MatrixEvent({
// where the name of a key comes from an expression content: {
const fakeReceipt = { [event.getId()]: {
content: {}, [receiptType]: {
[userId]: {
ts: event.getTs(),
},
},
},
},
type: "m.receipt", type: "m.receipt",
room_id: event.getRoomId(), room_id: event.getRoomId(),
}; });
fakeReceipt.content[event.getId()] = {};
fakeReceipt.content[event.getId()][receiptType] = {};
fakeReceipt.content[event.getId()][receiptType][userId] = {
ts: event.getTs(),
};
return new MatrixEvent(fakeReceipt);
} }
interface IOpts { interface IOpts {
@ -240,7 +240,7 @@ export class Room extends EventEmitter {
const serializedPendingEventList = client.sessionStore.store.getItem(pendingEventsKey(this.roomId)); const serializedPendingEventList = client.sessionStore.store.getItem(pendingEventsKey(this.roomId));
if (serializedPendingEventList) { if (serializedPendingEventList) {
JSON.parse(serializedPendingEventList) JSON.parse(serializedPendingEventList)
.forEach(async serializedEvent => { .forEach(async (serializedEvent: Partial<IEvent>) => {
const event = new MatrixEvent(serializedEvent); const event = new MatrixEvent(serializedEvent);
if (event.getType() === EventType.RoomMessageEncrypted) { if (event.getType() === EventType.RoomMessageEncrypted) {
await event.attemptDecryption(this.client.crypto); await event.attemptDecryption(this.client.crypto);
@ -997,14 +997,14 @@ export class Room extends EventEmitter {
* @return {array} The room's alias as an array of strings * @return {array} The room's alias as an array of strings
*/ */
public getAliases(): string[] { public getAliases(): string[] {
const aliasStrings = []; const aliasStrings: string[] = [];
const aliasEvents = this.currentState.getStateEvents(EventType.RoomAliases); const aliasEvents = this.currentState.getStateEvents(EventType.RoomAliases);
if (aliasEvents) { if (aliasEvents) {
for (let i = 0; i < aliasEvents.length; ++i) { for (let i = 0; i < aliasEvents.length; ++i) {
const aliasEvent = aliasEvents[i]; const aliasEvent = aliasEvents[i];
if (Array.isArray(aliasEvent.getContent().aliases)) { if (Array.isArray(aliasEvent.getContent().aliases)) {
const filteredAliases = aliasEvent.getContent().aliases.filter(a => { const filteredAliases = aliasEvent.getContent<{ aliases: string[] }>().aliases.filter(a => {
if (typeof(a) !== "string") return false; if (typeof(a) !== "string") return false;
if (a[0] !== '#') return false; if (a[0] !== '#') return false;
if (!a.endsWith(`:${aliasEvent.getStateKey()}`)) return false; if (!a.endsWith(`:${aliasEvent.getStateKey()}`)) return false;
@ -1992,7 +1992,7 @@ export class Room extends EventEmitter {
* @return {Object} Map of receipts by event ID * @return {Object} Map of receipts by event ID
*/ */
private buildReceiptCache(receipts: Receipts): ReceiptCache { private buildReceiptCache(receipts: Receipts): ReceiptCache {
const receiptCacheByEventId = {}; const receiptCacheByEventId: ReceiptCache = {};
Object.keys(receipts).forEach(function(receiptType) { Object.keys(receipts).forEach(function(receiptType) {
Object.keys(receipts[receiptType]).forEach(function(userId) { Object.keys(receipts[receiptType]).forEach(function(userId) {
const receipt = receipts[receiptType][userId]; const receipt = receipts[receiptType][userId];
@ -2185,7 +2185,7 @@ export class Room extends EventEmitter {
} }
// get members that are NOT ourselves and are actually in the room. // get members that are NOT ourselves and are actually in the room.
let otherNames = null; let otherNames: string[] = null;
if (this.summaryHeroes) { if (this.summaryHeroes) {
// if we have a summary, the member state events // if we have a summary, the member state events
// should be in the room state // should be in the room state
@ -2266,31 +2266,29 @@ function pendingEventsKey(roomId: string): string {
/* a map from current event status to a list of allowed next statuses /* a map from current event status to a list of allowed next statuses
*/ */
const ALLOWED_TRANSITIONS = {}; const ALLOWED_TRANSITIONS: Record<EventStatus, EventStatus[]> = {
[EventStatus.ENCRYPTING]: [
ALLOWED_TRANSITIONS[EventStatus.ENCRYPTING] = [ EventStatus.SENDING,
EventStatus.SENDING, EventStatus.NOT_SENT,
EventStatus.NOT_SENT, ],
]; [EventStatus.SENDING]: [
EventStatus.ENCRYPTING,
ALLOWED_TRANSITIONS[EventStatus.SENDING] = [ EventStatus.QUEUED,
EventStatus.ENCRYPTING, EventStatus.NOT_SENT,
EventStatus.QUEUED, EventStatus.SENT,
EventStatus.NOT_SENT, ],
EventStatus.SENT, [EventStatus.QUEUED]: [
]; EventStatus.SENDING,
EventStatus.CANCELLED,
ALLOWED_TRANSITIONS[EventStatus.QUEUED] = ],
[EventStatus.SENDING, EventStatus.CANCELLED]; [EventStatus.SENT]: [],
[EventStatus.NOT_SENT]: [
ALLOWED_TRANSITIONS[EventStatus.SENT] = EventStatus.SENDING,
[]; EventStatus.QUEUED,
EventStatus.CANCELLED,
ALLOWED_TRANSITIONS[EventStatus.NOT_SENT] = ],
[EventStatus.SENDING, EventStatus.QUEUED, EventStatus.CANCELLED]; [EventStatus.CANCELLED]: [],
};
ALLOWED_TRANSITIONS[EventStatus.CANCELLED] =
[];
// TODO i18n // TODO i18n
function memberNamesToRoomName(names: string[], count = (names.length + 1)) { function memberNamesToRoomName(names: string[], count = (names.length + 1)) {

View File

@ -284,7 +284,7 @@ export class MatrixScheduler<T = ISendEventResponse> {
} }
} }
function debuglog(...args) { function debuglog(...args: any[]) {
if (DEBUG) { if (DEBUG) {
logger.log(...args); logger.log(...args);
} }

View File

@ -51,14 +51,14 @@ export interface IStore {
* Set the sync token. * Set the sync token.
* @param {string} token * @param {string} token
*/ */
setSyncToken(token: string); setSyncToken(token: string): void;
/** /**
* No-op. * No-op.
* @param {Group} group * @param {Group} group
* @deprecated groups/communities never made it to the spec and support for them is being discontinued. * @deprecated groups/communities never made it to the spec and support for them is being discontinued.
*/ */
storeGroup(group: Group); storeGroup(group: Group): void;
/** /**
* No-op. * No-op.
@ -79,7 +79,7 @@ export interface IStore {
* No-op. * No-op.
* @param {Room} room * @param {Room} room
*/ */
storeRoom(room: Room); storeRoom(room: Room): void;
/** /**
* No-op. * No-op.
@ -98,7 +98,7 @@ export interface IStore {
* Permanently delete a room. * Permanently delete a room.
* @param {string} roomId * @param {string} roomId
*/ */
removeRoom(roomId: string); removeRoom(roomId: string): void;
/** /**
* No-op. * No-op.
@ -110,7 +110,7 @@ export interface IStore {
* No-op. * No-op.
* @param {User} user * @param {User} user
*/ */
storeUser(user: User); storeUser(user: User): void;
/** /**
* No-op. * No-op.
@ -140,13 +140,13 @@ export interface IStore {
* @param {string} token The token associated with these events. * @param {string} token The token associated with these events.
* @param {boolean} toStart True if these are paginated results. * @param {boolean} toStart True if these are paginated results.
*/ */
storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean); storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean): void;
/** /**
* Store a filter. * Store a filter.
* @param {Filter} filter * @param {Filter} filter
*/ */
storeFilter(filter: Filter); storeFilter(filter: Filter): void;
/** /**
* Retrieve a filter. * Retrieve a filter.
@ -168,13 +168,13 @@ export interface IStore {
* @param {string} filterName * @param {string} filterName
* @param {string} filterId * @param {string} filterId
*/ */
setFilterIdByName(filterName: string, filterId: string); setFilterIdByName(filterName: string, filterId: string): void;
/** /**
* Store user-scoped account data events * Store user-scoped account data events
* @param {Array<MatrixEvent>} events The events to store. * @param {Array<MatrixEvent>} events The events to store.
*/ */
storeAccountDataEvents(events: MatrixEvent[]); storeAccountDataEvents(events: MatrixEvent[]): void;
/** /**
* Get account data event by event type * Get account data event by event type

View File

@ -66,7 +66,7 @@ function selectQuery<T>(
): Promise<T[]> { ): Promise<T[]> {
const query = store.openCursor(keyRange); const query = store.openCursor(keyRange);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const results = []; const results: T[] = [];
query.onerror = () => { query.onerror = () => {
reject(new Error("Query failed: " + query.error)); reject(new Error("Query failed: " + query.error));
}; };
@ -238,7 +238,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
const range = IDBKeyRange.only(roomId); const range = IDBKeyRange.only(roomId);
const request = roomIndex.openCursor(range); const request = roomIndex.openCursor(range);
const membershipEvents = []; const membershipEvents: IEvent[] = [];
// did we encounter the oob_written marker object // did we encounter the oob_written marker object
// amongst the results? That means OOB member // amongst the results? That means OOB member
// loading already happened for this room // loading already happened for this room

View File

@ -90,23 +90,20 @@ export function removeElement<T>(
array: T[], array: T[],
fn: (t: T, i?: number, a?: T[]) => boolean, fn: (t: T, i?: number, a?: T[]) => boolean,
reverse?: boolean, reverse?: boolean,
) { ): boolean {
let i; let i: number;
let removed;
if (reverse) { if (reverse) {
for (i = array.length - 1; i >= 0; i--) { for (i = array.length - 1; i >= 0; i--) {
if (fn(array[i], i, array)) { if (fn(array[i], i, array)) {
removed = array[i];
array.splice(i, 1); array.splice(i, 1);
return removed; return true;
} }
} }
} else { } else {
for (i = 0; i < array.length; i++) { for (i = 0; i < array.length; i++) {
if (fn(array[i], i, array)) { if (fn(array[i], i, array)) {
removed = array[i];
array.splice(i, 1); array.splice(i, 1);
return removed; return true;
} }
} }
} }
@ -276,31 +273,6 @@ export function deepSortedObjectEntries(obj: any): [string, any][] {
return pairs; return pairs;
} }
/**
* Copy properties from one object to another.
*
* All enumerable properties, included inherited ones, are copied.
*
* This is approximately equivalent to ES6's Object.assign, except
* that the latter doesn't copy inherited properties.
*
* @param {Object} target The object that will receive new properties
* @param {...Object} source Objects from which to copy properties
*
* @return {Object} target
*/
export function extend(...restParams) {
const target = restParams[0] || {};
for (let i = 1; i < restParams.length; i++) {
const source = restParams[i];
if (!source) continue;
for (const propName in source) { // eslint-disable-line guard-for-in
target[propName] = source[propName];
}
}
return target;
}
/** /**
* Inherit the prototype methods from one constructor into another. This is a * Inherit the prototype methods from one constructor into another. This is a
* port of the Node.js implementation with an Object.create polyfill. * port of the Node.js implementation with an Object.create polyfill.