@unwanted/matrix-sdk-mini 34.13.0 → 36.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.
Files changed (95) hide show
  1. package/lib/@types/event.d.ts +25 -0
  2. package/lib/@types/event.d.ts.map +1 -1
  3. package/lib/@types/event.js +5 -0
  4. package/lib/@types/event.js.map +1 -1
  5. package/lib/client.d.ts +43 -8
  6. package/lib/client.d.ts.map +1 -1
  7. package/lib/client.js +147 -85
  8. package/lib/client.js.map +1 -1
  9. package/lib/embedded.d.ts +2 -1
  10. package/lib/embedded.d.ts.map +1 -1
  11. package/lib/embedded.js +57 -74
  12. package/lib/embedded.js.map +1 -1
  13. package/lib/feature.d.ts.map +1 -1
  14. package/lib/feature.js +2 -1
  15. package/lib/feature.js.map +1 -1
  16. package/lib/http-api/errors.d.ts +3 -3
  17. package/lib/http-api/errors.js +3 -3
  18. package/lib/http-api/errors.js.map +1 -1
  19. package/lib/http-api/utils.js +2 -2
  20. package/lib/http-api/utils.js.map +1 -1
  21. package/lib/models/event-timeline.d.ts.map +1 -1
  22. package/lib/models/event-timeline.js +1 -21
  23. package/lib/models/event-timeline.js.map +1 -1
  24. package/lib/models/event.d.ts +11 -1
  25. package/lib/models/event.d.ts.map +1 -1
  26. package/lib/models/event.js +48 -5
  27. package/lib/models/event.js.map +1 -1
  28. package/lib/models/invites-ignorer-types.d.ts +27 -0
  29. package/lib/models/invites-ignorer-types.d.ts.map +1 -0
  30. package/lib/models/invites-ignorer-types.js +36 -0
  31. package/lib/models/invites-ignorer-types.js.map +1 -0
  32. package/lib/models/invites-ignorer.d.ts +2 -26
  33. package/lib/models/invites-ignorer.d.ts.map +1 -1
  34. package/lib/models/invites-ignorer.js +2 -27
  35. package/lib/models/invites-ignorer.js.map +1 -1
  36. package/lib/models/room-member.d.ts +6 -1
  37. package/lib/models/room-member.d.ts.map +1 -1
  38. package/lib/models/room-member.js +7 -1
  39. package/lib/models/room-member.js.map +1 -1
  40. package/lib/models/room.d.ts +6 -1
  41. package/lib/models/room.d.ts.map +1 -1
  42. package/lib/models/room.js +7 -1
  43. package/lib/models/room.js.map +1 -1
  44. package/lib/oidc/authorize.d.ts +2 -2
  45. package/lib/oidc/authorize.d.ts.map +1 -1
  46. package/lib/oidc/authorize.js +5 -5
  47. package/lib/oidc/authorize.js.map +1 -1
  48. package/lib/oidc/discovery.d.ts +8 -0
  49. package/lib/oidc/discovery.d.ts.map +1 -1
  50. package/lib/oidc/discovery.js +22 -11
  51. package/lib/oidc/discovery.js.map +1 -1
  52. package/lib/oidc/index.d.ts +3 -4
  53. package/lib/oidc/index.d.ts.map +1 -1
  54. package/lib/oidc/index.js.map +1 -1
  55. package/lib/oidc/register.js +3 -3
  56. package/lib/oidc/register.js.map +1 -1
  57. package/lib/oidc/tokenRefresher.d.ts.map +1 -1
  58. package/lib/oidc/tokenRefresher.js +6 -5
  59. package/lib/oidc/tokenRefresher.js.map +1 -1
  60. package/lib/oidc/validate.d.ts +9 -23
  61. package/lib/oidc/validate.d.ts.map +1 -1
  62. package/lib/oidc/validate.js +13 -28
  63. package/lib/oidc/validate.js.map +1 -1
  64. package/lib/randomstring.d.ts +30 -3
  65. package/lib/randomstring.d.ts.map +1 -1
  66. package/lib/randomstring.js +68 -16
  67. package/lib/randomstring.js.map +1 -1
  68. package/lib/store/indexeddb-local-backend.js +4 -2
  69. package/lib/store/indexeddb-local-backend.js.map +1 -1
  70. package/lib/testing.d.ts +17 -0
  71. package/lib/testing.d.ts.map +1 -1
  72. package/lib/testing.js +42 -0
  73. package/lib/testing.js.map +1 -1
  74. package/package.json +5 -5
  75. package/src/@types/event.ts +17 -0
  76. package/src/client.ts +86 -28
  77. package/src/embedded.ts +39 -49
  78. package/src/feature.ts +1 -0
  79. package/src/http-api/errors.ts +3 -3
  80. package/src/http-api/utils.ts +2 -2
  81. package/src/models/event-timeline.ts +1 -21
  82. package/src/models/event.ts +46 -0
  83. package/src/models/invites-ignorer-types.ts +48 -0
  84. package/src/models/invites-ignorer.ts +7 -42
  85. package/src/models/room-member.ts +16 -1
  86. package/src/models/room.ts +16 -1
  87. package/src/oidc/authorize.ts +7 -7
  88. package/src/oidc/discovery.ts +16 -10
  89. package/src/oidc/index.ts +3 -4
  90. package/src/oidc/register.ts +3 -3
  91. package/src/oidc/tokenRefresher.ts +3 -2
  92. package/src/oidc/validate.ts +40 -63
  93. package/src/randomstring.ts +65 -19
  94. package/src/store/indexeddb-local-backend.ts +2 -2
  95. package/src/testing.ts +41 -0
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":["MatrixEvent","mkMatrixEvent","opts","_opts$eventId","_opts$ts","event","type","room_id","roomId","sender","content","event_id","eventId","Math","random","origin_server_ts","ts","unsigned","stateKey","undefined","state_key","mxEvent","userId","membership","name","rawDisplayName","getAvatarUrl","getMxcAvatarUrl"],"sources":["../src/testing.ts"],"sourcesContent":["/*\nCopyright 2024 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/**\n * This file is a secondary entrypoint for the js-sdk library, exposing utilities which might be useful for writing tests.\n *\n * In general, it should not be included in runtime applications.\n *\n * @packageDocumentation\n */\n\nimport { IContent, IEvent, IUnsigned, MatrixEvent } from \"./models/event.ts\";\nimport { RoomMember } from \"./models/room-member.ts\";\nimport { EventType } from \"./@types/event.ts\";\n\n/**\n * Create a {@link MatrixEvent}.\n *\n * @param opts - Values for the event.\n */\nexport function mkMatrixEvent(opts: {\n /** Room ID of the event. */\n roomId: string;\n\n /** The sender of the event. */\n sender: string;\n\n /** The type of the event. */\n type: EventType | string;\n\n /** Optional `state_key` for the event. If unspecified, a non-state event is created. */\n stateKey?: string;\n\n /** Optional `origin_server_ts` for the event. If unspecified, the timestamp will be set to 0. */\n ts?: number;\n\n /** Optional `event_id` for the event. If provided will be used as event ID; else an ID is generated. */\n eventId?: string;\n\n /** Content of the event. */\n content: IContent;\n\n /** Optional `unsigned` data for the event. */\n unsigned?: IUnsigned;\n}): MatrixEvent {\n const event: Partial<IEvent> = {\n type: opts.type,\n room_id: opts.roomId,\n sender: opts.sender,\n content: opts.content,\n event_id: opts.eventId ?? \"$\" + Math.random() + \"-\" + Math.random(),\n origin_server_ts: opts.ts ?? 0,\n unsigned: opts.unsigned,\n };\n if (opts.stateKey !== undefined) {\n event.state_key = opts.stateKey;\n }\n\n const mxEvent = new MatrixEvent(event);\n mxEvent.sender = {\n userId: opts.sender,\n membership: \"join\",\n name: opts.sender,\n rawDisplayName: opts.sender,\n roomId: opts.sender,\n getAvatarUrl: () => {},\n getMxcAvatarUrl: () => {},\n } as unknown as RoomMember;\n return mxEvent;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAAsCA,WAAW,QAAQ,mBAAmB;AAI5E;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,aAAaA,CAACC,IAwB7B,EAAe;EAAA,IAAAC,aAAA,EAAAC,QAAA;EACZ,IAAMC,KAAsB,GAAG;IAC3BC,IAAI,EAAEJ,IAAI,CAACI,IAAI;IACfC,OAAO,EAAEL,IAAI,CAACM,MAAM;IACpBC,MAAM,EAAEP,IAAI,CAACO,MAAM;IACnBC,OAAO,EAAER,IAAI,CAACQ,OAAO;IACrBC,QAAQ,GAAAR,aAAA,GAAED,IAAI,CAACU,OAAO,cAAAT,aAAA,cAAAA,aAAA,GAAI,GAAG,GAAGU,IAAI,CAACC,MAAM,CAAC,CAAC,GAAG,GAAG,GAAGD,IAAI,CAACC,MAAM,CAAC,CAAC;IACnEC,gBAAgB,GAAAX,QAAA,GAAEF,IAAI,CAACc,EAAE,cAAAZ,QAAA,cAAAA,QAAA,GAAI,CAAC;IAC9Ba,QAAQ,EAAEf,IAAI,CAACe;EACnB,CAAC;EACD,IAAIf,IAAI,CAACgB,QAAQ,KAAKC,SAAS,EAAE;IAC7Bd,KAAK,CAACe,SAAS,GAAGlB,IAAI,CAACgB,QAAQ;EACnC;EAEA,IAAMG,OAAO,GAAG,IAAIrB,WAAW,CAACK,KAAK,CAAC;EACtCgB,OAAO,CAACZ,MAAM,GAAG;IACba,MAAM,EAAEpB,IAAI,CAACO,MAAM;IACnBc,UAAU,EAAE,MAAM;IAClBC,IAAI,EAAEtB,IAAI,CAACO,MAAM;IACjBgB,cAAc,EAAEvB,IAAI,CAACO,MAAM;IAC3BD,MAAM,EAAEN,IAAI,CAACO,MAAM;IACnBiB,YAAY,EAAEA,CAAA,KAAM,CAAC,CAAC;IACtBC,eAAe,EAAEA,CAAA,KAAM,CAAC;EAC5B,CAA0B;EAC1B,OAAON,OAAO;AAClB","ignoreList":[]}
1
+ {"version":3,"file":"testing.js","names":["MatrixEvent","mkMatrixEvent","opts","_opts$eventId","_opts$ts","event","type","room_id","roomId","sender","content","event_id","eventId","Math","random","origin_server_ts","ts","unsigned","stateKey","undefined","state_key","mxEvent","userId","membership","name","rawDisplayName","getAvatarUrl","getMxcAvatarUrl","makeDelegatedAuthConfig","issuer","arguments","length","additionalGrantTypes","metadata","mockOpenIdConfiguration","_objectSpread","signingKeys","revocation_endpoint","token_endpoint","authorization_endpoint","registration_endpoint","device_authorization_endpoint","jwks_uri","response_types_supported","grant_types_supported","code_challenge_methods_supported"],"sources":["../src/testing.ts"],"sourcesContent":["/*\nCopyright 2024 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/**\n * This file is a secondary entrypoint for the js-sdk library, exposing utilities which might be useful for writing tests.\n *\n * In general, it should not be included in runtime applications.\n *\n * @packageDocumentation\n */\n\nimport { IContent, IEvent, IUnsigned, MatrixEvent } from \"./models/event.ts\";\nimport { RoomMember } from \"./models/room-member.ts\";\nimport { EventType } from \"./@types/event.ts\";\nimport { OidcClientConfig, ValidatedAuthMetadata } from \"./oidc/index.ts\";\n\n/**\n * Create a {@link MatrixEvent}.\n *\n * @param opts - Values for the event.\n */\nexport function mkMatrixEvent(opts: {\n /** Room ID of the event. */\n roomId: string;\n\n /** The sender of the event. */\n sender: string;\n\n /** The type of the event. */\n type: EventType | string;\n\n /** Optional `state_key` for the event. If unspecified, a non-state event is created. */\n stateKey?: string;\n\n /** Optional `origin_server_ts` for the event. If unspecified, the timestamp will be set to 0. */\n ts?: number;\n\n /** Optional `event_id` for the event. If provided will be used as event ID; else an ID is generated. */\n eventId?: string;\n\n /** Content of the event. */\n content: IContent;\n\n /** Optional `unsigned` data for the event. */\n unsigned?: IUnsigned;\n}): MatrixEvent {\n const event: Partial<IEvent> = {\n type: opts.type,\n room_id: opts.roomId,\n sender: opts.sender,\n content: opts.content,\n event_id: opts.eventId ?? \"$\" + Math.random() + \"-\" + Math.random(),\n origin_server_ts: opts.ts ?? 0,\n unsigned: opts.unsigned,\n };\n if (opts.stateKey !== undefined) {\n event.state_key = opts.stateKey;\n }\n\n const mxEvent = new MatrixEvent(event);\n mxEvent.sender = {\n userId: opts.sender,\n membership: \"join\",\n name: opts.sender,\n rawDisplayName: opts.sender,\n roomId: opts.sender,\n getAvatarUrl: () => {},\n getMxcAvatarUrl: () => {},\n } as unknown as RoomMember;\n return mxEvent;\n}\n\n/**\n * Makes a valid OidcClientConfig with minimum valid values\n * @param issuer used as the base for all other urls\n * @param additionalGrantTypes to add to the default grant types\n * @returns OidcClientConfig\n * @experimental\n */\nexport const makeDelegatedAuthConfig = (\n issuer = \"https://auth.org/\",\n additionalGrantTypes: string[] = [],\n): OidcClientConfig => {\n const metadata = mockOpenIdConfiguration(issuer, additionalGrantTypes);\n return {\n ...metadata,\n signingKeys: null,\n };\n};\n/**\n * Useful for mocking <issuer>/.well-known/openid-configuration\n * @param issuer used as the base for all other urls\n * @param additionalGrantTypes to add to the default grant types\n * @returns ValidatedAuthMetadata\n * @experimental\n */\nexport const mockOpenIdConfiguration = (\n issuer = \"https://auth.org/\",\n additionalGrantTypes: string[] = [],\n): ValidatedAuthMetadata => ({\n issuer,\n revocation_endpoint: issuer + \"revoke\",\n token_endpoint: issuer + \"token\",\n authorization_endpoint: issuer + \"auth\",\n registration_endpoint: issuer + \"registration\",\n device_authorization_endpoint: issuer + \"device\",\n jwks_uri: issuer + \"jwks\",\n response_types_supported: [\"code\"],\n grant_types_supported: [\"authorization_code\", \"refresh_token\", ...additionalGrantTypes],\n code_challenge_methods_supported: [\"S256\"],\n});"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unwanted/matrix-sdk-mini",
3
- "version": "34.13.0",
3
+ "version": "36.0.0",
4
4
  "description": "Matrix Client-Server mini SDK for Javascript",
5
5
  "engines": {
6
6
  "node": ">=20.0.0"
@@ -56,7 +56,7 @@
56
56
  "jwt-decode": "^4.0.0",
57
57
  "loglevel": "^1.7.1",
58
58
  "matrix-events-sdk": "0.0.1",
59
- "matrix-widget-api": "^1.10.0",
59
+ "matrix-widget-api": "^1.12.0",
60
60
  "oidc-client-ts": "^3.0.1",
61
61
  "p-retry": "4",
62
62
  "sdp-transform": "^2.15.0",
@@ -68,7 +68,7 @@
68
68
  "@action-validator/core": "^0.6.0",
69
69
  "@babel/cli": "^7.12.10",
70
70
  "@babel/core": "^7.12.10",
71
- "@babel/eslint-parser": "^7.12.10",
71
+ "@babel/eslint-parser": "^7.26.5",
72
72
  "@babel/eslint-plugin": "^7.12.10",
73
73
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
74
74
  "@babel/plugin-transform-class-properties": "^7.12.1",
@@ -87,7 +87,7 @@
87
87
  "@types/node": "18",
88
88
  "@types/sdp-transform": "^2.4.5",
89
89
  "@types/uuid": "10",
90
- "@typescript-eslint/eslint-plugin": "^8.0.0",
90
+ "@typescript-eslint/eslint-plugin": "^8.21.0",
91
91
  "@typescript-eslint/parser": "^8.0.0",
92
92
  "babel-jest": "^29.0.0",
93
93
  "babel-plugin-search-and-replace": "^1.1.1",
@@ -122,7 +122,7 @@
122
122
  "typedoc-plugin-coverage": "^3.4.0",
123
123
  "typedoc-plugin-mdn-links": "^3.0.3",
124
124
  "typedoc-plugin-missing-exports": "^3.0.0",
125
- "typescript": "^5.4.2"
125
+ "typescript": "^5.7.3"
126
126
  },
127
127
  "@casualbot/jest-sonar-reporter": {
128
128
  "outputDirectory": "coverage",
@@ -42,6 +42,9 @@ import { XOR } from "./common.ts";
42
42
  import { ReactionEventContent, RoomMessageEventContent, StickerEventContent } from "./events.ts";
43
43
 
44
44
  import { M_POLL_END, M_POLL_START, PollEndEventContent, PollStartEventContent } from "./polls.ts";
45
+ import { LocalNotificationSettings } from "./local_notifications.ts";
46
+ import { IPushRules } from "./PushRules.ts";
47
+ import { POLICIES_ACCOUNT_EVENT_TYPE } from "../models/invites-ignorer-types.ts";
45
48
 
46
49
  export enum EventType {
47
50
  // Room state events
@@ -334,3 +337,17 @@ export interface StateEvents {
334
337
  // MSC3672
335
338
  [M_BEACON_INFO.name]: MBeaconInfoEventContent;
336
339
  }
340
+
341
+ /**
342
+ * Mapped type from event type to content type for all specified global account_data events.
343
+ */
344
+ export interface AccountDataEvents {
345
+ [EventType.PushRules]: IPushRules;
346
+ [EventType.Direct]: { [userId: string]: string[] };
347
+ [EventType.IgnoredUserList]: { [userId: string]: {} };
348
+ "m.identity_server": { base_url: string | null };
349
+ [key: `${typeof LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${string}`]: LocalNotificationSettings;
350
+ // Invites-ignorer events
351
+ [POLICIES_ACCOUNT_EVENT_TYPE.name]: { [key: string]: any };
352
+ [POLICIES_ACCOUNT_EVENT_TYPE.altName]: { [key: string]: any };
353
+ }
package/src/client.ts CHANGED
@@ -101,6 +101,7 @@ import {
101
101
  UpdateDelayedEventAction,
102
102
  } from "./@types/requests.ts";
103
103
  import {
104
+ AccountDataEvents,
104
105
  EventType,
105
106
  LOCAL_NOTIFICATION_SETTINGS_PREFIX,
106
107
  MSC3912_RELATION_BASED_REDACTIONS_PROP,
@@ -124,7 +125,7 @@ import {
124
125
  Visibility,
125
126
  } from "./@types/partials.ts";
126
127
  import { EventMapper, eventMapperFor, MapperOpts } from "./event-mapper.ts";
127
- import { randomString } from "./randomstring.ts";
128
+ import { secureRandomString } from "./randomstring.ts";
128
129
  import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE, MSC3089TreeSpace } from "./models/MSC3089TreeSpace.ts";
129
130
  import { ISignatures } from "./@types/signed.ts";
130
131
  import { IStore } from "./store/index.ts";
@@ -184,6 +185,7 @@ import { RoomMessageEventContent, StickerEventContent } from "./@types/events.ts
184
185
  import { ImageInfo } from "./@types/media.ts";
185
186
  import { Capabilities, ServerCapabilities } from "./serverCapabilities.ts";
186
187
  import { sha256 } from "./digest.ts";
188
+ import { discoverAndValidateOIDCIssuerWellKnown, OidcClientConfig, validateAuthMetadataAndKeys } from "./oidc/index.ts";
187
189
 
188
190
  export type Store = IStore;
189
191
 
@@ -1094,7 +1096,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
1094
1096
  this.usingExternalCrypto = opts.usingExternalCrypto ?? false;
1095
1097
  this.store = opts.store || new StubStore();
1096
1098
  this.deviceId = opts.deviceId || null;
1097
- this.sessionId = randomString(10);
1099
+ this.sessionId = secureRandomString(10);
1098
1100
 
1099
1101
  const userId = opts.userId || null;
1100
1102
  this.credentials = { userId };
@@ -1598,7 +1600,10 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
1598
1600
  * @returns Promise which resolves: an empty object
1599
1601
  * @returns Rejects: with an error response.
1600
1602
  */
1601
- public setAccountData(eventType: EventType | string, content: IContent): Promise<{}> {
1603
+ public setAccountData<K extends keyof AccountDataEvents>(
1604
+ eventType: K,
1605
+ content: AccountDataEvents[K] | Record<string, never>,
1606
+ ): Promise<{}> {
1602
1607
  const path = utils.encodeUri("/user/$userId/account_data/$type", {
1603
1608
  $userId: this.credentials.userId!,
1604
1609
  $type: eventType,
@@ -1613,7 +1618,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
1613
1618
  * @param eventType - The event type
1614
1619
  * @returns The contents of the given account data event
1615
1620
  */
1616
- public getAccountData(eventType: string): MatrixEvent | undefined {
1621
+ public getAccountData<K extends keyof AccountDataEvents>(eventType: K): MatrixEvent | undefined {
1617
1622
  return this.store.getAccountData(eventType);
1618
1623
  }
1619
1624
 
@@ -1625,7 +1630,9 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
1625
1630
  * @returns Promise which resolves: The contents of the given account data event.
1626
1631
  * @returns Rejects: with an error response.
1627
1632
  */
1628
- public async getAccountDataFromServer<T extends { [k: string]: any }>(eventType: string): Promise<T | null> {
1633
+ public async getAccountDataFromServer<K extends keyof AccountDataEvents>(
1634
+ eventType: K,
1635
+ ): Promise<AccountDataEvents[K] | null> {
1629
1636
  if (this.isInitialSyncComplete()) {
1630
1637
  const event = this.store.getAccountData(eventType);
1631
1638
  if (!event) {
@@ -1633,7 +1640,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
1633
1640
  }
1634
1641
  // The network version below returns just the content, so this branch
1635
1642
  // does the same to match.
1636
- return event.getContent<T>();
1643
+ return event.getContent<AccountDataEvents[K]>();
1637
1644
  }
1638
1645
  const path = utils.encodeUri("/user/$userId/account_data/$type", {
1639
1646
  $userId: this.credentials.userId!,
@@ -1649,7 +1656,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
1649
1656
  }
1650
1657
  }
1651
1658
 
1652
- public async deleteAccountData(eventType: string): Promise<void> {
1659
+ public async deleteAccountData(eventType: keyof AccountDataEvents): Promise<void> {
1653
1660
  const msc3391DeleteAccountDataServerSupport = this.canSupport.get(Feature.AccountDataDeletion);
1654
1661
  // if deletion is not supported overwrite with empty content
1655
1662
  if (msc3391DeleteAccountDataServerSupport === ServerSupport.Unsupported) {
@@ -1672,7 +1679,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
1672
1679
  * @returns The array of users that are ignored (empty if none)
1673
1680
  */
1674
1681
  public getIgnoredUsers(): string[] {
1675
- const event = this.getAccountData("m.ignored_user_list");
1682
+ const event = this.getAccountData(EventType.IgnoredUserList);
1676
1683
  if (!event?.getContent()["ignored_users"]) return [];
1677
1684
  return Object.keys(event.getContent()["ignored_users"]);
1678
1685
  }
@@ -1688,7 +1695,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
1688
1695
  userIds.forEach((u) => {
1689
1696
  content.ignored_users[u] = {};
1690
1697
  });
1691
- return this.setAccountData("m.ignored_user_list", content);
1698
+ return this.setAccountData(EventType.IgnoredUserList, content);
1692
1699
  }
1693
1700
 
1694
1701
  /**
@@ -2352,7 +2359,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
2352
2359
  if (this.canSupport.get(Feature.RelationBasedRedactions) === ServerSupport.Unsupported) {
2353
2360
  throw new Error(
2354
2361
  "Server does not support relation based redactions " +
2355
- `roomId ${roomId} eventId ${eventId} txnId: ${txnId} threadId ${threadId}`,
2362
+ `roomId ${roomId} eventId ${eventId} txnId: ${txnId as string} threadId ${threadId}`,
2356
2363
  );
2357
2364
  }
2358
2365
 
@@ -4630,8 +4637,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
4630
4637
  if (room) {
4631
4638
  // Copy over a known event sender if we can
4632
4639
  for (const ev of sr.context.getTimeline()) {
4633
- const sender = room.getMember(ev.getSender()!);
4634
- if (!ev.sender && sender) ev.sender = sender;
4640
+ ev.setMetadata(room.currentState, false);
4635
4641
  }
4636
4642
  }
4637
4643
  searchResults.results.push(sr);
@@ -5170,7 +5176,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
5170
5176
  * @returns A new client secret
5171
5177
  */
5172
5178
  public generateClientSecret(): string {
5173
- return randomString(32);
5179
+ return secureRandomString(32);
5174
5180
  }
5175
5181
 
5176
5182
  /**
@@ -5410,27 +5416,33 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
5410
5416
  /**
5411
5417
  * @returns Promise which resolves to a LoginResponse object
5412
5418
  * @returns Rejects: with an error response.
5419
+ *
5420
+ * @deprecated This method has unintuitive behaviour: it updates the `MatrixClient` instance with *some* of the
5421
+ * returned credentials. Instead, call {@link loginRequest} and create a new `MatrixClient` instance using the
5422
+ * results. See https://github.com/matrix-org/matrix-js-sdk/issues/4502.
5413
5423
  */
5414
5424
  public login(loginType: LoginRequest["type"], data: Omit<LoginRequest, "type">): Promise<LoginResponse> {
5415
- return this.http
5416
- .authedRequest<LoginResponse>(Method.Post, "/login", undefined, {
5417
- ...data,
5418
- type: loginType,
5419
- })
5420
- .then((response) => {
5421
- if (response.access_token && response.user_id) {
5422
- this.http.opts.accessToken = response.access_token;
5423
- this.credentials = {
5424
- userId: response.user_id,
5425
- };
5426
- }
5427
- return response;
5428
- });
5425
+ return this.loginRequest({
5426
+ ...data,
5427
+ type: loginType,
5428
+ }).then((response) => {
5429
+ if (response.access_token && response.user_id) {
5430
+ this.http.opts.accessToken = response.access_token;
5431
+ this.credentials = {
5432
+ userId: response.user_id,
5433
+ };
5434
+ }
5435
+ return response;
5436
+ });
5429
5437
  }
5430
5438
 
5431
5439
  /**
5432
5440
  * @returns Promise which resolves to a LoginResponse object
5433
5441
  * @returns Rejects: with an error response.
5442
+ *
5443
+ * @deprecated This method has unintuitive behaviour: it updates the `MatrixClient` instance with *some* of the
5444
+ * returned credentials. Instead, call {@link loginRequest} with `data.type: "m.login.password"`, and create a new
5445
+ * `MatrixClient` instance using the results. See https://github.com/matrix-org/matrix-js-sdk/issues/4502.
5434
5446
  */
5435
5447
  public loginWithPassword(user: string, password: string): Promise<LoginResponse> {
5436
5448
  return this.login("m.login.password", {
@@ -5475,6 +5487,10 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
5475
5487
  * @param token - Login token previously received from homeserver
5476
5488
  * @returns Promise which resolves to a LoginResponse object
5477
5489
  * @returns Rejects: with an error response.
5490
+ *
5491
+ * @deprecated This method has unintuitive behaviour: it updates the `MatrixClient` instance with *some* of the
5492
+ * returned credentials. Instead, call {@link loginRequest} with `data.type: "m.login.token"`, and create a new
5493
+ * `MatrixClient` instance using the results. See https://github.com/matrix-org/matrix-js-sdk/issues/4502.
5478
5494
  */
5479
5495
  public loginWithToken(token: string): Promise<LoginResponse> {
5480
5496
  return this.login("m.login.token", {
@@ -5482,6 +5498,20 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
5482
5498
  });
5483
5499
  }
5484
5500
 
5501
+ /**
5502
+ * Sends a `POST /login` request to the server.
5503
+ *
5504
+ * If successful, this will create a new device and access token for the user.
5505
+ *
5506
+ * @see {@link MatrixClient.loginFlows} which makes a `GET /login` request.
5507
+ * @see https://spec.matrix.org/v1.13/client-server-api/#post_matrixclientv3login
5508
+ *
5509
+ * @param data - Credentials and other details for the login request.
5510
+ */
5511
+ public async loginRequest(data: LoginRequest): Promise<LoginResponse> {
5512
+ return await this.http.authedRequest<LoginResponse>(Method.Post, "/login", undefined, data);
5513
+ }
5514
+
5485
5515
  /**
5486
5516
  * Logs out the current session.
5487
5517
  * Obviously, further calls that require authorisation should fail after this
@@ -6422,7 +6452,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
6422
6452
  deviceId: string,
6423
6453
  notificationSettings: LocalNotificationSettings,
6424
6454
  ): Promise<{}> {
6425
- const key = `${LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${deviceId}`;
6455
+ const key = `${LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${deviceId}` as const;
6426
6456
  return this.setAccountData(key, notificationSettings);
6427
6457
  }
6428
6458
 
@@ -7384,6 +7414,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
7384
7414
  * @returns Resolves: A promise of an object containing the OIDC issuer if configured
7385
7415
  * @returns Rejects: when the request fails (module:http-api.MatrixError)
7386
7416
  * @experimental - part of MSC2965
7417
+ * @deprecated in favour of getAuthMetadata
7387
7418
  */
7388
7419
  public async getAuthIssuer(): Promise<{
7389
7420
  issuer: string;
@@ -7392,6 +7423,33 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
7392
7423
  prefix: ClientPrefix.Unstable + "/org.matrix.msc2965",
7393
7424
  });
7394
7425
  }
7426
+
7427
+ /**
7428
+ * Discover and validate delegated auth configuration
7429
+ * - delegated auth issuer openid-configuration is reachable
7430
+ * - delegated auth issuer openid-configuration is configured correctly for us
7431
+ * Fetches /auth_metadata falling back to legacy implementation using /auth_issuer followed by
7432
+ * https://oidc-issuer.example.com/.well-known/openid-configuration and other files linked therein.
7433
+ * When successful, validated metadata is returned
7434
+ * @returns validated authentication metadata and optionally signing keys
7435
+ * @throws when delegated auth config is invalid or unreachable
7436
+ * @experimental - part of MSC2965
7437
+ */
7438
+ public async getAuthMetadata(): Promise<OidcClientConfig> {
7439
+ let authMetadata: unknown | undefined;
7440
+ try {
7441
+ authMetadata = await this.http.request<unknown>(Method.Get, "/auth_metadata", undefined, undefined, {
7442
+ prefix: ClientPrefix.Unstable + "/org.matrix.msc2965",
7443
+ });
7444
+ } catch (e) {
7445
+ if (e instanceof MatrixError && e.errcode === "M_UNRECOGNIZED") {
7446
+ const { issuer } = await this.getAuthIssuer();
7447
+ return discoverAndValidateOIDCIssuerWellKnown(issuer);
7448
+ }
7449
+ throw e;
7450
+ }
7451
+ return validateAuthMetadataAndKeys(authMetadata);
7452
+ }
7395
7453
  }
7396
7454
 
7397
7455
  function getUnstableDelayQueryOpts(delayOpts: SendDelayedEventRequestOpts): QueryDict {
package/src/embedded.ts CHANGED
@@ -28,6 +28,7 @@ import {
28
28
  WidgetApiAction,
29
29
  IWidgetApiResponse,
30
30
  IWidgetApiResponseData,
31
+ IUpdateStateToWidgetActionRequest,
31
32
  } from "matrix-widget-api";
32
33
 
33
34
  import { MatrixEvent, IEvent, IContent } from "./models/event.ts";
@@ -134,6 +135,7 @@ export type EventHandlerMap = { [RoomWidgetClientEvent.PendingEventsChanged]: ()
134
135
  export class RoomWidgetClient extends MatrixClient {
135
136
  private room?: Room;
136
137
  private readonly widgetApiReady: Promise<void>;
138
+ private readonly roomStateSynced: Promise<void>;
137
139
  private lifecycle?: AbortController;
138
140
  private syncState: SyncState | null = null;
139
141
 
@@ -152,7 +154,7 @@ export class RoomWidgetClient extends MatrixClient {
152
154
  */
153
155
  public constructor(
154
156
  private readonly widgetApi: WidgetApi,
155
- private readonly capabilities: ICapabilities,
157
+ /*private readonly */capabilities: ICapabilities,
156
158
  private readonly roomId: string,
157
159
  opts: IMatrixClientCreateOpts,
158
160
  sendContentLoaded: boolean,
@@ -187,6 +189,11 @@ export class RoomWidgetClient extends MatrixClient {
187
189
  };
188
190
 
189
191
  this.widgetApiReady = new Promise<void>((resolve) => this.widgetApi.once("ready", resolve));
192
+ this.roomStateSynced = capabilities.receiveState?.length
193
+ ? new Promise<void>((resolve) =>
194
+ this.widgetApi.once(`action:${WidgetApiToWidgetAction.UpdateState}`, resolve),
195
+ )
196
+ : Promise.resolve();
190
197
 
191
198
  // Request capabilities for the functionality this client needs to support
192
199
  if (
@@ -239,6 +246,7 @@ export class RoomWidgetClient extends MatrixClient {
239
246
 
240
247
  widgetApi.on(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent);
241
248
  widgetApi.on(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice);
249
+ widgetApi.on(`action:${WidgetApiToWidgetAction.UpdateState}`, this.onStateUpdate);
242
250
 
243
251
  // Open communication with the host
244
252
  widgetApi.start();
@@ -274,28 +282,6 @@ export class RoomWidgetClient extends MatrixClient {
274
282
 
275
283
  await this.widgetApiReady;
276
284
 
277
- // Backfill the requested events
278
- // We only get the most recent event for every type + state key combo,
279
- // so it doesn't really matter what order we inject them in
280
- await Promise.all(
281
- this.capabilities.receiveState?.map(async ({ eventType, stateKey }) => {
282
- const rawEvents = await this.widgetApi.readStateEvents(eventType, undefined, stateKey, [this.roomId]);
283
- const events = rawEvents.map((rawEvent) => new MatrixEvent(rawEvent as Partial<IEvent>));
284
-
285
- if (this.syncApi instanceof SyncApi) {
286
- // Passing undefined for `stateAfterEventList` allows will make `injectRoomEvents` run in legacy mode
287
- // -> state events in `timelineEventList` will update the state.
288
- await this.syncApi.injectRoomEvents(this.room!, undefined, events);
289
- } else {
290
- await this.syncApi!.injectRoomEvents(this.room!, events); // Sliding Sync
291
- }
292
- events.forEach((event) => {
293
- this.emit(ClientEvent.Event, event);
294
- logger.info(`Backfilled event ${event.getId()} ${event.getType()} ${event.getStateKey()}`);
295
- });
296
- }) ?? [],
297
- );
298
-
299
285
  if (opts.clientWellKnownPollPeriod !== undefined) {
300
286
  this.clientWellKnownIntervalID = setInterval(() => {
301
287
  this.fetchClientWellKnown();
@@ -303,13 +289,15 @@ export class RoomWidgetClient extends MatrixClient {
303
289
  this.fetchClientWellKnown();
304
290
  }
305
291
 
292
+ await this.roomStateSynced;
306
293
  this.setSyncState(SyncState.Syncing);
307
- logger.info("Finished backfilling events");
294
+ logger.info("Finished initial sync");
308
295
  }
309
296
 
310
297
  public stopClient(): void {
311
298
  this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent);
312
299
  this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice);
300
+ this.widgetApi.off(`action:${WidgetApiToWidgetAction.UpdateState}`, this.onStateUpdate);
313
301
 
314
302
  super.stopClient();
315
303
  this.lifecycle!.abort(); // Signal to other async tasks that the client has stopped
@@ -473,36 +461,15 @@ export class RoomWidgetClient extends MatrixClient {
473
461
  // Only inject once we have update the txId
474
462
  await this.updateTxId(event);
475
463
 
476
- // The widget API does not tell us whether a state event came from `state_after` or not so we assume legacy behaviour for now.
477
464
  if (this.syncApi instanceof SyncApi) {
478
- // The code will want to be something like:
479
- // ```
480
- // if (!params.addToTimeline && !params.addToState) {
481
- // // Passing undefined for `stateAfterEventList` makes `injectRoomEvents` run in "legacy mode"
482
- // // -> state events part of the `timelineEventList` parameter will update the state.
483
- // this.injectRoomEvents(this.room!, [], undefined, [event]);
484
- // } else {
485
- // this.injectRoomEvents(this.room!, undefined, params.addToState ? [event] : [], params.addToTimeline ? [event] : []);
486
- // }
487
- // ```
488
-
489
- // Passing undefined for `stateAfterEventList` allows will make `injectRoomEvents` run in legacy mode
490
- // -> state events in `timelineEventList` will update the state.
491
- await this.syncApi.injectRoomEvents(this.room!, [], undefined, [event]);
465
+ await this.syncApi.injectRoomEvents(this.room!, undefined, [], [event]);
492
466
  } else {
493
- // The code will want to be something like:
494
- // ```
495
- // if (!params.addToTimeline && !params.addToState) {
496
- // this.injectRoomEvents(this.room!, [], [event]);
497
- // } else {
498
- // this.injectRoomEvents(this.room!, params.addToState ? [event] : [], params.addToTimeline ? [event] : []);
499
- // }
500
- // ```
501
- await this.syncApi!.injectRoomEvents(this.room!, [], [event]); // Sliding Sync
467
+ // Sliding Sync
468
+ await this.syncApi!.injectRoomEvents(this.room!, [], [event]);
502
469
  }
503
470
  this.emit(ClientEvent.Event, event);
504
471
  this.setSyncState(SyncState.Syncing);
505
- logger.info(`Received event ${event.getId()} ${event.getType()} ${event.getStateKey()}`);
472
+ logger.info(`Received event ${event.getId()} ${event.getType()}`);
506
473
  } else {
507
474
  const { event_id: eventId, room_id: roomId } = ev.detail.data;
508
475
  logger.info(`Received event ${eventId} for a different room ${roomId}; discarding`);
@@ -524,6 +491,29 @@ export class RoomWidgetClient extends MatrixClient {
524
491
  this.setSyncState(SyncState.Syncing);
525
492
  await this.ack(ev);
526
493
  };
494
+
495
+ private onStateUpdate = async (ev: CustomEvent<IUpdateStateToWidgetActionRequest>): Promise<void> => {
496
+ ev.preventDefault();
497
+ for (const rawEvent of ev.detail.data.state) {
498
+ // Verify the room ID matches, since it's possible for the client to
499
+ // send us state updates from other rooms if this widget is always
500
+ // on screen
501
+ if (rawEvent.room_id === this.roomId) {
502
+ const event = new MatrixEvent(rawEvent as Partial<IEvent>);
503
+ if (this.syncApi instanceof SyncApi) {
504
+ await this.syncApi.injectRoomEvents(this.room!, undefined, [event]);
505
+ } else {
506
+ // Sliding Sync
507
+ await this.syncApi!.injectRoomEvents(this.room!, [event]);
508
+ }
509
+ logger.info(`Updated state entry ${event.getType()} ${event.getStateKey()} to ${event.getId()}`);
510
+ } else {
511
+ const { event_id: eventId, room_id: roomId } = ev.detail.data;
512
+ logger.info(`Received state entry ${eventId} for a different room ${roomId}; discarding`);
513
+ }
514
+ }
515
+ await this.ack(ev);
516
+ };
527
517
  }
528
518
 
529
519
  function processAndThrow(error: unknown): never {
package/src/feature.ts CHANGED
@@ -60,6 +60,7 @@ const featureSupportResolver: Record<string, FeatureSupportCondition> = {
60
60
  },
61
61
  [Feature.RelationsRecursion]: {
62
62
  unstablePrefixes: ["org.matrix.msc3981"],
63
+ matrixVersion: "v1.10",
63
64
  },
64
65
  [Feature.IntentionalMentions]: {
65
66
  unstablePrefixes: ["org.matrix.msc3952_intentional_mentions"],
@@ -167,9 +167,9 @@ export class MatrixError extends HTTPError {
167
167
  }
168
168
 
169
169
  /**
170
- * @returns The recommended delay in milliseconds to wait before retrying
171
- * the request that triggered {@link error}, or {@link defaultMs} if the
172
- * error was not due to rate-limiting or if no valid delay is recommended.
170
+ * @returns The recommended delay in milliseconds to wait before retrying the request.
171
+ * @param error - The error to check for a retry delay.
172
+ * @param defaultMs - The delay to use if the error was not due to rate-limiting or if no valid delay is recommended.
173
173
  */
174
174
  export function safeGetRetryAfterMs(error: unknown, defaultMs: number): number {
175
175
  if (!(error instanceof HTTPError) || !error.isRateLimitError()) {
@@ -180,8 +180,8 @@ export function calculateRetryBackoff(err: any, attempts: number, retryConnectio
180
180
  return -1;
181
181
  }
182
182
 
183
- if (err.httpStatus && (err.httpStatus === 400 || err.httpStatus === 403 || err.httpStatus === 401)) {
184
- // client error; no amount of retrying will save you now.
183
+ if (err.httpStatus && Math.floor(err.httpStatus / 100) === 4 && err.httpStatus !== 429) {
184
+ // client error; no amount of retrying will save you now (except for rate limiting which is handled below)
185
185
  return -1;
186
186
  }
187
187
 
@@ -68,27 +68,7 @@ export class EventTimeline {
68
68
  * @param toStartOfTimeline - if true the event's forwardLooking flag is set false
69
69
  */
70
70
  public static setEventMetadata(event: MatrixEvent, stateContext: RoomState, toStartOfTimeline: boolean): void {
71
- // When we try to generate a sentinel member before we have that member
72
- // in the members object, we still generate a sentinel but it doesn't
73
- // have a membership event, so test to see if events.member is set. We
74
- // check this to avoid overriding non-sentinel members by sentinel ones
75
- // when adding the event to a filtered timeline
76
- if (!event.sender?.events?.member) {
77
- event.sender = stateContext.getSentinelMember(event.getSender()!);
78
- }
79
- if (!event.target?.events?.member && event.getType() === EventType.RoomMember) {
80
- event.target = stateContext.getSentinelMember(event.getStateKey()!);
81
- }
82
-
83
- if (event.isState()) {
84
- // room state has no concept of 'old' or 'current', but we want the
85
- // room state to regress back to previous values if toStartOfTimeline
86
- // is set, which means inspecting prev_content if it exists. This
87
- // is done by toggling the forwardLooking flag.
88
- if (toStartOfTimeline) {
89
- event.forwardLooking = false;
90
- }
91
- }
71
+ event.setMetadata(stateContext, toStartOfTimeline);
92
72
  }
93
73
 
94
74
  private readonly roomId: string | null;