matrix-js-sdk 42.4.0 → 43.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/lib/@types/PushRules.d.ts +3 -1
- package/lib/@types/PushRules.d.ts.map +1 -1
- package/lib/@types/PushRules.js +2 -0
- package/lib/@types/PushRules.js.map +1 -1
- package/lib/@types/event.d.ts +1 -0
- package/lib/@types/event.d.ts.map +1 -1
- package/lib/@types/event.js.map +1 -1
- package/lib/@types/matrix-sdk-crypto-wasm.d.js.map +1 -1
- package/lib/client.d.ts +88 -37
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +72 -47
- package/lib/client.js.map +1 -1
- package/lib/crypto-api/index.d.ts +3 -3
- package/lib/crypto-api/index.d.ts.map +1 -1
- package/lib/crypto-api/index.js.map +1 -1
- package/lib/embedded.d.ts +17 -1
- package/lib/embedded.d.ts.map +1 -1
- package/lib/embedded.js +46 -1
- package/lib/embedded.js.map +1 -1
- package/lib/errors.d.ts +1 -1
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +2 -2
- package/lib/errors.js.map +1 -1
- package/lib/http-api/fetch.d.ts +7 -1
- package/lib/http-api/fetch.d.ts.map +1 -1
- package/lib/http-api/fetch.js +14 -5
- package/lib/http-api/fetch.js.map +1 -1
- package/lib/http-api/interface.d.ts +34 -8
- package/lib/http-api/interface.d.ts.map +1 -1
- package/lib/http-api/interface.js +10 -3
- package/lib/http-api/interface.js.map +1 -1
- package/lib/http-api/refresh.d.ts +30 -11
- package/lib/http-api/refresh.d.ts.map +1 -1
- package/lib/http-api/refresh.js +72 -5
- package/lib/http-api/refresh.js.map +1 -1
- package/lib/matrix.d.ts +1 -1
- package/lib/matrix.d.ts.map +1 -1
- package/lib/matrix.js.map +1 -1
- package/lib/matrixrtc/CallMembership.d.ts.map +1 -1
- package/lib/matrixrtc/CallMembership.js +20 -6
- package/lib/matrixrtc/CallMembership.js.map +1 -1
- package/lib/matrixrtc/IMembershipManager.d.ts +5 -0
- package/lib/matrixrtc/IMembershipManager.d.ts.map +1 -1
- package/lib/matrixrtc/IMembershipManager.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.d.ts +27 -1
- package/lib/matrixrtc/MatrixRTCSession.d.ts.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.js +58 -36
- package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSessionManager.js +1 -1
- package/lib/matrixrtc/MatrixRTCSessionManager.js.map +1 -1
- package/lib/matrixrtc/MembershipManager.d.ts +76 -0
- package/lib/matrixrtc/MembershipManager.d.ts.map +1 -1
- package/lib/matrixrtc/MembershipManager.js +264 -47
- package/lib/matrixrtc/MembershipManager.js.map +1 -1
- package/lib/matrixrtc/index.d.ts +1 -1
- package/lib/matrixrtc/index.d.ts.map +1 -1
- package/lib/matrixrtc/index.js +1 -1
- package/lib/matrixrtc/index.js.map +1 -1
- package/lib/matrixrtc/membershipData/common.d.ts +8 -0
- package/lib/matrixrtc/membershipData/common.d.ts.map +1 -1
- package/lib/matrixrtc/membershipData/common.js +10 -0
- package/lib/matrixrtc/membershipData/common.js.map +1 -1
- package/lib/matrixrtc/membershipData/index.d.ts +1 -1
- package/lib/matrixrtc/membershipData/index.d.ts.map +1 -1
- package/lib/matrixrtc/membershipData/index.js +1 -1
- package/lib/matrixrtc/membershipData/index.js.map +1 -1
- package/lib/matrixrtc/types.d.ts +104 -11
- package/lib/matrixrtc/types.d.ts.map +1 -1
- package/lib/matrixrtc/types.js +263 -19
- package/lib/matrixrtc/types.js.map +1 -1
- package/lib/matrixrtc/utils.d.ts +22 -1
- package/lib/matrixrtc/utils.d.ts.map +1 -1
- package/lib/matrixrtc/utils.js +38 -0
- package/lib/matrixrtc/utils.js.map +1 -1
- package/lib/models/room-sticky-events.d.ts +7 -0
- package/lib/models/room-sticky-events.d.ts.map +1 -1
- package/lib/models/room-sticky-events.js +27 -0
- package/lib/models/room-sticky-events.js.map +1 -1
- package/lib/models/thread.d.ts.map +1 -1
- package/lib/models/thread.js +8 -0
- package/lib/models/thread.js.map +1 -1
- package/lib/oauth/authorize.js +1 -1
- package/lib/oauth/authorize.js.map +1 -1
- package/lib/oauth/index.d.ts +3 -5
- package/lib/oauth/index.d.ts.map +1 -1
- package/lib/oauth/index.js +7 -7
- package/lib/oauth/index.js.map +1 -1
- package/lib/oauth/tokenRefresher.d.ts +10 -4
- package/lib/oauth/tokenRefresher.d.ts.map +1 -1
- package/lib/oauth/tokenRefresher.js +34 -24
- package/lib/oauth/tokenRefresher.js.map +1 -1
- package/lib/receipt-accumulator.d.ts +10 -11
- package/lib/receipt-accumulator.d.ts.map +1 -1
- package/lib/receipt-accumulator.js +26 -25
- package/lib/receipt-accumulator.js.map +1 -1
- package/lib/room-summary-api.d.ts +71 -0
- package/lib/room-summary-api.d.ts.map +1 -0
- package/lib/room-summary-api.js +82 -0
- package/lib/room-summary-api.js.map +1 -0
- package/lib/rust-crypto/backup.d.ts +7 -0
- package/lib/rust-crypto/backup.d.ts.map +1 -1
- package/lib/rust-crypto/backup.js +41 -25
- package/lib/rust-crypto/backup.js.map +1 -1
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js +6 -1
- package/lib/sync.js.map +1 -1
- package/package.json +6 -6
- package/src/@types/PushRules.ts +2 -0
- package/src/@types/event.ts +1 -1
- package/src/@types/matrix-sdk-crypto-wasm.d.ts +15 -12
- package/src/client.ts +105 -62
- package/src/crypto-api/index.ts +3 -3
- package/src/embedded.ts +61 -2
- package/src/errors.ts +2 -1
- package/src/http-api/fetch.ts +14 -5
- package/src/http-api/interface.ts +36 -8
- package/src/http-api/refresh.ts +101 -17
- package/src/matrix.ts +1 -1
- package/src/matrixrtc/CallMembership.ts +22 -4
- package/src/matrixrtc/IMembershipManager.ts +6 -0
- package/src/matrixrtc/MatrixRTCSession.ts +72 -49
- package/src/matrixrtc/MatrixRTCSessionManager.ts +1 -1
- package/src/matrixrtc/MembershipManager.ts +284 -61
- package/src/matrixrtc/index.ts +7 -1
- package/src/matrixrtc/membershipData/common.ts +12 -0
- package/src/matrixrtc/membershipData/index.ts +1 -1
- package/src/matrixrtc/types.ts +351 -23
- package/src/matrixrtc/utils.ts +54 -1
- package/src/models/room-sticky-events.ts +26 -1
- package/src/models/thread.ts +9 -0
- package/src/oauth/authorize.ts +1 -1
- package/src/oauth/index.ts +7 -8
- package/src/oauth/tokenRefresher.ts +15 -5
- package/src/receipt-accumulator.ts +30 -26
- package/src/room-summary-api.ts +114 -0
- package/src/rust-crypto/backup.ts +46 -33
- package/src/sync.ts +9 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matrix-js-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "43.0.0",
|
|
4
4
|
"description": "Matrix Client-Server SDK for Javascript",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"devEngines": {
|
|
9
9
|
"packageManager": {
|
|
10
10
|
"name": "pnpm",
|
|
11
|
-
"version": "
|
|
11
|
+
"version": "12.3.4",
|
|
12
12
|
"onFail": "download"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
"@types/node": "22",
|
|
69
69
|
"@types/sdp-transform": "^3.0.0",
|
|
70
70
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
71
|
-
"@vitest/coverage-v8": "^
|
|
72
|
-
"@vitest/ui": "^
|
|
71
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
72
|
+
"@vitest/ui": "^5.0.0",
|
|
73
73
|
"concurrently": "^10.0.0",
|
|
74
74
|
"debug": "^4.3.4",
|
|
75
75
|
"fake-indexeddb": "^6.0.0",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"knip": "^6.0.0",
|
|
80
80
|
"lint-staged": "^17.0.0",
|
|
81
81
|
"matrix-mock-request": "^2.5.0",
|
|
82
|
-
"oxfmt": "^0.
|
|
82
|
+
"oxfmt": "^0.67.0",
|
|
83
83
|
"oxlint": "^1.70.0",
|
|
84
84
|
"oxlint-tsgolint": "^7.0.0",
|
|
85
85
|
"typedoc": "^0.28.1",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"typedoc-plugin-mdn-links": "^5.0.0",
|
|
88
88
|
"typedoc-plugin-missing-exports": "^4.0.0",
|
|
89
89
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
90
|
-
"vitest": "^
|
|
90
|
+
"vitest": "^5.0.0"
|
|
91
91
|
},
|
|
92
92
|
"scripts": {
|
|
93
93
|
"start": "concurrently 'pnpm run build:compile --watch' 'pnpm run build:types --watch'",
|
package/src/@types/PushRules.ts
CHANGED
|
@@ -155,6 +155,8 @@ export enum RuleId {
|
|
|
155
155
|
PollStartOneToOneUnstable = ".org.matrix.msc3930.rule.poll_start_one_to_one",
|
|
156
156
|
PollEndOneToOne = ".m.rule.poll_end_one_to_one",
|
|
157
157
|
PollEndOneToOneUnstable = ".org.matrix.msc3930.rule.poll_end_one_to_one",
|
|
158
|
+
RtcInviteForMe = ".org.matrix.msc4075.rule.rtc.invite_for_me",
|
|
159
|
+
RtcInviteForRoom = ".org.matrix.msc4075.rule.rtc.invite_for_room",
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
export type PushRuleSet = {
|
package/src/@types/event.ts
CHANGED
|
@@ -361,7 +361,7 @@ export interface TimelineEvents {
|
|
|
361
361
|
[M_BEACON.name]: MBeaconEventContent;
|
|
362
362
|
[M_POLL_START.name]: PollStartEventContent;
|
|
363
363
|
[M_POLL_END.name]: PollEndEventContent;
|
|
364
|
-
[EventType.RTCMembership]: RtcMembershipData | { msc4354_sticky_key: string };
|
|
364
|
+
[EventType.RTCMembership]: RtcMembershipData | { slot_id: string; msc4354_sticky_key: string };
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
/**
|
|
@@ -16,20 +16,23 @@ limitations under the License.
|
|
|
16
16
|
|
|
17
17
|
import type * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-wasm";
|
|
18
18
|
|
|
19
|
+
/** Return type of `SecretsBundle.to_json` */
|
|
20
|
+
type SecretsBundleJson = {
|
|
21
|
+
cross_signing: {
|
|
22
|
+
master_key: string;
|
|
23
|
+
self_signing_key: string;
|
|
24
|
+
user_signing_key: string;
|
|
25
|
+
};
|
|
26
|
+
backup?: {
|
|
27
|
+
algorithm: string;
|
|
28
|
+
key: string;
|
|
29
|
+
backup_version: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
19
33
|
declare module "@matrix-org/matrix-sdk-crypto-wasm" {
|
|
20
34
|
interface SecretsBundle {
|
|
21
|
-
to_json(): Promise<
|
|
22
|
-
cross_signing: {
|
|
23
|
-
master_key: string;
|
|
24
|
-
self_signing_key: string;
|
|
25
|
-
user_signing_key: string;
|
|
26
|
-
};
|
|
27
|
-
backup?: {
|
|
28
|
-
algorithm: string;
|
|
29
|
-
key: string;
|
|
30
|
-
backup_version: string;
|
|
31
|
-
};
|
|
32
|
-
}>;
|
|
35
|
+
to_json(): Promise<SecretsBundleJson>;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
interface Device {
|
package/src/client.ts
CHANGED
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
MediaPrefix,
|
|
74
74
|
Method,
|
|
75
75
|
retryNetworkOperation,
|
|
76
|
-
type
|
|
76
|
+
type TokenRefreshCallback,
|
|
77
77
|
type Upload,
|
|
78
78
|
type UploadOpts,
|
|
79
79
|
type UploadResponse,
|
|
@@ -251,7 +251,9 @@ import {
|
|
|
251
251
|
type LivekitGetTokenResponse,
|
|
252
252
|
type Transport,
|
|
253
253
|
} from "./matrixrtc/index.ts";
|
|
254
|
+
import { type IRTCDeclineContent, RTC_NOTIFICATION_MAX_LIFETIME_MS } from "./matrixrtc/types.ts";
|
|
254
255
|
import { RetentionPolicyService } from "./retentionPolicy.ts";
|
|
256
|
+
import { fetchRoomSummary, type RoomSummary } from "./room-summary-api.ts";
|
|
255
257
|
import { createRtcTransportsCachedValue } from "./rtcTransportsCachedValue.ts";
|
|
256
258
|
import { createWellKnownCachedValue } from "./wellKnownCachedValue.ts";
|
|
257
259
|
import { type PollingCachedValue } from "./pollingCachedValue.ts";
|
|
@@ -319,15 +321,32 @@ export interface ICreateClientOpts {
|
|
|
319
321
|
*/
|
|
320
322
|
deviceId?: string;
|
|
321
323
|
|
|
324
|
+
/**
|
|
325
|
+
* The access token to use. Can be omitted if to call only unauthenticated APIs, or provided to
|
|
326
|
+
* create an authenticated client.
|
|
327
|
+
*/
|
|
322
328
|
accessToken?: string;
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* The current refresh token, or omit if the session has no refresh token in which case the tokens
|
|
332
|
+
* will not be refreshed.
|
|
333
|
+
*/
|
|
323
334
|
refreshToken?: string;
|
|
324
335
|
|
|
325
336
|
/**
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
337
|
+
* Called when the access tokens are refreshed.
|
|
338
|
+
* The client must replace the tokens it had stored previously which will no
|
|
339
|
+
* longer be valid.
|
|
340
|
+
*
|
|
341
|
+
* Required if a {@link refreshToken} is provided.
|
|
329
342
|
*/
|
|
330
|
-
|
|
343
|
+
onTokenRefresh?: TokenRefreshCallback;
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* If this is an OAuth2-native session (as per MSC2965/MSC3861), the OAuth client ID this
|
|
347
|
+
* application is registered with the delegated auth server under.
|
|
348
|
+
*/
|
|
349
|
+
oauthClientId?: string;
|
|
331
350
|
|
|
332
351
|
/**
|
|
333
352
|
* Identity server provider to retrieve the user's access token when accessing
|
|
@@ -865,25 +884,8 @@ interface IThirdPartyUser {
|
|
|
865
884
|
fields: object;
|
|
866
885
|
}
|
|
867
886
|
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
* Proposed at https://github.com/matrix-org/matrix-doc/pull/3266
|
|
871
|
-
*/
|
|
872
|
-
export interface RoomSummary extends Omit<IPublicRoomsChunkRoom, "canonical_alias" | "aliases"> {
|
|
873
|
-
/**
|
|
874
|
-
* The current membership of this user in the room.
|
|
875
|
-
* Usually "leave" if the room is fetched over federation.
|
|
876
|
-
*/
|
|
877
|
-
"membership"?: Membership;
|
|
878
|
-
/**
|
|
879
|
-
* Version of the room.
|
|
880
|
-
*/
|
|
881
|
-
"im.nheko.summary.room_version"?: string;
|
|
882
|
-
/**
|
|
883
|
-
* The encryption algorithm used for this room, if the room is encrypted.
|
|
884
|
-
*/
|
|
885
|
-
"im.nheko.summary.encryption"?: string;
|
|
886
|
-
}
|
|
887
|
+
// Re-export for backwards compatibility
|
|
888
|
+
export { type RoomSummary };
|
|
887
889
|
|
|
888
890
|
interface IRoomHierarchy {
|
|
889
891
|
rooms: IHierarchyRoom[];
|
|
@@ -1358,7 +1360,14 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
1358
1360
|
idBaseUrl: opts.idBaseUrl,
|
|
1359
1361
|
accessToken: opts.accessToken,
|
|
1360
1362
|
refreshToken: opts.refreshToken,
|
|
1361
|
-
|
|
1363
|
+
onTokenRefresh: opts.onTokenRefresh,
|
|
1364
|
+
oauth2ClientConfig: opts.oauthClientId
|
|
1365
|
+
? {
|
|
1366
|
+
clientId: opts.oauthClientId,
|
|
1367
|
+
deviceId: this.deviceId ?? undefined,
|
|
1368
|
+
}
|
|
1369
|
+
: undefined,
|
|
1370
|
+
authMetadataCallback: this.getAuthMetadata.bind(this),
|
|
1362
1371
|
prefix: ClientPrefix.V3,
|
|
1363
1372
|
onlyData: true,
|
|
1364
1373
|
extraParams: opts.queryParams,
|
|
@@ -2769,7 +2778,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
2769
2778
|
* If we expect that an event is part of a thread but is missing the relation
|
|
2770
2779
|
* we need to add it manually, as well as the reply fallback
|
|
2771
2780
|
*/
|
|
2772
|
-
|
|
2781
|
+
protected addThreadRelationIfNeeded(content: IContent, threadId: string | null, roomId: string): void {
|
|
2773
2782
|
if (threadId && !content["m.relates_to"]?.rel_type) {
|
|
2774
2783
|
const isReply = !!content["m.relates_to"]?.["m.in_reply_to"];
|
|
2775
2784
|
content["m.relates_to"] = {
|
|
@@ -2794,12 +2803,18 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
2794
2803
|
}
|
|
2795
2804
|
|
|
2796
2805
|
/**
|
|
2797
|
-
*
|
|
2798
|
-
*
|
|
2799
|
-
* @
|
|
2806
|
+
* Sends an event, adding it to the local echo and encrypting it if the room requires it.
|
|
2807
|
+
*
|
|
2808
|
+
* @param params - What to send and where.
|
|
2809
|
+
* @param params.roomId - The room to send the event to.
|
|
2810
|
+
* @param params.threadId - The thread to send the event in, or `null` for the main timeline.
|
|
2811
|
+
* @param params.eventObject - An object with the partial structure of an event, to which event_id, user_id, room_id and origin_server_ts will be added.
|
|
2812
|
+
* @param params.queryDict - Optional query parameters for the send request.
|
|
2813
|
+
* @param params.txnId - Optional transaction ID. Generated if omitted.
|
|
2814
|
+
* @returns Promise which resolves: to an object with the ID of the sent event.
|
|
2800
2815
|
* @returns Rejects: with an error response.
|
|
2801
2816
|
*/
|
|
2802
|
-
|
|
2817
|
+
protected sendCompleteEvent(params: {
|
|
2803
2818
|
roomId: string;
|
|
2804
2819
|
threadId: string | null;
|
|
2805
2820
|
eventObject: Partial<IEvent>;
|
|
@@ -2808,13 +2823,18 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
2808
2823
|
}): Promise<ISendEventResponse>;
|
|
2809
2824
|
/**
|
|
2810
2825
|
* Sends a delayed event (MSC4140).
|
|
2811
|
-
*
|
|
2812
|
-
* @param
|
|
2813
|
-
* @param
|
|
2814
|
-
* @
|
|
2826
|
+
*
|
|
2827
|
+
* @param params - What to send and where.
|
|
2828
|
+
* @param params.roomId - The room to send the event to.
|
|
2829
|
+
* @param params.threadId - The thread to send the event in, or `null` for the main timeline.
|
|
2830
|
+
* @param params.eventObject - An object with the partial structure of an event, to which event_id, user_id, room_id and origin_server_ts will be added.
|
|
2831
|
+
* @param params.delayOpts - Properties of the delay for this event.
|
|
2832
|
+
* @param params.queryDict - Optional query parameters for the send request.
|
|
2833
|
+
* @param params.txnId - Optional transaction ID. Generated if omitted.
|
|
2834
|
+
* @returns Promise which resolves: to an object with the ID of the scheduled delayed event.
|
|
2815
2835
|
* @returns Rejects: with an error response.
|
|
2816
2836
|
*/
|
|
2817
|
-
|
|
2837
|
+
protected sendCompleteEvent(params: {
|
|
2818
2838
|
roomId: string;
|
|
2819
2839
|
threadId: string | null;
|
|
2820
2840
|
eventObject: Partial<IEvent>;
|
|
@@ -2822,7 +2842,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
2822
2842
|
queryDict?: QueryDict;
|
|
2823
2843
|
txnId?: string;
|
|
2824
2844
|
}): Promise<SendDelayedEventResponse>;
|
|
2825
|
-
|
|
2845
|
+
protected sendCompleteEvent({
|
|
2826
2846
|
roomId,
|
|
2827
2847
|
threadId,
|
|
2828
2848
|
eventObject,
|
|
@@ -3952,17 +3972,38 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
3952
3972
|
}
|
|
3953
3973
|
|
|
3954
3974
|
/**
|
|
3975
|
+
* Declines a MatrixRTC notification.
|
|
3955
3976
|
*
|
|
3956
|
-
*
|
|
3957
|
-
*
|
|
3958
|
-
*
|
|
3977
|
+
* The decline is sent as a sticky event (MSC4354) keyed on the notification's event ID, so that the
|
|
3978
|
+
* user's other devices stop notifying. If the server doesn't support sticky events, a regular event is
|
|
3979
|
+
* sent instead. That one still counts as a decline for any device that receives it, but it isn't
|
|
3980
|
+
* re-delivered after a gappy or initial sync the way a sticky event is, so a device that was offline
|
|
3981
|
+
* when it was sent keeps notifying until the notification's lifetime elapses.
|
|
3982
|
+
*
|
|
3983
|
+
* @param roomId The room the notification was received in.
|
|
3984
|
+
* @param notificationEventId The event ID of the notification being declined.
|
|
3985
|
+
* @param stickyDurationMs How long (in milliseconds) the decline should stay sticky. Must not be smaller
|
|
3986
|
+
* than the notification's `lifetime`, otherwise the notification can become valid again once the decline
|
|
3987
|
+
* expires. Defaults to the maximum lifetime a notification may have.
|
|
3959
3988
|
* @throws May throw a `MatrixSafetyError` if content is deemed unsafe.
|
|
3960
3989
|
* @see MatrixSafetyError
|
|
3961
3990
|
*/
|
|
3962
|
-
public sendRtcDecline(
|
|
3963
|
-
|
|
3991
|
+
public async sendRtcDecline(
|
|
3992
|
+
roomId: string,
|
|
3993
|
+
notificationEventId: string,
|
|
3994
|
+
stickyDurationMs: number = RTC_NOTIFICATION_MAX_LIFETIME_MS,
|
|
3995
|
+
): Promise<ISendEventResponse> {
|
|
3996
|
+
const content: IRTCDeclineContent = {
|
|
3964
3997
|
"m.relates_to": { event_id: notificationEventId, rel_type: RelationType.Reference },
|
|
3965
|
-
|
|
3998
|
+
"msc4354_sticky_key": notificationEventId,
|
|
3999
|
+
};
|
|
4000
|
+
try {
|
|
4001
|
+
return await this._unstable_sendStickyEvent(roomId, stickyDurationMs, null, EventType.RTCDecline, content);
|
|
4002
|
+
} catch (error) {
|
|
4003
|
+
if (!(error instanceof UnsupportedStickyEventsEndpointError)) throw error;
|
|
4004
|
+
this.logger.debug("Server does not support sticky events, sending decline as a regular event");
|
|
4005
|
+
return await this.sendEvent(roomId, EventType.RTCDecline, content);
|
|
4006
|
+
}
|
|
3966
4007
|
}
|
|
3967
4008
|
|
|
3968
4009
|
/**
|
|
@@ -6299,6 +6340,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
6299
6340
|
/**
|
|
6300
6341
|
* Get the API versions supported by the server, along with any
|
|
6301
6342
|
* unstable APIs it supports
|
|
6343
|
+
*
|
|
6302
6344
|
* @returns The server /versions response
|
|
6303
6345
|
*/
|
|
6304
6346
|
public async getVersions(): Promise<IServerVersions> {
|
|
@@ -6847,7 +6889,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
6847
6889
|
* method is called. The state of the MatrixClient object is not affected:
|
|
6848
6890
|
* it is up to the caller to either reset or destroy the MatrixClient after
|
|
6849
6891
|
* this method succeeds.
|
|
6850
|
-
*
|
|
6892
|
+
*
|
|
6893
|
+
* For an OAuth2-native session (ie. one created with `oauth2ClientConfig`), this revokes the access
|
|
6894
|
+
* and refresh tokens directly with the delegated auth server instead of calling the `/logout` API,
|
|
6895
|
+
* since the homeserver does not own the tokens in that case.
|
|
6896
|
+
*
|
|
6897
|
+
* @param stopClient - whether to stop the client before logging out to prevent invalid token errors.
|
|
6851
6898
|
* @returns Promise which resolves: On success, the empty object `{}`
|
|
6852
6899
|
*/
|
|
6853
6900
|
public async logout(stopClient = false): Promise<EmptyObject> {
|
|
@@ -6856,6 +6903,11 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
6856
6903
|
this.http.abort();
|
|
6857
6904
|
}
|
|
6858
6905
|
|
|
6906
|
+
if (this.http.opts.oauth2ClientConfig) {
|
|
6907
|
+
await this.http.revokeOAuthTokens();
|
|
6908
|
+
return {};
|
|
6909
|
+
}
|
|
6910
|
+
|
|
6859
6911
|
return this.http.authedRequest(Method.Post, "/logout");
|
|
6860
6912
|
}
|
|
6861
6913
|
|
|
@@ -8856,26 +8908,18 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
8856
8908
|
}
|
|
8857
8909
|
|
|
8858
8910
|
/**
|
|
8859
|
-
* Fetches the summary of a room
|
|
8860
|
-
*
|
|
8911
|
+
* Fetches the summary of a room.
|
|
8912
|
+
* https://spec.matrix.org/latest/client-server-api/#get_matrixclientv1room_summaryroomidoralias
|
|
8913
|
+
*
|
|
8914
|
+
* Uses the initial version of MSC3266, as implemented in older versions of Synapse, unless the
|
|
8915
|
+
* server advertises support for the spec version which stabilised it.
|
|
8916
|
+
*
|
|
8861
8917
|
* @param roomIdOrAlias - The ID or alias of the room to get the summary of.
|
|
8862
|
-
* @param via - The
|
|
8918
|
+
* @param via - The servers to attempt to request the summary from, when the local server cannot
|
|
8919
|
+
* generate it (for instance, because it has no local user in the room).
|
|
8863
8920
|
*/
|
|
8864
8921
|
public async getRoomSummary(roomIdOrAlias: string, via?: string[]): Promise<RoomSummary> {
|
|
8865
|
-
|
|
8866
|
-
prefix: "/_matrix/client/unstable/im.nheko.summary",
|
|
8867
|
-
};
|
|
8868
|
-
try {
|
|
8869
|
-
const path = utils.encodeUri("/summary/$roomid", { $roomid: roomIdOrAlias });
|
|
8870
|
-
return await this.http.authedRequest(Method.Get, path, { via }, undefined, paramOpts);
|
|
8871
|
-
} catch (e) {
|
|
8872
|
-
if (e instanceof MatrixError && e.errcode === "M_UNRECOGNIZED") {
|
|
8873
|
-
const path = utils.encodeUri("/rooms/$roomid/summary", { $roomid: roomIdOrAlias });
|
|
8874
|
-
return await this.http.authedRequest(Method.Get, path, { via }, undefined, paramOpts);
|
|
8875
|
-
} else {
|
|
8876
|
-
throw e;
|
|
8877
|
-
}
|
|
8878
|
-
}
|
|
8922
|
+
return fetchRoomSummary(this.http, await this.getVersions(), roomIdOrAlias, via);
|
|
8879
8923
|
}
|
|
8880
8924
|
|
|
8881
8925
|
/**
|
|
@@ -8982,9 +9026,8 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
8982
9026
|
* @throws when delegated auth config is invalid or unreachable
|
|
8983
9027
|
*/
|
|
8984
9028
|
public async getAuthMetadata(): Promise<ValidatedAuthMetadata> {
|
|
8985
|
-
const useStable = await this.isVersionSupported("v1.15");
|
|
8986
9029
|
const authMetadata = await this.http.request(Method.Get, "/auth_metadata", undefined, undefined, {
|
|
8987
|
-
prefix:
|
|
9030
|
+
prefix: ClientPrefix.V1,
|
|
8988
9031
|
});
|
|
8989
9032
|
|
|
8990
9033
|
if (isValidAuthMetadata(authMetadata)) {
|
package/src/crypto-api/index.ts
CHANGED
|
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import type { SecretsBundle } from "@matrix-org/matrix-sdk-crypto-wasm";
|
|
18
17
|
import type { IMegolmSessionData } from "../@types/crypto.ts";
|
|
19
18
|
import type { ToDeviceBatch, ToDevicePayload } from "../models/ToDeviceMessage.ts";
|
|
20
19
|
import { type Room } from "../models/room.ts";
|
|
@@ -31,6 +30,7 @@ import {
|
|
|
31
30
|
} from "./keybackup.ts";
|
|
32
31
|
import { type ISignatures } from "../@types/signed.ts";
|
|
33
32
|
import { type MatrixEvent } from "../models/event.ts";
|
|
33
|
+
import type { SecretsBundleJson } from "../@types/matrix-sdk-crypto-wasm.d.ts";
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* `matrix-js-sdk/lib/crypto-api`: End-to-end encryption support.
|
|
@@ -723,13 +723,13 @@ export interface CryptoApi {
|
|
|
723
723
|
/**
|
|
724
724
|
* Export secrets bundle for transmitting to another device as part of OAuth2 QR login
|
|
725
725
|
*/
|
|
726
|
-
exportSecretsBundle?(): Promise<
|
|
726
|
+
exportSecretsBundle?(): Promise<SecretsBundleJson>;
|
|
727
727
|
|
|
728
728
|
/**
|
|
729
729
|
* Import secrets bundle transmitted from another device.
|
|
730
730
|
* @param secrets - The secrets bundle received from the other device
|
|
731
731
|
*/
|
|
732
|
-
importSecretsBundle?(secrets:
|
|
732
|
+
importSecretsBundle?(secrets: SecretsBundleJson): Promise<void>;
|
|
733
733
|
}
|
|
734
734
|
|
|
735
735
|
/** A reason code for a failure to decrypt an event. */
|
package/src/embedded.ts
CHANGED
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
UpdateDelayedEventAction,
|
|
47
47
|
isSendDelayedEventRequestOpts,
|
|
48
48
|
} from "./@types/requests.ts";
|
|
49
|
-
import { EventType, type StateEvents } from "./@types/event.ts";
|
|
49
|
+
import { EventType, type StateEvents, type TimelineEvents } from "./@types/event.ts";
|
|
50
50
|
import { logger } from "./logger.ts";
|
|
51
51
|
import {
|
|
52
52
|
MatrixClient,
|
|
@@ -64,7 +64,12 @@ import { User } from "./models/user.ts";
|
|
|
64
64
|
import { type Room } from "./models/room.ts";
|
|
65
65
|
import { type ToDeviceBatch, type ToDevicePayload } from "./models/ToDeviceMessage.ts";
|
|
66
66
|
import { MapWithDefault, type QueryDict, recursiveMapToObject } from "./utils.ts";
|
|
67
|
-
import {
|
|
67
|
+
import {
|
|
68
|
+
type EmptyObject,
|
|
69
|
+
TypedEventEmitter,
|
|
70
|
+
UnsupportedDelayedEventsEndpointError,
|
|
71
|
+
UnsupportedStickyEventsEndpointError,
|
|
72
|
+
} from "./matrix.ts";
|
|
68
73
|
|
|
69
74
|
interface IStateEventRequest {
|
|
70
75
|
eventType: string;
|
|
@@ -539,6 +544,60 @@ export class RoomWidgetClient extends MatrixClient {
|
|
|
539
544
|
return this.validateSendDelayedEventResponse(response);
|
|
540
545
|
}
|
|
541
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Sends a sticky timeline event through the widget API.
|
|
549
|
+
*
|
|
550
|
+
* A widget can't probe the homeserver for MSC4354 support and doesn't need to: the host either granted it
|
|
551
|
+
* the capability to send sticky events or it didn't. A missing capability is reported the same way a
|
|
552
|
+
* missing server feature is, so that callers fall back to a regular event in both cases alike.
|
|
553
|
+
*
|
|
554
|
+
* The host may still refuse the request, typically because its own homeserver turns out not to support
|
|
555
|
+
* sticky events. Such a refusal reaches the widget without Matrix API error details, as those only accompany
|
|
556
|
+
* errors from requests the host actually made to the homeserver. It is therefore reported as unsupported too,
|
|
557
|
+
* with the host's error as `cause`. A refusal that does carry Matrix API error details came from the
|
|
558
|
+
* homeserver itself and is rethrown as is.
|
|
559
|
+
*/
|
|
560
|
+
public async _unstable_sendStickyEvent<K extends keyof TimelineEvents>(
|
|
561
|
+
roomId: string,
|
|
562
|
+
stickDuration: number,
|
|
563
|
+
threadId: string | null,
|
|
564
|
+
eventType: K,
|
|
565
|
+
content: TimelineEvents[K] & { msc4354_sticky_key?: string },
|
|
566
|
+
txnId?: string,
|
|
567
|
+
): Promise<ISendEventResponse> {
|
|
568
|
+
if (!this.widgetApi.hasCapability(MatrixCapabilities.MSC4407SendStickyEvent)) {
|
|
569
|
+
throw new UnsupportedStickyEventsEndpointError(
|
|
570
|
+
"Widget was not granted the capability to send sticky events",
|
|
571
|
+
"sendStickyEvent",
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
this.addThreadRelationIfNeeded(content, threadId, roomId);
|
|
576
|
+
txnId ??= this.makeTxnId();
|
|
577
|
+
try {
|
|
578
|
+
return await this.sendCompleteEvent({
|
|
579
|
+
roomId,
|
|
580
|
+
threadId,
|
|
581
|
+
eventObject: { type: eventType, content },
|
|
582
|
+
queryDict: { "org.matrix.msc4354.sticky_duration_ms": stickDuration },
|
|
583
|
+
txnId,
|
|
584
|
+
});
|
|
585
|
+
} catch (error) {
|
|
586
|
+
if (!(error instanceof WidgetApiResponseError) || error.data.matrix_api_error !== undefined) throw error;
|
|
587
|
+
|
|
588
|
+
// Callers fall back to sending a regular event, so drop the local echo of the failed sticky one
|
|
589
|
+
// rather than leaving it in the timeline as unsent.
|
|
590
|
+
const localEvent = this.getRoom(roomId)?.getEventForTxnId(txnId);
|
|
591
|
+
if (localEvent?.status === EventStatus.NOT_SENT) this.cancelPendingEvent(localEvent);
|
|
592
|
+
|
|
593
|
+
throw new UnsupportedStickyEventsEndpointError(
|
|
594
|
+
`Host could not send the sticky event: ${error.message}`,
|
|
595
|
+
"sendStickyEvent",
|
|
596
|
+
{ cause: error },
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
542
601
|
private validateSendDelayedEventResponse(response: ISendEventFromWidgetResponseData): SendDelayedEventResponse {
|
|
543
602
|
if (response.delay_id === undefined) {
|
|
544
603
|
throw new Error("'delay_id' absent from response to a delayed event request");
|
package/src/errors.ts
CHANGED
|
@@ -80,8 +80,9 @@ export class UnsupportedStickyEventsEndpointError extends Error {
|
|
|
80
80
|
public constructor(
|
|
81
81
|
message: string,
|
|
82
82
|
public clientEndpoint: "sendStickyEvent" | "sendStickyStateEvent",
|
|
83
|
+
options?: ErrorOptions,
|
|
83
84
|
) {
|
|
84
|
-
super(message);
|
|
85
|
+
super(message, options);
|
|
85
86
|
this.name = "UnsupportedStickyEventsEndpointError";
|
|
86
87
|
}
|
|
87
88
|
}
|
package/src/http-api/fetch.ts
CHANGED
|
@@ -33,11 +33,11 @@ import {
|
|
|
33
33
|
import { anySignal, parseErrorResponse, timeoutSignal } from "./utils.ts";
|
|
34
34
|
import { sanitizeUrlForLogs } from "./logging.ts";
|
|
35
35
|
import { type QueryDict } from "../utils.ts";
|
|
36
|
-
import {
|
|
36
|
+
import { TokenManager, TokenRefreshOutcome } from "./refresh.ts";
|
|
37
37
|
|
|
38
38
|
export class FetchHttpApi<O extends IHttpOpts> {
|
|
39
39
|
private abortController = new AbortController();
|
|
40
|
-
private readonly
|
|
40
|
+
private readonly tokenManager: TokenManager;
|
|
41
41
|
|
|
42
42
|
public constructor(
|
|
43
43
|
private eventEmitter: TypedEventEmitter<HttpApiEvent, HttpApiEventHandlerMap>,
|
|
@@ -49,7 +49,7 @@ export class FetchHttpApi<O extends IHttpOpts> {
|
|
|
49
49
|
}
|
|
50
50
|
opts.useAuthorizationHeader = opts.useAuthorizationHeader ?? true;
|
|
51
51
|
|
|
52
|
-
this.
|
|
52
|
+
this.tokenManager = new TokenManager(opts);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
public abort(): void {
|
|
@@ -57,6 +57,15 @@ export class FetchHttpApi<O extends IHttpOpts> {
|
|
|
57
57
|
this.abortController = new AbortController();
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Attempt to revoke the current access and refresh tokens with the OAuth2 authorization server, e.g. as
|
|
62
|
+
* part of logging out an OAuth2-native session. Does nothing if `opts.oauth2ClientConfig` was not supplied.
|
|
63
|
+
* @throws when discovery of the auth server metadata, or revocation of either token, fails
|
|
64
|
+
*/
|
|
65
|
+
public async revokeOAuthTokens(): Promise<void> {
|
|
66
|
+
return this.tokenManager.revokeTokens();
|
|
67
|
+
}
|
|
68
|
+
|
|
60
69
|
public fetch(resource: URL | string, options?: RequestInit): ReturnType<typeof globalThis.fetch> {
|
|
61
70
|
if (this.opts.fetchFn) {
|
|
62
71
|
return this.opts.fetchFn(resource, options);
|
|
@@ -147,7 +156,7 @@ export class FetchHttpApi<O extends IHttpOpts> {
|
|
|
147
156
|
opts.abortSignal = paramOpts.abortSignal;
|
|
148
157
|
|
|
149
158
|
// Take a snapshot of the current token state before we start the request so we can reference it if we error
|
|
150
|
-
const requestSnapshot = await this.
|
|
159
|
+
const requestSnapshot = await this.tokenManager.prepareForRequest();
|
|
151
160
|
if (requestSnapshot.accessToken) {
|
|
152
161
|
if (this.opts.useAuthorizationHeader) {
|
|
153
162
|
if (!opts.headers) {
|
|
@@ -173,7 +182,7 @@ export class FetchHttpApi<O extends IHttpOpts> {
|
|
|
173
182
|
}
|
|
174
183
|
|
|
175
184
|
if (error.errcode === "M_UNKNOWN_TOKEN") {
|
|
176
|
-
const outcome = await this.
|
|
185
|
+
const outcome = await this.tokenManager.handleUnknownToken(requestSnapshot, attempt);
|
|
177
186
|
if (outcome === TokenRefreshOutcome.Success) {
|
|
178
187
|
// if we got a new token retry the request
|
|
179
188
|
return this.doAuthedRequest(attempt + 1, method, path, queryParams, body, paramOpts);
|
|
@@ -17,6 +17,7 @@ limitations under the License.
|
|
|
17
17
|
import { type MatrixError } from "./errors.ts";
|
|
18
18
|
import { type Logger } from "../logger.ts";
|
|
19
19
|
import { type QueryDict } from "../utils.ts";
|
|
20
|
+
import { type ValidatedAuthMetadata } from "../oauth/discover.ts";
|
|
20
21
|
|
|
21
22
|
export type Body = Record<string, any> | BodyInit;
|
|
22
23
|
|
|
@@ -39,12 +40,25 @@ export type AccessTokens = {
|
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
43
|
+
* A callback function called when tokens are refreshed such that stored tokens can be updated with
|
|
44
|
+
* the refreshed ones.
|
|
45
|
+
*/
|
|
46
|
+
export type TokenRefreshCallback = (newTokens: AccessTokens) => void;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Configuration required for {@link IHttpOpts} to allow the SDK to manage the full lifecycle of tokens for an
|
|
50
|
+
* OAuth2-native session (as per MSC2965/MSC3861): discovering the delegated auth server's metadata, refreshing
|
|
51
|
+
* access/refresh tokens, and revoking them (e.g. on logout).
|
|
44
52
|
*
|
|
45
|
-
*
|
|
53
|
+
* The SDK constructs the underlying OAuth2 client itself, lazily, the first time it is actually needed (so that,
|
|
54
|
+
* for example, a client started with no network connection does not fail to ever set up token refresh).
|
|
46
55
|
*/
|
|
47
|
-
export
|
|
56
|
+
export interface OAuth2ClientConfig {
|
|
57
|
+
/** The OAuth2 client ID this application is registered with the delegated auth server under. */
|
|
58
|
+
clientId: string;
|
|
59
|
+
/** The device ID of the current session, used to scope refreshed/revoked tokens to this session. */
|
|
60
|
+
deviceId?: string;
|
|
61
|
+
}
|
|
48
62
|
|
|
49
63
|
/** Options object for `FetchHttpApi` and {@link MatrixHttpApi}. */
|
|
50
64
|
export interface IHttpOpts {
|
|
@@ -57,14 +71,28 @@ export interface IHttpOpts {
|
|
|
57
71
|
|
|
58
72
|
accessToken?: string;
|
|
59
73
|
/**
|
|
60
|
-
* Used in conjunction with
|
|
74
|
+
* Used in conjunction with oauth2ClientConfig to attempt token refresh
|
|
61
75
|
*/
|
|
62
76
|
refreshToken?: string;
|
|
63
77
|
/**
|
|
64
|
-
*
|
|
65
|
-
|
|
78
|
+
* Callback called when tokens are refreshed. Must be supplied if refreshToken is supplied.
|
|
79
|
+
*/
|
|
80
|
+
onTokenRefresh?: TokenRefreshCallback;
|
|
81
|
+
/**
|
|
82
|
+
* Configuration needed to refresh (given refreshToken) and revoke (e.g. on logout) tokens for an
|
|
83
|
+
* OAuth2-native session. Optional; if omitted, tokens will not be refreshed or revoked by the SDK.
|
|
84
|
+
* authMetadataCallback must also be supplied to refresh tokens.
|
|
85
|
+
*/
|
|
86
|
+
oauth2ClientConfig?: OAuth2ClientConfig;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Discovers and validates the delegated auth server's metadata for the current homeserver.
|
|
90
|
+
* Must be supplied along with oauth2ClientConfig in order to refresh tokens.
|
|
91
|
+
*
|
|
92
|
+
* @returns validated authentication metadata
|
|
93
|
+
* @throws when delegated auth config is invalid or unreachable
|
|
66
94
|
*/
|
|
67
|
-
|
|
95
|
+
authMetadataCallback?: () => Promise<ValidatedAuthMetadata>;
|
|
68
96
|
|
|
69
97
|
/**
|
|
70
98
|
* Whether to use the HTTP Authorization header over the `access_token` query parameter
|