diff --git a/README.md b/README.md
index 455b2fa897..86a30425de 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,20 @@ Test credentials:
Installation and usage documentation could be found here [EmbeddedChat installation and usage](https://rocketchat.github.io/EmbeddedChat/docs/docs/Usage/embeddedchat_setup)
+### Matrix Support (Experimental)
+
+EmbeddedChat now supports connecting to a Matrix homeserver.
+
+To use Matrix mode, set the `mode` prop to `'matrix'` and provide the `host` and `roomId`.
+
+```jsx
+
+```
+
## Development
### Local Setup
diff --git a/packages/api/package.json b/packages/api/package.json
index a05ca8e630..6d18201304 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -24,6 +24,7 @@
},
"dependencies": {
"@embeddedchat/auth": "workspace:^",
- "@rocket.chat/sdk": "^1.0.0-alpha.42"
+ "@rocket.chat/sdk": "^1.0.0-alpha.42",
+ "matrix-js-sdk": "^39.3.0-rc.0"
}
}
diff --git a/packages/api/src/EmbeddedChatApi.ts b/packages/api/src/EmbeddedChatApi.ts
index 46690e24e6..1995d6fb49 100644
--- a/packages/api/src/EmbeddedChatApi.ts
+++ b/packages/api/src/EmbeddedChatApi.ts
@@ -6,10 +6,11 @@ import {
RocketChatAuth,
ApiError,
} from "@embeddedchat/auth";
+import { IChatProvider } from "./IChatProvider";
// mutliple typing status can come at the same time they should be processed in order.
let typingHandlerLock = 0;
-export default class EmbeddedChatApi {
+export default class EmbeddedChatApi implements IChatProvider {
host: string;
rid: string;
rcClient: Rocketchat;
diff --git a/packages/api/src/IChatProvider.ts b/packages/api/src/IChatProvider.ts
new file mode 100644
index 0000000000..5b86764564
--- /dev/null
+++ b/packages/api/src/IChatProvider.ts
@@ -0,0 +1,34 @@
+import { RocketChatAuth } from "@embeddedchat/auth";
+
+export interface IChatProvider {
+ sendTypingStatus(username: string, typing: boolean): Promise;
+
+ addMessageListener(callback: (message: any) => void): void;
+ removeMessageListener(callback: (message: any) => void): void;
+ addMessageDeleteListener(callback: (messageId: string) => void): void;
+ removeMessageDeleteListener(callback: (messageId: string) => void): void;
+ addTypingStatusListener(callback: (users: string[]) => void): void;
+ removeTypingStatusListener(callback: (users: string[]) => void): void;
+ addActionTriggeredListener(callback: (data: any) => void): void;
+ removeActionTriggeredListener(callback: (data: any) => void): void;
+ addUiInteractionListener(callback: (data: any) => void): void;
+ removeUiInteractionListener(callback: (data: any) => void): void;
+
+ login(userOrEmail: string, password: string, code?: string): Promise;
+ logout(): Promise;
+ autoLogin(auth: {
+ flow: "PASSWORD" | "OAUTH" | "TOKEN";
+ credentials: any;
+ }): Promise;
+ googleSSOLogin(signIn: Function, acsCode: string): Promise;
+
+ getRCAppInfo(): Promise;
+ updateUserUsername(userid: string, username: string): Promise;
+ channelInfo(): Promise;
+ getRoomInfo(): Promise;
+ permissionInfo(): Promise;
+
+ setAuth(auth: RocketChatAuth): void;
+ getAuth(): RocketChatAuth;
+ getHost(): string;
+}
diff --git a/packages/api/src/MatrixProvider.ts b/packages/api/src/MatrixProvider.ts
new file mode 100644
index 0000000000..3da5eaca30
--- /dev/null
+++ b/packages/api/src/MatrixProvider.ts
@@ -0,0 +1,569 @@
+import * as sdk from "matrix-js-sdk";
+import { IChatProvider } from "./IChatProvider";
+import { RocketChatAuth } from "@embeddedchat/auth";
+
+class MatrixAuth extends RocketChatAuth {
+ private onAuthChangeCb: ((user: any) => void) | null = null;
+ currentUser: any | null = null;
+
+ constructor(config: any) {
+ super(config);
+ }
+
+ async onAuthChange(cb: (user: any) => void): Promise {
+ this.onAuthChangeCb = cb;
+ if (this.currentUser) {
+ cb(this.currentUser);
+ }
+ }
+
+ notifyAuthChange(user: any) {
+ this.currentUser = user;
+ if (this.onAuthChangeCb) {
+ this.onAuthChangeCb(user);
+ }
+ }
+}
+
+export default class MatrixProvider implements IChatProvider {
+ private client: any;
+ private host: string;
+ private roomId: string;
+ private auth: MatrixAuth;
+ private onMessageCallbacks: ((message: any) => void)[] = [];
+
+ constructor(host: string, roomId: string) {
+ this.host = host;
+ this.roomId = roomId;
+ this.auth = new MatrixAuth({
+ host: this.host,
+ deleteToken: async () => {},
+ getToken: async () => "",
+ saveToken: async () => {},
+ });
+ }
+
+ async connect(): Promise {
+ if (!this.client) {
+ this.client = sdk.createClient({
+ baseUrl: this.host,
+ });
+ }
+
+ // Map Matrix events to EmbeddedChat callbacks
+ this.client.removeAllListeners("Room.timeline");
+ this.client.on(
+ "Room.timeline",
+ (event: any, room: any, toStartOfTimeline: boolean) => {
+ // Ignore historical messages to prevent duplicates
+ if (toStartOfTimeline) {
+ return;
+ }
+ if (
+ event.getType() !== "m.room.message" &&
+ event.getType() !== "m.room.encrypted"
+ ) {
+ return;
+ }
+ if (room.roomId !== this.roomId) {
+ return;
+ }
+
+ const isEncrypted = event.getType() === "m.room.encrypted";
+ const text = isEncrypted
+ ? "⚠️ [Encrypted Message]"
+ : event.getContent().body;
+
+ // Get display name from room member
+ const senderId = event.getSender();
+ const member = room.getMember(senderId);
+ const displayName = member?.name || senderId;
+
+ // Convert Matrix event to RC message format
+ const message = {
+ _id: event.getId(),
+ msg: text,
+ md: [
+ {
+ type: "PARAGRAPH",
+ value: [
+ {
+ type: "PLAIN_TEXT",
+ value: text,
+ },
+ ],
+ },
+ ],
+ ts: new Date(event.getTs()).toISOString(),
+ u: {
+ _id: senderId,
+ username: displayName,
+ name: displayName,
+ },
+ rid: room.roomId,
+ };
+
+ this.onMessageCallbacks.forEach((cb) => cb(message));
+ }
+ );
+
+ if (!this.client.clientRunning) {
+ await this.client.startClient({ initialSyncLimit: 10 });
+ }
+
+ await new Promise((resolve) => {
+ if (!this.client) {
+ resolve();
+ return;
+ }
+ const state = this.client.getSyncState();
+ if (state === "PREPARED" || state === "SYNCING") {
+ resolve();
+ } else {
+ const checkSync = (state: any) => {
+ if (state === "PREPARED" || state === "SYNCING") {
+ if (this.client) {
+ this.client.removeListener("Sync", checkSync);
+ }
+ resolve();
+ }
+ };
+ this.client.on("Sync", checkSync);
+
+ // Timeout after 5 seconds to prevent hanging
+ setTimeout(() => {
+ if (this.client) {
+ this.client.removeListener("Sync", checkSync);
+ }
+ resolve();
+ }, 5000);
+ }
+ });
+
+ if (!this.client) {
+ console.log("Matrix: client became null during sync wait");
+ return;
+ }
+
+ let room = this.client.getRoom(this.roomId);
+ if (!room) {
+ try {
+ await this.client.joinRoom(this.roomId);
+
+ // Wait for room to appear in store
+ let retries = 0;
+ while (!room && retries < 20 && this.client) {
+ await new Promise((r) => setTimeout(r, 1000));
+ room = this.client?.getRoom(this.roomId);
+ retries++;
+ }
+ } catch (error) {
+ console.error(
+ `MatrixProvider: Failed to join room ${this.roomId}`,
+ error
+ );
+ }
+ }
+ }
+
+ async login(
+ userOrEmail: string,
+ password: string,
+ code?: string
+ ): Promise {
+ if (!this.client) {
+ this.client = sdk.createClient({
+ baseUrl: this.host,
+ });
+ }
+
+ try {
+ const response = await this.client.login("m.login.password", {
+ identifier: {
+ type: "m.id.user",
+ user: userOrEmail,
+ },
+ password: password,
+ });
+
+ // Ensure we connect (start client and sync) after login
+ await this.connect();
+
+ const user = {
+ username: response.user_id,
+ _id: response.user_id,
+ name: response.user_id,
+ avatarUrl: "", // Placeholder
+ roles: [],
+ };
+
+ // Notify auth change to update UI
+ this.auth.notifyAuthChange({ me: user });
+
+ return { status: "success", me: user };
+ } catch (error: any) {
+ // Return error in Rocket.Chat format for toast notifications
+ console.error("Matrix login failed:", error);
+ return {
+ error: error.httpStatus === 403 ? 403 : "Unauthorized",
+ message: error.message || "Invalid username or password",
+ };
+ }
+ }
+
+ async close(): Promise {
+ if (this.client) {
+ this.client.stopClient();
+ }
+ this.auth.notifyAuthChange(null);
+ }
+
+ async getStarredMessages(): Promise {
+ return { messages: [] };
+ }
+
+ async getAllFiles(): Promise {
+ return { files: [] };
+ }
+
+ async getMessages(
+ anonymousMode: boolean,
+ options?: any,
+ isChannelPrivate?: boolean
+ ): Promise {
+ if (!this.client) return { messages: [], count: 0 };
+ const room = this.client.getRoom(this.roomId);
+ if (!room) {
+ return { messages: [], count: 0 };
+ }
+
+ const events = room.getLiveTimeline().getEvents();
+
+ // Reverse events to match Rocket.Chat's newest-first expectation
+ const messages = events
+ .slice() // Create a copy before reversing
+ .reverse()
+ .filter(
+ (event: any) =>
+ event.getType() === "m.room.message" ||
+ event.getType() === "m.room.encrypted"
+ )
+ .map((event: any) => {
+ const isEncrypted = event.getType() === "m.room.encrypted";
+ const text = isEncrypted
+ ? "⚠️ [Encrypted Message]"
+ : event.getContent().body;
+
+ // Get display name from room member
+ const senderId = event.getSender();
+ const member = room.getMember(senderId);
+ const displayName = member?.name || senderId;
+
+ return {
+ _id: event.getId(),
+ msg: text,
+ md: [
+ {
+ type: "PARAGRAPH",
+ value: [
+ {
+ type: "PLAIN_TEXT",
+ value: text,
+ },
+ ],
+ },
+ ],
+ ts: new Date(event.getTs()).toISOString(),
+ u: {
+ _id: senderId,
+ username: displayName,
+ name: displayName,
+ },
+ rid: room.roomId,
+ };
+ });
+
+ return { messages, count: messages.length, success: true };
+ }
+
+ async channelInfo(): Promise {
+ if (!this.client) {
+ return {
+ success: false,
+ errorType: "error-room-not-found",
+ error: "Not connected to Matrix server",
+ };
+ }
+ const room = this.client.getRoom(this.roomId);
+ if (!room) {
+ return {
+ success: false,
+ errorType: "error-room-not-found",
+ error: `Room ${this.roomId} not found`,
+ };
+ }
+ return {
+ success: true,
+ room: {
+ _id: room.roomId,
+ name: room.name || "Matrix Room",
+ t: "c",
+ },
+ };
+ }
+
+ async getRoomInfo(): Promise {
+ if (!this.client) {
+ return {
+ success: false,
+ errorType: "error-room-not-found",
+ error: "Not connected to Matrix server",
+ };
+ }
+ const room = this.client.getRoom(this.roomId);
+ if (!room) {
+ return {
+ success: false,
+ errorType: "error-room-not-found",
+ error: `Room ${this.roomId} not found`,
+ };
+ }
+ return {
+ success: true,
+ room: {
+ _id: room.roomId,
+ name: room.name,
+ t: "c",
+ },
+ };
+ }
+
+ async sendMessage(message: any, threadId?: string): Promise {
+ const content = {
+ msgtype: "m.text",
+ body: typeof message === "string" ? message : message.msg,
+ };
+ try {
+ const response = await this.client.sendEvent(
+ this.roomId,
+ "m.room.message",
+ content
+ );
+ return { success: true, message: { _id: response.event_id } };
+ } catch (error: any) {
+ console.error("Matrix sendMessage failed:", error);
+ return { success: false, error: error.message };
+ }
+ }
+
+ async getOlderMessages(
+ anonymousMode: boolean,
+ options?: any,
+ isChannelPrivate?: boolean
+ ): Promise {
+ return { messages: [] };
+ }
+
+ async getThreadMessages(
+ tmid: string,
+ isChannelPrivate?: boolean
+ ): Promise {
+ return { messages: [] };
+ }
+
+ async deleteMessage(msgId: string): Promise {
+ // Matrix message deletion not implemented
+ return {
+ success: false,
+ error: "Message deletion not supported in Matrix mode",
+ };
+ }
+
+ async updateMessage(msgId: string, text: string): Promise {
+ // Matrix message editing not implemented
+ return {
+ success: false,
+ error: "Message editing not supported in Matrix mode",
+ };
+ }
+
+ async starMessage(msgId: string): Promise {
+ // Matrix doesn't have native starring - could use room account data
+ return { success: true }; // Silently succeed for now
+ }
+
+ async unstarMessage(msgId: string): Promise {
+ return { success: true };
+ }
+
+ async pinMessage(msgId: string): Promise {
+ // Matrix has m.room.pinned_events state event
+ return { success: true }; // Stub for now
+ }
+
+ async unpinMessage(msgId: string): Promise {
+ return { success: true };
+ }
+
+ async reactToMessage(
+ emoji: string,
+ msgId: string,
+ shouldReact: boolean
+ ): Promise {
+ // Matrix supports reactions via m.reaction
+ return { success: true }; // Stub for now
+ }
+
+ async getChannelRoles(isChannelPrivate?: boolean): Promise {
+ return [];
+ }
+
+ async getUsersInRole(role: string): Promise {
+ return [];
+ }
+
+ async getUserRoles(): Promise {
+ return [];
+ }
+
+ async sendTypingStatus(username: string, typing: boolean): Promise {
+ await this.client.sendTyping(this.roomId, typing, 3000);
+ }
+
+ addMessageListener(callback: (message: any) => void): void {
+ this.onMessageCallbacks.push(callback);
+ }
+
+ removeMessageListener(callback: (message: any) => void): void {
+ this.onMessageCallbacks = this.onMessageCallbacks.filter(
+ (c) => c !== callback
+ );
+ }
+
+ addMessageDeleteListener(callback: (messageId: string) => void): void {}
+
+ removeMessageDeleteListener(callback: (messageId: string) => void): void {}
+
+ addTypingStatusListener(callback: (users: string[]) => void): void {}
+
+ removeTypingStatusListener(callback: (users: string[]) => void): void {}
+
+ addActionTriggeredListener(callback: (data: any) => void): void {}
+
+ removeActionTriggeredListener(callback: (data: any) => void): void {}
+
+ addUiInteractionListener(callback: (data: any) => void): void {}
+
+ removeUiInteractionListener(callback: (data: any) => void): void {}
+
+ async logout(): Promise {
+ if (this.client) {
+ await this.client.logout();
+ }
+ this.auth.notifyAuthChange(null);
+ }
+
+ async autoLogin(auth: {
+ flow: "PASSWORD" | "OAUTH" | "TOKEN";
+ credentials: any;
+ }): Promise {}
+
+ async googleSSOLogin(signIn: Function, acsCode: string): Promise {}
+
+ async getRCAppInfo(): Promise {
+ return null;
+ }
+
+ async updateUserUsername(userid: string, username: string): Promise {
+ return {};
+ }
+
+ async permissionInfo(): Promise {
+ return [];
+ }
+
+ setAuth(auth: RocketChatAuth): void {
+ // We ignore external auth setting for now as we manage our own MatrixAuth
+ }
+
+ getAuth(): RocketChatAuth {
+ return this.auth;
+ }
+
+ getHost(): string {
+ return this.host;
+ }
+
+ async getMessageLimit(): Promise {
+ return { value: 5000 }; // Default limit
+ }
+
+ // Additional methods for toast compatibility
+ async reportMessage(messageId: string, description: string): Promise {
+ // Matrix doesn't have built-in message reporting
+ return {
+ success: false,
+ error: "Message reporting not supported in Matrix mode",
+ };
+ }
+
+ async getSearchMessages(text: string): Promise {
+ // Matrix search would require server-side search API
+ return { messages: [] };
+ }
+
+ async me(): Promise {
+ if (!this.client) return {};
+ const userId = this.client.getUserId();
+ if (!userId) return {};
+ return {
+ _id: userId,
+ username: userId,
+ name: userId,
+ };
+ }
+
+ async userData(username: string): Promise {
+ // Matrix user profile lookup
+ return { user: null };
+ }
+
+ async getUserStatus(userId: string): Promise {
+ // Matrix presence API
+ return { status: "online" };
+ }
+
+ async findOrCreateInvite(): Promise {
+ // Matrix room invite link
+ return { url: "", expires: new Date().toISOString() };
+ }
+
+ async getAllImages(): Promise {
+ return { files: [] };
+ }
+
+ async execCommand(command: {
+ command: string;
+ params: string;
+ }): Promise {
+ // Matrix doesn't have slash commands in the same way
+ return { success: false, error: "Commands not supported in Matrix mode" };
+ }
+
+ async getChannelMembers(isChannelPrivate?: boolean): Promise {
+ if (!this.client) return { members: [] };
+ const room = this.client.getRoom(this.roomId);
+ if (!room) return { members: [] };
+
+ const members = room.getJoinedMembers().map((member: any) => ({
+ _id: member.userId,
+ username: member.name || member.userId,
+ name: member.name || member.userId,
+ }));
+ return { members };
+ }
+
+ async getCommandsList(): Promise {
+ return { commands: [] };
+ }
+}
diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts
index b4ff83a1c6..046d30f34d 100644
--- a/packages/api/src/index.ts
+++ b/packages/api/src/index.ts
@@ -1 +1,3 @@
export { default as EmbeddedChatApi } from "./EmbeddedChatApi";
+export { default as MatrixProvider } from "./MatrixProvider";
+export * from "./IChatProvider";
diff --git a/packages/react/src/stories/MatrixMode.stories.js b/packages/react/src/stories/MatrixMode.stories.js
new file mode 100644
index 0000000000..598d2a645c
--- /dev/null
+++ b/packages/react/src/stories/MatrixMode.stories.js
@@ -0,0 +1,21 @@
+import { EmbeddedChat } from '..';
+
+export default {
+ title: 'EmbeddedChat/Matrix',
+ component: EmbeddedChat,
+};
+
+export const MatrixMode = {
+ args: {
+ mode: 'matrix',
+ host: 'https://matrix.org', // Replace with your Matrix homeserver URL
+ roomId: '', // Replace with a public room ID (e.g., Matrix HQ)
+ channelName: 'Matrix Room',
+ headerColor: 'white',
+ toastBarPosition: 'bottom right',
+ showRoles: true,
+ enableThreads: true,
+ hideHeader: false,
+ dark: false,
+ },
+};
diff --git a/packages/react/src/views/ChatInput/ChatInput.js b/packages/react/src/views/ChatInput/ChatInput.js
index 998e9007cd..fa5b5e1e70 100644
--- a/packages/react/src/views/ChatInput/ChatInput.js
+++ b/packages/react/src/views/ChatInput/ChatInput.js
@@ -321,7 +321,10 @@ const ChatInput = ({ scrollToBottom }) => {
pendingMessage.tmid = threadId;
}
- upsertMessage(pendingMessage, ECOptions.enableThreads);
+ // Skip optimistic rendering for Matrix - it provides real-time updates via Room.timeline
+ if (ECOptions.mode !== 'matrix') {
+ upsertMessage(pendingMessage, ECOptions.enableThreads);
+ }
const res = await RCInstance.sendMessage(
{
@@ -333,7 +336,10 @@ const ChatInput = ({ scrollToBottom }) => {
if (res.success) {
clearQuoteMessages();
- replaceMessage(pendingMessage, res.message);
+ // In Matrix mode, don't replace - the message will come via Room.timeline
+ if (ECOptions.mode !== 'matrix') {
+ replaceMessage(pendingMessage, res.message);
+ }
}
};
@@ -348,7 +354,10 @@ const ChatInput = ({ scrollToBottom }) => {
message.replace(/\n/g, '\\n')
);
if (!res.success) {
- handleSendError('Error editing message, login again');
+ dispatchToastMessage({
+ type: 'error',
+ message: res.error || 'Message editing not supported',
+ });
}
};
diff --git a/packages/react/src/views/ChatInput/ChatInputFormattingToolbar.js b/packages/react/src/views/ChatInput/ChatInputFormattingToolbar.js
index 5d8c20a600..a930009255 100644
--- a/packages/react/src/views/ChatInput/ChatInputFormattingToolbar.js
+++ b/packages/react/src/views/ChatInput/ChatInputFormattingToolbar.js
@@ -116,6 +116,7 @@ const ChatInputFormattingToolbar = ({
audio: (
formatter.find((item) => item.name === name))
.map((item) =>
isPopoverOpen && popOverItems.includes('formatter') ? (
- <>
+
{item.name}
- >
+
) : (
{
secure = false,
dark = false,
remoteOpt = false,
+ mode = 'rocketchat', // 'rocketchat' or 'matrix'
} = config;
const hasMounted = useRef(false);
@@ -90,6 +91,9 @@ const EmbeddedChat = (props) => {
}
const initializeRCInstance = useCallback(() => {
+ if (mode === 'matrix') {
+ return new MatrixProvider(host, roomId);
+ }
const newRCInstance = new EmbeddedChatApi(host, roomId, {
getToken,
deleteToken,
@@ -97,7 +101,7 @@ const EmbeddedChat = (props) => {
});
return newRCInstance;
- }, [host, roomId, getToken, deleteToken, saveToken]);
+ }, [host, roomId, getToken, deleteToken, saveToken, mode]);
const [RCInstance, setRCInstance] = useState(() => initializeRCInstance());
@@ -138,7 +142,7 @@ const EmbeddedChat = (props) => {
if (user) {
RCInstance.connect()
.then(() => {
- console.log(`Connected to RocketChat ${RCInstance.host}`);
+ console.log(`Connected to chat provider ${RCInstance.host}`);
const { me } = user;
setAuthenticatedAvatarUrl(me.avatarUrl);
setAuthenticatedUsername(me.username);
@@ -198,6 +202,7 @@ const EmbeddedChat = (props) => {
showUsername,
hideHeader,
anonymousMode,
+ mode,
}),
[
enableThreads,
@@ -214,6 +219,7 @@ const EmbeddedChat = (props) => {
showUsername,
hideHeader,
anonymousMode,
+ mode,
]
);
@@ -288,6 +294,7 @@ EmbeddedChat.propTypes = {
style: PropTypes.object,
hideHeader: PropTypes.bool,
dark: PropTypes.bool,
+ mode: PropTypes.oneOf(['rocketchat', 'matrix']),
};
export default memo(EmbeddedChat);
diff --git a/yarn.lock b/yarn.lock
index 23b67cfd11..c0d992066c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2293,6 +2293,7 @@ __metadata:
dependencies:
"@embeddedchat/auth": "workspace:^"
"@rocket.chat/sdk": ^1.0.0-alpha.42
+ matrix-js-sdk: ^39.3.0-rc.0
parcel: ^2.10.3
rollup: ^3.23.0
rollup-plugin-dts: ^6.0.1
@@ -4600,6 +4601,13 @@ __metadata:
languageName: node
linkType: hard
+"@matrix-org/matrix-sdk-crypto-wasm@npm:^15.3.0":
+ version: 15.3.0
+ resolution: "@matrix-org/matrix-sdk-crypto-wasm@npm:15.3.0"
+ checksum: 1c84eefd49ccb2e76b3163846409d314a12986e8bc8d42b6342021904b6831efe455925bbc1d8e46c36a1baaf848a0b1763b65cd31cf18d9315e3828a6a8a938
+ languageName: node
+ linkType: hard
+
"@mdx-js/react@npm:^2.1.5":
version: 2.3.0
resolution: "@mdx-js/react@npm:2.3.0"
@@ -9482,6 +9490,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/events@npm:^3.0.0":
+ version: 3.0.3
+ resolution: "@types/events@npm:3.0.3"
+ checksum: 50af9312fab001fd6bd4bb3ff65830f940877e6778de140a92481a0d9bf5f4853d44ec758a8800ef60e0598ac43ed1b5688116a3c65906ae54e989278d6c7c82
+ languageName: node
+ linkType: hard
+
"@types/express-serve-static-core@npm:^4.17.33":
version: 4.17.41
resolution: "@types/express-serve-static-core@npm:4.17.41"
@@ -11013,6 +11028,13 @@ __metadata:
languageName: node
linkType: hard
+"another-json@npm:^0.2.0":
+ version: 0.2.0
+ resolution: "another-json@npm:0.2.0"
+ checksum: b1d27bd5d7a35364ff2e8eb66e65ef9a53f3ab84f7a4ae38495bf14ba0b346654f107487b4f2f247dbe6a22a8fb4ca2a94330738176516b78494e641fce05178
+ languageName: node
+ linkType: hard
+
"anser@npm:^1.4.9":
version: 1.4.10
resolution: "anser@npm:1.4.10"
@@ -12096,6 +12118,13 @@ __metadata:
languageName: node
linkType: hard
+"base-x@npm:^5.0.0":
+ version: 5.0.1
+ resolution: "base-x@npm:5.0.1"
+ checksum: 6e4f847ef842e0a71c6b6020a6ec482a2a5e727f5a98534dbfd5d5a4e8afbc0d1bdf1fd57174b3f0455d107f10a932c3c7710bec07e2878f80178607f8f605c8
+ languageName: node
+ linkType: hard
+
"base64-js@npm:^1.0.2, base64-js@npm:^1.1.2, base64-js@npm:^1.2.3, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1":
version: 1.5.1
resolution: "base64-js@npm:1.5.1"
@@ -12523,6 +12552,15 @@ __metadata:
languageName: node
linkType: hard
+"bs58@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "bs58@npm:6.0.0"
+ dependencies:
+ base-x: ^5.0.0
+ checksum: 820334f9513bba6195136dfc9dfbd1f5aded6c7864639f3ee7b63c2d9d6f9f2813b9949b1f6beb9c161237be2a461097444c2ff587c8c3b824fe18878fa22448
+ languageName: node
+ linkType: hard
+
"bser@npm:2.1.1":
version: 2.1.1
resolution: "bser@npm:2.1.1"
@@ -13739,7 +13777,7 @@ __metadata:
languageName: node
linkType: hard
-"content-type@npm:~1.0.4, content-type@npm:~1.0.5":
+"content-type@npm:^1.0.4, content-type@npm:~1.0.4, content-type@npm:~1.0.5":
version: 1.0.5
resolution: "content-type@npm:1.0.5"
checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766
@@ -19930,6 +19968,13 @@ __metadata:
languageName: node
linkType: hard
+"is-network-error@npm:^1.1.0":
+ version: 1.3.0
+ resolution: "is-network-error@npm:1.3.0"
+ checksum: 56dc0b8ed9c0bb72202058f172ad0c3121cf68772e8cbba343d3775f6e2ec7877d423cbcea45f4cedcd345de8693de1b52dfe0c6fc15d652c4aa98c2abf0185a
+ languageName: node
+ linkType: hard
+
"is-number-object@npm:^1.0.4":
version: 1.0.7
resolution: "is-number-object@npm:1.0.7"
@@ -21419,6 +21464,13 @@ __metadata:
languageName: node
linkType: hard
+"jwt-decode@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "jwt-decode@npm:4.0.0"
+ checksum: 390e2edcb31a92e86c8cbdd1edeea4c0d62acd371f8a8f0a8878e499390c0ecf4c658b365c4e941e4ef37d0170e4ca650aaa49f99a45c0b9695a235b210154b0
+ languageName: node
+ linkType: hard
+
"keyv@npm:^4.5.3":
version: 4.5.4
resolution: "keyv@npm:4.5.4"
@@ -22164,6 +22216,13 @@ __metadata:
languageName: node
linkType: hard
+"loglevel@npm:^1.9.2":
+ version: 1.9.2
+ resolution: "loglevel@npm:1.9.2"
+ checksum: 896c67b90a507bfcfc1e9a4daa7bf789a441dd70d95cd13b998d6dd46233a3bfadfb8fadb07250432bbfb53bf61e95f2520f9b11f9d3175cc460e5c251eca0af
+ languageName: node
+ linkType: hard
+
"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0":
version: 1.4.0
resolution: "loose-envify@npm:1.4.0"
@@ -22453,6 +22512,45 @@ __metadata:
languageName: node
linkType: hard
+"matrix-events-sdk@npm:0.0.1":
+ version: 0.0.1
+ resolution: "matrix-events-sdk@npm:0.0.1"
+ checksum: 18b61a1a2cd9947e5cec4f9332186f5609e3a47c6c6e775b306e9af0e12babcdb2f68459133c4d44ebc5a7e5ee60e7528813dfccb80d8a8b55668338cd81ee49
+ languageName: node
+ linkType: hard
+
+"matrix-js-sdk@npm:^39.3.0-rc.0":
+ version: 39.3.0-rc.0
+ resolution: "matrix-js-sdk@npm:39.3.0-rc.0"
+ dependencies:
+ "@babel/runtime": ^7.12.5
+ "@matrix-org/matrix-sdk-crypto-wasm": ^15.3.0
+ another-json: ^0.2.0
+ bs58: ^6.0.0
+ content-type: ^1.0.4
+ jwt-decode: ^4.0.0
+ loglevel: ^1.9.2
+ matrix-events-sdk: 0.0.1
+ matrix-widget-api: ^1.14.0
+ oidc-client-ts: ^3.0.1
+ p-retry: 7
+ sdp-transform: ^3.0.0
+ unhomoglyph: ^1.0.6
+ uuid: 13
+ checksum: c3279836d0d30c9ea174140979dabc36ba0772023ee156e138a042e940b33f692738a32ca265f235bd2fb1095746f1b8a635e7eb3234c59de023a6f8b66a3c65
+ languageName: node
+ linkType: hard
+
+"matrix-widget-api@npm:^1.14.0":
+ version: 1.15.0
+ resolution: "matrix-widget-api@npm:1.15.0"
+ dependencies:
+ "@types/events": ^3.0.0
+ events: ^3.2.0
+ checksum: bd77ade78987ebfd202bae45204f3b43f8d7baa53b7df3910843dfecf8c5d66eada2a644a1a5b0ab5d4307847815b69d9d6c27981c97a0d82417d88ec8df1b8f
+ languageName: node
+ linkType: hard
+
"maxmin@npm:^2.1.0":
version: 2.1.0
resolution: "maxmin@npm:2.1.0"
@@ -24711,6 +24809,15 @@ __metadata:
languageName: node
linkType: hard
+"oidc-client-ts@npm:^3.0.1":
+ version: 3.4.1
+ resolution: "oidc-client-ts@npm:3.4.1"
+ dependencies:
+ jwt-decode: ^4.0.0
+ checksum: 3c0298e11a5ae89131c4a0a77699dabc7470e68a7128d19a30321a629e0fb0a777138eb14c0c68e01fd645b56b19b55f26cb2f6a6de2b832e79bdc0eb764a1e1
+ languageName: node
+ linkType: hard
+
"on-finished@npm:2.4.1":
version: 2.4.1
resolution: "on-finished@npm:2.4.1"
@@ -25085,6 +25192,15 @@ __metadata:
languageName: node
linkType: hard
+"p-retry@npm:7":
+ version: 7.1.0
+ resolution: "p-retry@npm:7.1.0"
+ dependencies:
+ is-network-error: ^1.1.0
+ checksum: 5f8b34218d0041adac2d9133e116d18a9ff6e61f55390910cb63dbc9bfb4088de8ce36a6da3dad48878ef1bf9b565b883a2ef5ff4733cb8cc3c8eab82d9b2e6d
+ languageName: node
+ linkType: hard
+
"p-timeout@npm:^3.2.0":
version: 3.2.0
resolution: "p-timeout@npm:3.2.0"
@@ -28530,6 +28646,15 @@ __metadata:
languageName: node
linkType: hard
+"sdp-transform@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "sdp-transform@npm:3.0.0"
+ bin:
+ sdp-verify: checker.js
+ checksum: a9bd43d7135ec3b0db36cf3a7896abd18ffe19811dd59d4ca271c4ba8ebb679c2fc930708d4b3e8f0a08dbc513d1e888e6971b51ab04cfec5c4c58d6ec895bc6
+ languageName: node
+ linkType: hard
+
"semver@npm:2 || 3 || 4 || 5, semver@npm:^5.3.0, semver@npm:^5.5.0, semver@npm:^5.6.0, semver@npm:^5.7.1":
version: 5.7.2
resolution: "semver@npm:5.7.2"
@@ -31110,6 +31235,13 @@ __metadata:
languageName: node
linkType: hard
+"unhomoglyph@npm:^1.0.6":
+ version: 1.0.6
+ resolution: "unhomoglyph@npm:1.0.6"
+ checksum: 2401fa3f8129fb1093d9ae59680b1dc8e395016e48401f9e706861a6edd28cafc60b0ac7e001cc127ee544942ed16236881b969afd856c28ebfe5d77afa1f0c2
+ languageName: node
+ linkType: hard
+
"unicode-canonical-property-names-ecmascript@npm:^2.0.0":
version: 2.0.0
resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0"
@@ -31545,6 +31677,15 @@ __metadata:
languageName: node
linkType: hard
+"uuid@npm:13":
+ version: 13.0.0
+ resolution: "uuid@npm:13.0.0"
+ bin:
+ uuid: dist-node/bin/uuid
+ checksum: 7510ee1ab371be5339ef26ff8cabc2f4a2c60640ff880652968f758072f53bd4f4af1c8b0e671a8c9bb29ef926a24dec3ef0e3861d78183b39291a85743a9f96
+ languageName: node
+ linkType: hard
+
"uuid@npm:8.3.2, uuid@npm:^8.0.0, uuid@npm:^8.3.2, uuid@npm:~8.3.2":
version: 8.3.2
resolution: "uuid@npm:8.3.2"