From 2a3b13ecce4d40f5e0fd98d59fb0645ad6a541ab Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 18 Nov 2021 17:06:20 +0530 Subject: [PATCH 01/37] Add request type --- src/platform/types/Platform.ts | 37 ++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/platform/types/Platform.ts diff --git a/src/platform/types/Platform.ts b/src/platform/types/Platform.ts new file mode 100644 index 00000000..ac125e2c --- /dev/null +++ b/src/platform/types/Platform.ts @@ -0,0 +1,37 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import type {RequestResult} from "../web/dom/request/fetch.js"; +import type {BlobHandle} from "../web/dom/BlobHandle.js"; + +//ts-todo: This should go somewhere else? +interface BlobBody { + mimeType: string; + body: BlobHandle; + length: number; +} + +interface IRequestOptions { + uploadProgress?: (loadedBytes: number) => void; + timeout?: number; + body?: string | BlobBody; + headers?: { [key: string]: number | string }; + cache?: boolean; + method: string; + format: string; +} + +export type Request = (url: string, options: IRequestOptions) => RequestResult; From 9688a561b37edb7531a76ca3fa59cf872b4b9aa9 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 18 Nov 2021 17:13:30 +0530 Subject: [PATCH 02/37] Move interface to common.ts --- src/matrix/net/{common.js => common.ts} | 8 ++++++++ src/platform/types/Platform.ts | 9 +-------- 2 files changed, 9 insertions(+), 8 deletions(-) rename src/matrix/net/{common.js => common.ts} (90%) diff --git a/src/matrix/net/common.js b/src/matrix/net/common.ts similarity index 90% rename from src/matrix/net/common.js rename to src/matrix/net/common.ts index 889042ae..1f0a9f69 100644 --- a/src/matrix/net/common.js +++ b/src/matrix/net/common.ts @@ -15,6 +15,14 @@ See the License for the specific language governing permissions and limitations under the License. */ +import type {BlobHandle} from "../../platform/web/dom/BlobHandle.js"; + +export interface BlobBody { + mimeType: string; + body: BlobHandle; + length: number; +} + export function encodeQueryParams(queryParams) { return Object.entries(queryParams || {}) .filter(([, value]) => value !== undefined) diff --git a/src/platform/types/Platform.ts b/src/platform/types/Platform.ts index ac125e2c..fce55f81 100644 --- a/src/platform/types/Platform.ts +++ b/src/platform/types/Platform.ts @@ -15,14 +15,7 @@ limitations under the License. */ import type {RequestResult} from "../web/dom/request/fetch.js"; -import type {BlobHandle} from "../web/dom/BlobHandle.js"; - -//ts-todo: This should go somewhere else? -interface BlobBody { - mimeType: string; - body: BlobHandle; - length: number; -} +import type {BlobBody} from "../../matrix/net/common"; interface IRequestOptions { uploadProgress?: (loadedBytes: number) => void; From 3a24019d96b0d9d1616280b9519508a96e2c440a Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 21 Nov 2021 20:50:07 +0530 Subject: [PATCH 03/37] Convert common.js to ts --- src/matrix/net/common.ts | 20 +++++++++++--------- src/platform/types/Platform.ts | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index 1f0a9f69..ce9baeba 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -15,15 +15,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type {BlobHandle} from "../../platform/web/dom/BlobHandle.js"; +import {BlobHandle} from "../../platform/web/dom/BlobHandle.js"; -export interface BlobBody { +export interface IEncodedBody { mimeType: string; - body: BlobHandle; + body: BlobHandle | string; length: number; } -export function encodeQueryParams(queryParams) { +export function encodeQueryParams(queryParams: object): string { return Object.entries(queryParams || {}) .filter(([, value]) => value !== undefined) .map(([name, value]) => { @@ -35,9 +35,10 @@ export function encodeQueryParams(queryParams) { .join("&"); } -export function encodeBody(body) { - if (body.nativeBlob && body.mimeType) { - const blob = body; +export function encodeBody(body: {}): IEncodedBody { + // todo: code change here + if (body instanceof BlobHandle) { + const blob = body as BlobHandle; return { mimeType: blob.mimeType, body: blob, // will be unwrapped in request fn @@ -48,8 +49,9 @@ export function encodeBody(body) { return { mimeType: "application/json", body: json, - length: body.length - }; + // todo: code change here; body.length is a mistake? + length: json.length + } } else { throw new Error("Unknown body type: " + body); } diff --git a/src/platform/types/Platform.ts b/src/platform/types/Platform.ts index fce55f81..1cc972a8 100644 --- a/src/platform/types/Platform.ts +++ b/src/platform/types/Platform.ts @@ -15,12 +15,12 @@ limitations under the License. */ import type {RequestResult} from "../web/dom/request/fetch.js"; -import type {BlobBody} from "../../matrix/net/common"; +import type {IEncodedBody} from "../../matrix/net/common"; interface IRequestOptions { uploadProgress?: (loadedBytes: number) => void; timeout?: number; - body?: string | BlobBody; + body?: IEncodedBody; headers?: { [key: string]: number | string }; cache?: boolean; method: string; From e1a823400ad3efdda63574a73696d1c979a97f34 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 21 Nov 2021 21:12:28 +0530 Subject: [PATCH 04/37] Convert ExponentialRetryDelay.js to ts --- src/matrix/SessionContainer.js | 2 +- ...RetryDelay.js => ExponentialRetryDelay.ts} | 24 +++++++++++++------ src/matrix/net/HomeServerApi.js | 2 +- src/matrix/net/MediaRepository.js | 2 +- src/matrix/net/Reconnector.js | 2 +- src/matrix/net/RequestScheduler.js | 2 +- src/platform/types/Platform.ts | 2 ++ 7 files changed, 24 insertions(+), 12 deletions(-) rename src/matrix/net/{ExponentialRetryDelay.js => ExponentialRetryDelay.ts} (86%) diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 44d7b3e4..89325d49 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -21,7 +21,7 @@ import {AbortableOperation} from "../utils/AbortableOperation"; import {ObservableValue} from "../observable/ObservableValue"; import {HomeServerApi} from "./net/HomeServerApi.js"; import {Reconnector, ConnectionStatus} from "./net/Reconnector.js"; -import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay.js"; +import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay"; import {MediaRepository} from "./net/MediaRepository.js"; import {RequestScheduler} from "./net/RequestScheduler.js"; import {Sync, SyncStatus} from "./Sync.js"; diff --git a/src/matrix/net/ExponentialRetryDelay.js b/src/matrix/net/ExponentialRetryDelay.ts similarity index 86% rename from src/matrix/net/ExponentialRetryDelay.js rename to src/matrix/net/ExponentialRetryDelay.ts index 853f8758..a6a874f3 100644 --- a/src/matrix/net/ExponentialRetryDelay.js +++ b/src/matrix/net/ExponentialRetryDelay.ts @@ -15,18 +15,28 @@ limitations under the License. */ import {AbortError} from "../../utils/error"; +import type {Timeout} from "../../platform/web/dom/Clock.js"; + +type TimeoutCreator = (ms: number) => Timeout; + +const enum Default { start = 2000 } export class ExponentialRetryDelay { - constructor(createTimeout) { + private readonly _start: number = Default.start; + private _current: number = Default.start; + private readonly _createTimeout: TimeoutCreator; + private readonly _max: number; + private _timeout?: Timeout; + + constructor(createTimeout: TimeoutCreator) { const start = 2000; this._start = start; this._current = start; this._createTimeout = createTimeout; this._max = 60 * 5 * 1000; //5 min - this._timeout = null; } - async waitForRetry() { + async waitForRetry(): Promise { this._timeout = this._createTimeout(this._current); try { await this._timeout.elapsed(); @@ -39,22 +49,22 @@ export class ExponentialRetryDelay { throw err; } } finally { - this._timeout = null; + this._timeout = undefined; } } - abort() { + abort(): void { if (this._timeout) { this._timeout.abort(); } } - reset() { + reset(): void { this._current = this._start; this.abort(); } - get nextValue() { + get nextValue(): number { return this._current; } } diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.js index 308e71d9..01f5cb45 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {encodeQueryParams, encodeBody} from "./common.js"; +import {encodeQueryParams, encodeBody} from "./common"; import {HomeServerRequest} from "./HomeServerRequest.js"; const CS_R0_PREFIX = "/_matrix/client/r0"; diff --git a/src/matrix/net/MediaRepository.js b/src/matrix/net/MediaRepository.js index 3f718c85..a7875d99 100644 --- a/src/matrix/net/MediaRepository.js +++ b/src/matrix/net/MediaRepository.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {encodeQueryParams} from "./common.js"; +import {encodeQueryParams} from "./common"; import {decryptAttachment} from "../e2ee/attachment.js"; export class MediaRepository { diff --git a/src/matrix/net/Reconnector.js b/src/matrix/net/Reconnector.js index 6eaa78d7..c4231c79 100644 --- a/src/matrix/net/Reconnector.js +++ b/src/matrix/net/Reconnector.js @@ -120,7 +120,7 @@ export class Reconnector { import {Clock as MockClock} from "../../mocks/Clock.js"; -import {ExponentialRetryDelay} from "./ExponentialRetryDelay.js"; +import {ExponentialRetryDelay} from "./ExponentialRetryDelay"; import {ConnectionError} from "../error.js" export function tests() { diff --git a/src/matrix/net/RequestScheduler.js b/src/matrix/net/RequestScheduler.js index f9adec97..b5c5a8fc 100644 --- a/src/matrix/net/RequestScheduler.js +++ b/src/matrix/net/RequestScheduler.js @@ -18,7 +18,7 @@ limitations under the License. import {AbortError} from "../../utils/error"; import {HomeServerError} from "../error.js"; import {HomeServerApi} from "./HomeServerApi.js"; -import {ExponentialRetryDelay} from "./ExponentialRetryDelay.js"; +import {ExponentialRetryDelay} from "./ExponentialRetryDelay"; class Request { constructor(methodName, args) { diff --git a/src/platform/types/Platform.ts b/src/platform/types/Platform.ts index 1cc972a8..b8b715ed 100644 --- a/src/platform/types/Platform.ts +++ b/src/platform/types/Platform.ts @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// todo: this file should be called something else? + import type {RequestResult} from "../web/dom/request/fetch.js"; import type {IEncodedBody} from "../../matrix/net/common"; From ff53c2757d85b08126a857cd47ae0fbf7988b4ed Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 21 Nov 2021 21:28:16 +0530 Subject: [PATCH 05/37] Convert HomeServerRequest.js to ts --- src/matrix/net/HomeServerApi.js | 2 +- ...{HomeServerRequest.js => HomeServerRequest.ts} | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) rename src/matrix/net/{HomeServerRequest.js => HomeServerRequest.ts} (92%) diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.js index 01f5cb45..fe5e470b 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.js @@ -16,7 +16,7 @@ limitations under the License. */ import {encodeQueryParams, encodeBody} from "./common"; -import {HomeServerRequest} from "./HomeServerRequest.js"; +import {HomeServerRequest} from "./HomeServerRequest"; const CS_R0_PREFIX = "/_matrix/client/r0"; const DEHYDRATION_PREFIX = "/_matrix/client/unstable/org.matrix.msc2697.v2"; diff --git a/src/matrix/net/HomeServerRequest.js b/src/matrix/net/HomeServerRequest.ts similarity index 92% rename from src/matrix/net/HomeServerRequest.js rename to src/matrix/net/HomeServerRequest.ts index 97728c28..f57fac2a 100644 --- a/src/matrix/net/HomeServerRequest.js +++ b/src/matrix/net/HomeServerRequest.ts @@ -16,9 +16,16 @@ limitations under the License. */ import {HomeServerError, ConnectionError} from "../error.js"; +import type {RequestResult} from "../../platform/web/dom/request/fetch.js"; +import type {LogItem} from "../../logging/LogItem"; export class HomeServerRequest { - constructor(method, url, sourceRequest, log) { + // todo: Shouldn't log be of type ILogItem; but ILogItem does not have finish method + private readonly _log?: LogItem; + private _sourceRequest?: RequestResult; + private readonly _promise: Promise; + + constructor(method:string, url:string, sourceRequest:RequestResult, log?: LogItem) { this._log = log; this._sourceRequest = sourceRequest; this._promise = sourceRequest.response().then(response => { @@ -80,16 +87,16 @@ export class HomeServerRequest { }); } - abort() { + abort(): void { if (this._sourceRequest) { this._log?.set("aborted", true); this._sourceRequest.abort(); // to mark that it was on purpose in above rejection handler - this._sourceRequest = null; + this._sourceRequest = undefined; } } - response() { + response(): Promise { return this._promise; } } From 90e3fde35d48627b7150bf936cd80f1161717bf1 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 22 Nov 2021 12:39:33 +0530 Subject: [PATCH 06/37] Convert MediaRepository.js to ts --- src/matrix/SessionContainer.js | 2 +- ...{MediaRepository.js => MediaRepository.ts} | 22 +++++--- src/matrix/net/types/response.ts | 54 +++++++++++++++++++ 3 files changed, 69 insertions(+), 9 deletions(-) rename src/matrix/net/{MediaRepository.js => MediaRepository.ts} (71%) create mode 100644 src/matrix/net/types/response.ts diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 89325d49..7b0dfa1e 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -22,7 +22,7 @@ import {ObservableValue} from "../observable/ObservableValue"; import {HomeServerApi} from "./net/HomeServerApi.js"; import {Reconnector, ConnectionStatus} from "./net/Reconnector.js"; import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay"; -import {MediaRepository} from "./net/MediaRepository.js"; +import {MediaRepository} from "./net/MediaRepository"; import {RequestScheduler} from "./net/RequestScheduler.js"; import {Sync, SyncStatus} from "./Sync.js"; import {Session} from "./Session.js"; diff --git a/src/matrix/net/MediaRepository.js b/src/matrix/net/MediaRepository.ts similarity index 71% rename from src/matrix/net/MediaRepository.js rename to src/matrix/net/MediaRepository.ts index a7875d99..0bf70149 100644 --- a/src/matrix/net/MediaRepository.js +++ b/src/matrix/net/MediaRepository.ts @@ -16,14 +16,20 @@ limitations under the License. import {encodeQueryParams} from "./common"; import {decryptAttachment} from "../e2ee/attachment.js"; +import {Platform} from "../../platform/web/Platform.js"; +import {BlobHandle} from "../../platform/web/dom/BlobHandle.js"; +import type {IAttachment, IEncryptedFile} from "./types/response"; export class MediaRepository { - constructor({homeserver, platform}) { + private readonly _homeserver: string; + private readonly _platform: Platform; + + constructor({homeserver, platform}: {homeserver:string, platform: Platform}) { this._homeserver = homeserver; this._platform = platform; } - mxcUrlThumbnail(url, width, height, method) { + mxcUrlThumbnail(url: string, width: number, height: number, method: "crop" | "scale"): string | null { const parts = this._parseMxcUrl(url); if (parts) { const [serverName, mediaId] = parts; @@ -33,7 +39,7 @@ export class MediaRepository { return null; } - mxcUrl(url) { + mxcUrl(url: string): string | null { const parts = this._parseMxcUrl(url); if (parts) { const [serverName, mediaId] = parts; @@ -43,7 +49,7 @@ export class MediaRepository { } } - _parseMxcUrl(url) { + _parseMxcUrl(url: string): string[] | null { const prefix = "mxc://"; if (url.startsWith(prefix)) { return url.substr(prefix.length).split("/", 2); @@ -52,24 +58,24 @@ export class MediaRepository { } } - async downloadEncryptedFile(fileEntry, cache = false) { + async downloadEncryptedFile(fileEntry: IEncryptedFile, cache: boolean = false): Promise { const url = this.mxcUrl(fileEntry.url); const {body: encryptedBuffer} = await this._platform.request(url, {method: "GET", format: "buffer", cache}).response(); const decryptedBuffer = await decryptAttachment(this._platform, encryptedBuffer, fileEntry); return this._platform.createBlob(decryptedBuffer, fileEntry.mimetype); } - async downloadPlaintextFile(mxcUrl, mimetype, cache = false) { + async downloadPlaintextFile(mxcUrl: string, mimetype: string, cache: boolean = false): Promise { const url = this.mxcUrl(mxcUrl); const {body: buffer} = await this._platform.request(url, {method: "GET", format: "buffer", cache}).response(); return this._platform.createBlob(buffer, mimetype); } - async downloadAttachment(content, cache = false) { + async downloadAttachment(content: IAttachment, cache: boolean = false): Promise { if (content.file) { return this.downloadEncryptedFile(content.file, cache); } else { - return this.downloadPlaintextFile(content.url, content.info?.mimetype, cache); + return this.downloadPlaintextFile(content.url!, content.info?.mimetype, cache); } } } diff --git a/src/matrix/net/types/response.ts b/src/matrix/net/types/response.ts new file mode 100644 index 00000000..762bd683 --- /dev/null +++ b/src/matrix/net/types/response.ts @@ -0,0 +1,54 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export interface IAttachment { + body: string; + info: IAttachmentInfo; + // todo: what about m.audio? + msgtype: "m.image" | "m.file" | "m.video"; + url?: string; + file?: IEncryptedFile; + filename?: string; +} + +export interface IEncryptedFile { + key: JsonWebKey; + iv: string; + hashes: { + sha256: string; + }; + url: string; + v: string; + mimetype?: string; +} + +interface IAttachmentInfo { + h?: number; + w?: number; + mimetype: string; + size: number; + duration?: number; + thumbnail_url?: string; + thumbnail_file?: IEncryptedFile; + thumbnail_info?: IThumbnailInfo; +} + +interface IThumbnailInfo { + h: number; + w: number; + mimetype: string; + size: number; +} From f120ce50e6698736cbefc3238f6643faee403e00 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 22 Nov 2021 15:16:46 +0530 Subject: [PATCH 07/37] Convert Reconnector.js to ts --- src/domain/session/SessionStatusViewModel.js | 2 +- src/matrix/SessionContainer.js | 2 +- .../net/{Reconnector.js => Reconnector.ts} | 45 ++++++++++++------- src/matrix/net/types/response.ts | 5 +++ src/platform/web/dom/Clock.js | 1 - 5 files changed, 35 insertions(+), 20 deletions(-) rename src/matrix/net/{Reconnector.js => Reconnector.ts} (79%) diff --git a/src/domain/session/SessionStatusViewModel.js b/src/domain/session/SessionStatusViewModel.js index 27dad7cc..fcedb371 100644 --- a/src/domain/session/SessionStatusViewModel.js +++ b/src/domain/session/SessionStatusViewModel.js @@ -16,7 +16,7 @@ limitations under the License. import {ViewModel} from "../ViewModel.js"; import {createEnum} from "../../utils/enum"; -import {ConnectionStatus} from "../../matrix/net/Reconnector.js"; +import {ConnectionStatus} from "../../matrix/net/Reconnector"; import {SyncStatus} from "../../matrix/Sync.js"; const SessionStatus = createEnum( diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 7b0dfa1e..9dad9333 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -20,7 +20,7 @@ import {lookupHomeserver} from "./well-known.js"; import {AbortableOperation} from "../utils/AbortableOperation"; import {ObservableValue} from "../observable/ObservableValue"; import {HomeServerApi} from "./net/HomeServerApi.js"; -import {Reconnector, ConnectionStatus} from "./net/Reconnector.js"; +import {Reconnector, ConnectionStatus} from "./net/Reconnector"; import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay"; import {MediaRepository} from "./net/MediaRepository"; import {RequestScheduler} from "./net/RequestScheduler.js"; diff --git a/src/matrix/net/Reconnector.js b/src/matrix/net/Reconnector.ts similarity index 79% rename from src/matrix/net/Reconnector.js rename to src/matrix/net/Reconnector.ts index c4231c79..7f9c9660 100644 --- a/src/matrix/net/Reconnector.js +++ b/src/matrix/net/Reconnector.ts @@ -14,42 +14,53 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {createEnum} from "../../utils/enum"; import {ObservableValue} from "../../observable/ObservableValue"; +import type {ExponentialRetryDelay} from "./ExponentialRetryDelay"; +import type {TimeMeasure} from "../../platform/web/dom/Clock.js"; +import type {OnlineStatus} from "../../platform/web/dom/OnlineStatus.js"; +import type {IVersionResponse} from "./types/response"; +import type {HomeServerApi} from "./HomeServerApi.js"; -export const ConnectionStatus = createEnum( +export enum ConnectionStatus { "Waiting", "Reconnecting", "Online" -); +}; export class Reconnector { - constructor({retryDelay, createMeasure, onlineStatus}) { + private readonly _retryDelay: ExponentialRetryDelay; + private readonly _createTimeMeasure: () => TimeMeasure; + private readonly _onlineStatus: OnlineStatus; + private readonly _state: ObservableValue; + private _isReconnecting: boolean; + private _versionsResponse?: IVersionResponse = undefined; + private _stateSince: TimeMeasure; + + constructor({retryDelay, createMeasure, onlineStatus}: {retryDelay: ExponentialRetryDelay, createMeasure: () => TimeMeasure, onlineStatus: OnlineStatus}) { this._onlineStatus = onlineStatus; this._retryDelay = retryDelay; this._createTimeMeasure = createMeasure; // assume online, and do our thing when something fails this._state = new ObservableValue(ConnectionStatus.Online); this._isReconnecting = false; - this._versionsResponse = null; } - get lastVersionsResponse() { + get lastVersionsResponse(): IVersionResponse | undefined { return this._versionsResponse; } - get connectionStatus() { + get connectionStatus(): ObservableValue { return this._state; } - get retryIn() { + get retryIn(): number { if (this._state.get() === ConnectionStatus.Waiting) { return this._retryDelay.nextValue - this._stateSince.measure(); } return 0; } - async onRequestFailed(hsApi) { + async onRequestFailed(hsApi: HomeServerApi): Promise { if (!this._isReconnecting) { this._isReconnecting = true; @@ -75,14 +86,14 @@ export class Reconnector { } } - tryNow() { + tryNow(): void { if (this._retryDelay) { // this will interrupt this._retryDelay.waitForRetry() in _reconnectLoop this._retryDelay.abort(); } } - _setState(state) { + _setState(state: ConnectionStatus): void { if (state !== this._state.get()) { if (state === ConnectionStatus.Waiting) { this._stateSince = this._createTimeMeasure(); @@ -93,8 +104,8 @@ export class Reconnector { } } - async _reconnectLoop(hsApi) { - this._versionsResponse = null; + async _reconnectLoop(hsApi: HomeServerApi): Promise { + this._versionsResponse = undefined; this._retryDelay.reset(); while (!this._versionsResponse) { @@ -120,7 +131,7 @@ export class Reconnector { import {Clock as MockClock} from "../../mocks/Clock.js"; -import {ExponentialRetryDelay} from "./ExponentialRetryDelay"; +import {ExponentialRetryDelay as _ExponentialRetryDelay} from "./ExponentialRetryDelay"; import {ConnectionError} from "../error.js" export function tests() { @@ -146,10 +157,10 @@ export function tests() { const clock = new MockClock(); const {createMeasure} = clock; const onlineStatus = new ObservableValue(false); - const retryDelay = new ExponentialRetryDelay(clock.createTimeout); + const retryDelay = new _ExponentialRetryDelay(clock.createTimeout); const reconnector = new Reconnector({retryDelay, onlineStatus, createMeasure}); const {connectionStatus} = reconnector; - const statuses = []; + const statuses: ConnectionStatus[] = []; const subscription = reconnector.connectionStatus.subscribe(s => { statuses.push(s); }); @@ -170,7 +181,7 @@ export function tests() { const clock = new MockClock(); const {createMeasure} = clock; const onlineStatus = new ObservableValue(false); - const retryDelay = new ExponentialRetryDelay(clock.createTimeout); + const retryDelay = new _ExponentialRetryDelay(clock.createTimeout); const reconnector = new Reconnector({retryDelay, onlineStatus, createMeasure}); const {connectionStatus} = reconnector; reconnector.onRequestFailed(createHsApiMock(1)); diff --git a/src/matrix/net/types/response.ts b/src/matrix/net/types/response.ts index 762bd683..4c08adc0 100644 --- a/src/matrix/net/types/response.ts +++ b/src/matrix/net/types/response.ts @@ -52,3 +52,8 @@ interface IThumbnailInfo { mimetype: string; size: number; } + +export interface IVersionResponse { + versions: string[]; + unstable_features?: Record; +} diff --git a/src/platform/web/dom/Clock.js b/src/platform/web/dom/Clock.js index 855e925c..6691bc73 100644 --- a/src/platform/web/dom/Clock.js +++ b/src/platform/web/dom/Clock.js @@ -60,7 +60,6 @@ class Interval { } } - class TimeMeasure { constructor() { this._start = window.performance.now(); From 0aae31a4505185e9a22d091788d2d02aa5d1f553 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 22 Nov 2021 15:21:48 +0530 Subject: [PATCH 08/37] Change year in copyright notice --- src/matrix/net/types/response.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/types/response.ts b/src/matrix/net/types/response.ts index 4c08adc0..e4b71d36 100644 --- a/src/matrix/net/types/response.ts +++ b/src/matrix/net/types/response.ts @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2021 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From cf54b78af74123945e671f8603e6c9b6ce0af241 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 11:58:15 +0530 Subject: [PATCH 09/37] Convert RequestScheduler.js to ts --- src/matrix/SessionContainer.js | 2 +- ...equestScheduler.js => RequestScheduler.ts} | 82 ++++++++++++------- 2 files changed, 52 insertions(+), 32 deletions(-) rename src/matrix/net/{RequestScheduler.js => RequestScheduler.ts} (56%) diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 9dad9333..7bbe74cb 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -23,7 +23,7 @@ import {HomeServerApi} from "./net/HomeServerApi.js"; import {Reconnector, ConnectionStatus} from "./net/Reconnector"; import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay"; import {MediaRepository} from "./net/MediaRepository"; -import {RequestScheduler} from "./net/RequestScheduler.js"; +import {RequestScheduler} from "./net/RequestScheduler"; import {Sync, SyncStatus} from "./Sync.js"; import {Session} from "./Session.js"; import {PasswordLoginMethod} from "./login/PasswordLoginMethod"; diff --git a/src/matrix/net/RequestScheduler.js b/src/matrix/net/RequestScheduler.ts similarity index 56% rename from src/matrix/net/RequestScheduler.js rename to src/matrix/net/RequestScheduler.ts index b5c5a8fc..c11a81d0 100644 --- a/src/matrix/net/RequestScheduler.js +++ b/src/matrix/net/RequestScheduler.ts @@ -19,33 +19,43 @@ import {AbortError} from "../../utils/error"; import {HomeServerError} from "../error.js"; import {HomeServerApi} from "./HomeServerApi.js"; import {ExponentialRetryDelay} from "./ExponentialRetryDelay"; +import {Clock} from "../../platform/web/dom/Clock.js"; +import type {HomeServerRequest} from "./HomeServerRequest.js"; class Request { - constructor(methodName, args) { - this._methodName = methodName; - this._args = args; + public readonly methodName: string; + public readonly args: any[]; + public resolve: (result: Response) => void; + public reject: (error: AbortError) => void; + public requestResult?: HomeServerRequest; + private readonly _responsePromise: Promise; + + constructor(methodName: string, args: any[]) { + this.methodName = methodName; + this.args = args; this._responsePromise = new Promise((resolve, reject) => { - this._resolve = resolve; - this._reject = reject; + this.resolve = resolve; + this.reject = reject; }); - this._requestResult = null; } - abort() { - if (this._requestResult) { - this._requestResult.abort(); + abort(): void { + if (this.requestResult) { + this.requestResult.abort(); } else { - this._reject(new AbortError()); + this.reject(new AbortError()); } } - response() { + response(): Promise { return this._responsePromise; } } class HomeServerApiWrapper { - constructor(scheduler) { + private readonly _scheduler: RequestScheduler; + + constructor(scheduler: RequestScheduler) { this._scheduler = scheduler; } } @@ -60,21 +70,22 @@ for (const methodName of Object.getOwnPropertyNames(HomeServerApi.prototype)) { } export class RequestScheduler { - constructor({hsApi, clock}) { + private readonly _hsApi: HomeServerApi; + private readonly _clock: Clock; + private readonly _requests: Set = new Set(); + private _stopped = false; + private _wrapper = new HomeServerApiWrapper(this); + + constructor({ hsApi, clock }: { hsApi: HomeServerApi; clock: Clock }) { this._hsApi = hsApi; this._clock = clock; - this._requests = new Set(); - this._isRateLimited = false; - this._isDrainingRateLimit = false; - this._stopped = true; - this._wrapper = new HomeServerApiWrapper(this); } - get hsApi() { + get hsApi(): HomeServerApiWrapper { return this._wrapper; } - stop() { + stop(): void { this._stopped = true; for (const request of this._requests) { request.abort(); @@ -82,40 +93,49 @@ export class RequestScheduler { this._requests.clear(); } - start() { + start(): void { this._stopped = false; } - _hsApiRequest(name, args) { + _hsApiRequest(name: string, args: any[]): Request { const request = new Request(name, args); this._doSend(request); return request; } - async _doSend(request) { + private async _doSend(request: Request): Promise { this._requests.add(request); try { - let retryDelay; + let retryDelay: ExponentialRetryDelay | undefined; while (!this._stopped) { try { - const requestResult = this._hsApi[request._methodName].apply(this._hsApi, request._args); + const requestResult = this._hsApi[ + request.methodName + ].apply(this._hsApi, request.args); // so the request can be aborted - request._requestResult = requestResult; + request.requestResult = requestResult; const response = await requestResult.response(); - request._resolve(response); + request.resolve(response); return; } catch (err) { - if (err instanceof HomeServerError && err.errcode === "M_LIMIT_EXCEEDED") { + if ( + err instanceof HomeServerError && + err.errcode === "M_LIMIT_EXCEEDED" + ) { if (Number.isSafeInteger(err.retry_after_ms)) { - await this._clock.createTimeout(err.retry_after_ms).elapsed(); + await this._clock + .createTimeout(err.retry_after_ms) + .elapsed(); } else { if (!retryDelay) { - retryDelay = new ExponentialRetryDelay(this._clock.createTimeout); + retryDelay = new ExponentialRetryDelay( + this._clock.createTimeout + ); } await retryDelay.waitForRetry(); } } else { - request._reject(err); + request.reject(err); return; } } From 145b40f28d39de78edb08561927039c0318d2b4b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 11:59:06 +0530 Subject: [PATCH 10/37] Fomatting fix --- src/matrix/net/HomeServerRequest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/HomeServerRequest.ts b/src/matrix/net/HomeServerRequest.ts index f57fac2a..7f323181 100644 --- a/src/matrix/net/HomeServerRequest.ts +++ b/src/matrix/net/HomeServerRequest.ts @@ -25,7 +25,7 @@ export class HomeServerRequest { private _sourceRequest?: RequestResult; private readonly _promise: Promise; - constructor(method:string, url:string, sourceRequest:RequestResult, log?: LogItem) { + constructor(method: string, url: string, sourceRequest: RequestResult, log?: LogItem) { this._log = log; this._sourceRequest = sourceRequest; this._promise = sourceRequest.response().then(response => { From 7403cbc3894539b3cb134f4370b684ed3077a97e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 18:09:33 +0530 Subject: [PATCH 11/37] WIP - HomeServerApi.js to ts conversion --- src/matrix/SessionContainer.js | 2 +- .../{HomeServerApi.js => HomeServerApi.ts} | 149 ++++++++++-------- src/matrix/net/HomeServerRequest.ts | 4 +- src/matrix/net/Reconnector.ts | 6 +- src/matrix/net/RequestScheduler.ts | 2 +- src/matrix/net/common.ts | 2 +- src/platform/types/Platform.ts | 13 +- 7 files changed, 99 insertions(+), 79 deletions(-) rename src/matrix/net/{HomeServerApi.js => HomeServerApi.ts} (55%) diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 7bbe74cb..677cde34 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -19,7 +19,7 @@ import {createEnum} from "../utils/enum"; import {lookupHomeserver} from "./well-known.js"; import {AbortableOperation} from "../utils/AbortableOperation"; import {ObservableValue} from "../observable/ObservableValue"; -import {HomeServerApi} from "./net/HomeServerApi.js"; +import {HomeServerApi} from "./net/HomeServerApi"; import {Reconnector, ConnectionStatus} from "./net/Reconnector"; import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay"; import {MediaRepository} from "./net/MediaRepository"; diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.ts similarity index 55% rename from src/matrix/net/HomeServerApi.js rename to src/matrix/net/HomeServerApi.ts index fe5e470b..6cf1153c 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.ts @@ -17,12 +17,23 @@ limitations under the License. import {encodeQueryParams, encodeBody} from "./common"; import {HomeServerRequest} from "./HomeServerRequest"; +import type {Reconnector} from "./Reconnector"; +import type {IEncodedBody} from "./common"; +import type {IRequestOptions, RequestFunction} from "../../platform/types/Platform"; +import type {LogItem} from "../../logging/LogItem"; + +type RequestMethod = "POST" | "GET" | "PUT"; const CS_R0_PREFIX = "/_matrix/client/r0"; const DEHYDRATION_PREFIX = "/_matrix/client/unstable/org.matrix.msc2697.v2"; export class HomeServerApi { - constructor({homeserver, accessToken, request, reconnector}) { + private readonly _homeserver: string; + private readonly _accessToken: string; + private readonly _requestFn: RequestFunction; + private readonly _reconnector: Reconnector; + + constructor({homeserver, accessToken, request, reconnector}: {homeserver: string, accessToken: string, request: RequestFunction, reconnector: Reconnector}) { // store these both in a closure somehow so it's harder to get at in case of XSS? // one could change the homeserver as well so the token gets sent there, so both must be protected from read/write this._homeserver = homeserver; @@ -31,14 +42,14 @@ export class HomeServerApi { this._reconnector = reconnector; } - _url(csPath, prefix = CS_R0_PREFIX) { + _url(csPath: string, prefix: string = CS_R0_PREFIX): string { return this._homeserver + prefix + csPath; } - _baseRequest(method, url, queryParams, body, options, accessToken) { + _baseRequest(method: RequestMethod, url: string, queryParams?: object, body?: object, options?: IRequestOptions, accessToken?: string): HomeServerRequest { const queryString = encodeQueryParams(queryParams); url = `${url}?${queryString}`; - let log; + let log: LogItem | undefined; if (options?.log) { const parent = options?.log; log = parent.child({ @@ -47,8 +58,8 @@ export class HomeServerApi { method, }, parent.level.Info); } - let encodedBody; - const headers = new Map(); + let encodedBody: IEncodedBody["body"]; + const headers: Map = new Map(); if (accessToken) { headers.set("Authorization", `Bearer ${accessToken}`); } @@ -56,6 +67,7 @@ export class HomeServerApi { if (body) { const encoded = encodeBody(body); headers.set("Content-Type", encoded.mimeType); + //todo: remove this? headers.set("Content-Length", encoded.length); encodedBody = encoded.body; } @@ -86,63 +98,63 @@ export class HomeServerApi { return hsRequest; } - _unauthedRequest(method, url, queryParams, body, options) { - return this._baseRequest(method, url, queryParams, body, options, null); + _unauthedRequest(method: RequestMethod, url: string, queryParams?: object, body?: object, options?: IRequestOptions): HomeServerRequest { + return this._baseRequest(method, url, queryParams, body, options); } - _authedRequest(method, url, queryParams, body, options) { + _authedRequest(method: RequestMethod, url: string, queryParams?: object, body?: object, options?: IRequestOptions): HomeServerRequest { return this._baseRequest(method, url, queryParams, body, options, this._accessToken); } - _post(csPath, queryParams, body, options) { + _post(csPath: string, queryParams: object, body: object, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("POST", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - _put(csPath, queryParams, body, options) { + _put(csPath: string, queryParams: object, body?: object, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("PUT", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - _get(csPath, queryParams, body, options) { + _get(csPath: string, queryParams?: object, body?: object, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("GET", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - sync(since, filter, timeout, options = null) { - return this._get("/sync", {since, timeout, filter}, null, options); + sync(since: string, filter: string, timeout: number, options?: IRequestOptions) { + return this._get("/sync", {since, timeout, filter}, undefined, options); } // params is from, dir and optionally to, limit, filter. - messages(roomId, params, options = null) { - return this._get(`/rooms/${encodeURIComponent(roomId)}/messages`, params, null, options); + messages(roomId: string, params: object, options?: IRequestOptions) { + return this._get(`/rooms/${encodeURIComponent(roomId)}/messages`, params, undefined, options); } // params is at, membership and not_membership - members(roomId, params, options = null) { - return this._get(`/rooms/${encodeURIComponent(roomId)}/members`, params, null, options); + members(roomId: string, params: object, options?: IRequestOptions) { + return this._get(`/rooms/${encodeURIComponent(roomId)}/members`, params, undefined, options); } - send(roomId, eventType, txnId, content, options = null) { + send(roomId: string, eventType: string, txnId: string, content: object, options?: IRequestOptions) { return this._put(`/rooms/${encodeURIComponent(roomId)}/send/${encodeURIComponent(eventType)}/${encodeURIComponent(txnId)}`, {}, content, options); } - redact(roomId, eventId, txnId, content, options = null) { + redact(roomId: string, eventId: string, txnId: string, content: object, options?: IRequestOptions) { return this._put(`/rooms/${encodeURIComponent(roomId)}/redact/${encodeURIComponent(eventId)}/${encodeURIComponent(txnId)}`, {}, content, options); } - receipt(roomId, receiptType, eventId, options = null) { + receipt(roomId: string, receiptType: string, eventId: string, options?: IRequestOptions) { return this._post(`/rooms/${encodeURIComponent(roomId)}/receipt/${encodeURIComponent(receiptType)}/${encodeURIComponent(eventId)}`, {}, {}, options); } - state(roomId, eventType, stateKey, options = null) { - return this._get(`/rooms/${encodeURIComponent(roomId)}/state/${encodeURIComponent(eventType)}/${encodeURIComponent(stateKey)}`, {}, null, options); + state(roomId: string, eventType: string, stateKey: string, options?: IRequestOptions) { + return this._get(`/rooms/${encodeURIComponent(roomId)}/state/${encodeURIComponent(eventType)}/${encodeURIComponent(stateKey)}`, {}, undefined, options); } getLoginFlows() { - return this._unauthedRequest("GET", this._url("/login"), null, null, null); + return this._unauthedRequest("GET", this._url("/login")); } - passwordLogin(username, password, initialDeviceDisplayName, options = null) { - return this._unauthedRequest("POST", this._url("/login"), null, { + passwordLogin(username: string, password: string, initialDeviceDisplayName: string, options?: IRequestOptions) { + return this._unauthedRequest("POST", this._url("/login"), undefined, { "type": "m.login.password", "identifier": { "type": "m.id.user", @@ -153,8 +165,8 @@ export class HomeServerApi { }, options); } - tokenLogin(loginToken, txnId, initialDeviceDisplayName, options = null) { - return this._unauthedRequest("POST", this._url("/login"), null, { + tokenLogin(loginToken: string, txnId: string, initialDeviceDisplayName: string, options?: IRequestOptions) { + return this._unauthedRequest("POST", this._url("/login"), undefined, { "type": "m.login.token", "identifier": { "type": "m.id.user", @@ -165,91 +177,91 @@ export class HomeServerApi { }, options); } - createFilter(userId, filter, options = null) { - return this._post(`/user/${encodeURIComponent(userId)}/filter`, null, filter, options); + createFilter(userId: string, filter: object, options?: IRequestOptions) { + return this._post(`/user/${encodeURIComponent(userId)}/filter`, {}, filter, options); } - versions(options = null) { - return this._unauthedRequest("GET", `${this._homeserver}/_matrix/client/versions`, null, null, options); + versions(options?: IRequestOptions) { + return this._unauthedRequest("GET", `${this._homeserver}/_matrix/client/versions`, undefined, undefined, options); } - uploadKeys(dehydratedDeviceId, payload, options = null) { + uploadKeys(dehydratedDeviceId: string, payload: object, options?: IRequestOptions) { let path = "/keys/upload"; if (dehydratedDeviceId) { path = path + `/${encodeURIComponent(dehydratedDeviceId)}`; } - return this._post(path, null, payload, options); + return this._post(path, {}, payload, options); } - queryKeys(queryRequest, options = null) { - return this._post("/keys/query", null, queryRequest, options); + queryKeys(queryRequest: object, options?: IRequestOptions) { + return this._post("/keys/query", {}, queryRequest, options); } - claimKeys(payload, options = null) { - return this._post("/keys/claim", null, payload, options); + claimKeys(payload: object, options?: IRequestOptions) { + return this._post("/keys/claim", {}, payload, options); } - sendToDevice(type, payload, txnId, options = null) { - return this._put(`/sendToDevice/${encodeURIComponent(type)}/${encodeURIComponent(txnId)}`, null, payload, options); + sendToDevice(type: string, payload: object, txnId: string, options?: IRequestOptions) { + return this._put(`/sendToDevice/${encodeURIComponent(type)}/${encodeURIComponent(txnId)}`, {}, payload, options); } - roomKeysVersion(version = null, options = null) { + roomKeysVersion(version?: string, options?: IRequestOptions) { let versionPart = ""; if (version) { versionPart = `/${encodeURIComponent(version)}`; } - return this._get(`/room_keys/version${versionPart}`, null, null, options); + return this._get(`/room_keys/version${versionPart}`, undefined, undefined, options); } - roomKeyForRoomAndSession(version, roomId, sessionId, options = null) { - return this._get(`/room_keys/keys/${encodeURIComponent(roomId)}/${encodeURIComponent(sessionId)}`, {version}, null, options); + roomKeyForRoomAndSession(version: string, roomId: string, sessionId: string, options?: IRequestOptions) { + return this._get(`/room_keys/keys/${encodeURIComponent(roomId)}/${encodeURIComponent(sessionId)}`, {version}, undefined, options); } - uploadAttachment(blob, filename, options = null) { + uploadAttachment(blob: Blob, filename: string, options?: IRequestOptions) { return this._authedRequest("POST", `${this._homeserver}/_matrix/media/r0/upload`, {filename}, blob, options); } - setPusher(pusher, options = null) { - return this._post("/pushers/set", null, pusher, options); + setPusher(pusher: object, options?: IRequestOptions) { + return this._post("/pushers/set", {}, pusher, options); } - getPushers(options = null) { - return this._get("/pushers", null, null, options); + getPushers(options?: IRequestOptions) { + return this._get("/pushers", undefined, undefined, options); } - join(roomId, options = null) { - return this._post(`/rooms/${encodeURIComponent(roomId)}/join`, null, null, options); + join(roomId: string, options?: IRequestOptions) { + return this._post(`/rooms/${encodeURIComponent(roomId)}/join`, {}, {}, options); } - joinIdOrAlias(roomIdOrAlias, options = null) { - return this._post(`/join/${encodeURIComponent(roomIdOrAlias)}`, null, null, options); + joinIdOrAlias(roomIdOrAlias: string, options?: IRequestOptions) { + return this._post(`/join/${encodeURIComponent(roomIdOrAlias)}`, {}, {}, options); } - leave(roomId, options = null) { - return this._post(`/rooms/${encodeURIComponent(roomId)}/leave`, null, null, options); + leave(roomId: string, options?: IRequestOptions) { + return this._post(`/rooms/${encodeURIComponent(roomId)}/leave`, {}, {}, options); } - forget(roomId, options = null) { - return this._post(`/rooms/${encodeURIComponent(roomId)}/forget`, null, null, options); + forget(roomId: string, options?: IRequestOptions) { + return this._post(`/rooms/${encodeURIComponent(roomId)}/forget`, {}, {}, options); } - logout(options = null) { - return this._post(`/logout`, null, null, options); + logout(options?: IRequestOptions) { + return this._post(`/logout`, {}, {}, options); } - getDehydratedDevice(options = {}) { + getDehydratedDevice(options: IRequestOptions) { options.prefix = DEHYDRATION_PREFIX; - return this._get(`/dehydrated_device`, null, null, options); + return this._get(`/dehydrated_device`, undefined, undefined, options); } - createDehydratedDevice(payload, options = {}) { + createDehydratedDevice(payload: object, options: IRequestOptions) { options.prefix = DEHYDRATION_PREFIX; - return this._put(`/dehydrated_device`, null, payload, options); + return this._put(`/dehydrated_device`, {}, payload, options); } - claimDehydratedDevice(deviceId, options = {}) { + claimDehydratedDevice(deviceId: string, options: IRequestOptions) { options.prefix = DEHYDRATION_PREFIX; - return this._post(`/dehydrated_device/claim`, null, {device_id: deviceId}, options); + return this._post(`/dehydrated_device/claim`, {}, {device_id: deviceId}, options); } } @@ -258,11 +270,14 @@ import {Request as MockRequest} from "../../mocks/Request.js"; export function tests() { return { "superficial happy path for GET": async assert => { + // @ts-ignore const hsApi = new HomeServerApi({ request: () => new MockRequest().respond(200, 42), - homeserver: "https://hs.tld" + homeserver: "https://hs.tld", }); - const result = await hsApi._get("foo", null, null, null).response(); + const result = await hsApi + ._get("foo", undefined, undefined, undefined) + .response(); assert.strictEqual(result, 42); } } diff --git a/src/matrix/net/HomeServerRequest.ts b/src/matrix/net/HomeServerRequest.ts index 7f323181..aad45f1b 100644 --- a/src/matrix/net/HomeServerRequest.ts +++ b/src/matrix/net/HomeServerRequest.ts @@ -23,7 +23,7 @@ export class HomeServerRequest { // todo: Shouldn't log be of type ILogItem; but ILogItem does not have finish method private readonly _log?: LogItem; private _sourceRequest?: RequestResult; - private readonly _promise: Promise; + private readonly _promise: Promise; constructor(method: string, url: string, sourceRequest: RequestResult, log?: LogItem) { this._log = log; @@ -96,7 +96,7 @@ export class HomeServerRequest { } } - response(): Promise { + response(): Promise { return this._promise; } } diff --git a/src/matrix/net/Reconnector.ts b/src/matrix/net/Reconnector.ts index 7f9c9660..b1394425 100644 --- a/src/matrix/net/Reconnector.ts +++ b/src/matrix/net/Reconnector.ts @@ -19,7 +19,7 @@ import type {ExponentialRetryDelay} from "./ExponentialRetryDelay"; import type {TimeMeasure} from "../../platform/web/dom/Clock.js"; import type {OnlineStatus} from "../../platform/web/dom/OnlineStatus.js"; import type {IVersionResponse} from "./types/response"; -import type {HomeServerApi} from "./HomeServerApi.js"; +import type {HomeServerApi} from "./HomeServerApi"; export enum ConnectionStatus { "Waiting", @@ -33,7 +33,7 @@ export class Reconnector { private readonly _onlineStatus: OnlineStatus; private readonly _state: ObservableValue; private _isReconnecting: boolean; - private _versionsResponse?: IVersionResponse = undefined; + private _versionsResponse?: IVersionResponse; private _stateSince: TimeMeasure; constructor({retryDelay, createMeasure, onlineStatus}: {retryDelay: ExponentialRetryDelay, createMeasure: () => TimeMeasure, onlineStatus: OnlineStatus}) { @@ -164,6 +164,7 @@ export function tests() { const subscription = reconnector.connectionStatus.subscribe(s => { statuses.push(s); }); + // @ts-ignore reconnector.onRequestFailed(createHsApiMock(1)); await connectionStatus.waitFor(s => s === ConnectionStatus.Waiting).promise; clock.elapse(2000); @@ -184,6 +185,7 @@ export function tests() { const retryDelay = new _ExponentialRetryDelay(clock.createTimeout); const reconnector = new Reconnector({retryDelay, onlineStatus, createMeasure}); const {connectionStatus} = reconnector; + // @ts-ignore reconnector.onRequestFailed(createHsApiMock(1)); await connectionStatus.waitFor(s => s === ConnectionStatus.Waiting).promise; onlineStatus.set(true); //skip waiting diff --git a/src/matrix/net/RequestScheduler.ts b/src/matrix/net/RequestScheduler.ts index c11a81d0..b47845c4 100644 --- a/src/matrix/net/RequestScheduler.ts +++ b/src/matrix/net/RequestScheduler.ts @@ -17,7 +17,7 @@ limitations under the License. import {AbortError} from "../../utils/error"; import {HomeServerError} from "../error.js"; -import {HomeServerApi} from "./HomeServerApi.js"; +import {HomeServerApi} from "./HomeServerApi"; import {ExponentialRetryDelay} from "./ExponentialRetryDelay"; import {Clock} from "../../platform/web/dom/Clock.js"; import type {HomeServerRequest} from "./HomeServerRequest.js"; diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index ce9baeba..7a07c445 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -23,7 +23,7 @@ export interface IEncodedBody { length: number; } -export function encodeQueryParams(queryParams: object): string { +export function encodeQueryParams(queryParams?: object): string { return Object.entries(queryParams || {}) .filter(([, value]) => value !== undefined) .map(([name, value]) => { diff --git a/src/platform/types/Platform.ts b/src/platform/types/Platform.ts index b8b715ed..8390a92d 100644 --- a/src/platform/types/Platform.ts +++ b/src/platform/types/Platform.ts @@ -18,15 +18,18 @@ limitations under the License. import type {RequestResult} from "../web/dom/request/fetch.js"; import type {IEncodedBody} from "../../matrix/net/common"; +import {LogItem} from "../../logging/LogItem"; -interface IRequestOptions { +export interface IRequestOptions { uploadProgress?: (loadedBytes: number) => void; timeout?: number; body?: IEncodedBody; - headers?: { [key: string]: number | string }; + headers?: Map; cache?: boolean; - method: string; - format: string; + log?: LogItem; + prefix?: string; + method?: string; + format?: string; } -export type Request = (url: string, options: IRequestOptions) => RequestResult; +export type RequestFunction = (url: string, options: IRequestOptions) => RequestResult; From 885abc59be4db7a1e7189298ac90535e04c82898 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 18:13:40 +0530 Subject: [PATCH 12/37] Add return types --- src/matrix/net/HomeServerApi.ts | 58 ++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index 6cf1153c..3088022b 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -118,42 +118,42 @@ export class HomeServerApi { return this._authedRequest("GET", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - sync(since: string, filter: string, timeout: number, options?: IRequestOptions) { + sync(since: string, filter: string, timeout: number, options?: IRequestOptions): HomeServerRequest { return this._get("/sync", {since, timeout, filter}, undefined, options); } // params is from, dir and optionally to, limit, filter. - messages(roomId: string, params: object, options?: IRequestOptions) { + messages(roomId: string, params: object, options?: IRequestOptions): HomeServerRequest { return this._get(`/rooms/${encodeURIComponent(roomId)}/messages`, params, undefined, options); } // params is at, membership and not_membership - members(roomId: string, params: object, options?: IRequestOptions) { + members(roomId: string, params: object, options?: IRequestOptions): HomeServerRequest { return this._get(`/rooms/${encodeURIComponent(roomId)}/members`, params, undefined, options); } - send(roomId: string, eventType: string, txnId: string, content: object, options?: IRequestOptions) { + send(roomId: string, eventType: string, txnId: string, content: object, options?: IRequestOptions): HomeServerRequest { return this._put(`/rooms/${encodeURIComponent(roomId)}/send/${encodeURIComponent(eventType)}/${encodeURIComponent(txnId)}`, {}, content, options); } - redact(roomId: string, eventId: string, txnId: string, content: object, options?: IRequestOptions) { + redact(roomId: string, eventId: string, txnId: string, content: object, options?: IRequestOptions): HomeServerRequest { return this._put(`/rooms/${encodeURIComponent(roomId)}/redact/${encodeURIComponent(eventId)}/${encodeURIComponent(txnId)}`, {}, content, options); } - receipt(roomId: string, receiptType: string, eventId: string, options?: IRequestOptions) { + receipt(roomId: string, receiptType: string, eventId: string, options?: IRequestOptions): HomeServerRequest { return this._post(`/rooms/${encodeURIComponent(roomId)}/receipt/${encodeURIComponent(receiptType)}/${encodeURIComponent(eventId)}`, {}, {}, options); } - state(roomId: string, eventType: string, stateKey: string, options?: IRequestOptions) { + state(roomId: string, eventType: string, stateKey: string, options?: IRequestOptions): HomeServerRequest { return this._get(`/rooms/${encodeURIComponent(roomId)}/state/${encodeURIComponent(eventType)}/${encodeURIComponent(stateKey)}`, {}, undefined, options); } - getLoginFlows() { + getLoginFlows(): HomeServerRequest { return this._unauthedRequest("GET", this._url("/login")); } - passwordLogin(username: string, password: string, initialDeviceDisplayName: string, options?: IRequestOptions) { + passwordLogin(username: string, password: string, initialDeviceDisplayName: string, options?: IRequestOptions): HomeServerRequest { return this._unauthedRequest("POST", this._url("/login"), undefined, { "type": "m.login.password", "identifier": { @@ -165,7 +165,7 @@ export class HomeServerApi { }, options); } - tokenLogin(loginToken: string, txnId: string, initialDeviceDisplayName: string, options?: IRequestOptions) { + tokenLogin(loginToken: string, txnId: string, initialDeviceDisplayName: string, options?: IRequestOptions): HomeServerRequest { return this._unauthedRequest("POST", this._url("/login"), undefined, { "type": "m.login.token", "identifier": { @@ -177,15 +177,15 @@ export class HomeServerApi { }, options); } - createFilter(userId: string, filter: object, options?: IRequestOptions) { + createFilter(userId: string, filter: object, options?: IRequestOptions): HomeServerRequest { return this._post(`/user/${encodeURIComponent(userId)}/filter`, {}, filter, options); } - versions(options?: IRequestOptions) { + versions(options?: IRequestOptions): HomeServerRequest { return this._unauthedRequest("GET", `${this._homeserver}/_matrix/client/versions`, undefined, undefined, options); } - uploadKeys(dehydratedDeviceId: string, payload: object, options?: IRequestOptions) { + uploadKeys(dehydratedDeviceId: string, payload: object, options?: IRequestOptions): HomeServerRequest { let path = "/keys/upload"; if (dehydratedDeviceId) { path = path + `/${encodeURIComponent(dehydratedDeviceId)}`; @@ -193,19 +193,19 @@ export class HomeServerApi { return this._post(path, {}, payload, options); } - queryKeys(queryRequest: object, options?: IRequestOptions) { + queryKeys(queryRequest: object, options?: IRequestOptions): HomeServerRequest { return this._post("/keys/query", {}, queryRequest, options); } - claimKeys(payload: object, options?: IRequestOptions) { + claimKeys(payload: object, options?: IRequestOptions): HomeServerRequest { return this._post("/keys/claim", {}, payload, options); } - sendToDevice(type: string, payload: object, txnId: string, options?: IRequestOptions) { + sendToDevice(type: string, payload: object, txnId: string, options?: IRequestOptions): HomeServerRequest { return this._put(`/sendToDevice/${encodeURIComponent(type)}/${encodeURIComponent(txnId)}`, {}, payload, options); } - roomKeysVersion(version?: string, options?: IRequestOptions) { + roomKeysVersion(version?: string, options?: IRequestOptions): HomeServerRequest { let versionPart = ""; if (version) { versionPart = `/${encodeURIComponent(version)}`; @@ -213,53 +213,53 @@ export class HomeServerApi { return this._get(`/room_keys/version${versionPart}`, undefined, undefined, options); } - roomKeyForRoomAndSession(version: string, roomId: string, sessionId: string, options?: IRequestOptions) { + roomKeyForRoomAndSession(version: string, roomId: string, sessionId: string, options?: IRequestOptions): HomeServerRequest { return this._get(`/room_keys/keys/${encodeURIComponent(roomId)}/${encodeURIComponent(sessionId)}`, {version}, undefined, options); } - uploadAttachment(blob: Blob, filename: string, options?: IRequestOptions) { + uploadAttachment(blob: Blob, filename: string, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("POST", `${this._homeserver}/_matrix/media/r0/upload`, {filename}, blob, options); } - setPusher(pusher: object, options?: IRequestOptions) { + setPusher(pusher: object, options?: IRequestOptions): HomeServerRequest { return this._post("/pushers/set", {}, pusher, options); } - getPushers(options?: IRequestOptions) { + getPushers(options?: IRequestOptions): HomeServerRequest { return this._get("/pushers", undefined, undefined, options); } - join(roomId: string, options?: IRequestOptions) { + join(roomId: string, options?: IRequestOptions): HomeServerRequest { return this._post(`/rooms/${encodeURIComponent(roomId)}/join`, {}, {}, options); } - joinIdOrAlias(roomIdOrAlias: string, options?: IRequestOptions) { + joinIdOrAlias(roomIdOrAlias: string, options?: IRequestOptions): HomeServerRequest { return this._post(`/join/${encodeURIComponent(roomIdOrAlias)}`, {}, {}, options); } - leave(roomId: string, options?: IRequestOptions) { + leave(roomId: string, options?: IRequestOptions): HomeServerRequest { return this._post(`/rooms/${encodeURIComponent(roomId)}/leave`, {}, {}, options); } - forget(roomId: string, options?: IRequestOptions) { + forget(roomId: string, options?: IRequestOptions): HomeServerRequest { return this._post(`/rooms/${encodeURIComponent(roomId)}/forget`, {}, {}, options); } - logout(options?: IRequestOptions) { + logout(options?: IRequestOptions): HomeServerRequest { return this._post(`/logout`, {}, {}, options); } - getDehydratedDevice(options: IRequestOptions) { + getDehydratedDevice(options: IRequestOptions): HomeServerRequest { options.prefix = DEHYDRATION_PREFIX; return this._get(`/dehydrated_device`, undefined, undefined, options); } - createDehydratedDevice(payload: object, options: IRequestOptions) { + createDehydratedDevice(payload: object, options: IRequestOptions): HomeServerRequest { options.prefix = DEHYDRATION_PREFIX; return this._put(`/dehydrated_device`, {}, payload, options); } - claimDehydratedDevice(deviceId: string, options: IRequestOptions) { + claimDehydratedDevice(deviceId: string, options: IRequestOptions): HomeServerRequest { options.prefix = DEHYDRATION_PREFIX; return this._post(`/dehydrated_device/claim`, {}, {device_id: deviceId}, options); } From 8387215efd53fe396eb729b924d70fd26a664122 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 18:15:22 +0530 Subject: [PATCH 13/37] Add comment --- src/matrix/net/HomeServerRequest.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/matrix/net/HomeServerRequest.ts b/src/matrix/net/HomeServerRequest.ts index aad45f1b..4a9fdf75 100644 --- a/src/matrix/net/HomeServerRequest.ts +++ b/src/matrix/net/HomeServerRequest.ts @@ -23,6 +23,7 @@ export class HomeServerRequest { // todo: Shouldn't log be of type ILogItem; but ILogItem does not have finish method private readonly _log?: LogItem; private _sourceRequest?: RequestResult; + // as we add types for expected responses from hs, this could be a generic class instead private readonly _promise: Promise; constructor(method: string, url: string, sourceRequest: RequestResult, log?: LogItem) { From 57d24dcf90ca9a3a4550e20ad70422bded10ffc7 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 19:12:07 +0530 Subject: [PATCH 14/37] Treat wrapper hsapi as HomeServerApi --- src/matrix/net/RequestScheduler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/matrix/net/RequestScheduler.ts b/src/matrix/net/RequestScheduler.ts index b47845c4..2b9fe855 100644 --- a/src/matrix/net/RequestScheduler.ts +++ b/src/matrix/net/RequestScheduler.ts @@ -81,8 +81,8 @@ export class RequestScheduler { this._clock = clock; } - get hsApi(): HomeServerApiWrapper { - return this._wrapper; + get hsApi(): HomeServerApi { + return this._wrapper as unknown as HomeServerApi; } stop(): void { From 9b315d1564670eedea7a55830c34dcb8f30f27f3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 19:12:18 +0530 Subject: [PATCH 15/37] Replace object with Record --- src/matrix/net/HomeServerApi.ts | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index 3088022b..d8da297f 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -46,7 +46,7 @@ export class HomeServerApi { return this._homeserver + prefix + csPath; } - _baseRequest(method: RequestMethod, url: string, queryParams?: object, body?: object, options?: IRequestOptions, accessToken?: string): HomeServerRequest { + _baseRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions, accessToken?: string): HomeServerRequest { const queryString = encodeQueryParams(queryParams); url = `${url}?${queryString}`; let log: LogItem | undefined; @@ -98,23 +98,23 @@ export class HomeServerApi { return hsRequest; } - _unauthedRequest(method: RequestMethod, url: string, queryParams?: object, body?: object, options?: IRequestOptions): HomeServerRequest { + _unauthedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { return this._baseRequest(method, url, queryParams, body, options); } - _authedRequest(method: RequestMethod, url: string, queryParams?: object, body?: object, options?: IRequestOptions): HomeServerRequest { + _authedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { return this._baseRequest(method, url, queryParams, body, options, this._accessToken); } - _post(csPath: string, queryParams: object, body: object, options?: IRequestOptions): HomeServerRequest { + _post(csPath: string, queryParams: Record, body: Record, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("POST", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - _put(csPath: string, queryParams: object, body?: object, options?: IRequestOptions): HomeServerRequest { + _put(csPath: string, queryParams: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("PUT", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - _get(csPath: string, queryParams?: object, body?: object, options?: IRequestOptions): HomeServerRequest { + _get(csPath: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("GET", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } @@ -123,20 +123,20 @@ export class HomeServerApi { } // params is from, dir and optionally to, limit, filter. - messages(roomId: string, params: object, options?: IRequestOptions): HomeServerRequest { + messages(roomId: string, params: Record, options?: IRequestOptions): HomeServerRequest { return this._get(`/rooms/${encodeURIComponent(roomId)}/messages`, params, undefined, options); } // params is at, membership and not_membership - members(roomId: string, params: object, options?: IRequestOptions): HomeServerRequest { + members(roomId: string, params: Record, options?: IRequestOptions): HomeServerRequest { return this._get(`/rooms/${encodeURIComponent(roomId)}/members`, params, undefined, options); } - send(roomId: string, eventType: string, txnId: string, content: object, options?: IRequestOptions): HomeServerRequest { + send(roomId: string, eventType: string, txnId: string, content: Record, options?: IRequestOptions): HomeServerRequest { return this._put(`/rooms/${encodeURIComponent(roomId)}/send/${encodeURIComponent(eventType)}/${encodeURIComponent(txnId)}`, {}, content, options); } - redact(roomId: string, eventId: string, txnId: string, content: object, options?: IRequestOptions): HomeServerRequest { + redact(roomId: string, eventId: string, txnId: string, content: Record, options?: IRequestOptions): HomeServerRequest { return this._put(`/rooms/${encodeURIComponent(roomId)}/redact/${encodeURIComponent(eventId)}/${encodeURIComponent(txnId)}`, {}, content, options); } @@ -177,7 +177,7 @@ export class HomeServerApi { }, options); } - createFilter(userId: string, filter: object, options?: IRequestOptions): HomeServerRequest { + createFilter(userId: string, filter: Record, options?: IRequestOptions): HomeServerRequest { return this._post(`/user/${encodeURIComponent(userId)}/filter`, {}, filter, options); } @@ -185,7 +185,7 @@ export class HomeServerApi { return this._unauthedRequest("GET", `${this._homeserver}/_matrix/client/versions`, undefined, undefined, options); } - uploadKeys(dehydratedDeviceId: string, payload: object, options?: IRequestOptions): HomeServerRequest { + uploadKeys(dehydratedDeviceId: string, payload: Record, options?: IRequestOptions): HomeServerRequest { let path = "/keys/upload"; if (dehydratedDeviceId) { path = path + `/${encodeURIComponent(dehydratedDeviceId)}`; @@ -193,15 +193,15 @@ export class HomeServerApi { return this._post(path, {}, payload, options); } - queryKeys(queryRequest: object, options?: IRequestOptions): HomeServerRequest { + queryKeys(queryRequest: Record, options?: IRequestOptions): HomeServerRequest { return this._post("/keys/query", {}, queryRequest, options); } - claimKeys(payload: object, options?: IRequestOptions): HomeServerRequest { + claimKeys(payload: Record, options?: IRequestOptions): HomeServerRequest { return this._post("/keys/claim", {}, payload, options); } - sendToDevice(type: string, payload: object, txnId: string, options?: IRequestOptions): HomeServerRequest { + sendToDevice(type: string, payload: Record, txnId: string, options?: IRequestOptions): HomeServerRequest { return this._put(`/sendToDevice/${encodeURIComponent(type)}/${encodeURIComponent(txnId)}`, {}, payload, options); } @@ -221,7 +221,7 @@ export class HomeServerApi { return this._authedRequest("POST", `${this._homeserver}/_matrix/media/r0/upload`, {filename}, blob, options); } - setPusher(pusher: object, options?: IRequestOptions): HomeServerRequest { + setPusher(pusher: Record, options?: IRequestOptions): HomeServerRequest { return this._post("/pushers/set", {}, pusher, options); } @@ -254,7 +254,7 @@ export class HomeServerApi { return this._get(`/dehydrated_device`, undefined, undefined, options); } - createDehydratedDevice(payload: object, options: IRequestOptions): HomeServerRequest { + createDehydratedDevice(payload: Record, options: IRequestOptions): HomeServerRequest { options.prefix = DEHYDRATION_PREFIX; return this._put(`/dehydrated_device`, {}, payload, options); } From 2dd050bd906b7221b50e11a81dab1655a81a3010 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 19:23:15 +0530 Subject: [PATCH 16/37] Change object to Record --- src/matrix/net/common.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index 7a07c445..0cabdb1f 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -23,7 +23,7 @@ export interface IEncodedBody { length: number; } -export function encodeQueryParams(queryParams?: object): string { +export function encodeQueryParams(queryParams?: Record): string { return Object.entries(queryParams || {}) .filter(([, value]) => value !== undefined) .map(([name, value]) => { @@ -35,7 +35,7 @@ export function encodeQueryParams(queryParams?: object): string { .join("&"); } -export function encodeBody(body: {}): IEncodedBody { +export function encodeBody(body: Record): IEncodedBody { // todo: code change here if (body instanceof BlobHandle) { const blob = body as BlobHandle; From 69e67ad5ace7210dff60f5ca5a2faa2d1aa5047f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 19:31:13 +0530 Subject: [PATCH 17/37] Make more functions private --- src/matrix/net/HomeServerApi.ts | 19 +++++++++---------- src/matrix/net/MediaRepository.ts | 2 +- src/matrix/net/Reconnector.ts | 4 ++-- src/matrix/net/RequestScheduler.ts | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index d8da297f..3f99497d 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -42,11 +42,11 @@ export class HomeServerApi { this._reconnector = reconnector; } - _url(csPath: string, prefix: string = CS_R0_PREFIX): string { + private _url(csPath: string, prefix: string = CS_R0_PREFIX): string { return this._homeserver + prefix + csPath; } - _baseRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions, accessToken?: string): HomeServerRequest { + private _baseRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions, accessToken?: string): HomeServerRequest { const queryString = encodeQueryParams(queryParams); url = `${url}?${queryString}`; let log: LogItem | undefined; @@ -98,23 +98,23 @@ export class HomeServerApi { return hsRequest; } - _unauthedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { + private _unauthedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { return this._baseRequest(method, url, queryParams, body, options); } - _authedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { + private _authedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { return this._baseRequest(method, url, queryParams, body, options, this._accessToken); } - _post(csPath: string, queryParams: Record, body: Record, options?: IRequestOptions): HomeServerRequest { + private _post(csPath: string, queryParams: Record, body: Record, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("POST", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - _put(csPath: string, queryParams: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { + private _put(csPath: string, queryParams: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("PUT", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - _get(csPath: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { + private _get(csPath: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { return this._authedRequest("GET", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } @@ -275,9 +275,8 @@ export function tests() { request: () => new MockRequest().respond(200, 42), homeserver: "https://hs.tld", }); - const result = await hsApi - ._get("foo", undefined, undefined, undefined) - .response(); + // @ts-ignore + const result = await hsApi._get("foo", undefined, undefined, undefined).response(); assert.strictEqual(result, 42); } } diff --git a/src/matrix/net/MediaRepository.ts b/src/matrix/net/MediaRepository.ts index 0bf70149..a19eac9a 100644 --- a/src/matrix/net/MediaRepository.ts +++ b/src/matrix/net/MediaRepository.ts @@ -49,7 +49,7 @@ export class MediaRepository { } } - _parseMxcUrl(url: string): string[] | null { + private _parseMxcUrl(url: string): string[] | null { const prefix = "mxc://"; if (url.startsWith(prefix)) { return url.substr(prefix.length).split("/", 2); diff --git a/src/matrix/net/Reconnector.ts b/src/matrix/net/Reconnector.ts index b1394425..0d20b623 100644 --- a/src/matrix/net/Reconnector.ts +++ b/src/matrix/net/Reconnector.ts @@ -93,7 +93,7 @@ export class Reconnector { } } - _setState(state: ConnectionStatus): void { + private _setState(state: ConnectionStatus): void { if (state !== this._state.get()) { if (state === ConnectionStatus.Waiting) { this._stateSince = this._createTimeMeasure(); @@ -104,7 +104,7 @@ export class Reconnector { } } - async _reconnectLoop(hsApi: HomeServerApi): Promise { + private async _reconnectLoop(hsApi: HomeServerApi): Promise { this._versionsResponse = undefined; this._retryDelay.reset(); diff --git a/src/matrix/net/RequestScheduler.ts b/src/matrix/net/RequestScheduler.ts index 2b9fe855..c0ab1d60 100644 --- a/src/matrix/net/RequestScheduler.ts +++ b/src/matrix/net/RequestScheduler.ts @@ -97,7 +97,7 @@ export class RequestScheduler { this._stopped = false; } - _hsApiRequest(name: string, args: any[]): Request { + private _hsApiRequest(name: string, args: any[]): Request { const request = new Request(name, args); this._doSend(request); return request; From 4bdcafad4bcff61f5930943d2d938a2dda6e50d9 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 23 Nov 2021 19:37:25 +0530 Subject: [PATCH 18/37] Rename file to types.ts --- src/matrix/net/HomeServerApi.ts | 2 +- src/platform/types/{Platform.ts => types.ts} | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) rename src/platform/types/{Platform.ts => types.ts} (91%) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index 3f99497d..20d13dd9 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -19,7 +19,7 @@ import {encodeQueryParams, encodeBody} from "./common"; import {HomeServerRequest} from "./HomeServerRequest"; import type {Reconnector} from "./Reconnector"; import type {IEncodedBody} from "./common"; -import type {IRequestOptions, RequestFunction} from "../../platform/types/Platform"; +import type {IRequestOptions, RequestFunction} from "../../platform/types/types"; import type {LogItem} from "../../logging/LogItem"; type RequestMethod = "POST" | "GET" | "PUT"; diff --git a/src/platform/types/Platform.ts b/src/platform/types/types.ts similarity index 91% rename from src/platform/types/Platform.ts rename to src/platform/types/types.ts index 8390a92d..817f3739 100644 --- a/src/platform/types/Platform.ts +++ b/src/platform/types/types.ts @@ -14,11 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -// todo: this file should be called something else? - import type {RequestResult} from "../web/dom/request/fetch.js"; import type {IEncodedBody} from "../../matrix/net/common"; -import {LogItem} from "../../logging/LogItem"; +import type {LogItem} from "../../logging/LogItem"; export interface IRequestOptions { uploadProgress?: (loadedBytes: number) => void; From 2e6b90917320f824eacad1e5e8b0958091cf4833 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 12:59:10 +0530 Subject: [PATCH 19/37] No need to pass undefined --- src/matrix/net/HomeServerApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index 20d13dd9..c459ab9c 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -276,7 +276,7 @@ export function tests() { homeserver: "https://hs.tld", }); // @ts-ignore - const result = await hsApi._get("foo", undefined, undefined, undefined).response(); + const result = await hsApi._get("foo").response(); assert.strictEqual(result, 42); } } From 238b9aafb1c3397c8789621757d016904e86de67 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 12:59:27 +0530 Subject: [PATCH 20/37] Convert replay.js to ts --- src/main.js | 2 +- .../net/request/{replay.js => replay.ts} | 62 ++++++++++++------- 2 files changed, 40 insertions(+), 24 deletions(-) rename src/matrix/net/request/{replay.js => replay.ts} (64%) diff --git a/src/main.js b/src/main.js index 0754b2ab..49386c3b 100644 --- a/src/main.js +++ b/src/main.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// import {RecordRequester, ReplayRequester} from "./matrix/net/request/replay.js"; +// import {RecordRequester, ReplayRequester} from "./matrix/net/request/replay"; import {SessionContainer} from "./matrix/SessionContainer.js"; import {RootViewModel} from "./domain/RootViewModel.js"; import {createNavigation, createRouter} from "./domain/navigation/index.js"; diff --git a/src/matrix/net/request/replay.js b/src/matrix/net/request/replay.ts similarity index 64% rename from src/matrix/net/request/replay.js rename to src/matrix/net/request/replay.ts index c85a32fd..32a059d3 100644 --- a/src/matrix/net/request/replay.js +++ b/src/matrix/net/request/replay.ts @@ -14,29 +14,36 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { - AbortError, - ConnectionError -} from "../../error.js"; +import {AbortError, ConnectionError} from "../../error.js"; +import type {IRequestOptions, RequestFunction} from "../../../platform/types/types.js"; +import type {RequestResult} from "../../../platform/web/dom/request/fetch.js"; + +interface IOptions extends IRequestOptions { + method?: any; + delay?: boolean; +} class RequestLogItem { - constructor(url, options) { + public readonly url: string; + public readonly options: IOptions; + public error: {aborted: boolean, network: boolean, message: string}; + public status: number; + public body: Response["body"]; + public start: number = performance.now(); + public end: number = 0; + + constructor(url: string, options: IOptions) { this.url = url; this.options = options; - this.error = null; - this.body = null; - this.status = status; - this.start = performance.now(); - this.end = 0; } - async handleResponse(response) { + async handleResponse(response: Response) { this.end = performance.now(); this.status = response.status; this.body = response.body; } - handleError(err) { + handleError(err: Error): void { this.end = performance.now(); this.error = { aborted: err instanceof AbortError, @@ -47,13 +54,15 @@ class RequestLogItem { } export class RecordRequester { - constructor(request) { + private readonly _origRequest: RequestFunction; + private readonly _requestLog: RequestLogItem[] = []; + + constructor(request: RequestFunction) { this._origRequest = request; - this._requestLog = []; this.request = this.request.bind(this); } - request(url, options) { + request(url: string, options: IOptions): RequestResult { const requestItem = new RequestLogItem(url, options); this._requestLog.push(requestItem); try { @@ -68,24 +77,27 @@ export class RecordRequester { } } - log() { + log(): RequestLogItem[] { return this._requestLog; } } export class ReplayRequester { - constructor(log, options) { + private readonly _log: RequestLogItem[]; + private readonly _options: IOptions; + + constructor(log: RequestLogItem[], options: IOptions) { this._log = log.slice(); this._options = options; this.request = this.request.bind(this); } - request(url, options) { - const idx = this._log.findIndex(item => { + request(url: string, options: IOptions): ReplayRequestResult { + const idx = this._log.findIndex((item) => { return item.url === url && options.method === item.options.method; }); if (idx === -1) { - return new ReplayRequestResult({status: 404}, options); + return new ReplayRequestResult({ status: 404 } as RequestLogItem, options); } else { const [item] = this._log.splice(idx, 1); return new ReplayRequestResult(item, options); @@ -94,17 +106,21 @@ export class ReplayRequester { } class ReplayRequestResult { - constructor(item, options) { + private readonly _item: RequestLogItem; + private readonly _options: IOptions; + private _aborted: boolean; + + constructor(item: RequestLogItem, options: IOptions) { this._item = item; this._options = options; this._aborted = false; } - abort() { + abort(): void { this._aborted = true; } - async response() { + async response(): Promise { if (this._options.delay) { const delay = this._item.end - this._item.start; await new Promise(resolve => setTimeout(resolve, delay)); From a8870f2d24b6d7052a5d6380ac52536bb4660198 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 13:05:13 +0530 Subject: [PATCH 21/37] Extract ctor types out --- src/matrix/net/HomeServerApi.ts | 9 ++++++++- src/matrix/net/Reconnector.ts | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index c459ab9c..8f6ab0df 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -27,13 +27,20 @@ type RequestMethod = "POST" | "GET" | "PUT"; const CS_R0_PREFIX = "/_matrix/client/r0"; const DEHYDRATION_PREFIX = "/_matrix/client/unstable/org.matrix.msc2697.v2"; +type Ctor = { + homeserver: string; + accessToken: string; + request: RequestFunction; + reconnector: Reconnector; +}; + export class HomeServerApi { private readonly _homeserver: string; private readonly _accessToken: string; private readonly _requestFn: RequestFunction; private readonly _reconnector: Reconnector; - constructor({homeserver, accessToken, request, reconnector}: {homeserver: string, accessToken: string, request: RequestFunction, reconnector: Reconnector}) { + constructor({homeserver, accessToken, request, reconnector}: Ctor) { // store these both in a closure somehow so it's harder to get at in case of XSS? // one could change the homeserver as well so the token gets sent there, so both must be protected from read/write this._homeserver = homeserver; diff --git a/src/matrix/net/Reconnector.ts b/src/matrix/net/Reconnector.ts index 0d20b623..607ba0b4 100644 --- a/src/matrix/net/Reconnector.ts +++ b/src/matrix/net/Reconnector.ts @@ -27,6 +27,12 @@ export enum ConnectionStatus { "Online" }; +type Ctor = { + retryDelay: ExponentialRetryDelay; + createMeasure: () => TimeMeasure; + onlineStatus: OnlineStatus +}; + export class Reconnector { private readonly _retryDelay: ExponentialRetryDelay; private readonly _createTimeMeasure: () => TimeMeasure; @@ -36,7 +42,7 @@ export class Reconnector { private _versionsResponse?: IVersionResponse; private _stateSince: TimeMeasure; - constructor({retryDelay, createMeasure, onlineStatus}: {retryDelay: ExponentialRetryDelay, createMeasure: () => TimeMeasure, onlineStatus: OnlineStatus}) { + constructor({retryDelay, createMeasure, onlineStatus}: Ctor) { this._onlineStatus = onlineStatus; this._retryDelay = retryDelay; this._createTimeMeasure = createMeasure; From 05121e32b17f40968d3369d554a3bd652dffd64f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 24 Nov 2021 21:05:01 +0530 Subject: [PATCH 22/37] Pull interface out for HomeServerApi --- src/matrix/net/HomeServerApi.ts | 71 +++++++++++++++-------------- src/matrix/net/HomeServerRequest.ts | 7 ++- src/matrix/net/RequestScheduler.ts | 6 +-- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index 8f6ab0df..cd604388 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -17,6 +17,7 @@ limitations under the License. import {encodeQueryParams, encodeBody} from "./common"; import {HomeServerRequest} from "./HomeServerRequest"; +import type {IHomeServerRequest} from "./HomeServerRequest"; import type {Reconnector} from "./Reconnector"; import type {IEncodedBody} from "./common"; import type {IRequestOptions, RequestFunction} from "../../platform/types/types"; @@ -53,7 +54,7 @@ export class HomeServerApi { return this._homeserver + prefix + csPath; } - private _baseRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions, accessToken?: string): HomeServerRequest { + private _baseRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions, accessToken?: string): IHomeServerRequest { const queryString = encodeQueryParams(queryParams); url = `${url}?${queryString}`; let log: LogItem | undefined; @@ -105,62 +106,62 @@ export class HomeServerApi { return hsRequest; } - private _unauthedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { + private _unauthedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): IHomeServerRequest { return this._baseRequest(method, url, queryParams, body, options); } - private _authedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { + private _authedRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions): IHomeServerRequest { return this._baseRequest(method, url, queryParams, body, options, this._accessToken); } - private _post(csPath: string, queryParams: Record, body: Record, options?: IRequestOptions): HomeServerRequest { + private _post(csPath: string, queryParams: Record, body: Record, options?: IRequestOptions): IHomeServerRequest { return this._authedRequest("POST", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - private _put(csPath: string, queryParams: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { + private _put(csPath: string, queryParams: Record, body?: Record, options?: IRequestOptions): IHomeServerRequest { return this._authedRequest("PUT", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - private _get(csPath: string, queryParams?: Record, body?: Record, options?: IRequestOptions): HomeServerRequest { + private _get(csPath: string, queryParams?: Record, body?: Record, options?: IRequestOptions): IHomeServerRequest { return this._authedRequest("GET", this._url(csPath, options?.prefix || CS_R0_PREFIX), queryParams, body, options); } - sync(since: string, filter: string, timeout: number, options?: IRequestOptions): HomeServerRequest { + sync(since: string, filter: string, timeout: number, options?: IRequestOptions): IHomeServerRequest { return this._get("/sync", {since, timeout, filter}, undefined, options); } // params is from, dir and optionally to, limit, filter. - messages(roomId: string, params: Record, options?: IRequestOptions): HomeServerRequest { + messages(roomId: string, params: Record, options?: IRequestOptions): IHomeServerRequest { return this._get(`/rooms/${encodeURIComponent(roomId)}/messages`, params, undefined, options); } // params is at, membership and not_membership - members(roomId: string, params: Record, options?: IRequestOptions): HomeServerRequest { + members(roomId: string, params: Record, options?: IRequestOptions): IHomeServerRequest { return this._get(`/rooms/${encodeURIComponent(roomId)}/members`, params, undefined, options); } - send(roomId: string, eventType: string, txnId: string, content: Record, options?: IRequestOptions): HomeServerRequest { + send(roomId: string, eventType: string, txnId: string, content: Record, options?: IRequestOptions): IHomeServerRequest { return this._put(`/rooms/${encodeURIComponent(roomId)}/send/${encodeURIComponent(eventType)}/${encodeURIComponent(txnId)}`, {}, content, options); } - redact(roomId: string, eventId: string, txnId: string, content: Record, options?: IRequestOptions): HomeServerRequest { + redact(roomId: string, eventId: string, txnId: string, content: Record, options?: IRequestOptions): IHomeServerRequest { return this._put(`/rooms/${encodeURIComponent(roomId)}/redact/${encodeURIComponent(eventId)}/${encodeURIComponent(txnId)}`, {}, content, options); } - receipt(roomId: string, receiptType: string, eventId: string, options?: IRequestOptions): HomeServerRequest { + receipt(roomId: string, receiptType: string, eventId: string, options?: IRequestOptions): IHomeServerRequest { return this._post(`/rooms/${encodeURIComponent(roomId)}/receipt/${encodeURIComponent(receiptType)}/${encodeURIComponent(eventId)}`, {}, {}, options); } - state(roomId: string, eventType: string, stateKey: string, options?: IRequestOptions): HomeServerRequest { + state(roomId: string, eventType: string, stateKey: string, options?: IRequestOptions): IHomeServerRequest { return this._get(`/rooms/${encodeURIComponent(roomId)}/state/${encodeURIComponent(eventType)}/${encodeURIComponent(stateKey)}`, {}, undefined, options); } - getLoginFlows(): HomeServerRequest { + getLoginFlows(): IHomeServerRequest { return this._unauthedRequest("GET", this._url("/login")); } - passwordLogin(username: string, password: string, initialDeviceDisplayName: string, options?: IRequestOptions): HomeServerRequest { + passwordLogin(username: string, password: string, initialDeviceDisplayName: string, options?: IRequestOptions): IHomeServerRequest { return this._unauthedRequest("POST", this._url("/login"), undefined, { "type": "m.login.password", "identifier": { @@ -172,7 +173,7 @@ export class HomeServerApi { }, options); } - tokenLogin(loginToken: string, txnId: string, initialDeviceDisplayName: string, options?: IRequestOptions): HomeServerRequest { + tokenLogin(loginToken: string, txnId: string, initialDeviceDisplayName: string, options?: IRequestOptions): IHomeServerRequest { return this._unauthedRequest("POST", this._url("/login"), undefined, { "type": "m.login.token", "identifier": { @@ -184,15 +185,15 @@ export class HomeServerApi { }, options); } - createFilter(userId: string, filter: Record, options?: IRequestOptions): HomeServerRequest { + createFilter(userId: string, filter: Record, options?: IRequestOptions): IHomeServerRequest { return this._post(`/user/${encodeURIComponent(userId)}/filter`, {}, filter, options); } - versions(options?: IRequestOptions): HomeServerRequest { + versions(options?: IRequestOptions): IHomeServerRequest { return this._unauthedRequest("GET", `${this._homeserver}/_matrix/client/versions`, undefined, undefined, options); } - uploadKeys(dehydratedDeviceId: string, payload: Record, options?: IRequestOptions): HomeServerRequest { + uploadKeys(dehydratedDeviceId: string, payload: Record, options?: IRequestOptions): IHomeServerRequest { let path = "/keys/upload"; if (dehydratedDeviceId) { path = path + `/${encodeURIComponent(dehydratedDeviceId)}`; @@ -200,19 +201,19 @@ export class HomeServerApi { return this._post(path, {}, payload, options); } - queryKeys(queryRequest: Record, options?: IRequestOptions): HomeServerRequest { + queryKeys(queryRequest: Record, options?: IRequestOptions): IHomeServerRequest { return this._post("/keys/query", {}, queryRequest, options); } - claimKeys(payload: Record, options?: IRequestOptions): HomeServerRequest { + claimKeys(payload: Record, options?: IRequestOptions): IHomeServerRequest { return this._post("/keys/claim", {}, payload, options); } - sendToDevice(type: string, payload: Record, txnId: string, options?: IRequestOptions): HomeServerRequest { + sendToDevice(type: string, payload: Record, txnId: string, options?: IRequestOptions): IHomeServerRequest { return this._put(`/sendToDevice/${encodeURIComponent(type)}/${encodeURIComponent(txnId)}`, {}, payload, options); } - roomKeysVersion(version?: string, options?: IRequestOptions): HomeServerRequest { + roomKeysVersion(version?: string, options?: IRequestOptions): IHomeServerRequest { let versionPart = ""; if (version) { versionPart = `/${encodeURIComponent(version)}`; @@ -220,53 +221,53 @@ export class HomeServerApi { return this._get(`/room_keys/version${versionPart}`, undefined, undefined, options); } - roomKeyForRoomAndSession(version: string, roomId: string, sessionId: string, options?: IRequestOptions): HomeServerRequest { + roomKeyForRoomAndSession(version: string, roomId: string, sessionId: string, options?: IRequestOptions): IHomeServerRequest { return this._get(`/room_keys/keys/${encodeURIComponent(roomId)}/${encodeURIComponent(sessionId)}`, {version}, undefined, options); } - uploadAttachment(blob: Blob, filename: string, options?: IRequestOptions): HomeServerRequest { + uploadAttachment(blob: Blob, filename: string, options?: IRequestOptions): IHomeServerRequest { return this._authedRequest("POST", `${this._homeserver}/_matrix/media/r0/upload`, {filename}, blob, options); } - setPusher(pusher: Record, options?: IRequestOptions): HomeServerRequest { + setPusher(pusher: Record, options?: IRequestOptions): IHomeServerRequest { return this._post("/pushers/set", {}, pusher, options); } - getPushers(options?: IRequestOptions): HomeServerRequest { + getPushers(options?: IRequestOptions): IHomeServerRequest { return this._get("/pushers", undefined, undefined, options); } - join(roomId: string, options?: IRequestOptions): HomeServerRequest { + join(roomId: string, options?: IRequestOptions): IHomeServerRequest { return this._post(`/rooms/${encodeURIComponent(roomId)}/join`, {}, {}, options); } - joinIdOrAlias(roomIdOrAlias: string, options?: IRequestOptions): HomeServerRequest { + joinIdOrAlias(roomIdOrAlias: string, options?: IRequestOptions): IHomeServerRequest { return this._post(`/join/${encodeURIComponent(roomIdOrAlias)}`, {}, {}, options); } - leave(roomId: string, options?: IRequestOptions): HomeServerRequest { + leave(roomId: string, options?: IRequestOptions): IHomeServerRequest { return this._post(`/rooms/${encodeURIComponent(roomId)}/leave`, {}, {}, options); } - forget(roomId: string, options?: IRequestOptions): HomeServerRequest { + forget(roomId: string, options?: IRequestOptions): IHomeServerRequest { return this._post(`/rooms/${encodeURIComponent(roomId)}/forget`, {}, {}, options); } - logout(options?: IRequestOptions): HomeServerRequest { + logout(options?: IRequestOptions): IHomeServerRequest { return this._post(`/logout`, {}, {}, options); } - getDehydratedDevice(options: IRequestOptions): HomeServerRequest { + getDehydratedDevice(options: IRequestOptions): IHomeServerRequest { options.prefix = DEHYDRATION_PREFIX; return this._get(`/dehydrated_device`, undefined, undefined, options); } - createDehydratedDevice(payload: Record, options: IRequestOptions): HomeServerRequest { + createDehydratedDevice(payload: Record, options: IRequestOptions): IHomeServerRequest { options.prefix = DEHYDRATION_PREFIX; return this._put(`/dehydrated_device`, {}, payload, options); } - claimDehydratedDevice(deviceId: string, options: IRequestOptions): HomeServerRequest { + claimDehydratedDevice(deviceId: string, options: IRequestOptions): IHomeServerRequest { options.prefix = DEHYDRATION_PREFIX; return this._post(`/dehydrated_device/claim`, {}, {device_id: deviceId}, options); } diff --git a/src/matrix/net/HomeServerRequest.ts b/src/matrix/net/HomeServerRequest.ts index 4a9fdf75..ca3912e5 100644 --- a/src/matrix/net/HomeServerRequest.ts +++ b/src/matrix/net/HomeServerRequest.ts @@ -19,7 +19,12 @@ import {HomeServerError, ConnectionError} from "../error.js"; import type {RequestResult} from "../../platform/web/dom/request/fetch.js"; import type {LogItem} from "../../logging/LogItem"; -export class HomeServerRequest { +export interface IHomeServerRequest { + abort(): void; + response(): Promise; +} + +export class HomeServerRequest implements IHomeServerRequest { // todo: Shouldn't log be of type ILogItem; but ILogItem does not have finish method private readonly _log?: LogItem; private _sourceRequest?: RequestResult; diff --git a/src/matrix/net/RequestScheduler.ts b/src/matrix/net/RequestScheduler.ts index c0ab1d60..6823ee29 100644 --- a/src/matrix/net/RequestScheduler.ts +++ b/src/matrix/net/RequestScheduler.ts @@ -20,14 +20,14 @@ import {HomeServerError} from "../error.js"; import {HomeServerApi} from "./HomeServerApi"; import {ExponentialRetryDelay} from "./ExponentialRetryDelay"; import {Clock} from "../../platform/web/dom/Clock.js"; -import type {HomeServerRequest} from "./HomeServerRequest.js"; +import type {IHomeServerRequest} from "./HomeServerRequest.js"; -class Request { +class Request implements IHomeServerRequest { public readonly methodName: string; public readonly args: any[]; public resolve: (result: Response) => void; public reject: (error: AbortError) => void; - public requestResult?: HomeServerRequest; + public requestResult?: IHomeServerRequest; private readonly _responsePromise: Promise; constructor(methodName: string, args: any[]) { From 4f43398db047e7c54c7ca0e9c109b9c4883a3a0b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 25 Nov 2021 12:24:14 +0530 Subject: [PATCH 23/37] Fix promise resolve type --- src/matrix/net/RequestScheduler.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/matrix/net/RequestScheduler.ts b/src/matrix/net/RequestScheduler.ts index 6823ee29..45405da3 100644 --- a/src/matrix/net/RequestScheduler.ts +++ b/src/matrix/net/RequestScheduler.ts @@ -25,10 +25,10 @@ import type {IHomeServerRequest} from "./HomeServerRequest.js"; class Request implements IHomeServerRequest { public readonly methodName: string; public readonly args: any[]; - public resolve: (result: Response) => void; - public reject: (error: AbortError) => void; + public resolve: (result: any) => void; + public reject: (error: Error) => void; public requestResult?: IHomeServerRequest; - private readonly _responsePromise: Promise; + private readonly _responsePromise: Promise; constructor(methodName: string, args: any[]) { this.methodName = methodName; @@ -47,7 +47,7 @@ class Request implements IHomeServerRequest { } } - response(): Promise { + response(): Promise { return this._responsePromise; } } From b5438f2ba8f04a1157eefc00c6517f4b27f7a5fa Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 29 Nov 2021 12:14:40 +0530 Subject: [PATCH 24/37] Do not set content-length --- src/matrix/net/HomeServerApi.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index cd604388..f7e39544 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -75,8 +75,6 @@ export class HomeServerApi { if (body) { const encoded = encodeBody(body); headers.set("Content-Type", encoded.mimeType); - //todo: remove this? - headers.set("Content-Length", encoded.length); encodedBody = encoded.body; } From 3fbf65355d301bfc8ed012078e2be89a5f53df48 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Wed, 1 Dec 2021 11:21:11 +0530 Subject: [PATCH 25/37] Rename Ctor to Options Co-authored-by: Bruno Windels --- src/matrix/net/HomeServerApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index f7e39544..a94c01da 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -28,7 +28,7 @@ type RequestMethod = "POST" | "GET" | "PUT"; const CS_R0_PREFIX = "/_matrix/client/r0"; const DEHYDRATION_PREFIX = "/_matrix/client/unstable/org.matrix.msc2697.v2"; -type Ctor = { +type Options = { homeserver: string; accessToken: string; request: RequestFunction; From e9cea73357ba1ddb9f9f0681ab9fadfbf40aeffc Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 11:20:38 +0530 Subject: [PATCH 26/37] Remove comment --- src/matrix/net/common.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index 0cabdb1f..ea7970d4 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -49,7 +49,6 @@ export function encodeBody(body: Record): IEncodedBody { return { mimeType: "application/json", body: json, - // todo: code change here; body.length is a mistake? length: json.length } } else { From b328c54da8ef99bbf88a2bee0f53aa9393a50930 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 11:21:58 +0530 Subject: [PATCH 27/37] Change type from Ctor to Options --- src/matrix/net/HomeServerApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index a94c01da..1de5a4dc 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -41,7 +41,7 @@ export class HomeServerApi { private readonly _requestFn: RequestFunction; private readonly _reconnector: Reconnector; - constructor({homeserver, accessToken, request, reconnector}: Ctor) { + constructor({homeserver, accessToken, request, reconnector}: Options) { // store these both in a closure somehow so it's harder to get at in case of XSS? // one could change the homeserver as well so the token gets sent there, so both must be protected from read/write this._homeserver = homeserver; From 82de3c9867b4cd1996f9fb1fa2dc2c0e49b58c57 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 11:42:24 +0530 Subject: [PATCH 28/37] Prefer type over interface --- src/matrix/net/HomeServerApi.ts | 4 ++-- src/matrix/net/MediaRepository.ts | 6 +++--- src/matrix/net/Reconnector.ts | 6 +++--- src/matrix/net/common.ts | 4 ++-- src/matrix/net/request/replay.ts | 18 +++++++++--------- src/matrix/net/types/response.ts | 18 +++++++++--------- src/platform/types/types.ts | 4 ++-- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index 1de5a4dc..69b86bbb 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -19,7 +19,7 @@ import {encodeQueryParams, encodeBody} from "./common"; import {HomeServerRequest} from "./HomeServerRequest"; import type {IHomeServerRequest} from "./HomeServerRequest"; import type {Reconnector} from "./Reconnector"; -import type {IEncodedBody} from "./common"; +import type {EncodedBody} from "./common"; import type {IRequestOptions, RequestFunction} from "../../platform/types/types"; import type {LogItem} from "../../logging/LogItem"; @@ -66,7 +66,7 @@ export class HomeServerApi { method, }, parent.level.Info); } - let encodedBody: IEncodedBody["body"]; + let encodedBody: EncodedBody["body"]; const headers: Map = new Map(); if (accessToken) { headers.set("Authorization", `Bearer ${accessToken}`); diff --git a/src/matrix/net/MediaRepository.ts b/src/matrix/net/MediaRepository.ts index a19eac9a..357b17c6 100644 --- a/src/matrix/net/MediaRepository.ts +++ b/src/matrix/net/MediaRepository.ts @@ -18,7 +18,7 @@ import {encodeQueryParams} from "./common"; import {decryptAttachment} from "../e2ee/attachment.js"; import {Platform} from "../../platform/web/Platform.js"; import {BlobHandle} from "../../platform/web/dom/BlobHandle.js"; -import type {IAttachment, IEncryptedFile} from "./types/response"; +import type {Attachment, EncryptedFile} from "./types/response"; export class MediaRepository { private readonly _homeserver: string; @@ -58,7 +58,7 @@ export class MediaRepository { } } - async downloadEncryptedFile(fileEntry: IEncryptedFile, cache: boolean = false): Promise { + async downloadEncryptedFile(fileEntry: EncryptedFile, cache: boolean = false): Promise { const url = this.mxcUrl(fileEntry.url); const {body: encryptedBuffer} = await this._platform.request(url, {method: "GET", format: "buffer", cache}).response(); const decryptedBuffer = await decryptAttachment(this._platform, encryptedBuffer, fileEntry); @@ -71,7 +71,7 @@ export class MediaRepository { return this._platform.createBlob(buffer, mimetype); } - async downloadAttachment(content: IAttachment, cache: boolean = false): Promise { + async downloadAttachment(content: Attachment, cache: boolean = false): Promise { if (content.file) { return this.downloadEncryptedFile(content.file, cache); } else { diff --git a/src/matrix/net/Reconnector.ts b/src/matrix/net/Reconnector.ts index 607ba0b4..bc54ab73 100644 --- a/src/matrix/net/Reconnector.ts +++ b/src/matrix/net/Reconnector.ts @@ -18,7 +18,7 @@ import {ObservableValue} from "../../observable/ObservableValue"; import type {ExponentialRetryDelay} from "./ExponentialRetryDelay"; import type {TimeMeasure} from "../../platform/web/dom/Clock.js"; import type {OnlineStatus} from "../../platform/web/dom/OnlineStatus.js"; -import type {IVersionResponse} from "./types/response"; +import type {VersionResponse} from "./types/response"; import type {HomeServerApi} from "./HomeServerApi"; export enum ConnectionStatus { @@ -39,7 +39,7 @@ export class Reconnector { private readonly _onlineStatus: OnlineStatus; private readonly _state: ObservableValue; private _isReconnecting: boolean; - private _versionsResponse?: IVersionResponse; + private _versionsResponse?: VersionResponse; private _stateSince: TimeMeasure; constructor({retryDelay, createMeasure, onlineStatus}: Ctor) { @@ -51,7 +51,7 @@ export class Reconnector { this._isReconnecting = false; } - get lastVersionsResponse(): IVersionResponse | undefined { + get lastVersionsResponse(): VersionResponse | undefined { return this._versionsResponse; } diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index ea7970d4..287e5e9e 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -17,7 +17,7 @@ limitations under the License. import {BlobHandle} from "../../platform/web/dom/BlobHandle.js"; -export interface IEncodedBody { +export type EncodedBody = { mimeType: string; body: BlobHandle | string; length: number; @@ -35,7 +35,7 @@ export function encodeQueryParams(queryParams?: Record): string { .join("&"); } -export function encodeBody(body: Record): IEncodedBody { +export function encodeBody(body: Record): EncodedBody { // todo: code change here if (body instanceof BlobHandle) { const blob = body as BlobHandle; diff --git a/src/matrix/net/request/replay.ts b/src/matrix/net/request/replay.ts index 32a059d3..461049f8 100644 --- a/src/matrix/net/request/replay.ts +++ b/src/matrix/net/request/replay.ts @@ -18,21 +18,21 @@ import {AbortError, ConnectionError} from "../../error.js"; import type {IRequestOptions, RequestFunction} from "../../../platform/types/types.js"; import type {RequestResult} from "../../../platform/web/dom/request/fetch.js"; -interface IOptions extends IRequestOptions { +type Options = IRequestOptions & { method?: any; delay?: boolean; } class RequestLogItem { public readonly url: string; - public readonly options: IOptions; + public readonly options: Options; public error: {aborted: boolean, network: boolean, message: string}; public status: number; public body: Response["body"]; public start: number = performance.now(); public end: number = 0; - constructor(url: string, options: IOptions) { + constructor(url: string, options: Options) { this.url = url; this.options = options; } @@ -62,7 +62,7 @@ export class RecordRequester { this.request = this.request.bind(this); } - request(url: string, options: IOptions): RequestResult { + request(url: string, options: Options): RequestResult { const requestItem = new RequestLogItem(url, options); this._requestLog.push(requestItem); try { @@ -84,15 +84,15 @@ export class RecordRequester { export class ReplayRequester { private readonly _log: RequestLogItem[]; - private readonly _options: IOptions; + private readonly _options: Options; - constructor(log: RequestLogItem[], options: IOptions) { + constructor(log: RequestLogItem[], options: Options) { this._log = log.slice(); this._options = options; this.request = this.request.bind(this); } - request(url: string, options: IOptions): ReplayRequestResult { + request(url: string, options: Options): ReplayRequestResult { const idx = this._log.findIndex((item) => { return item.url === url && options.method === item.options.method; }); @@ -107,10 +107,10 @@ export class ReplayRequester { class ReplayRequestResult { private readonly _item: RequestLogItem; - private readonly _options: IOptions; + private readonly _options: Options; private _aborted: boolean; - constructor(item: RequestLogItem, options: IOptions) { + constructor(item: RequestLogItem, options: Options) { this._item = item; this._options = options; this._aborted = false; diff --git a/src/matrix/net/types/response.ts b/src/matrix/net/types/response.ts index e4b71d36..4f0af7ec 100644 --- a/src/matrix/net/types/response.ts +++ b/src/matrix/net/types/response.ts @@ -14,17 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -export interface IAttachment { +export type Attachment = { body: string; - info: IAttachmentInfo; + info: AttachmentInfo; // todo: what about m.audio? msgtype: "m.image" | "m.file" | "m.video"; url?: string; - file?: IEncryptedFile; + file?: EncryptedFile; filename?: string; } -export interface IEncryptedFile { +export type EncryptedFile = { key: JsonWebKey; iv: string; hashes: { @@ -35,25 +35,25 @@ export interface IEncryptedFile { mimetype?: string; } -interface IAttachmentInfo { +type AttachmentInfo = { h?: number; w?: number; mimetype: string; size: number; duration?: number; thumbnail_url?: string; - thumbnail_file?: IEncryptedFile; - thumbnail_info?: IThumbnailInfo; + thumbnail_file?: EncryptedFile; + thumbnail_info?: ThumbnailInfo; } -interface IThumbnailInfo { +type ThumbnailInfo = { h: number; w: number; mimetype: string; size: number; } -export interface IVersionResponse { +export type VersionResponse = { versions: string[]; unstable_features?: Record; } diff --git a/src/platform/types/types.ts b/src/platform/types/types.ts index 817f3739..f619c706 100644 --- a/src/platform/types/types.ts +++ b/src/platform/types/types.ts @@ -15,13 +15,13 @@ limitations under the License. */ import type {RequestResult} from "../web/dom/request/fetch.js"; -import type {IEncodedBody} from "../../matrix/net/common"; +import type {EncodedBody} from "../../matrix/net/common"; import type {LogItem} from "../../logging/LogItem"; export interface IRequestOptions { uploadProgress?: (loadedBytes: number) => void; timeout?: number; - body?: IEncodedBody; + body?: EncodedBody; headers?: Map; cache?: boolean; log?: LogItem; From f89b937ee7cdbb068ea1f234d671d8c73444b2c1 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 12:52:30 +0530 Subject: [PATCH 29/37] Use object instead of Record --- src/matrix/net/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index 287e5e9e..5239cf56 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -35,7 +35,7 @@ export function encodeQueryParams(queryParams?: Record): string { .join("&"); } -export function encodeBody(body: Record): EncodedBody { +export function encodeBody(body: BlobHandle | object): EncodedBody { // todo: code change here if (body instanceof BlobHandle) { const blob = body as BlobHandle; From bf93bd79c91682407ec7486c92cbd5f59ad84eec Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 13:42:55 +0530 Subject: [PATCH 30/37] types.js --> types --- src/matrix/net/request/replay.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/request/replay.ts b/src/matrix/net/request/replay.ts index 461049f8..e03b91a8 100644 --- a/src/matrix/net/request/replay.ts +++ b/src/matrix/net/request/replay.ts @@ -15,7 +15,7 @@ limitations under the License. */ import {AbortError, ConnectionError} from "../../error.js"; -import type {IRequestOptions, RequestFunction} from "../../../platform/types/types.js"; +import type {IRequestOptions, RequestFunction} from "../../../platform/types/types"; import type {RequestResult} from "../../../platform/web/dom/request/fetch.js"; type Options = IRequestOptions & { From 0541cf8f2ba3818e1f6f81a48608c2ac41fe8ff6 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 15:13:48 +0530 Subject: [PATCH 31/37] Change object to Record --- src/matrix/net/common.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index 5239cf56..9c476dd6 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -35,8 +35,7 @@ export function encodeQueryParams(queryParams?: Record): string { .join("&"); } -export function encodeBody(body: BlobHandle | object): EncodedBody { - // todo: code change here +export function encodeBody(body: BlobHandle | Record): EncodedBody { if (body instanceof BlobHandle) { const blob = body as BlobHandle; return { From 66b4f9bfe5fea25f51b689aec3e7608c5c8108f0 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 16:09:42 +0530 Subject: [PATCH 32/37] LogItem --> ILogItem --- src/logging/types.ts | 1 + src/matrix/net/HomeServerRequest.ts | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/logging/types.ts b/src/logging/types.ts index 01755960..9e6e1210 100644 --- a/src/logging/types.ts +++ b/src/logging/types.ts @@ -50,6 +50,7 @@ export interface ILogItem { ensureRefId(): void; catch(err: Error): Error; serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined; + finish(): void; } export interface ILogger { diff --git a/src/matrix/net/HomeServerRequest.ts b/src/matrix/net/HomeServerRequest.ts index ca3912e5..ea5d2e40 100644 --- a/src/matrix/net/HomeServerRequest.ts +++ b/src/matrix/net/HomeServerRequest.ts @@ -17,7 +17,7 @@ limitations under the License. import {HomeServerError, ConnectionError} from "../error.js"; import type {RequestResult} from "../../platform/web/dom/request/fetch.js"; -import type {LogItem} from "../../logging/LogItem"; +import type {ILogItem} from "../../logging/types"; export interface IHomeServerRequest { abort(): void; @@ -25,13 +25,12 @@ export interface IHomeServerRequest { } export class HomeServerRequest implements IHomeServerRequest { - // todo: Shouldn't log be of type ILogItem; but ILogItem does not have finish method - private readonly _log?: LogItem; + private readonly _log?: ILogItem; private _sourceRequest?: RequestResult; // as we add types for expected responses from hs, this could be a generic class instead private readonly _promise: Promise; - constructor(method: string, url: string, sourceRequest: RequestResult, log?: LogItem) { + constructor(method: string, url: string, sourceRequest: RequestResult, log?: ILogItem) { this._log = log; this._sourceRequest = sourceRequest; this._promise = sourceRequest.response().then(response => { From 640cd88b6e3bcafabb35fb8bb46ef2e35f141262 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 16:10:22 +0530 Subject: [PATCH 33/37] make type string --- src/matrix/net/types/response.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/types/response.ts b/src/matrix/net/types/response.ts index 4f0af7ec..aabcde73 100644 --- a/src/matrix/net/types/response.ts +++ b/src/matrix/net/types/response.ts @@ -18,7 +18,7 @@ export type Attachment = { body: string; info: AttachmentInfo; // todo: what about m.audio? - msgtype: "m.image" | "m.file" | "m.video"; + msgtype: string; url?: string; file?: EncryptedFile; filename?: string; From 49a56efa82d5a8d8c3f4f06374c2ee381e14a9b3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 1 Dec 2021 16:13:35 +0530 Subject: [PATCH 34/37] Remove comment --- src/matrix/net/types/response.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/matrix/net/types/response.ts b/src/matrix/net/types/response.ts index aabcde73..f1102a1b 100644 --- a/src/matrix/net/types/response.ts +++ b/src/matrix/net/types/response.ts @@ -17,7 +17,6 @@ limitations under the License. export type Attachment = { body: string; info: AttachmentInfo; - // todo: what about m.audio? msgtype: string; url?: string; file?: EncryptedFile; From d6378133d83150d1253819235d42e5f37e4cf6ed Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 3 Dec 2021 11:23:10 +0530 Subject: [PATCH 35/37] Remove length property --- src/matrix/net/common.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index 9c476dd6..5fd5c963 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -20,7 +20,6 @@ import {BlobHandle} from "../../platform/web/dom/BlobHandle.js"; export type EncodedBody = { mimeType: string; body: BlobHandle | string; - length: number; } export function encodeQueryParams(queryParams?: Record): string { @@ -40,15 +39,13 @@ export function encodeBody(body: BlobHandle | Record): EncodedBody const blob = body as BlobHandle; return { mimeType: blob.mimeType, - body: blob, // will be unwrapped in request fn - length: blob.size + body: blob // will be unwrapped in request fn }; } else if (typeof body === "object") { const json = JSON.stringify(body); return { mimeType: "application/json", - body: json, - length: json.length + body: json } } else { throw new Error("Unknown body type: " + body); From e2abc312d3bb33550a8a1b42add4a4b49e012f0b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 3 Dec 2021 11:48:01 +0530 Subject: [PATCH 36/37] Fix typescript errors --- src/logging/types.ts | 1 + src/matrix/net/HomeServerApi.ts | 4 ++-- src/platform/types/types.ts | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/logging/types.ts b/src/logging/types.ts index 9e6e1210..3094eaf4 100644 --- a/src/logging/types.ts +++ b/src/logging/types.ts @@ -51,6 +51,7 @@ export interface ILogItem { catch(err: Error): Error; serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined; finish(): void; + child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; } export interface ILogger { diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index 69b86bbb..bacf26b0 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -21,7 +21,7 @@ import type {IHomeServerRequest} from "./HomeServerRequest"; import type {Reconnector} from "./Reconnector"; import type {EncodedBody} from "./common"; import type {IRequestOptions, RequestFunction} from "../../platform/types/types"; -import type {LogItem} from "../../logging/LogItem"; +import type {ILogItem} from "../../logging/types"; type RequestMethod = "POST" | "GET" | "PUT"; @@ -57,7 +57,7 @@ export class HomeServerApi { private _baseRequest(method: RequestMethod, url: string, queryParams?: Record, body?: Record, options?: IRequestOptions, accessToken?: string): IHomeServerRequest { const queryString = encodeQueryParams(queryParams); url = `${url}?${queryString}`; - let log: LogItem | undefined; + let log: ILogItem | undefined; if (options?.log) { const parent = options?.log; log = parent.child({ diff --git a/src/platform/types/types.ts b/src/platform/types/types.ts index f619c706..58d2216f 100644 --- a/src/platform/types/types.ts +++ b/src/platform/types/types.ts @@ -16,7 +16,7 @@ limitations under the License. import type {RequestResult} from "../web/dom/request/fetch.js"; import type {EncodedBody} from "../../matrix/net/common"; -import type {LogItem} from "../../logging/LogItem"; +import type {ILogItem} from "../../logging/types"; export interface IRequestOptions { uploadProgress?: (loadedBytes: number) => void; @@ -24,7 +24,7 @@ export interface IRequestOptions { body?: EncodedBody; headers?: Map; cache?: boolean; - log?: LogItem; + log?: ILogItem; prefix?: string; method?: string; format?: string; From 734ecccb9c006c8bdb2e0a9419b8ce08e1258412 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 3 Dec 2021 17:34:23 +0530 Subject: [PATCH 37/37] Use object instead of Record here --- src/matrix/net/common.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/matrix/net/common.ts b/src/matrix/net/common.ts index 5fd5c963..4ba42395 100644 --- a/src/matrix/net/common.ts +++ b/src/matrix/net/common.ts @@ -22,7 +22,7 @@ export type EncodedBody = { body: BlobHandle | string; } -export function encodeQueryParams(queryParams?: Record): string { +export function encodeQueryParams(queryParams?: object): string { return Object.entries(queryParams || {}) .filter(([, value]) => value !== undefined) .map(([name, value]) => { @@ -34,7 +34,7 @@ export function encodeQueryParams(queryParams?: Record): string { .join("&"); } -export function encodeBody(body: BlobHandle | Record): EncodedBody { +export function encodeBody(body: BlobHandle | object): EncodedBody { if (body instanceof BlobHandle) { const blob = body as BlobHandle; return {