init
This commit is contained in:
478
node_modules/matrix-js-sdk/README.md
generated
vendored
Normal file
478
node_modules/matrix-js-sdk/README.md
generated
vendored
Normal file
@@ -0,0 +1,478 @@
|
||||
[](https://www.npmjs.com/package/matrix-js-sdk)
|
||||

|
||||

|
||||
[](https://sonarcloud.io/summary/new_code?id=matrix-js-sdk)
|
||||
[](https://sonarcloud.io/summary/new_code?id=matrix-js-sdk)
|
||||
[](https://sonarcloud.io/summary/new_code?id=matrix-js-sdk)
|
||||
[](https://sonarcloud.io/summary/new_code?id=matrix-js-sdk)
|
||||
|
||||
# Matrix JavaScript SDK
|
||||
|
||||
This is the [Matrix](https://matrix.org) Client-Server SDK for JavaScript and TypeScript. This SDK can be run in a
|
||||
browser or in Node.js.
|
||||
|
||||
---
|
||||
|
||||
<picture>
|
||||
<source srcset="contrib/element-logo-light.png" media="(prefers-color-scheme: dark)">
|
||||
<source srcset="contrib/element-logo-dark.png" media="(prefers-color-scheme: light)">
|
||||
<img src="contrib/element-logo-fallback.png" alt="Element logo">
|
||||
</picture>
|
||||
|
||||
<br>
|
||||
|
||||
Development and maintenance is proudly sponsored by [Element](https://element.io). Element uses the SDK in their flagship [web](https://github.com/element-hq/element-web) and [desktop](https://github.com/element-hq/element-desktop) clients.
|
||||
|
||||
The SDK is also the basis for multiple Matrix projects and we welcome contributions from all.
|
||||
|
||||
---
|
||||
|
||||
#### Minimum Matrix server version: v1.1
|
||||
|
||||
The Matrix specification is constantly evolving - while this SDK aims for maximum backwards compatibility, it only
|
||||
guarantees that a feature will be supported for at least 4 spec releases. For example, if a feature the js-sdk supports
|
||||
is removed in v1.4 then the feature is _eligible_ for removal from the SDK when v1.8 is released. This SDK has no
|
||||
guarantee on implementing all features of any particular spec release, currently. This can mean that the SDK will call
|
||||
endpoints from before Matrix 1.1, for example.
|
||||
|
||||
# Quickstart
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Servers may require or use authenticated endpoints for media (images, files, avatars, etc). See the
|
||||
> [Authenticated Media](#authenticated-media) section for information on how to enable support for this.
|
||||
|
||||
Using `pnpm` instead of `npm` is recommended. Please see the pnpm [install
|
||||
guide](https://pnpm.io/installation#using-corepack) if you do not have it already.
|
||||
|
||||
`pnpm add matrix-js-sdk`
|
||||
|
||||
```javascript
|
||||
import * as sdk from "matrix-js-sdk";
|
||||
const client = sdk.createClient({ baseUrl: "https://matrix.org" });
|
||||
client.publicRooms(function (err, data) {
|
||||
console.log("Public Rooms: %s", JSON.stringify(data));
|
||||
});
|
||||
```
|
||||
|
||||
See [below](#end-to-end-encryption-support) for how to enable end-to-end-encryption, or check
|
||||
[the Node.js terminal app](https://github.com/matrix-org/matrix-js-sdk/tree/develop/examples/node) for a more complex example.
|
||||
|
||||
To start the client:
|
||||
|
||||
```javascript
|
||||
await client.startClient({ initialSyncLimit: 10 });
|
||||
```
|
||||
|
||||
You can perform a call to `/sync` to get the current state of the client:
|
||||
|
||||
```javascript
|
||||
client.once(ClientEvent.sync, function (state, prevState, res) {
|
||||
if (state === "PREPARED") {
|
||||
console.log("prepared");
|
||||
} else {
|
||||
console.log(state);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
To send a message:
|
||||
|
||||
```javascript
|
||||
const content = {
|
||||
body: "message text",
|
||||
msgtype: "m.text",
|
||||
};
|
||||
client.sendEvent("roomId", "m.room.message", content, "", (err, res) => {
|
||||
console.log(err);
|
||||
});
|
||||
```
|
||||
|
||||
To listen for message events:
|
||||
|
||||
```javascript
|
||||
client.on(RoomEvent.Timeline, function (event, room, toStartOfTimeline) {
|
||||
if (event.getType() !== "m.room.message") {
|
||||
return; // only use messages
|
||||
}
|
||||
console.log(event.event.content.body);
|
||||
});
|
||||
```
|
||||
|
||||
By default, the `matrix-js-sdk` client uses the `MemoryStore` to store events as they are received. For example to iterate through the currently stored timeline for a room:
|
||||
|
||||
```javascript
|
||||
Object.keys(client.store.rooms).forEach((roomId) => {
|
||||
client.getRoom(roomId).timeline.forEach((t) => {
|
||||
console.log(t.event);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Authenticated media
|
||||
|
||||
Servers supporting [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916) (Matrix 1.11) will require clients, like
|
||||
yours, to include an `Authorization` header when `/download`ing or `/thumbnail`ing media. For NodeJS environments this
|
||||
may be as easy as the following code snippet, though web browsers may need to use [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
|
||||
to append the header when using the endpoints in `<img />` elements and similar.
|
||||
|
||||
```javascript
|
||||
const downloadUrl = client.mxcUrlToHttp(
|
||||
/*mxcUrl=*/ "mxc://example.org/abc123", // the MXC URI to download/thumbnail, typically from an event or profile
|
||||
/*width=*/ undefined, // part of the thumbnail API. Use as required.
|
||||
/*height=*/ undefined, // part of the thumbnail API. Use as required.
|
||||
/*resizeMethod=*/ undefined, // part of the thumbnail API. Use as required.
|
||||
/*allowDirectLinks=*/ false, // should generally be left `false`.
|
||||
/*allowRedirects=*/ true, // implied supported with authentication
|
||||
/*useAuthentication=*/ true, // the flag we're after in this example
|
||||
);
|
||||
const img = await fetch(downloadUrl, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${client.getAccessToken()}`,
|
||||
},
|
||||
});
|
||||
// Do something with `img`.
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> In future the js-sdk will _only_ return authentication-required URLs, mandating population of the `Authorization` header.
|
||||
|
||||
## What does this SDK do?
|
||||
|
||||
This SDK provides a full object model around the Matrix Client-Server API and emits
|
||||
events for incoming data and state changes. Aside from wrapping the HTTP API, it:
|
||||
|
||||
- Handles syncing (via `/sync`)
|
||||
- Handles the generation of "friendly" room and member names.
|
||||
- Handles historical `RoomMember` information (e.g. display names).
|
||||
- Manages room member state across multiple events (e.g. it handles typing, power
|
||||
levels and membership changes).
|
||||
- Exposes high-level objects like `Rooms`, `RoomState`, `RoomMembers` and `Users`
|
||||
which can be listened to for things like name changes, new messages, membership
|
||||
changes, presence changes, and more.
|
||||
- Handle "local echo" of messages sent using the SDK. This means that messages
|
||||
that have just been sent will appear in the timeline as 'sending', until it
|
||||
completes. This is beneficial because it prevents there being a gap between
|
||||
hitting the send button and having the "remote echo" arrive.
|
||||
- Mark messages which failed to send as not sent.
|
||||
- Automatically retry requests to send messages due to network errors.
|
||||
- Automatically retry requests to send messages due to rate limiting errors.
|
||||
- Handle queueing of messages.
|
||||
- Handles pagination.
|
||||
- Handle assigning push actions for events.
|
||||
- Handles room initial sync on accepting invites.
|
||||
- Handles WebRTC calling.
|
||||
|
||||
# Usage
|
||||
|
||||
## Supported platforms
|
||||
|
||||
`matrix-js-sdk` can be used in either Node.js applications (ensure you have the latest LTS version of Node.js installed),
|
||||
or in browser applications, via a bundler such as Webpack or Vite.
|
||||
|
||||
You can also use the sdk with [Deno](https://deno.land/) (`import npm:matrix-js-sdk`) but its not officially supported.
|
||||
|
||||
## Emitted events
|
||||
|
||||
The SDK raises notifications to the application using
|
||||
[`EventEmitter`s](https://nodejs.org/api/events.html#class-eventemitter). The `MatrixClient` itself
|
||||
implements `EventEmitter`, as do many of the high-level abstractions such as `Room` and `RoomMember`.
|
||||
|
||||
```javascript
|
||||
// Listen for low-level MatrixEvents
|
||||
client.on(ClientEvent.Event, function (event) {
|
||||
console.log(event.getType());
|
||||
});
|
||||
|
||||
// Listen for typing changes
|
||||
client.on(RoomMemberEvent.Typing, function (event, member) {
|
||||
if (member.typing) {
|
||||
console.log(member.name + " is typing...");
|
||||
} else {
|
||||
console.log(member.name + " stopped typing.");
|
||||
}
|
||||
});
|
||||
|
||||
// start the client to setup the connection to the server
|
||||
client.startClient();
|
||||
```
|
||||
|
||||
## Entry points
|
||||
|
||||
As well as the primary entry point (`matrix-js-sdk`), there are several other entry points which may be useful:
|
||||
|
||||
| Entry point | Description |
|
||||
| ------------------------------ | --------------------------------------------------------------------------------------------------- |
|
||||
| `matrix-js-sdk` | Primary entry point. High-level functionality, and lots of historical clutter in need of a cleanup. |
|
||||
| `matrix-js-sdk/lib/crypto-api` | Cryptography functionality. |
|
||||
| `matrix-js-sdk/lib/types` | Low-level types, reflecting data structures defined in the Matrix spec. |
|
||||
| `matrix-js-sdk/lib/testing` | Test utilities, which may be useful in test code but should not be used in production code. |
|
||||
| `matrix-js-sdk/lib/rendezvous` | Utilities around MSC4108 QR code login and rendezvous servers. |
|
||||
| `matrix-js-sdk/lib/utils/*.js` | A set of modules exporting standalone functions (and their types). |
|
||||
|
||||
## Examples
|
||||
|
||||
This section provides some useful code snippets which demonstrate the
|
||||
core functionality of the SDK. These examples assume the SDK is set up like this:
|
||||
|
||||
```javascript
|
||||
import * as sdk from "matrix-js-sdk";
|
||||
const myUserId = "@example:localhost";
|
||||
const myAccessToken = "QGV4YW1wbGU6bG9jYWxob3N0.qPEvLuYfNBjxikiCjP";
|
||||
const matrixClient = sdk.createClient({
|
||||
baseUrl: "http://localhost:8008",
|
||||
accessToken: myAccessToken,
|
||||
userId: myUserId,
|
||||
});
|
||||
```
|
||||
|
||||
### Automatically join rooms when invited
|
||||
|
||||
```javascript
|
||||
matrixClient.on(RoomEvent.MyMembership, function (room, membership, prevMembership) {
|
||||
if (membership === KnownMembership.Invite) {
|
||||
matrixClient.joinRoom(room.roomId).then(function () {
|
||||
console.log("Auto-joined %s", room.roomId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
matrixClient.startClient();
|
||||
```
|
||||
|
||||
### Print out messages for all rooms
|
||||
|
||||
```javascript
|
||||
matrixClient.on(RoomEvent.Timeline, function (event, room, toStartOfTimeline) {
|
||||
if (toStartOfTimeline) {
|
||||
return; // don't print paginated results
|
||||
}
|
||||
if (event.getType() !== "m.room.message") {
|
||||
return; // only print messages
|
||||
}
|
||||
console.log(
|
||||
// the room name will update with m.room.name events automatically
|
||||
"(%s) %s :: %s",
|
||||
room.name,
|
||||
event.getSender(),
|
||||
event.getContent().body,
|
||||
);
|
||||
});
|
||||
|
||||
matrixClient.startClient();
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
(My Room) @megan:localhost :: Hello world
|
||||
(My Room) @megan:localhost :: how are you?
|
||||
(My Room) @example:localhost :: I am good
|
||||
(My Room) @example:localhost :: change the room name
|
||||
(My New Room) @megan:localhost :: done
|
||||
```
|
||||
|
||||
### Print out membership lists whenever they are changed
|
||||
|
||||
```javascript
|
||||
matrixClient.on(RoomStateEvent.Members, function (event, state, member) {
|
||||
const room = matrixClient.getRoom(state.roomId);
|
||||
if (!room) {
|
||||
return;
|
||||
}
|
||||
const memberList = state.getMembers();
|
||||
console.log(room.name);
|
||||
console.log(Array(room.name.length + 1).join("=")); // underline
|
||||
for (var i = 0; i < memberList.length; i++) {
|
||||
console.log("(%s) %s", memberList[i].membership, memberList[i].name);
|
||||
}
|
||||
});
|
||||
|
||||
matrixClient.startClient();
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
My Room
|
||||
=======
|
||||
(join) @example:localhost
|
||||
(leave) @alice:localhost
|
||||
(join) Bob
|
||||
(invite) @charlie:localhost
|
||||
```
|
||||
|
||||
# API Reference
|
||||
|
||||
A hosted reference can be found at
|
||||
http://matrix-org.github.io/matrix-js-sdk/index.html
|
||||
|
||||
This SDK uses [Typedoc](https://typedoc.org/guides/doccomments) doc comments. You can manually build and
|
||||
host the API reference from the source files like this:
|
||||
|
||||
```
|
||||
$ pnpm gendoc
|
||||
$ cd docs
|
||||
$ python -m http.server 8005
|
||||
```
|
||||
|
||||
Then visit `http://localhost:8005` to see the API docs.
|
||||
|
||||
# End-to-end encryption support
|
||||
|
||||
`matrix-js-sdk`'s end-to-end encryption support is based on the [WebAssembly bindings](https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm) of the Rust [matrix-sdk-crypto](https://github.com/matrix-org/matrix-rust-sdk/tree/main/crates/matrix-sdk-crypto) library.
|
||||
|
||||
## Initialization
|
||||
|
||||
To initialize the end-to-end encryption support in the matrix client:
|
||||
|
||||
```javascript
|
||||
// Create a new matrix client
|
||||
const matrixClient = sdk.createClient({
|
||||
baseUrl: "http://localhost:8008",
|
||||
accessToken: myAccessToken,
|
||||
userId: myUserId,
|
||||
});
|
||||
|
||||
// Initialize to enable end-to-end encryption support.
|
||||
await matrixClient.initRustCrypto();
|
||||
```
|
||||
|
||||
Note that by default it will attempt to use the Indexed DB provided by the browser as a crypto store. If running outside the browser, you will need to pass [an options object](https://matrix-org.github.io/matrix-js-sdk/classes/matrix.MatrixClient.html#initrustcrypto) which includes `useIndexedDB: false`, to use an ephemeral in-memory store instead. Note that without a persistent store, you'll need to create a new device on the server side (with [`MatrixClient.loginRequest`](https://matrix-org.github.io/matrix-js-sdk/classes/matrix.MatrixClient.html#loginrequest)) each time your application starts.
|
||||
|
||||
After calling `initRustCrypto`, you can obtain a reference to the [`CryptoApi`](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto-api.CryptoApi.html) interface, which is the main entry point for end-to-end encryption, by calling [`MatrixClient.getCrypto`](https://matrix-org.github.io/matrix-js-sdk/classes/matrix.MatrixClient.html#getCrypto).
|
||||
|
||||
**WARNING**: the cryptography stack is not thread-safe. Having multiple `MatrixClient` instances connected to the same Indexed DB will cause data corruption and decryption failures. The application layer is responsible for ensuring that only one `MatrixClient` issue is instantiated at a time.
|
||||
|
||||
## Secret storage
|
||||
|
||||
You should normally set up [secret storage](https://spec.matrix.org/v1.12/client-server-api/#secret-storage) before using the end-to-end encryption. To do this, call [`CryptoApi.bootstrapSecretStorage`](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto_api.CryptoApi.html#bootstrapSecretStorage).
|
||||
`bootstrapSecretStorage` can be called unconditionally: it will only set up the secret storage if it is not already set up (unless you use the `setupNewSecretStorage` parameter).
|
||||
|
||||
```javascript
|
||||
const matrixClient = sdk.createClient({
|
||||
...,
|
||||
cryptoCallbacks: {
|
||||
getSecretStorageKey: async (keys) => {
|
||||
// This function should prompt the user to enter their secret storage key.
|
||||
return mySecretStorageKeys;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
matrixClient.getCrypto().bootstrapSecretStorage({
|
||||
// This function will be called if a new secret storage key (aka recovery key) is needed.
|
||||
// You should prompt the user to save the key somewhere, because they will need it to unlock secret storage in future.
|
||||
createSecretStorageKey: async () => {
|
||||
return mySecretStorageKey;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The example above will create a new secret storage key if secret storage was not previously set up.
|
||||
The secret storage data will be encrypted using the secret storage key returned in [`createSecretStorageKey`](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto_api.CreateSecretStorageOpts.html#createSecretStorageKey).
|
||||
|
||||
We recommend that you prompt the user to re-enter this key when [`CryptoCallbacks.getSecretStorageKey`](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto_api.CryptoCallbacks.html#getSecretStorageKey) is called (when the secret storage access is needed).
|
||||
|
||||
## Set up cross-signing
|
||||
|
||||
To set up cross-signing to verify devices and other users, call
|
||||
[`CryptoApi.bootstrapCrossSigning`](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto_api.CryptoApi.html#bootstrapCrossSigning):
|
||||
|
||||
```javascript
|
||||
matrixClient.getCrypto().bootstrapCrossSigning({
|
||||
authUploadDeviceSigningKeys: async (makeRequest) => {
|
||||
return makeRequest(authDict);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The [`authUploadDeviceSigningKeys`](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto_api.BootstrapCrossSigningOpts.html#authUploadDeviceSigningKeys)
|
||||
callback is required in order to upload newly-generated public cross-signing keys to the server.
|
||||
|
||||
## Key backup
|
||||
|
||||
If the user doesn't already have a [key backup](https://spec.matrix.org/v1.12/client-server-api/#server-side-key-backups) you should create one:
|
||||
|
||||
```javascript
|
||||
// Check if we have a key backup.
|
||||
// If checkKeyBackupAndEnable returns null, there is no key backup.
|
||||
const hasKeyBackup = (await matrixClient.getCrypto().checkKeyBackupAndEnable()) !== null;
|
||||
|
||||
// Create the key backup
|
||||
await matrixClient.getCrypto().resetKeyBackup();
|
||||
```
|
||||
|
||||
## Verify a new device
|
||||
|
||||
Once the cross-signing is set up on one of your devices, you can verify another device with two methods:
|
||||
|
||||
1. Use `CryptoApi.bootstrapCrossSigning`.
|
||||
|
||||
`bootstrapCrossSigning` will call the [CryptoCallbacks.getSecretStorageKey](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto_api.CryptoCallbacks.html#getSecretStorageKey) callback. The device is verified with the private cross-signing keys fetched from the secret storage.
|
||||
|
||||
2. Request an interactive verification against existing devices, by calling [CryptoApi.requestOwnUserVerification](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto_api.CryptoApi.html#requestOwnUserVerification).
|
||||
|
||||
## Migrating from the legacy crypto stack to Rust crypto
|
||||
|
||||
If your application previously used the legacy crypto stack, (i.e, it called `MatrixClient.initLegacyCrypto()`), you will
|
||||
need to migrate existing devices to the Rust crypto stack.
|
||||
|
||||
This migration happens automatically when you call `initRustCrypto()` instead of `initLegacyCrypto()`,
|
||||
but you need to provide the legacy [`cryptoStore`](https://matrix-org.github.io/matrix-js-sdk/interfaces/matrix.ICreateClientOpts.html#cryptoStore) and [`pickleKey`](https://matrix-org.github.io/matrix-js-sdk/interfaces/matrix.ICreateClientOpts.html#pickleKey) to [`createClient`](https://matrix-org.github.io/matrix-js-sdk/functions/matrix.createClient.html):
|
||||
|
||||
```javascript
|
||||
// You should provide the legacy crypto store and the pickle key to the matrix client in order to migrate the data.
|
||||
const matrixClient = sdk.createClient({
|
||||
cryptoStore: myCryptoStore,
|
||||
pickleKey: myPickleKey,
|
||||
baseUrl: "http://localhost:8008",
|
||||
accessToken: myAccessToken,
|
||||
userId: myUserId,
|
||||
});
|
||||
|
||||
// The migration will be done automatically when you call `initRustCrypto`.
|
||||
await matrixClient.initRustCrypto();
|
||||
```
|
||||
|
||||
To follow the migration progress, you can listen to the [`CryptoEvent.LegacyCryptoStoreMigrationProgress`](https://matrix-org.github.io/matrix-js-sdk/enums/crypto_api.CryptoEvent.html#LegacyCryptoStoreMigrationProgress) event:
|
||||
|
||||
```javascript
|
||||
// When progress === total === -1, the migration is finished.
|
||||
matrixClient.on(CryptoEvent.LegacyCryptoStoreMigrationProgress, (progress, total) => {
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
The Rust crypto stack is not supported in a lot of deprecated methods of [`MatrixClient`](https://matrix-org.github.io/matrix-js-sdk/classes/matrix.MatrixClient.html). If you use them, you should migrate to the [`CryptoApi`](https://matrix-org.github.io/matrix-js-sdk/interfaces/crypto_api.CryptoApi.html). Also, the legacy `MatrixClient.crypto` object is not available any more: you should use `MatrixClient.getCrypto()` instead.
|
||||
|
||||
# Contributing
|
||||
|
||||
_This section is for people who want to modify the SDK. If you just
|
||||
want to use this SDK, skip this section._
|
||||
|
||||
First, you need to pull in the right build tools:
|
||||
|
||||
```
|
||||
$ pnpm install
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To build a browser version from scratch when developing:
|
||||
|
||||
```
|
||||
$ pnpm build
|
||||
```
|
||||
|
||||
To run tests:
|
||||
|
||||
```
|
||||
$ pnpm test
|
||||
```
|
||||
|
||||
To run linting:
|
||||
|
||||
```
|
||||
$ pnpm lint
|
||||
```
|
||||
Reference in New Issue
Block a user