mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-22 22:29:30 +00:00
use the prebuild rust-sdk package
This commit is contained in:
@@ -1,3 +0,0 @@
|
|||||||
# uniffi-generated MatrixRTC SDK bindings, vendored by scripts/sync-matrix-rtc-sdk.sh
|
|
||||||
src/matrix-rtc-sdk/generated/** linguist-generated=true
|
|
||||||
src/matrix-rtc-sdk/generated/**/*.wasm binary
|
|
||||||
@@ -42,6 +42,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
node-version-file: ".node-version"
|
node-version-file: ".node-version"
|
||||||
|
- name: Authenticate to GitHub Packages
|
||||||
|
# The MatrixRTC SDK (@billcarsonfr/matrix-rtc, see .npmrc) is on the GitHub
|
||||||
|
# Packages npm registry, which needs a token with read:packages even for
|
||||||
|
# public packages. A workflow's GITHUB_TOKEN only reaches packages of its own
|
||||||
|
# repository, so this is a personal access token kept as a repository secret.
|
||||||
|
env:
|
||||||
|
NPM_REGISTRY_TOKEN: ${{ secrets.MATRIX_RTC_NPM_TOKEN }}
|
||||||
|
run: echo "//npm.pkg.github.com/:_authToken=${NPM_REGISTRY_TOKEN}" >> ~/.npmrc
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
||||||
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
||||||
|
|||||||
@@ -102,6 +102,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
node-version-file: ".node-version"
|
node-version-file: ".node-version"
|
||||||
|
- name: Authenticate to GitHub Packages
|
||||||
|
# The MatrixRTC SDK (@billcarsonfr/matrix-rtc, see .npmrc) is on the GitHub
|
||||||
|
# Packages npm registry, which needs a token with read:packages even for
|
||||||
|
# public packages. A workflow's GITHUB_TOKEN only reaches packages of its own
|
||||||
|
# repository, so this is a personal access token kept as a repository secret.
|
||||||
|
env:
|
||||||
|
NPM_REGISTRY_TOKEN: ${{ secrets.MATRIX_RTC_NPM_TOKEN }}
|
||||||
|
run: echo "//npm.pkg.github.com/:_authToken=${NPM_REGISTRY_TOKEN}" >> ~/.npmrc
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
||||||
- name: Build Storybook
|
- name: Build Storybook
|
||||||
|
|||||||
@@ -17,6 +17,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
node-version-file: ".node-version"
|
node-version-file: ".node-version"
|
||||||
|
- name: Authenticate to GitHub Packages
|
||||||
|
# The MatrixRTC SDK (@billcarsonfr/matrix-rtc, see .npmrc) is on the GitHub
|
||||||
|
# Packages npm registry, which needs a token with read:packages even for
|
||||||
|
# public packages. A workflow's GITHUB_TOKEN only reaches packages of its own
|
||||||
|
# repository, so this is a personal access token kept as a repository secret.
|
||||||
|
env:
|
||||||
|
NPM_REGISTRY_TOKEN: ${{ secrets.MATRIX_RTC_NPM_TOKEN }}
|
||||||
|
run: echo "//npm.pkg.github.com/:_authToken=${NPM_REGISTRY_TOKEN}" >> ~/.npmrc
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
||||||
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
||||||
|
|||||||
@@ -19,6 +19,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
node-version-file: ".node-version"
|
node-version-file: ".node-version"
|
||||||
|
- name: Authenticate to GitHub Packages
|
||||||
|
# The MatrixRTC SDK (@billcarsonfr/matrix-rtc, see .npmrc) is on the GitHub
|
||||||
|
# Packages npm registry, which needs a token with read:packages even for
|
||||||
|
# public packages. A workflow's GITHUB_TOKEN only reaches packages of its own
|
||||||
|
# repository, so this is a personal access token kept as a repository secret.
|
||||||
|
env:
|
||||||
|
NPM_REGISTRY_TOKEN: ${{ secrets.MATRIX_RTC_NPM_TOKEN }}
|
||||||
|
run: echo "//npm.pkg.github.com/:_authToken=${NPM_REGISTRY_TOKEN}" >> ~/.npmrc
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
||||||
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
||||||
@@ -65,6 +73,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
node-version-file: ".node-version"
|
node-version-file: ".node-version"
|
||||||
|
- name: Authenticate to GitHub Packages
|
||||||
|
# The MatrixRTC SDK (@billcarsonfr/matrix-rtc, see .npmrc) is on the GitHub
|
||||||
|
# Packages npm registry, which needs a token with read:packages even for
|
||||||
|
# public packages. A workflow's GITHUB_TOKEN only reaches packages of its own
|
||||||
|
# repository, so this is a personal access token kept as a repository secret.
|
||||||
|
env:
|
||||||
|
NPM_REGISTRY_TOKEN: ${{ secrets.MATRIX_RTC_NPM_TOKEN }}
|
||||||
|
run: echo "//npm.pkg.github.com/:_authToken=${NPM_REGISTRY_TOKEN}" >> ~/.npmrc
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
||||||
run: pnpm install --frozen-lockfile --ignore-pnpmfile
|
run: pnpm install --frozen-lockfile --ignore-pnpmfile
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ jobs:
|
|||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
node-version-file: ".node-version"
|
node-version-file: ".node-version"
|
||||||
|
|
||||||
|
- name: Authenticate to GitHub Packages
|
||||||
|
# The MatrixRTC SDK (@billcarsonfr/matrix-rtc, see .npmrc) is on the GitHub
|
||||||
|
# Packages npm registry, which needs a token with read:packages even for
|
||||||
|
# public packages. A workflow's GITHUB_TOKEN only reaches packages of its own
|
||||||
|
# repository, so this is a personal access token kept as a repository secret.
|
||||||
|
env:
|
||||||
|
NPM_REGISTRY_TOKEN: ${{ secrets.MATRIX_RTC_NPM_TOKEN }}
|
||||||
|
run: echo "//npm.pkg.github.com/:_authToken=${NPM_REGISTRY_TOKEN}" >> ~/.npmrc
|
||||||
- name: Install Deps
|
- name: Install Deps
|
||||||
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
# ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present)
|
||||||
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
run: "pnpm install --frozen-lockfile --ignore-pnpmfile"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# The MatrixRTC SDK (`@element-hq/matrix-rtc`, aliased in package.json to the
|
||||||
|
# name the fork's CI publishes it under) comes from the GitHub Packages npm
|
||||||
|
# registry, which needs a token with `read:packages` even for public
|
||||||
|
# packages. This is a stop-gap while the SDK is in flux; once it is published
|
||||||
|
# to npmjs.com this file and the alias go away (docs/matrix_rtc_sdk.md).
|
||||||
|
# Only the scope->registry mapping lives here; the token goes in your
|
||||||
|
# user-level npm config (~/.npmrc), never in this file. CI writes it there
|
||||||
|
# from a repository secret (see .github/workflows).
|
||||||
|
@billcarsonfr:registry=https://npm.pkg.github.com
|
||||||
+1
-6
@@ -2,10 +2,5 @@
|
|||||||
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||||
"printWidth": 80,
|
"printWidth": 80,
|
||||||
"sortPackageJson": false,
|
"sortPackageJson": false,
|
||||||
"ignorePatterns": [
|
"ignorePatterns": ["pnpm-lock.yaml", "node_modules", "dist"]
|
||||||
"pnpm-lock.yaml",
|
|
||||||
"node_modules",
|
|
||||||
"dist",
|
|
||||||
"src/matrix-rtc-sdk/generated"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,6 @@
|
|||||||
"env": {
|
"env": {
|
||||||
"builtin": true
|
"builtin": true
|
||||||
},
|
},
|
||||||
// uniffi-generated bindings and wasm-bindgen glue, vendored by
|
|
||||||
// scripts/sync-matrix-rtc-sdk.sh; not ours to lint
|
|
||||||
"ignorePatterns": ["src/matrix-rtc-sdk/generated/**"],
|
|
||||||
"rules": {
|
"rules": {
|
||||||
"element-call/copyright-header": [
|
"element-call/copyright-header": [
|
||||||
"error",
|
"error",
|
||||||
|
|||||||
@@ -206,6 +206,19 @@ corepack enable
|
|||||||
pnpm install
|
pnpm install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`pnpm install` currently needs a GitHub token: the MatrixRTC SDK
|
||||||
|
(`@element-hq/matrix-rtc`) is, as a stop-gap until it is published to npmjs.com,
|
||||||
|
an npm package on the GitHub Packages registry, which rejects anonymous
|
||||||
|
requests even for public packages. Create a classic personal access token with
|
||||||
|
the `read:packages` scope and add it to your user-level npm config once:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo "//npm.pkg.github.com/:_authToken=<your token>" >> ~/.npmrc
|
||||||
|
```
|
||||||
|
|
||||||
|
See [The MatrixRTC SDK package](./docs/matrix_rtc_sdk.md) for the details, CI
|
||||||
|
setup and developing against a local crate.
|
||||||
|
|
||||||
To use it, create a local config by, e.g.,
|
To use it, create a local config by, e.g.,
|
||||||
`cp ./config/config.devenv.json ./public/config.json` and adapt it if necessary.
|
`cp ./config/config.devenv.json ./public/config.json` and adapt it if necessary.
|
||||||
The `config.devenv.json` config should work with the backend development
|
The `config.devenv.json` config should work with the backend development
|
||||||
@@ -220,6 +233,7 @@ pnpm dev
|
|||||||
See also:
|
See also:
|
||||||
|
|
||||||
- [Developing with linked packages](./docs/linking.md)
|
- [Developing with linked packages](./docs/linking.md)
|
||||||
|
- [The MatrixRTC SDK package](./docs/matrix_rtc_sdk.md)
|
||||||
|
|
||||||
#### Element Call as a component (experimental)
|
#### Element Call as a component (experimental)
|
||||||
|
|
||||||
@@ -298,7 +312,9 @@ The package is not published yet. A host installs it as a git dependency on the
|
|||||||
|
|
||||||
whose `prepare` script runs the build on install. That build needs pnpm (via
|
whose `prepare` script runs the build on install. That build needs pnpm (via
|
||||||
Corepack) on the host's machine, runs a full `pnpm install` of this repository
|
Corepack) on the host's machine, runs a full `pnpm install` of this repository
|
||||||
and is memory-hungry, since it inherits the `--max-old-space-size` setting of
|
(so the host needs the GitHub Packages token described in
|
||||||
|
[The MatrixRTC SDK package](./docs/matrix_rtc_sdk.md) as well) and is
|
||||||
|
memory-hungry, since it inherits the `--max-old-space-size` setting of
|
||||||
the app build; the host's pnpm also has to allow it to run at all
|
the app build; the host's pnpm also has to allow it to run at all
|
||||||
(`allowBuilds` in its `pnpm-workspace.yaml`). Note that `component/` is a pnpm
|
(`allowBuilds` in its `pnpm-workspace.yaml`). Note that `component/` is a pnpm
|
||||||
project of its own for this reason, so pnpm commands run from inside that
|
project of its own for this reason, so pnpm commands run from inside that
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ This folder contains documentation for setup, usage, and development of Element
|
|||||||
- [MatrixRTC modes](./matrix_rtc_modes.md)
|
- [MatrixRTC modes](./matrix_rtc_modes.md)
|
||||||
- [Self-Hosting](./self_hosting.md)
|
- [Self-Hosting](./self_hosting.md)
|
||||||
- [Developing with linked packages](./linking.md)
|
- [Developing with linked packages](./linking.md)
|
||||||
|
- [The MatrixRTC SDK package](./matrix_rtc_sdk.md) (registry token, CI, local crate)
|
||||||
|
|
||||||
### Writing code for Element Call (agent-readable conventions)
|
### Writing code for Element Call (agent-readable conventions)
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ Instead, create a file named `.links.cjs` in the Element Call project directory
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
"matrix-js-sdk": "../your/path/matrix-js-sdk",
|
"matrix-js-sdk": "../your/path/matrix-js-sdk",
|
||||||
"matrix-widget-api": "../your/path/matrix-widget-api",
|
"matrix-widget-api": "../your/path/matrix-widget-api",
|
||||||
|
// The MatrixRTC SDK: run `npm run build` in that directory first
|
||||||
|
"@element-hq/matrix-rtc":
|
||||||
|
"../your/path/matrix-rust-rtc/MatrixSdkArchitectureDraft/web-test-app",
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
# The MatrixRTC SDK package
|
||||||
|
|
||||||
|
Element Call's MatrixRTC logic (session membership, keep-alive, transport
|
||||||
|
tokens, media key exchange) runs in the Rust `matrix-rtc` crate, compiled to
|
||||||
|
WebAssembly and shipped as the npm package `@element-hq/matrix-rtc`. The
|
||||||
|
package is built and published by the
|
||||||
|
[`npm-web-bindings.yml`](https://github.com/element-hq/matrix-rust-rtc/blob/main/.github/workflows/npm-web-bindings.yml)
|
||||||
|
workflow of the `matrix-rust-rtc` repository, from its
|
||||||
|
`MatrixSdkArchitectureDraft/web-test-app` directory. Element Call loads it in
|
||||||
|
`src/matrix-rtc-sdk/index.ts`, the only module that imports the package
|
||||||
|
directly.
|
||||||
|
|
||||||
|
## Where the package comes from
|
||||||
|
|
||||||
|
For now the package lives on the **GitHub Packages** npm registry
|
||||||
|
(`https://npm.pkg.github.com`), not on npmjs.com. **This is a stop-gap** for
|
||||||
|
the phase in which the crate's API still changes with every push: publishing
|
||||||
|
from the crate's CI into a registry that comes with the repository needs no
|
||||||
|
account or secret upstream, and nothing else consumes the package yet. Once
|
||||||
|
the SDK is ready for consumers beyond Element Call, it should be published to
|
||||||
|
**npmjs.com** as `@element-hq/matrix-rtc`, which makes everything in this
|
||||||
|
document about tokens and scopes go away: `pnpm install` works anonymously
|
||||||
|
again, forks and Renovate can install, component hosts need no setup, and the
|
||||||
|
alias in `package.json` and the scope line in `.npmrc` are deleted.
|
||||||
|
|
||||||
|
Until then, two properties of GitHub Packages shape the setup below:
|
||||||
|
|
||||||
|
- **Every request needs a token**, including reads of public packages. There
|
||||||
|
is no anonymous install.
|
||||||
|
- **A package is scoped to the owner of the repository whose CI published
|
||||||
|
it.** While the crate is developed on the `BillCarsonFr` fork, the package is
|
||||||
|
published as `@billcarsonfr/matrix-rtc`; once it is published from
|
||||||
|
`element-hq/matrix-rust-rtc` it becomes `@element-hq/matrix-rtc`.
|
||||||
|
|
||||||
|
So that the code does not have to change when that happens, `package.json`
|
||||||
|
installs the fork's package under the final name:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"@element-hq/matrix-rtc": "npm:@billcarsonfr/matrix-rtc@next"
|
||||||
|
```
|
||||||
|
|
||||||
|
and the repository's `.npmrc` maps only the scope to the registry:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
@billcarsonfr:registry=https://npm.pkg.github.com
|
||||||
|
```
|
||||||
|
|
||||||
|
When the package moves to `element-hq`, change the alias to the plain package
|
||||||
|
and the scope line in `.npmrc` accordingly; nothing else in the repository
|
||||||
|
refers to the fork's name.
|
||||||
|
|
||||||
|
## Setting up your machine
|
||||||
|
|
||||||
|
1. Create a **personal access token (classic)** at
|
||||||
|
<https://github.com/settings/tokens> with only the `read:packages` scope.
|
||||||
|
Fine-grained tokens do not work with GitHub Packages.
|
||||||
|
2. Add it to your **user-level** npm config. Never put it in the repository's
|
||||||
|
`.npmrc`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo "//npm.pkg.github.com/:_authToken=<your token>" >> ~/.npmrc
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run `pnpm install` as usual.
|
||||||
|
|
||||||
|
Without the token, `pnpm install` fails while resolving
|
||||||
|
`@billcarsonfr/matrix-rtc` with a `401` or `404` from `npm.pkg.github.com`;
|
||||||
|
that error always means "no or wrong token", never "the package does not
|
||||||
|
exist".
|
||||||
|
|
||||||
|
## CI and other consumers
|
||||||
|
|
||||||
|
A workflow's built-in `GITHUB_TOKEN` can only read packages owned by the
|
||||||
|
repository's own owner, so element-hq's workflows cannot read a package owned
|
||||||
|
by the `BillCarsonFr` user. The workflows that run `pnpm install` therefore
|
||||||
|
write a personal access token from the repository secret
|
||||||
|
`MATRIX_RTC_NPM_TOKEN` (scope `read:packages`) to `~/.npmrc` before installing.
|
||||||
|
Keep in mind:
|
||||||
|
|
||||||
|
- **Pull requests from forks and from Renovate do not receive secrets**, so
|
||||||
|
their installs fail until the package is readable with the built-in token.
|
||||||
|
- **Hosts of the [component](../README.md#element-call-as-a-component-experimental)**
|
||||||
|
install it as a git dependency whose `prepare` script runs
|
||||||
|
`pnpm install --frozen-lockfile` in this repository, so they need the same
|
||||||
|
token in their `~/.npmrc` or CI.
|
||||||
|
|
||||||
|
Publishing from `element-hq/matrix-rust-rtc` (and granting the Element Call
|
||||||
|
repository access to the package) would let the built-in token work for
|
||||||
|
element-hq's own workflows, but that only patches the CI case. The intended end
|
||||||
|
state is the npmjs.com publication described above, which removes the token
|
||||||
|
requirement for everyone.
|
||||||
|
|
||||||
|
## Versions
|
||||||
|
|
||||||
|
The package version tracks the crate's `Cargo.toml`. Every push to the tracked
|
||||||
|
branches of `matrix-rust-rtc` publishes a `next` pre-release named
|
||||||
|
`<version>-next.<run number>.<short sha>`, and a `matrix-rtc-v<version>` tag
|
||||||
|
publishes `latest`. Element Call follows `next`; `pnpm install` picks up a new
|
||||||
|
pre-release only when the lockfile is updated, e.g. with
|
||||||
|
`pnpm update @element-hq/matrix-rtc`.
|
||||||
|
|
||||||
|
The publish job runs only after the crate's own `cargo test` job passed on a
|
||||||
|
_push_ (pull-request runs never publish). If a `next` build you expect is
|
||||||
|
missing, check that workflow's push runs for a failed crate job and re-run it;
|
||||||
|
its tests are known to be timing-sensitive.
|
||||||
|
|
||||||
|
## Developing against a local crate checkout
|
||||||
|
|
||||||
|
To run Element Call against a crate you are changing, build the package there
|
||||||
|
and link it, instead of waiting for CI:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd ../matrix-rust-rtc/MatrixSdkArchitectureDraft/web-test-app
|
||||||
|
npm install && npm run build # produces dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
then add it to `.links.cjs` in this repository and run `pnpm links:on`, as
|
||||||
|
described in [Developing with linked packages](./linking.md):
|
||||||
|
|
||||||
|
```cjs
|
||||||
|
"@element-hq/matrix-rtc": "../matrix-rust-rtc/MatrixSdkArchitectureDraft/web-test-app",
|
||||||
|
```
|
||||||
|
|
||||||
|
`pnpm links:off` restores the registry package before committing.
|
||||||
|
|
||||||
|
## How the wasm is loaded
|
||||||
|
|
||||||
|
`initMatrixRtcSdk()` in `src/matrix-rtc-sdk/index.ts` is the single entry
|
||||||
|
point: it awaits the package's `initAsync`, then installs the log sink that
|
||||||
|
routes the crate's logs into Element Call's logger. The wasm is imported as
|
||||||
|
`@element-hq/matrix-rtc/wasm?url`, so the app builds emit it as an asset next
|
||||||
|
to the other `.wasm` files and the component build inlines it. Unit tests read
|
||||||
|
the bytes from the installed package instead (`src/utils/test-matrix-rtc.ts`),
|
||||||
|
since vitest has no server to fetch from. A component host can point at a copy
|
||||||
|
it serves itself through `initializeElementCall(config, { matrixRtcWasm })`.
|
||||||
@@ -59,8 +59,9 @@ files it touches are listed there.
|
|||||||
`src/utils/logger.ts` (S6) so a later swap is one line.
|
`src/utils/logger.ts` (S6) so a later swap is one line.
|
||||||
- Writing a matrix-rust-sdk-backed driver (Element X). The interface is shaped
|
- Writing a matrix-rust-sdk-backed driver (Element X). The interface is shaped
|
||||||
so one can be written; none is written here.
|
so one can be written; none is written here.
|
||||||
- Publishing the crate as an npm package. Until it exists, the generated
|
- Publishing the crate as an npm package: done upstream (`@element-hq/matrix-rtc`,
|
||||||
bindings are vendored (§5.1).
|
built and published by `npm-web-bindings.yml` in matrix-rust-rtc; consumed
|
||||||
|
here since 2026-09-16, §5.1).
|
||||||
- Turning on MSC4153 (cross-signed sender) enforcement. Parity first (§5.8).
|
- Turning on MSC4153 (cross-signed sender) enforcement. Parity first (§5.8).
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -501,13 +502,24 @@ RateLimited`, 403 → `Rejected`, 404/`M_UNRECOGNIZED` → `Unsupported`.
|
|||||||
|
|
||||||
## 5. Decisions and assumptions
|
## 5. Decisions and assumptions
|
||||||
|
|
||||||
1. **Vendored bindings.** `src/matrix-rtc-sdk/generated/` holds `matrix_rtc.ts`,
|
1. **The SDK is an npm package.** `@element-hq/matrix-rtc` (the draft's
|
||||||
`matrix_rtc-ffi.ts`, `wasm-bindgen/index.js`, `index_bg.wasm` and a
|
`web-test-app/`, built by `npm-web-bindings.yml`: uniffi bindings, the
|
||||||
hand-written `wasm-bindgen/index.d.ts` (no `allowJs` in `tsconfig.json`),
|
wasm-bindgen glue, a `wasm-opt`'d ~760 KB wasm, `.d.ts`, and `@ubjs/core`
|
||||||
synced by `scripts/sync-matrix-rtc-sdk.sh` (runs `ubrn build web` in the
|
as its own dependency) is a devDependency, aliased in `package.json` to
|
||||||
draft **without** the `runtime-probe` feature, copies). Committed so CI
|
`@billcarsonfr/matrix-rtc@next` while it is published from the fork, so
|
||||||
works. `@ubjs/core` becomes a dependency. The wasm is ~6.5 MB unoptimised.
|
the imports already say `@element-hq/matrix-rtc`. It lives on the GitHub
|
||||||
**Assumption:** committing the binary is acceptable for the draft phase.
|
Packages registry: `.npmrc` maps the scope, a `read:packages` token goes
|
||||||
|
in `~/.npmrc` (CI: the `MATRIX_RTC_NPM_TOKEN` secret). **The GitHub
|
||||||
|
Packages registry is a stop-gap** for the phase in which the crate's API
|
||||||
|
moves with every push; once the SDK is ready for consumers beyond Element
|
||||||
|
Call it belongs on npmjs.com as `@element-hq/matrix-rtc`, which drops the
|
||||||
|
alias, `.npmrc`, the CI secret and every token requirement
|
||||||
|
(`docs/matrix_rtc_sdk.md`). `src/matrix-rtc-sdk/`
|
||||||
|
keeps only the loader (`initMatrixRtcSdk`: package `initAsync` + our log
|
||||||
|
sink, wasm via `@element-hq/matrix-rtc/wasm?url`) and the curated
|
||||||
|
re-exports. _History:_ until 2026-09-16 the bindings were vendored under
|
||||||
|
`src/matrix-rtc-sdk/generated/` by `scripts/sync-matrix-rtc-sdk.sh`; local
|
||||||
|
crate work now goes through `pnpm links:on` (`docs/linking.md`).
|
||||||
2. **Wasm loading.** Verified: Vite 8 library mode inlines `?url` and
|
2. **Wasm loading.** Verified: Vite 8 library mode inlines `?url` and
|
||||||
`new URL(…, import.meta.url)` assets as base64 regardless of
|
`new URL(…, import.meta.url)` assets as base64 regardless of
|
||||||
`assetsInlineLimit`; `?url&no-inline` emits a file. App builds use `?url`;
|
`assetsInlineLimit`; `?url&no-inline` emits a file. App builds use `?url`;
|
||||||
@@ -599,12 +611,14 @@ Gate: `cargo test --features uniffi`, `cargo clippy --all-targets --features uni
|
|||||||
|
|
||||||
### S0b — SDK intake ☑
|
### S0b — SDK intake ☑
|
||||||
|
|
||||||
- `scripts/sync-matrix-rtc-sdk.sh`, `src/matrix-rtc-sdk/generated/**`,
|
- ~~`scripts/sync-matrix-rtc-sdk.sh`, `src/matrix-rtc-sdk/generated/**`~~
|
||||||
|
(replaced by the `@element-hq/matrix-rtc` package on 2026-09-16, §5.1),
|
||||||
`src/matrix-rtc-sdk/index.ts` (loader + curated re-exports),
|
`src/matrix-rtc-sdk/index.ts` (loader + curated re-exports),
|
||||||
`src/matrix-rtc-sdk/index.test.ts` (boot, one join round-trip against the
|
`src/matrix-rtc-sdk/index.test.ts` (boot, one join round-trip against the
|
||||||
TS mock driver).
|
TS mock driver).
|
||||||
- `package.json` (`@ubjs/core`), `knip.ts` (`ignore` for `generated/**`),
|
- `package.json` (~~`@ubjs/core`~~ now `@element-hq/matrix-rtc`; the
|
||||||
`.oxlintrc.json` `ignorePatterns`, `.oxfmtrc.json` ignore,
|
`generated/**` carve-outs in `knip.ts`, `.oxlintrc.json`, `.oxfmtrc.json`,
|
||||||
|
`vitest.config.ts` and `.gitattributes` went with the vendored files),
|
||||||
`vite.config.ts` (nothing needed for `?url`; verified `vite-plugin-wasm`
|
`vite.config.ts` (nothing needed for `?url`; verified `vite-plugin-wasm`
|
||||||
ignores it), `tsconfig.json` untouched thanks to the `.d.ts`.
|
ignores it), `tsconfig.json` untouched thanks to the `.d.ts`.
|
||||||
- Gate: `pnpm lint && pnpm format:check && pnpm test:unit`.
|
- Gate: `pnpm lint && pnpm format:check && pnpm test:unit`.
|
||||||
|
|||||||
@@ -26,10 +26,7 @@ export default {
|
|||||||
// This is a shell built-in.
|
// This is a shell built-in.
|
||||||
"printf",
|
"printf",
|
||||||
],
|
],
|
||||||
// uniffi-generated bindings (scripts/sync-matrix-rtc-sdk.sh): every
|
|
||||||
// export the crate has, most of them unused here by design
|
|
||||||
ignore: [
|
ignore: [
|
||||||
"src/matrix-rtc-sdk/generated/**",
|
|
||||||
// The host-facing driver seam, landed ahead of its consumers (the
|
// The host-facing driver seam, landed ahead of its consumers (the
|
||||||
// `CallParticipation` layer and the hosts, see element-call-oxidation-plan.md)
|
// `CallParticipation` layer and the hosts, see element-call-oxidation-plan.md)
|
||||||
"src/driver/**",
|
"src/driver/**",
|
||||||
|
|||||||
+1
-1
@@ -48,6 +48,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@codecov/vite-plugin": "^1.3.0",
|
"@codecov/vite-plugin": "^1.3.0",
|
||||||
|
"@element-hq/matrix-rtc": "npm:@billcarsonfr/matrix-rtc@next",
|
||||||
"@fontsource/inconsolata": "^5.1.0",
|
"@fontsource/inconsolata": "^5.1.0",
|
||||||
"@fontsource/inter": "^5.1.0",
|
"@fontsource/inter": "^5.1.0",
|
||||||
"@formatjs/intl-durationformat": "^0.10.0",
|
"@formatjs/intl-durationformat": "^0.10.0",
|
||||||
@@ -82,7 +83,6 @@
|
|||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
"@types/sdp-transform": "^2.4.5",
|
"@types/sdp-transform": "^2.4.5",
|
||||||
"@typescript-eslint/utils": "^8.61.0",
|
"@typescript-eslint/utils": "^8.61.0",
|
||||||
"@ubjs/core": "0.31.0-5",
|
|
||||||
"@use-gesture/react": "^10.2.11",
|
"@use-gesture/react": "^10.2.11",
|
||||||
"@vector-im/compound-design-tokens": "^10.0.0",
|
"@vector-im/compound-design-tokens": "^10.0.0",
|
||||||
"@vector-im/compound-web": "^10.0.0",
|
"@vector-im/compound-web": "^10.0.0",
|
||||||
|
|||||||
Generated
+15
-3
@@ -25,6 +25,9 @@ importers:
|
|||||||
'@codecov/vite-plugin':
|
'@codecov/vite-plugin':
|
||||||
specifier: ^1.3.0
|
specifier: ^1.3.0
|
||||||
version: 1.9.1(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(sass@1.103.1)(terser@5.46.1)(yaml@2.9.0))
|
version: 1.9.1(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(sass@1.103.1)(terser@5.46.1)(yaml@2.9.0))
|
||||||
|
'@element-hq/matrix-rtc':
|
||||||
|
specifier: npm:@billcarsonfr/matrix-rtc@next
|
||||||
|
version: '@billcarsonfr/matrix-rtc@0.1.0-next.7.c5a5a80(matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/24929be0e741be6a5d0a7226f1c682e245263b8a)'
|
||||||
'@fontsource/inconsolata':
|
'@fontsource/inconsolata':
|
||||||
specifier: ^5.1.0
|
specifier: ^5.1.0
|
||||||
version: 5.3.0
|
version: 5.3.0
|
||||||
@@ -127,9 +130,6 @@ importers:
|
|||||||
'@typescript-eslint/utils':
|
'@typescript-eslint/utils':
|
||||||
specifier: ^8.61.0
|
specifier: ^8.61.0
|
||||||
version: 8.69.0(eslint@8.57.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
version: 8.69.0(eslint@8.57.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||||
'@ubjs/core':
|
|
||||||
specifier: 0.31.0-5
|
|
||||||
version: 0.31.0-5
|
|
||||||
'@use-gesture/react':
|
'@use-gesture/react':
|
||||||
specifier: ^10.2.11
|
specifier: ^10.2.11
|
||||||
version: 10.3.1(react@19.2.8)
|
version: 10.3.1(react@19.2.8)
|
||||||
@@ -412,6 +412,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
|
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@billcarsonfr/matrix-rtc@0.1.0-next.7.c5a5a80':
|
||||||
|
resolution: {integrity: sha512-6Ti4jQZahHPI2Y9F/6dUplSEvoDdWP0OTLJXFUe708YFa13nRwW3t7QoRRbsSB5O0eWQHwu9hHVJQHEjpx4EwA==, tarball: https://npm.pkg.github.com/download/@billcarsonfr/matrix-rtc/0.1.0-next.7.c5a5a80/55919d699c12752b2316ad6d97a00c4b78088057}
|
||||||
|
version: 0.1.0-next.7.c5a5a80
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
peerDependencies:
|
||||||
|
matrix-js-sdk: '>=42'
|
||||||
|
|
||||||
'@blazediff/core@1.9.1':
|
'@blazediff/core@1.9.1':
|
||||||
resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==}
|
resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==}
|
||||||
|
|
||||||
@@ -6365,6 +6372,11 @@ snapshots:
|
|||||||
|
|
||||||
'@bcoe/v8-coverage@1.0.2': {}
|
'@bcoe/v8-coverage@1.0.2': {}
|
||||||
|
|
||||||
|
'@billcarsonfr/matrix-rtc@0.1.0-next.7.c5a5a80(matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/24929be0e741be6a5d0a7226f1c682e245263b8a)':
|
||||||
|
dependencies:
|
||||||
|
'@ubjs/core': 0.31.0-5
|
||||||
|
matrix-js-sdk: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/24929be0e741be6a5d0a7226f1c682e245263b8a
|
||||||
|
|
||||||
'@blazediff/core@1.9.1': {}
|
'@blazediff/core@1.9.1': {}
|
||||||
|
|
||||||
'@bufbuild/protobuf@1.10.1': {}
|
'@bufbuild/protobuf@1.10.1': {}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ supportedArchitectures:
|
|||||||
cpu: [current, arm64]
|
cpu: [current, arm64]
|
||||||
libc: [current, glibc]
|
libc: [current, glibc]
|
||||||
minimumReleaseAgeExclude:
|
minimumReleaseAgeExclude:
|
||||||
|
# The MatrixRTC SDK is consumed as `next` pre-releases straight from its CI
|
||||||
|
- "@billcarsonfr/matrix-rtc"
|
||||||
- "@vector-im/compound-design-tokens"
|
- "@vector-im/compound-design-tokens"
|
||||||
- "@vector-im/compound-web"
|
- "@vector-im/compound-web"
|
||||||
- matrix-js-sdk
|
- matrix-js-sdk
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Copyright 2026 Element Creations Ltd.
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
# Please see LICENSE in the repository root for full details.
|
|
||||||
#
|
|
||||||
# Vendors the matrix-rtc crate's uniffi web bindings into
|
|
||||||
# src/matrix-rtc-sdk/generated/. Until the crate ships as an npm package this
|
|
||||||
# is how Element Call picks up a new build of it: build it there, copy the
|
|
||||||
# generated TypeScript, the wasm-bindgen glue and the wasm here.
|
|
||||||
#
|
|
||||||
# scripts/sync-matrix-rtc-sdk.sh [path-to-MatrixSdkArchitectureDraft] [--no-build]
|
|
||||||
#
|
|
||||||
# The build uses web-test-app/ubrn.element-call.config.yaml (feature `uniffi`
|
|
||||||
# only, release profile, its own output directory so the app's test build is
|
|
||||||
# left alone). Pass --no-build to copy whatever was built last.
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
DRAFT="${1:-../matrix-rust-rtc/MatrixSdkArchitectureDraft}"
|
|
||||||
BUILD=1
|
|
||||||
for arg in "$@"; do
|
|
||||||
[[ "$arg" == "--no-build" ]] && BUILD=0
|
|
||||||
done
|
|
||||||
|
|
||||||
APP="$DRAFT/web-test-app"
|
|
||||||
GENERATED="$APP/src/generated-element-call"
|
|
||||||
DEST="$(cd "$(dirname "$0")/.." && pwd)/src/matrix-rtc-sdk/generated"
|
|
||||||
|
|
||||||
if [[ ! -f "$APP/ubrn.element-call.config.yaml" ]]; then
|
|
||||||
echo "No web-test-app/ubrn.element-call.config.yaml under $DRAFT" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$BUILD" == 1 ]]; then
|
|
||||||
(cd "$APP" && npx ubrn build web --config ubrn.element-call.config.yaml --release)
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$DEST/wasm-bindgen"
|
|
||||||
cp "$GENERATED/matrix_rtc.ts" "$GENERATED/matrix_rtc-ffi.ts" "$DEST/"
|
|
||||||
cp "$GENERATED/wasm-bindgen/index.js" "$GENERATED/wasm-bindgen/index_bg.wasm" "$DEST/wasm-bindgen/"
|
|
||||||
|
|
||||||
REV="$(git -C "$DRAFT" rev-parse --short HEAD 2>/dev/null || echo unknown)"
|
|
||||||
DIRTY="$(git -C "$DRAFT" status --porcelain 2>/dev/null | grep -q . && echo '-dirty' || true)"
|
|
||||||
cat > "$DEST/VERSION" <<VERSION
|
|
||||||
matrix-rtc (MatrixSdkArchitectureDraft) ${REV}${DIRTY}
|
|
||||||
built $(date -u +%Y-%m-%dT%H:%M:%SZ) by scripts/sync-matrix-rtc-sdk.sh
|
|
||||||
VERSION
|
|
||||||
|
|
||||||
echo "Synced matrix-rtc bindings from $DRAFT ($REV$DIRTY) into $DEST"
|
|
||||||
ls -la "$DEST" "$DEST/wasm-bindgen"
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
matrix-rtc (MatrixSdkArchitectureDraft) 61140bc-dirty
|
|
||||||
built 2026-09-16T12:10:06Z by scripts/sync-matrix-rtc-sdk.sh
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
// This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate.
|
|
||||||
// Trust me, you don't want to mess with it!
|
|
||||||
|
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
// @ts-nocheck
|
|
||||||
|
|
||||||
// Structs and function types for calling back into Typescript from Rust.
|
|
||||||
export type UniffiRustFutureContinuationCallback = (data: bigint, pollResult: number) => void;
|
|
||||||
export type UniffiForeignFutureDroppedCallback = (handle: bigint) => void;
|
|
||||||
export type UniffiForeignFutureDroppedCallbackStruct = {
|
|
||||||
handle: bigint;
|
|
||||||
free: UniffiForeignFutureDroppedCallback;
|
|
||||||
};
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcConnectionsListenerMethod0 = (uniffiHandle: bigint, connections: Uint8Array) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceCloneMatrixRtcConnectionsListener = (handle: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceFreeMatrixRtcConnectionsListener = (handle: bigint) => void;
|
|
||||||
export type UniffiVTableCallbackInterfaceMatrixRtcConnectionsListener = {
|
|
||||||
uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcConnectionsListener;
|
|
||||||
uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcConnectionsListener;
|
|
||||||
on_connections_change: UniffiCallbackInterfaceMatrixRtcConnectionsListenerMethod0;
|
|
||||||
};
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcKeyMapListenerMethod0 = (uniffiHandle: bigint, keyMap: Uint8Array, change: Uint8Array) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceCloneMatrixRtcKeyMapListener = (handle: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceFreeMatrixRtcKeyMapListener = (handle: bigint) => void;
|
|
||||||
export type UniffiVTableCallbackInterfaceMatrixRtcKeyMapListener = {
|
|
||||||
uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcKeyMapListener;
|
|
||||||
uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcKeyMapListener;
|
|
||||||
on_key_map_change: UniffiCallbackInterfaceMatrixRtcKeyMapListenerMethod0;
|
|
||||||
};
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcKeyRejectedListenerMethod0 = (uniffiHandle: bigint, memberId: Uint8Array, reason: Uint8Array) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceCloneMatrixRtcKeyRejectedListener = (handle: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceFreeMatrixRtcKeyRejectedListener = (handle: bigint) => void;
|
|
||||||
export type UniffiVTableCallbackInterfaceMatrixRtcKeyRejectedListener = {
|
|
||||||
uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcKeyRejectedListener;
|
|
||||||
uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcKeyRejectedListener;
|
|
||||||
on_key_rejected: UniffiCallbackInterfaceMatrixRtcKeyRejectedListenerMethod0;
|
|
||||||
};
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcLogSinkMethod0 = (uniffiHandle: bigint, level: Uint8Array, target: Uint8Array, message: Uint8Array) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceCloneMatrixRtcLogSink = (handle: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceFreeMatrixRtcLogSink = (handle: bigint) => void;
|
|
||||||
export type UniffiVTableCallbackInterfaceMatrixRtcLogSink = {
|
|
||||||
uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcLogSink;
|
|
||||||
uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcLogSink;
|
|
||||||
log: UniffiCallbackInterfaceMatrixRtcLogSinkMethod0;
|
|
||||||
};
|
|
||||||
export type UniffiForeignFutureResultRustBuffer = {
|
|
||||||
return_value: Uint8Array;
|
|
||||||
call_status: UniffiRustCallStatus;
|
|
||||||
};
|
|
||||||
export type UniffiForeignFutureCompleterustBuffer = (callbackData: bigint, result: UniffiForeignFutureResultRustBuffer) => void;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod0 = (uniffiHandle: bigint, roomId: Uint8Array, eventType: Uint8Array, contentJson: Uint8Array, durationMs: bigint, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod1 = (uniffiHandle: bigint, roomId: Uint8Array, eventType: Uint8Array, stateKey: Uint8Array, contentJson: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod2 = (uniffiHandle: bigint, roomId: Uint8Array, eventType: Uint8Array, contentJson: Uint8Array, delayMs: bigint, stickyDurationMs: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod3 = (uniffiHandle: bigint, roomId: Uint8Array, eventType: Uint8Array, stateKey: Uint8Array, contentJson: Uint8Array, delayMs: bigint, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
export type UniffiForeignFutureResultVoid = {
|
|
||||||
call_status: UniffiRustCallStatus;
|
|
||||||
};
|
|
||||||
export type UniffiForeignFutureCompletevoid = (callbackData: bigint, result: UniffiForeignFutureResultVoid) => void;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod4 = (uniffiHandle: bigint, roomId: Uint8Array, delayId: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompletevoid, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod5 = (uniffiHandle: bigint, roomId: Uint8Array, delayId: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompletevoid, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod6 = (uniffiHandle: bigint, request: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompletevoid, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod7 = (uniffiHandle: bigint, request: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompletevoid, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod8 = (uniffiHandle: bigint, recipients: Uint8Array, eventType: Uint8Array, contentJson: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod9 = (uniffiHandle: bigint, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod10 = (uniffiHandle: bigint, request: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod11 = (uniffiHandle: bigint, eventType: Uint8Array, stateKey: Uint8Array, limit: number, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod12 = (uniffiHandle: bigint, eventType: Uint8Array, stateKey: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod13 = (uniffiHandle: bigint, sink: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod14 = (uniffiHandle: bigint, sink: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod15 = (uniffiHandle: bigint, sink: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod16 = (uniffiHandle: bigint) => number;
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod17 = (uniffiHandle: bigint, sink: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceCloneMatrixRtcMatrixDriverCallback = (handle: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceFreeMatrixRtcMatrixDriverCallback = (handle: bigint) => void;
|
|
||||||
export type UniffiVTableCallbackInterfaceMatrixRtcMatrixDriverCallback = {
|
|
||||||
uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcMatrixDriverCallback;
|
|
||||||
uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcMatrixDriverCallback;
|
|
||||||
send_sticky_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod0;
|
|
||||||
send_state_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod1;
|
|
||||||
send_delayed_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod2;
|
|
||||||
send_delayed_state_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod3;
|
|
||||||
restart_delayed_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod4;
|
|
||||||
cancel_delayed_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod5;
|
|
||||||
delegate_delayed_leave_via_homeserver: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod6;
|
|
||||||
delegate_delayed_leave_via_transport: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod7;
|
|
||||||
send_to_device: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod8;
|
|
||||||
get_rtc_transports: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod9;
|
|
||||||
get_livekit_token: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod10;
|
|
||||||
read_events: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod11;
|
|
||||||
read_state: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod12;
|
|
||||||
subscribe_room_events: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod13;
|
|
||||||
subscribe_to_device_events: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod14;
|
|
||||||
subscribe_state_updates: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod15;
|
|
||||||
is_homeserver_connected: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod16;
|
|
||||||
subscribe_connectivity: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod17;
|
|
||||||
};
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcMembershipsListenerMethod0 = (uniffiHandle: bigint, memberships: Uint8Array) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceCloneMatrixRtcMembershipsListener = (handle: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceFreeMatrixRtcMembershipsListener = (handle: bigint) => void;
|
|
||||||
export type UniffiVTableCallbackInterfaceMatrixRtcMembershipsListener = {
|
|
||||||
uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcMembershipsListener;
|
|
||||||
uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcMembershipsListener;
|
|
||||||
on_memberships_change: UniffiCallbackInterfaceMatrixRtcMembershipsListenerMethod0;
|
|
||||||
};
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcSessionListenerMethod0 = (uniffiHandle: bigint, session: Uint8Array) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceCloneMatrixRtcSessionListener = (handle: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceFreeMatrixRtcSessionListener = (handle: bigint) => void;
|
|
||||||
export type UniffiVTableCallbackInterfaceMatrixRtcSessionListener = {
|
|
||||||
uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcSessionListener;
|
|
||||||
uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcSessionListener;
|
|
||||||
on_session_change: UniffiCallbackInterfaceMatrixRtcSessionListenerMethod0;
|
|
||||||
};
|
|
||||||
type UniffiCallbackInterfaceMatrixRtcStatusListenerMethod0 = (uniffiHandle: bigint, status: Uint8Array) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceCloneMatrixRtcStatusListener = (handle: bigint) => UniffiResult<void>;
|
|
||||||
type UniffiCallbackInterfaceFreeMatrixRtcStatusListener = (handle: bigint) => void;
|
|
||||||
export type UniffiVTableCallbackInterfaceMatrixRtcStatusListener = {
|
|
||||||
uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcStatusListener;
|
|
||||||
uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcStatusListener;
|
|
||||||
on_status_change: UniffiCallbackInterfaceMatrixRtcStatusListenerMethod0;
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2026 Element Creations Ltd.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Hand-written declaration for the wasm-bindgen glue next to it, which ubrn
|
|
||||||
// emits as plain JavaScript. Only the loading entry points are declared; the
|
|
||||||
// exported `ubrn_*` FFI functions are reached through matrix_rtc.ts alone.
|
|
||||||
// Kept out of the sync script's way: it is not generated.
|
|
||||||
|
|
||||||
/** What wasm-bindgen's loader accepts as the module to instantiate. */
|
|
||||||
export type InitInput =
|
|
||||||
| RequestInfo
|
|
||||||
| URL
|
|
||||||
| Response
|
|
||||||
| BufferSource
|
|
||||||
| WebAssembly.Module;
|
|
||||||
|
|
||||||
export default function initAsync(
|
|
||||||
moduleOrPath?:
|
|
||||||
| { module_or_path?: InitInput | Promise<InitInput> }
|
|
||||||
| InitInput
|
|
||||||
| Promise<InitInput>,
|
|
||||||
): Promise<unknown>;
|
|
||||||
|
|
||||||
export function initSync(
|
|
||||||
module: { module: BufferSource | WebAssembly.Module } | BufferSource | WebAssembly.Module,
|
|
||||||
): unknown;
|
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+23
-19
@@ -7,17 +7,18 @@ Please see LICENSE in the repository root for full details.
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The MatrixRTC SDK: the Rust `matrix-rtc` crate through its uniffi web
|
* The MatrixRTC SDK: the Rust `matrix-rtc` crate through its uniffi web
|
||||||
* bindings. Everything Element Call needs to *participate* in a MatrixRTC
|
* bindings, shipped as the `@element-hq/matrix-rtc` npm package. Everything
|
||||||
* session — the session projection, our own membership with its keep-alive,
|
* Element Call needs to *participate* in a MatrixRTC session — the session
|
||||||
* transport tokens and the media key exchange — lives in the crate; this
|
* projection, our own membership with its keep-alive, transport tokens and
|
||||||
* module loads it and re-exports the surface Element Call uses.
|
* the media key exchange — lives in the crate; this module loads it and
|
||||||
|
* re-exports the surface Element Call uses.
|
||||||
*
|
*
|
||||||
* The bindings under `generated/` are vendored by
|
* Nothing else imports the package directly: the boot below is the one place
|
||||||
* `scripts/sync-matrix-rtc-sdk.sh` and never edited by hand.
|
* the wasm is loaded and the crate's logging is wired up, so a caller cannot
|
||||||
|
* end up with a silent or half-initialised SDK.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import initAsync, { type InitInput } from "./generated/wasm-bindgen/index.js";
|
import { initAsync, type WasmSource } from "@element-hq/matrix-rtc";
|
||||||
import bindings from "./generated/matrix_rtc";
|
|
||||||
import { installMatrixRtcLogSink } from "./logSink";
|
import { installMatrixRtcLogSink } from "./logSink";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -38,7 +39,7 @@ export {
|
|||||||
FfiTransportIntent,
|
FfiTransportIntent,
|
||||||
RtcError,
|
RtcError,
|
||||||
computeSessionsFromEvents,
|
computeSessionsFromEvents,
|
||||||
} from "./generated/matrix_rtc";
|
} from "@element-hq/matrix-rtc";
|
||||||
export type {
|
export type {
|
||||||
FfiConnectionData,
|
FfiConnectionData,
|
||||||
FfiConnectionWithMembers,
|
FfiConnectionWithMembers,
|
||||||
@@ -62,14 +63,14 @@ export type {
|
|||||||
RoomEventSinkLike,
|
RoomEventSinkLike,
|
||||||
StateUpdateSinkLike,
|
StateUpdateSinkLike,
|
||||||
ToDeviceSinkLike,
|
ToDeviceSinkLike,
|
||||||
} from "./generated/matrix_rtc";
|
} from "@element-hq/matrix-rtc";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Where to load the wasm from. A URL (or anything `fetch` accepts) in a
|
* Where to load the wasm from. A URL (or anything `fetch` accepts) in a
|
||||||
* browser; bytes or a compiled module where there is nothing to fetch from,
|
* browser; bytes or a compiled module where there is nothing to fetch from,
|
||||||
* such as tests.
|
* such as tests.
|
||||||
*/
|
*/
|
||||||
export type MatrixRtcWasmSource = InitInput;
|
export type MatrixRtcWasmSource = WasmSource;
|
||||||
|
|
||||||
let loading: Promise<void> | null = null;
|
let loading: Promise<void> | null = null;
|
||||||
|
|
||||||
@@ -77,25 +78,28 @@ let loading: Promise<void> | null = null;
|
|||||||
* Loads and initialises the SDK. Idempotent: the first call decides the
|
* Loads and initialises the SDK. Idempotent: the first call decides the
|
||||||
* source, later calls await the same load.
|
* source, later calls await the same load.
|
||||||
*
|
*
|
||||||
* Without a `source`, the wasm is the one bundled next to this module (an
|
* Without a `source`, the wasm is the package's own copy as the bundler
|
||||||
* asset URL in the app builds). A host that serves the file from somewhere
|
* placed it (an asset URL in the app builds). A host that serves the file
|
||||||
* else, or a test runner with no server, passes its own.
|
* from somewhere else, or a test runner with no server, passes its own.
|
||||||
*/
|
*/
|
||||||
export async function initMatrixRtcSdk(
|
export async function initMatrixRtcSdk(
|
||||||
source?: MatrixRtcWasmSource,
|
source?: MatrixRtcWasmSource,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
loading ??= (async (): Promise<void> => {
|
loading ??= (async (): Promise<void> => {
|
||||||
await initAsync({ module_or_path: source ?? (await bundledWasm()) });
|
await initAsync(source ?? (await bundledWasm()));
|
||||||
bindings.initialize();
|
|
||||||
// The crate is silent until told where to log.
|
// The crate is silent until told where to log.
|
||||||
installMatrixRtcLogSink();
|
installMatrixRtcLogSink();
|
||||||
})();
|
})();
|
||||||
await loading;
|
await loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The wasm as the bundler placed it, resolved lazily so nothing is fetched until needed. */
|
/**
|
||||||
|
* The wasm as the bundler placed it, resolved lazily so nothing is fetched
|
||||||
|
* until needed. Asked for explicitly, rather than leaving the package to its
|
||||||
|
* `import.meta.url` default, so that the dev server's dependency
|
||||||
|
* pre-bundling, which rewrites module URLs, cannot lose track of it.
|
||||||
|
*/
|
||||||
async function bundledWasm(): Promise<string> {
|
async function bundledWasm(): Promise<string> {
|
||||||
const { default: url } =
|
const { default: url } = await import("@element-hq/matrix-rtc/wasm?url");
|
||||||
await import("./generated/wasm-bindgen/index_bg.wasm?url");
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
|
|||||||
|
|
||||||
import { type Logger, logger as rootLogger } from "matrix-js-sdk/lib/logger";
|
import { type Logger, logger as rootLogger } from "matrix-js-sdk/lib/logger";
|
||||||
|
|
||||||
import { FfiLogLevel, type LogSink, setLogSink } from "./generated/matrix_rtc";
|
import { FfiLogLevel, type LogSink, setLogSink } from "@element-hq/matrix-rtc";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link LogSink} that writes the crate's lines to a matrix-js-sdk logger,
|
* A {@link LogSink} that writes the crate's lines to a matrix-js-sdk logger,
|
||||||
|
|||||||
@@ -6,26 +6,25 @@ Please see LICENSE in the repository root for full details.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
import { resolve } from "node:path";
|
import { createRequire } from "node:module";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
import { initMatrixRtcSdk } from "../matrix-rtc-sdk";
|
import { initMatrixRtcSdk } from "../matrix-rtc-sdk";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the MatrixRTC SDK for a unit test. The browser builds fetch the wasm
|
* Loads the MatrixRTC SDK for a unit test. The browser builds fetch the wasm
|
||||||
* by URL; under vitest there is no server, so the bytes come from disk.
|
* by URL; under vitest there is no server, so the bytes come from disk: the
|
||||||
|
* `.wasm` the installed package exports as `@element-hq/matrix-rtc/wasm`.
|
||||||
*
|
*
|
||||||
* Only suites that construct a participation manager need this; do not put
|
* Only suites that construct a participation manager need this; do not put
|
||||||
* it in the global setup, where every test file would pay for the boot.
|
* it in the global setup, where every test file would pay for the boot.
|
||||||
*/
|
*/
|
||||||
export async function initMatrixRtcSdkForTests(): Promise<void> {
|
export async function initMatrixRtcSdkForTests(): Promise<void> {
|
||||||
// Relative to this file: under the jsdom environment `import.meta.url` is
|
// Resolved from this file's directory: under the jsdom environment
|
||||||
// not a file URL and `process.cwd()` is not the repository, but vitest
|
// `import.meta.url` is not a file URL and `process.cwd()` is not the
|
||||||
// still provides `__dirname`.
|
// repository, but vitest still provides `__dirname`.
|
||||||
const wasm = readFileSync(
|
const wasm = createRequire(join(__dirname, "test-matrix-rtc.ts")).resolve(
|
||||||
resolve(
|
"@element-hq/matrix-rtc/wasm",
|
||||||
__dirname,
|
|
||||||
"../matrix-rtc-sdk/generated/wasm-bindgen/index_bg.wasm",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
await initMatrixRtcSdk(wasm);
|
await initMatrixRtcSdk(readFileSync(wasm));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ export default defineConfig((configEnv) =>
|
|||||||
"src/utils/test-fixtures.ts",
|
"src/utils/test-fixtures.ts",
|
||||||
"src/utils/test-matrix-rtc.ts",
|
"src/utils/test-matrix-rtc.ts",
|
||||||
"src/utils/test-participation.ts",
|
"src/utils/test-participation.ts",
|
||||||
"src/matrix-rtc-sdk/generated/**",
|
|
||||||
"playwright/**",
|
"playwright/**",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user