summaryrefslogtreecommitdiff
path: root/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api
diff options
context:
space:
mode:
authorRaindropsSys <contact@minteck.org>2023-04-24 14:03:36 +0200
committerRaindropsSys <contact@minteck.org>2023-04-24 14:03:36 +0200
commit633c92eae865e957121e08de634aeee11a8b3992 (patch)
tree09d881bee1dae0b6eee49db1dfaf0f500240606c /includes/external/matrix/node_modules/matrix-js-sdk/src/http-api
parentc4657e4509733699c0f26a3c900bab47e915d5a0 (diff)
downloadpluralconnect-633c92eae865e957121e08de634aeee11a8b3992.tar.gz
pluralconnect-633c92eae865e957121e08de634aeee11a8b3992.tar.bz2
pluralconnect-633c92eae865e957121e08de634aeee11a8b3992.zip
Updated 18 files, added 1692 files and deleted includes/system/compare.inc (automated)
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/src/http-api')
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/errors.ts84
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/fetch.ts311
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/index.ts191
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/interface.ts147
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/method.ts22
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/prefix.ts48
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/utils.ts153
7 files changed, 956 insertions, 0 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/errors.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/errors.ts
new file mode 100644
index 0000000..e48fc02
--- /dev/null
+++ b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/errors.ts
@@ -0,0 +1,84 @@
+/*
+Copyright 2022 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 { IUsageLimit } from "../@types/partials";
+import { MatrixEvent } from "../models/event";
+
+interface IErrorJson extends Partial<IUsageLimit> {
+ [key: string]: any; // extensible
+ errcode?: string;
+ error?: string;
+}
+
+/**
+ * Construct a generic HTTP error. This is a JavaScript Error with additional information
+ * specific to HTTP responses.
+ * @param msg - The error message to include.
+ * @param httpStatus - The HTTP response status code.
+ */
+export class HTTPError extends Error {
+ public constructor(msg: string, public readonly httpStatus?: number) {
+ super(msg);
+ }
+}
+
+export class MatrixError extends HTTPError {
+ // The Matrix 'errcode' value, e.g. "M_FORBIDDEN".
+ public readonly errcode?: string;
+ // The raw Matrix error JSON used to construct this object.
+ public data: IErrorJson;
+
+ /**
+ * Construct a Matrix error. This is a JavaScript Error with additional
+ * information specific to the standard Matrix error response.
+ * @param errorJson - The Matrix error JSON returned from the homeserver.
+ * @param httpStatus - The numeric HTTP status code given
+ */
+ public constructor(
+ errorJson: IErrorJson = {},
+ public readonly httpStatus?: number,
+ public url?: string,
+ public event?: MatrixEvent,
+ ) {
+ let message = errorJson.error || "Unknown message";
+ if (httpStatus) {
+ message = `[${httpStatus}] ${message}`;
+ }
+ if (url) {
+ message = `${message} (${url})`;
+ }
+ super(`MatrixError: ${message}`, httpStatus);
+ this.errcode = errorJson.errcode;
+ this.name = errorJson.errcode || "Unknown error code";
+ this.data = errorJson;
+ }
+}
+
+/**
+ * Construct a ConnectionError. This is a JavaScript Error indicating
+ * that a request failed because of some error with the connection, either
+ * CORS was not correctly configured on the server, the server didn't response,
+ * the request timed out, or the internet connection on the client side went down.
+ */
+export class ConnectionError extends Error {
+ public constructor(message: string, cause?: Error) {
+ super(message + (cause ? `: ${cause.message}` : ""));
+ }
+
+ public get name(): string {
+ return "ConnectionError";
+ }
+}
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/fetch.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/fetch.ts
new file mode 100644
index 0000000..ecb0908
--- /dev/null
+++ b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/fetch.ts
@@ -0,0 +1,311 @@
+/*
+Copyright 2022 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * This is an internal module. See {@link MatrixHttpApi} for the public class.
+ */
+
+import * as utils from "../utils";
+import { TypedEventEmitter } from "../models/typed-event-emitter";
+import { Method } from "./method";
+import { ConnectionError, MatrixError } from "./errors";
+import { HttpApiEvent, HttpApiEventHandlerMap, IHttpOpts, IRequestOpts } from "./interface";
+import { anySignal, parseErrorResponse, timeoutSignal } from "./utils";
+import { QueryDict } from "../utils";
+
+type Body = Record<string, any> | BodyInit;
+
+interface TypedResponse<T> extends Response {
+ json(): Promise<T>;
+}
+
+export type ResponseType<T, O extends IHttpOpts> = O extends undefined
+ ? T
+ : O extends { onlyData: true }
+ ? T
+ : TypedResponse<T>;
+
+export class FetchHttpApi<O extends IHttpOpts> {
+ private abortController = new AbortController();
+
+ public constructor(
+ private eventEmitter: TypedEventEmitter<HttpApiEvent, HttpApiEventHandlerMap>,
+ public readonly opts: O,
+ ) {
+ utils.checkObjectHasKeys(opts, ["baseUrl", "prefix"]);
+ opts.onlyData = !!opts.onlyData;
+ opts.useAuthorizationHeader = opts.useAuthorizationHeader ?? true;
+ }
+
+ public abort(): void {
+ this.abortController.abort();
+ this.abortController = new AbortController();
+ }
+
+ public fetch(resource: URL | string, options?: RequestInit): ReturnType<typeof global.fetch> {
+ if (this.opts.fetchFn) {
+ return this.opts.fetchFn(resource, options);
+ }
+ return global.fetch(resource, options);
+ }
+
+ /**
+ * Sets the base URL for the identity server
+ * @param url - The new base url
+ */
+ public setIdBaseUrl(url: string): void {
+ this.opts.idBaseUrl = url;
+ }
+
+ public idServerRequest<T extends {} = Record<string, unknown>>(
+ method: Method,
+ path: string,
+ params: Record<string, string | string[]> | undefined,
+ prefix: string,
+ accessToken?: string,
+ ): Promise<ResponseType<T, O>> {
+ if (!this.opts.idBaseUrl) {
+ throw new Error("No identity server base URL set");
+ }
+
+ let queryParams: QueryDict | undefined = undefined;
+ let body: Record<string, string | string[]> | undefined = undefined;
+ if (method === Method.Get) {
+ queryParams = params;
+ } else {
+ body = params;
+ }
+
+ const fullUri = this.getUrl(path, queryParams, prefix, this.opts.idBaseUrl);
+
+ const opts: IRequestOpts = {
+ json: true,
+ headers: {},
+ };
+ if (accessToken) {
+ opts.headers!.Authorization = `Bearer ${accessToken}`;
+ }
+
+ return this.requestOtherUrl(method, fullUri, body, opts);
+ }
+
+ /**
+ * Perform an authorised request to the homeserver.
+ * @param method - The HTTP method e.g. "GET".
+ * @param path - The HTTP path <b>after</b> the supplied prefix e.g.
+ * "/createRoom".
+ *
+ * @param queryParams - A dict of query params (these will NOT be
+ * urlencoded). If unspecified, there will be no query params.
+ *
+ * @param body - The HTTP JSON body.
+ *
+ * @param opts - additional options. If a number is specified,
+ * this is treated as `opts.localTimeoutMs`.
+ *
+ * @returns Promise which resolves to
+ * ```
+ * {
+ * data: {Object},
+ * headers: {Object},
+ * code: {Number},
+ * }
+ * ```
+ * If `onlyData` is set, this will resolve to the `data` object only.
+ * @returns Rejects with an error if a problem occurred.
+ * This includes network problems and Matrix-specific error JSON.
+ */
+ public authedRequest<T>(
+ method: Method,
+ path: string,
+ queryParams?: QueryDict,
+ body?: Body,
+ opts: IRequestOpts = {},
+ ): Promise<ResponseType<T, O>> {
+ if (!queryParams) queryParams = {};
+
+ if (this.opts.accessToken) {
+ if (this.opts.useAuthorizationHeader) {
+ if (!opts.headers) {
+ opts.headers = {};
+ }
+ if (!opts.headers.Authorization) {
+ opts.headers.Authorization = "Bearer " + this.opts.accessToken;
+ }
+ if (queryParams.access_token) {
+ delete queryParams.access_token;
+ }
+ } else if (!queryParams.access_token) {
+ queryParams.access_token = this.opts.accessToken;
+ }
+ }
+
+ const requestPromise = this.request<T>(method, path, queryParams, body, opts);
+
+ requestPromise.catch((err: MatrixError) => {
+ if (err.errcode == "M_UNKNOWN_TOKEN" && !opts?.inhibitLogoutEmit) {
+ this.eventEmitter.emit(HttpApiEvent.SessionLoggedOut, err);
+ } else if (err.errcode == "M_CONSENT_NOT_GIVEN") {
+ this.eventEmitter.emit(HttpApiEvent.NoConsent, err.message, err.data.consent_uri);
+ }
+ });
+
+ // return the original promise, otherwise tests break due to it having to
+ // go around the event loop one more time to process the result of the request
+ return requestPromise;
+ }
+
+ /**
+ * Perform a request to the homeserver without any credentials.
+ * @param method - The HTTP method e.g. "GET".
+ * @param path - The HTTP path <b>after</b> the supplied prefix e.g.
+ * "/createRoom".
+ *
+ * @param queryParams - A dict of query params (these will NOT be
+ * urlencoded). If unspecified, there will be no query params.
+ *
+ * @param body - The HTTP JSON body.
+ *
+ * @param opts - additional options
+ *
+ * @returns Promise which resolves to
+ * ```
+ * {
+ * data: {Object},
+ * headers: {Object},
+ * code: {Number},
+ * }
+ * ```
+ * If `onlyData</code> is set, this will resolve to the <code>data`
+ * object only.
+ * @returns Rejects with an error if a problem
+ * occurred. This includes network problems and Matrix-specific error JSON.
+ */
+ public request<T>(
+ method: Method,
+ path: string,
+ queryParams?: QueryDict,
+ body?: Body,
+ opts?: IRequestOpts,
+ ): Promise<ResponseType<T, O>> {
+ const fullUri = this.getUrl(path, queryParams, opts?.prefix, opts?.baseUrl);
+ return this.requestOtherUrl<T>(method, fullUri, body, opts);
+ }
+
+ /**
+ * Perform a request to an arbitrary URL.
+ * @param method - The HTTP method e.g. "GET".
+ * @param url - The HTTP URL object.
+ *
+ * @param body - The HTTP JSON body.
+ *
+ * @param opts - additional options
+ *
+ * @returns Promise which resolves to data unless `onlyData` is specified as false,
+ * where the resolved value will be a fetch Response object.
+ * @returns Rejects with an error if a problem
+ * occurred. This includes network problems and Matrix-specific error JSON.
+ */
+ public async requestOtherUrl<T>(
+ method: Method,
+ url: URL | string,
+ body?: Body,
+ opts: Pick<IRequestOpts, "headers" | "json" | "localTimeoutMs" | "keepAlive" | "abortSignal"> = {},
+ ): Promise<ResponseType<T, O>> {
+ const headers = Object.assign({}, opts.headers || {});
+ const json = opts.json ?? true;
+ // We can't use getPrototypeOf here as objects made in other contexts e.g. over postMessage won't have same ref
+ const jsonBody = json && body?.constructor?.name === Object.name;
+
+ if (json) {
+ if (jsonBody && !headers["Content-Type"]) {
+ headers["Content-Type"] = "application/json";
+ }
+
+ if (!headers["Accept"]) {
+ headers["Accept"] = "application/json";
+ }
+ }
+
+ const timeout = opts.localTimeoutMs ?? this.opts.localTimeoutMs;
+ const keepAlive = opts.keepAlive ?? false;
+ const signals = [this.abortController.signal];
+ if (timeout !== undefined) {
+ signals.push(timeoutSignal(timeout));
+ }
+ if (opts.abortSignal) {
+ signals.push(opts.abortSignal);
+ }
+
+ let data: BodyInit;
+ if (jsonBody) {
+ data = JSON.stringify(body);
+ } else {
+ data = body as BodyInit;
+ }
+
+ const { signal, cleanup } = anySignal(signals);
+
+ let res: Response;
+ try {
+ res = await this.fetch(url, {
+ signal,
+ method,
+ body: data,
+ headers,
+ mode: "cors",
+ redirect: "follow",
+ referrer: "",
+ referrerPolicy: "no-referrer",
+ cache: "no-cache",
+ credentials: "omit", // we send credentials via headers
+ keepalive: keepAlive,
+ });
+ } catch (e) {
+ if ((<Error>e).name === "AbortError") {
+ throw e;
+ }
+ throw new ConnectionError("fetch failed", <Error>e);
+ } finally {
+ cleanup();
+ }
+
+ if (!res.ok) {
+ throw parseErrorResponse(res, await res.text());
+ }
+
+ if (this.opts.onlyData) {
+ return json ? res.json() : res.text();
+ }
+ return res as ResponseType<T, O>;
+ }
+
+ /**
+ * Form and return a homeserver request URL based on the given path params and prefix.
+ * @param path - The HTTP path <b>after</b> the supplied prefix e.g. "/createRoom".
+ * @param queryParams - A dict of query params (these will NOT be urlencoded).
+ * @param prefix - The full prefix to use e.g. "/_matrix/client/v2_alpha", defaulting to this.opts.prefix.
+ * @param baseUrl - The baseUrl to use e.g. "https://matrix.org/", defaulting to this.opts.baseUrl.
+ * @returns URL
+ */
+ public getUrl(path: string, queryParams?: QueryDict, prefix?: string, baseUrl?: string): URL {
+ const url = new URL((baseUrl ?? this.opts.baseUrl) + (prefix ?? this.opts.prefix) + path);
+ if (queryParams) {
+ utils.encodeParams(queryParams, url.searchParams);
+ }
+ return url;
+ }
+}
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/index.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/index.ts
new file mode 100644
index 0000000..c5e8e2a
--- /dev/null
+++ b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/index.ts
@@ -0,0 +1,191 @@
+/*
+Copyright 2022 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 { FetchHttpApi } from "./fetch";
+import { FileType, IContentUri, IHttpOpts, Upload, UploadOpts, UploadResponse } from "./interface";
+import { MediaPrefix } from "./prefix";
+import * as utils from "../utils";
+import * as callbacks from "../realtime-callbacks";
+import { Method } from "./method";
+import { ConnectionError } from "./errors";
+import { parseErrorResponse } from "./utils";
+
+export * from "./interface";
+export * from "./prefix";
+export * from "./errors";
+export * from "./method";
+export * from "./utils";
+
+export class MatrixHttpApi<O extends IHttpOpts> extends FetchHttpApi<O> {
+ private uploads: Upload[] = [];
+
+ /**
+ * Upload content to the homeserver
+ *
+ * @param file - The object to upload. On a browser, something that
+ * can be sent to XMLHttpRequest.send (typically a File). Under node.js,
+ * a Buffer, String or ReadStream.
+ *
+ * @param opts - options object
+ *
+ * @returns Promise which resolves to response object, as
+ * determined by this.opts.onlyData, opts.rawResponse, and
+ * opts.onlyContentUri. Rejects with an error (usually a MatrixError).
+ */
+ public uploadContent(file: FileType, opts: UploadOpts = {}): Promise<UploadResponse> {
+ const includeFilename = opts.includeFilename ?? true;
+ const abortController = opts.abortController ?? new AbortController();
+
+ // If the file doesn't have a mime type, use a default since the HS errors if we don't supply one.
+ const contentType = opts.type ?? (file as File).type ?? "application/octet-stream";
+ const fileName = opts.name ?? (file as File).name;
+
+ const upload = {
+ loaded: 0,
+ total: 0,
+ abortController,
+ } as Upload;
+ const defer = utils.defer<UploadResponse>();
+
+ if (global.XMLHttpRequest) {
+ const xhr = new global.XMLHttpRequest();
+
+ const timeoutFn = function (): void {
+ xhr.abort();
+ defer.reject(new Error("Timeout"));
+ };
+
+ // set an initial timeout of 30s; we'll advance it each time we get a progress notification
+ let timeoutTimer = callbacks.setTimeout(timeoutFn, 30000);
+
+ xhr.onreadystatechange = function (): void {
+ switch (xhr.readyState) {
+ case global.XMLHttpRequest.DONE:
+ callbacks.clearTimeout(timeoutTimer);
+ try {
+ if (xhr.status === 0) {
+ throw new DOMException(xhr.statusText, "AbortError"); // mimic fetch API
+ }
+ if (!xhr.responseText) {
+ throw new Error("No response body.");
+ }
+
+ if (xhr.status >= 400) {
+ defer.reject(parseErrorResponse(xhr, xhr.responseText));
+ } else {
+ defer.resolve(JSON.parse(xhr.responseText));
+ }
+ } catch (err) {
+ if ((<Error>err).name === "AbortError") {
+ defer.reject(err);
+ return;
+ }
+ defer.reject(new ConnectionError("request failed", <Error>err));
+ }
+ break;
+ }
+ };
+
+ xhr.upload.onprogress = (ev: ProgressEvent): void => {
+ callbacks.clearTimeout(timeoutTimer);
+ upload.loaded = ev.loaded;
+ upload.total = ev.total;
+ timeoutTimer = callbacks.setTimeout(timeoutFn, 30000);
+ opts.progressHandler?.({
+ loaded: ev.loaded,
+ total: ev.total,
+ });
+ };
+
+ const url = this.getUrl("/upload", undefined, MediaPrefix.R0);
+
+ if (includeFilename && fileName) {
+ url.searchParams.set("filename", encodeURIComponent(fileName));
+ }
+
+ if (!this.opts.useAuthorizationHeader && this.opts.accessToken) {
+ url.searchParams.set("access_token", encodeURIComponent(this.opts.accessToken));
+ }
+
+ xhr.open(Method.Post, url.href);
+ if (this.opts.useAuthorizationHeader && this.opts.accessToken) {
+ xhr.setRequestHeader("Authorization", "Bearer " + this.opts.accessToken);
+ }
+ xhr.setRequestHeader("Content-Type", contentType);
+ xhr.send(file);
+
+ abortController.signal.addEventListener("abort", () => {
+ xhr.abort();
+ });
+ } else {
+ const queryParams: utils.QueryDict = {};
+ if (includeFilename && fileName) {
+ queryParams.filename = fileName;
+ }
+
+ const headers: Record<string, string> = { "Content-Type": contentType };
+
+ this.authedRequest<UploadResponse>(Method.Post, "/upload", queryParams, file, {
+ prefix: MediaPrefix.R0,
+ headers,
+ abortSignal: abortController.signal,
+ })
+ .then((response) => {
+ return this.opts.onlyData ? <UploadResponse>response : response.json();
+ })
+ .then(defer.resolve, defer.reject);
+ }
+
+ // remove the upload from the list on completion
+ upload.promise = defer.promise.finally(() => {
+ utils.removeElement(this.uploads, (elem) => elem === upload);
+ });
+ abortController.signal.addEventListener("abort", () => {
+ utils.removeElement(this.uploads, (elem) => elem === upload);
+ defer.reject(new DOMException("Aborted", "AbortError"));
+ });
+ this.uploads.push(upload);
+ return upload.promise;
+ }
+
+ public cancelUpload(promise: Promise<UploadResponse>): boolean {
+ const upload = this.uploads.find((u) => u.promise === promise);
+ if (upload) {
+ upload.abortController.abort();
+ return true;
+ }
+ return false;
+ }
+
+ public getCurrentUploads(): Upload[] {
+ return this.uploads;
+ }
+
+ /**
+ * Get the content repository url with query parameters.
+ * @returns An object with a 'base', 'path' and 'params' for base URL,
+ * path and query parameters respectively.
+ */
+ public getContentUri(): IContentUri {
+ return {
+ base: this.opts.baseUrl,
+ path: MediaPrefix.R0 + "/upload",
+ params: {
+ access_token: this.opts.accessToken!,
+ },
+ };
+ }
+}
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/interface.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/interface.ts
new file mode 100644
index 0000000..9946aa3
--- /dev/null
+++ b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/interface.ts
@@ -0,0 +1,147 @@
+/*
+Copyright 2022 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 { MatrixError } from "./errors";
+
+export interface IHttpOpts {
+ fetchFn?: typeof global.fetch;
+
+ baseUrl: string;
+ idBaseUrl?: string;
+ prefix: string;
+ extraParams?: Record<string, string>;
+
+ accessToken?: string;
+ useAuthorizationHeader?: boolean; // defaults to true
+
+ onlyData?: boolean;
+ localTimeoutMs?: number;
+}
+
+export interface IRequestOpts {
+ /**
+ * The alternative base url to use.
+ * If not specified, uses this.opts.baseUrl
+ */
+ baseUrl?: string;
+ /**
+ * The full prefix to use e.g.
+ * "/_matrix/client/v2_alpha". If not specified, uses this.opts.prefix.
+ */
+ prefix?: string;
+ /**
+ * map of additional request headers
+ */
+ headers?: Record<string, string>;
+ abortSignal?: AbortSignal;
+ /**
+ * The maximum amount of time to wait before
+ * timing out the request. If not specified, there is no timeout.
+ */
+ localTimeoutMs?: number;
+ keepAlive?: boolean; // defaults to false
+ json?: boolean; // defaults to true
+
+ // Set to true to prevent the request function from emitting a Session.logged_out event.
+ // This is intended for use on endpoints where M_UNKNOWN_TOKEN is a valid/notable error response,
+ // such as with token refreshes.
+ inhibitLogoutEmit?: boolean;
+}
+
+export interface IContentUri {
+ base: string;
+ path: string;
+ params: {
+ // eslint-disable-next-line camelcase
+ access_token: string;
+ };
+}
+
+export enum HttpApiEvent {
+ SessionLoggedOut = "Session.logged_out",
+ NoConsent = "no_consent",
+}
+
+export type HttpApiEventHandlerMap = {
+ /**
+ * Fires whenever the login session the JS SDK is using is no
+ * longer valid and the user must log in again.
+ * NB. This only fires when action is required from the user, not
+ * when then login session can be renewed by using a refresh token.
+ * @example
+ * ```
+ * matrixClient.on("Session.logged_out", function(errorObj){
+ * // show the login screen
+ * });
+ * ```
+ */
+ [HttpApiEvent.SessionLoggedOut]: (err: MatrixError) => void;
+ /**
+ * Fires when the JS SDK receives a M_CONSENT_NOT_GIVEN error in response
+ * to a HTTP request.
+ * @example
+ * ```
+ * matrixClient.on("no_consent", function(message, contentUri) {
+ * console.info(message + ' Go to ' + contentUri);
+ * });
+ * ```
+ */
+ [HttpApiEvent.NoConsent]: (message: string, consentUri: string) => void;
+};
+
+export interface UploadProgress {
+ loaded: number;
+ total: number;
+}
+
+export interface UploadOpts {
+ /**
+ * Name to give the file on the server. Defaults to <tt>file.name</tt>.
+ */
+ name?: string;
+ /**
+ * Content-type for the upload. Defaults to
+ * <tt>file.type</tt>, or <tt>applicaton/octet-stream</tt>.
+ */
+ type?: string;
+ /**
+ * if false will not send the filename,
+ * e.g for encrypted file uploads where filename leaks are undesirable.
+ * Defaults to true.
+ */
+ includeFilename?: boolean;
+ /**
+ * Optional. Called when a chunk of
+ * data has been uploaded, with an object containing the fields `loaded`
+ * (number of bytes transferred) and `total` (total size, if known).
+ */
+ progressHandler?(progress: UploadProgress): void;
+ abortController?: AbortController;
+}
+
+export interface Upload {
+ loaded: number;
+ total: number;
+ promise: Promise<UploadResponse>;
+ abortController: AbortController;
+}
+
+export interface UploadResponse {
+ // eslint-disable-next-line camelcase
+ content_uri: string;
+}
+
+export type FileType = XMLHttpRequestBodyInit;
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/method.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/method.ts
new file mode 100644
index 0000000..1914360
--- /dev/null
+++ b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/method.ts
@@ -0,0 +1,22 @@
+/*
+Copyright 2022 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 enum Method {
+ Get = "GET",
+ Put = "PUT",
+ Post = "POST",
+ Delete = "DELETE",
+}
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/prefix.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/prefix.ts
new file mode 100644
index 0000000..f15b1ac
--- /dev/null
+++ b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/prefix.ts
@@ -0,0 +1,48 @@
+/*
+Copyright 2022 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 enum ClientPrefix {
+ /**
+ * A constant representing the URI path for release 0 of the Client-Server HTTP API.
+ */
+ R0 = "/_matrix/client/r0",
+ /**
+ * A constant representing the URI path for the legacy release v1 of the Client-Server HTTP API.
+ */
+ V1 = "/_matrix/client/v1",
+ /**
+ * A constant representing the URI path for Client-Server API endpoints versioned at v3.
+ */
+ V3 = "/_matrix/client/v3",
+ /**
+ * A constant representing the URI path for as-yet unspecified Client-Server HTTP APIs.
+ */
+ Unstable = "/_matrix/client/unstable",
+}
+
+export enum IdentityPrefix {
+ /**
+ * URI path for the v2 identity API
+ */
+ V2 = "/_matrix/identity/v2",
+}
+
+export enum MediaPrefix {
+ /**
+ * URI path for the media repo API
+ */
+ R0 = "/_matrix/media/r0",
+}
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/utils.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/utils.ts
new file mode 100644
index 0000000..c49be74
--- /dev/null
+++ b/includes/external/matrix/node_modules/matrix-js-sdk/src/http-api/utils.ts
@@ -0,0 +1,153 @@
+/*
+Copyright 2022 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 { parse as parseContentType, ParsedMediaType } from "content-type";
+
+import { logger } from "../logger";
+import { sleep } from "../utils";
+import { ConnectionError, HTTPError, MatrixError } from "./errors";
+
+// Ponyfill for https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout
+export function timeoutSignal(ms: number): AbortSignal {
+ const controller = new AbortController();
+ setTimeout(() => {
+ controller.abort();
+ }, ms);
+
+ return controller.signal;
+}
+
+export function anySignal(signals: AbortSignal[]): {
+ signal: AbortSignal;
+ cleanup(): void;
+} {
+ const controller = new AbortController();
+
+ function cleanup(): void {
+ for (const signal of signals) {
+ signal.removeEventListener("abort", onAbort);
+ }
+ }
+
+ function onAbort(): void {
+ controller.abort();
+ cleanup();
+ }
+
+ for (const signal of signals) {
+ if (signal.aborted) {
+ onAbort();
+ break;
+ }
+ signal.addEventListener("abort", onAbort);
+ }
+
+ return {
+ signal: controller.signal,
+ cleanup,
+ };
+}
+
+/**
+ * Attempt to turn an HTTP error response into a Javascript Error.
+ *
+ * If it is a JSON response, we will parse it into a MatrixError. Otherwise
+ * we return a generic Error.
+ *
+ * @param response - response object
+ * @param body - raw body of the response
+ * @returns
+ */
+export function parseErrorResponse(response: XMLHttpRequest | Response, body?: string): Error {
+ let contentType: ParsedMediaType | null;
+ try {
+ contentType = getResponseContentType(response);
+ } catch (e) {
+ return <Error>e;
+ }
+
+ if (contentType?.type === "application/json" && body) {
+ return new MatrixError(
+ JSON.parse(body),
+ response.status,
+ isXhr(response) ? response.responseURL : response.url,
+ );
+ }
+ if (contentType?.type === "text/plain") {
+ return new HTTPError(`Server returned ${response.status} error: ${body}`, response.status);
+ }
+ return new HTTPError(`Server returned ${response.status} error`, response.status);
+}
+
+function isXhr(response: XMLHttpRequest | Response): response is XMLHttpRequest {
+ return "getResponseHeader" in response;
+}
+
+/**
+ * extract the Content-Type header from the response object, and
+ * parse it to a `{type, parameters}` object.
+ *
+ * returns null if no content-type header could be found.
+ *
+ * @param response - response object
+ * @returns parsed content-type header, or null if not found
+ */
+function getResponseContentType(response: XMLHttpRequest | Response): ParsedMediaType | null {
+ let contentType: string | null;
+ if (isXhr(response)) {
+ contentType = response.getResponseHeader("Content-Type");
+ } else {
+ contentType = response.headers.get("Content-Type");
+ }
+
+ if (!contentType) return null;
+
+ try {
+ return parseContentType(contentType);
+ } catch (e) {
+ throw new Error(`Error parsing Content-Type '${contentType}': ${e}`);
+ }
+}
+
+/**
+ * Retries a network operation run in a callback.
+ * @param maxAttempts - maximum attempts to try
+ * @param callback - callback that returns a promise of the network operation. If rejected with ConnectionError, it will be retried by calling the callback again.
+ * @returns the result of the network operation
+ * @throws {@link ConnectionError} If after maxAttempts the callback still throws ConnectionError
+ */
+export async function retryNetworkOperation<T>(maxAttempts: number, callback: () => Promise<T>): Promise<T> {
+ let attempts = 0;
+ let lastConnectionError: ConnectionError | null = null;
+ while (attempts < maxAttempts) {
+ try {
+ if (attempts > 0) {
+ const timeout = 1000 * Math.pow(2, attempts);
+ logger.log(`network operation failed ${attempts} times, retrying in ${timeout}ms...`);
+ await sleep(timeout);
+ }
+ return await callback();
+ } catch (err) {
+ if (err instanceof ConnectionError) {
+ attempts += 1;
+ lastConnectionError = err;
+ } else {
+ throw err;
+ }
+ }
+ }
+ throw lastConnectionError;
+}