matrix-js-sdk 41.3.0 → 41.4.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 (43) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/lib/@types/event.d.ts +9 -0
  3. package/lib/@types/event.d.ts.map +1 -1
  4. package/lib/@types/event.js.map +1 -1
  5. package/lib/crypto-api/index.d.ts +27 -5
  6. package/lib/crypto-api/index.d.ts.map +1 -1
  7. package/lib/crypto-api/index.js +22 -3
  8. package/lib/crypto-api/index.js.map +1 -1
  9. package/lib/embedded.js +1 -1
  10. package/lib/embedded.js.map +1 -1
  11. package/lib/matrixrtc/MatrixRTCSession.js +2 -1
  12. package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
  13. package/lib/matrixrtc/membershipData/rtc.d.ts.map +1 -1
  14. package/lib/matrixrtc/membershipData/rtc.js +5 -4
  15. package/lib/matrixrtc/membershipData/rtc.js.map +1 -1
  16. package/lib/oidc/authorize.d.ts +8 -4
  17. package/lib/oidc/authorize.d.ts.map +1 -1
  18. package/lib/oidc/authorize.js +18 -6
  19. package/lib/oidc/authorize.js.map +1 -1
  20. package/lib/oidc/discovery.js +1 -1
  21. package/lib/oidc/discovery.js.map +1 -1
  22. package/lib/rust-crypto/backup.d.ts +6 -2
  23. package/lib/rust-crypto/backup.d.ts.map +1 -1
  24. package/lib/rust-crypto/backup.js +30 -10
  25. package/lib/rust-crypto/backup.js.map +1 -1
  26. package/lib/rust-crypto/rust-crypto.d.ts +16 -11
  27. package/lib/rust-crypto/rust-crypto.d.ts.map +1 -1
  28. package/lib/rust-crypto/rust-crypto.js +38 -21
  29. package/lib/rust-crypto/rust-crypto.js.map +1 -1
  30. package/lib/store/indexeddb-local-backend.d.ts.map +1 -1
  31. package/lib/store/indexeddb-local-backend.js +4 -2
  32. package/lib/store/indexeddb-local-backend.js.map +1 -1
  33. package/package.json +14 -10
  34. package/src/@types/event.ts +14 -2
  35. package/src/crypto-api/index.ts +30 -5
  36. package/src/embedded.ts +1 -1
  37. package/src/matrixrtc/MatrixRTCSession.ts +2 -1
  38. package/src/matrixrtc/membershipData/rtc.ts +5 -4
  39. package/src/oidc/authorize.ts +25 -6
  40. package/src/oidc/discovery.ts +1 -1
  41. package/src/rust-crypto/backup.ts +31 -10
  42. package/src/rust-crypto/rust-crypto.ts +28 -13
  43. package/src/store/indexeddb-local-backend.ts +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"indexeddb-local-backend.d.ts","sourceRoot":"","sources":["../../src/store/indexeddb-local-backend.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAsC,KAAK,aAAa,EAAmB,MAAM,wBAAwB,CAAC;AAIjH,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAkGtG,qBAAa,0BAA2B,YAAW,iBAAiB;IAyB5D,OAAO,CAAC,QAAQ,CAAC,SAAS;WAxBhB,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK7E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,EAAE,CAAC,CAAc;IACzB,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,qBAAqB,CAAC,CAAgB;IAC9C,OAAO,CAAC,uBAAuB,CAAmB;IAElD;;;;;;;;;OASG;gBAEkB,SAAS,EAAE,UAAU,EACtC,MAAM,SAAY;IAMtB;;;;OAIG;IACI,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAiDnD,8EAA8E;IACvE,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;;OAGG;IACH,OAAO,CAAC,IAAI;IAgBZ;;;;;OAKG;IACI,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,EAAE,GAAG,IAAI,CAAC;IA0CnF;;;;;OAKG;IACU,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7F,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCjE;;;;OAIG;IACI,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BrC;;;;;;;;OAQG;IACI,YAAY,CAAC,IAAI,UAAO,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAYrD,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIpC,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1D;;;;;;OAMG;IACU,cAAc,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAWrD,gBAAgB;IAa9B;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAcjC;;;;;OAKG;IACI,qBAAqB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAUpD;;;OAGG;IACH,OAAO,CAAC,eAAe;IAcvB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAiBb,gBAAgB,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAUpD,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7D,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IASrE,sBAAsB,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAgB9D,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAGxC"}
1
+ {"version":3,"file":"indexeddb-local-backend.d.ts","sourceRoot":"","sources":["../../src/store/indexeddb-local-backend.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAsC,KAAK,aAAa,EAAmB,MAAM,wBAAwB,CAAC;AAIjH,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAmGtG,qBAAa,0BAA2B,YAAW,iBAAiB;IAyB5D,OAAO,CAAC,QAAQ,CAAC,SAAS;WAxBhB,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK7E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,EAAE,CAAC,CAAc;IACzB,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,qBAAqB,CAAC,CAAgB;IAC9C,OAAO,CAAC,uBAAuB,CAAmB;IAElD;;;;;;;;;OASG;gBAEkB,SAAS,EAAE,UAAU,EACtC,MAAM,SAAY;IAMtB;;;;OAIG;IACI,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAiDnD,8EAA8E;IACvE,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;;OAGG;IACH,OAAO,CAAC,IAAI;IAgBZ;;;;;OAKG;IACI,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,EAAE,GAAG,IAAI,CAAC;IA0CnF;;;;;OAKG;IACU,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7F,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCjE;;;;OAIG;IACI,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BrC;;;;;;;;OAQG;IACI,YAAY,CAAC,IAAI,UAAO,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAYrD,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIpC,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1D;;;;;;OAMG;IACU,cAAc,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAWrD,gBAAgB;IAa9B;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAcjC;;;;;OAKG;IACI,qBAAqB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAUpD;;;OAGG;IACH,OAAO,CAAC,eAAe;IAcvB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAiBb,gBAAgB,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAUpD,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7D,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IASrE,sBAAsB,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAgB9D,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAGxC"}
@@ -63,14 +63,16 @@ var VERSION = DB_MIGRATIONS.length;
63
63
  * Return the data you want to keep.
64
64
  * @returns Promise which resolves to an array of whatever you returned from
65
65
  * resultMapper.
66
+ * @throws If there was an error completing the query.
66
67
  */
67
68
  function selectQuery(store, keyRange, resultMapper) {
68
69
  var query = store.openCursor(keyRange);
69
70
  return new Promise((resolve, reject) => {
70
71
  var results = [];
71
72
  query.onerror = () => {
72
- var _query$error;
73
- reject(new Error("Query failed: " + ((_query$error = query.error) === null || _query$error === void 0 ? void 0 : _query$error.name)));
73
+ reject(new Error("selectQuery failed for ".concat(store.name), {
74
+ cause: query.error
75
+ }));
74
76
  };
75
77
  // collect results
76
78
  query.onsuccess = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"indexeddb-local-backend.js","names":["SyncAccumulator","deepCopy","promiseTry","exists","idbExists","logger","DB_MIGRATIONS","db","createObjectStore","keyPath","oobMembersStore","createIndex","autoIncrement","VERSION","length","selectQuery","store","keyRange","resultMapper","query","openCursor","Promise","resolve","reject","results","onerror","_query$error","Error","error","name","onsuccess","cursor","result","push","continue","txnAsPromise","txn","oncomplete","event","reqAsEventPromise","req","reqAsPromise","err","reqAsCursorPromise","then","LocalIndexedDBStoreBackend","indexedDB","dbName","constructor","arguments","undefined","_defineProperty","syncAccumulator","connect","onClose","_this","disconnected","log","open","onupgradeneeded","ev","oldVersion","concat","_isNewlyCreated","forEach","migration","index","onblocked","_asyncToGenerator","onversionchange","_this$db","close","onclose","init","isNewlyCreated","all","loadAccountData","loadSyncData","_ref2","accountData","syncData","accumulate","next_batch","nextBatch","rooms","roomsData","account_data","events","getOutOfBandMembers","roomId","tx","transaction","objectStore","roomIndex","range","IDBKeyRange","only","request","membershipEvents","oobWritten","record","value","oob_written","setOutOfBandMembers","_this2","e","put","markerObject","room_id","state_key","clearOutOfBandMembers","_this3","readTx","roomRange","minStateKeyProm","openKeyCursor","primaryKey","maxStateKeyProm","minStateKey","maxStateKey","writeTx","writeStore","membersKeyRange","bound","delete","clearDatabase","_this$db2","deleteDatabase","_req$error","warn","getSavedSync","copy","data","getJSON","getNextBatchToken","setSyncData","syncToDatabase","userTuples","_this4","syncToDatabasePromise","pendingUserPresenceData","unshift","doSyncToDatabase","_this5","persistUserPresenceEvents","persistAccountData","persistSyncData","clobber","tuples","tuple","userId","getUserPresenceEvents","getClientOptions","_cursor$value","options","storeClientOptions","_this6","saveToDeviceBatches","batches","_this7","batch","add","getOldestToDeviceBatch","_this8","resultBatch","id","key","txnId","eventType","removeToDeviceBatch","_this9","destroy","_this0","_this0$db"],"sources":["../../src/store/indexeddb-local-backend.ts"],"sourcesContent":["/*\nCopyright 2017 - 2021 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\nimport { type IMinimalEvent, type ISyncData, type ISyncResponse, SyncAccumulator } from \"../sync-accumulator.ts\";\nimport { deepCopy, promiseTry } from \"../utils.ts\";\nimport { exists as idbExists } from \"../indexeddb-helpers.ts\";\nimport { logger } from \"../logger.ts\";\nimport { type IStateEventWithRoomId, type IStoredClientOpts } from \"../matrix.ts\";\nimport { type ISavedSync } from \"./index.ts\";\nimport { type IIndexedDBBackend, type UserTuple } from \"./indexeddb-backend.ts\";\nimport { type IndexedToDeviceBatch, type ToDeviceBatchWithTxnId } from \"../models/ToDeviceMessage.ts\";\n\ntype DbMigration = (db: IDBDatabase) => void;\nconst DB_MIGRATIONS: DbMigration[] = [\n (db): void => {\n // Make user store, clobber based on user ID. (userId property of User objects)\n db.createObjectStore(\"users\", { keyPath: [\"userId\"] });\n\n // Make account data store, clobber based on event type.\n // (event.type property of MatrixEvent objects)\n db.createObjectStore(\"accountData\", { keyPath: [\"type\"] });\n\n // Make /sync store (sync tokens, room data, etc), always clobber (const key).\n db.createObjectStore(\"sync\", { keyPath: [\"clobber\"] });\n },\n (db): void => {\n const oobMembersStore = db.createObjectStore(\"oob_membership_events\", {\n keyPath: [\"room_id\", \"state_key\"],\n });\n oobMembersStore.createIndex(\"room\", \"room_id\");\n },\n (db): void => {\n db.createObjectStore(\"client_options\", { keyPath: [\"clobber\"] });\n },\n (db): void => {\n db.createObjectStore(\"to_device_queue\", { autoIncrement: true });\n },\n // Expand as needed.\n];\nconst VERSION = DB_MIGRATIONS.length;\n\n/**\n * Helper method to collect results from a Cursor and promiseify it.\n * @param store - The store to perform openCursor on.\n * @param keyRange - Optional key range to apply on the cursor.\n * @param resultMapper - A function which is repeatedly called with a\n * Cursor.\n * Return the data you want to keep.\n * @returns Promise which resolves to an array of whatever you returned from\n * resultMapper.\n */\nfunction selectQuery<T>(\n store: IDBObjectStore,\n keyRange: IDBKeyRange | IDBValidKey | undefined,\n resultMapper: (cursor: IDBCursorWithValue) => T,\n): Promise<T[]> {\n const query = store.openCursor(keyRange);\n return new Promise((resolve, reject) => {\n const results: T[] = [];\n query.onerror = (): void => {\n reject(new Error(\"Query failed: \" + query.error?.name));\n };\n // collect results\n query.onsuccess = (): void => {\n const cursor = query.result;\n if (!cursor) {\n resolve(results);\n return; // end of results\n }\n results.push(resultMapper(cursor));\n cursor.continue();\n };\n });\n}\n\nfunction txnAsPromise(txn: IDBTransaction): Promise<Event> {\n return new Promise((resolve, reject) => {\n txn.oncomplete = function (event): void {\n resolve(event);\n };\n txn.onerror = function (): void {\n reject(txn.error);\n };\n });\n}\n\nfunction reqAsEventPromise(req: IDBRequest): Promise<Event> {\n return new Promise((resolve, reject) => {\n req.onsuccess = function (event): void {\n resolve(event);\n };\n req.onerror = function (): void {\n reject(req.error);\n };\n });\n}\n\nfunction reqAsPromise(req: IDBRequest): Promise<IDBRequest> {\n return new Promise((resolve, reject) => {\n req.onsuccess = (): void => resolve(req);\n req.onerror = (err): void => reject(err);\n });\n}\n\nfunction reqAsCursorPromise<T>(req: IDBRequest<T>): Promise<T> {\n return reqAsEventPromise(req).then((event) => req.result);\n}\n\nexport class LocalIndexedDBStoreBackend implements IIndexedDBBackend {\n public static exists(indexedDB: IDBFactory, dbName: string): Promise<boolean> {\n dbName = \"matrix-js-sdk:\" + (dbName || \"default\");\n return idbExists(indexedDB, dbName);\n }\n\n private readonly dbName: string;\n private readonly syncAccumulator: SyncAccumulator;\n private db?: IDBDatabase;\n private disconnected = true;\n private _isNewlyCreated = false;\n private syncToDatabasePromise?: Promise<void>;\n private pendingUserPresenceData: UserTuple[] = [];\n\n /**\n * Does the actual reading from and writing to the indexeddb\n *\n * Construct a new Indexed Database store backend. This requires a call to\n * `connect()` before this store can be used.\n * @param indexedDB - The Indexed DB interface e.g\n * `window.indexedDB`\n * @param dbName - Optional database name. The same name must be used\n * to open the same database.\n */\n public constructor(\n private readonly indexedDB: IDBFactory,\n dbName = \"default\",\n ) {\n this.dbName = \"matrix-js-sdk:\" + dbName;\n this.syncAccumulator = new SyncAccumulator();\n }\n\n /**\n * Attempt to connect to the database. This can fail if the user does not\n * grant permission.\n * @returns Promise which resolves if successfully connected.\n */\n public connect(onClose?: () => void): Promise<void> {\n if (!this.disconnected) {\n logger.log(`LocalIndexedDBStoreBackend.connect: already connected or connecting`);\n return Promise.resolve();\n }\n\n this.disconnected = false;\n\n logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`);\n const req = this.indexedDB.open(this.dbName, VERSION);\n req.onupgradeneeded = (ev): void => {\n const db = req.result;\n const oldVersion = ev.oldVersion;\n logger.log(`LocalIndexedDBStoreBackend.connect: upgrading from ${oldVersion}`);\n if (oldVersion < 1) {\n // The database did not previously exist\n this._isNewlyCreated = true;\n }\n DB_MIGRATIONS.forEach((migration, index) => {\n if (oldVersion <= index) migration(db);\n });\n };\n\n req.onblocked = (): void => {\n logger.log(`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`);\n };\n\n logger.log(`LocalIndexedDBStoreBackend.connect: awaiting connection...`);\n return reqAsEventPromise(req).then(async () => {\n logger.log(`LocalIndexedDBStoreBackend.connect: connected`);\n this.db = req.result;\n\n // add a poorly-named listener for when deleteDatabase is called\n // so we can close our db connections.\n this.db.onversionchange = (): void => {\n this.db?.close(); // this does not call onclose\n this.disconnected = true;\n this.db = undefined;\n };\n this.db.onclose = (): void => {\n this.disconnected = true;\n this.db = undefined;\n onClose?.();\n };\n\n await this.init();\n });\n }\n\n /** @returns whether or not the database was newly created in this session. */\n public isNewlyCreated(): Promise<boolean> {\n return Promise.resolve(this._isNewlyCreated);\n }\n\n /**\n * Having connected, load initial data from the database and prepare for use\n * @returns Promise which resolves on success\n */\n private init(): Promise<unknown> {\n return Promise.all([this.loadAccountData(), this.loadSyncData()]).then(([accountData, syncData]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded initial data`);\n this.syncAccumulator.accumulate(\n {\n next_batch: syncData.nextBatch,\n rooms: syncData.roomsData,\n account_data: {\n events: accountData,\n },\n },\n true,\n );\n });\n }\n\n /**\n * Returns the out-of-band membership events for this room that\n * were previously loaded.\n * @returns the events, potentially an empty array if OOB loading didn't yield any new members\n * @returns in case the members for this room haven't been stored yet\n */\n public getOutOfBandMembers(roomId: string): Promise<IStateEventWithRoomId[] | null> {\n return new Promise<IStateEventWithRoomId[] | null>((resolve, reject) => {\n const tx = this.db!.transaction([\"oob_membership_events\"], \"readonly\");\n const store = tx.objectStore(\"oob_membership_events\");\n const roomIndex = store.index(\"room\");\n const range = IDBKeyRange.only(roomId);\n const request = roomIndex.openCursor(range);\n\n const membershipEvents: IStateEventWithRoomId[] = [];\n // did we encounter the oob_written marker object\n // amongst the results? That means OOB member\n // loading already happened for this room\n // but there were no members to persist as they\n // were all known already\n let oobWritten = false;\n\n request.onsuccess = (): void => {\n const cursor = request.result;\n if (!cursor) {\n // Unknown room\n if (!membershipEvents.length && !oobWritten) {\n return resolve(null);\n }\n return resolve(membershipEvents);\n }\n const record = cursor.value;\n if (record.oob_written) {\n oobWritten = true;\n } else {\n membershipEvents.push(record);\n }\n cursor.continue();\n };\n request.onerror = (err): void => {\n reject(err);\n };\n }).then((events) => {\n logger.log(`LL: got ${events?.length} membershipEvents from storage for room ${roomId} ...`);\n return events;\n });\n }\n\n /**\n * Stores the out-of-band membership events for this room. Note that\n * it still makes sense to store an empty array as the OOB status for the room is\n * marked as fetched, and getOutOfBandMembers will return an empty array instead of null\n * @param membershipEvents - the membership events to store\n */\n public async setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> {\n logger.log(`LL: backend about to store ${membershipEvents.length}` + ` members for ${roomId}`);\n const tx = this.db!.transaction([\"oob_membership_events\"], \"readwrite\");\n const store = tx.objectStore(\"oob_membership_events\");\n membershipEvents.forEach((e) => {\n store.put(e);\n });\n // aside from all the events, we also write a marker object to the store\n // to mark the fact that OOB members have been written for this room.\n // It's possible that 0 members need to be written as all where previously know\n // but we still need to know whether to return null or [] from getOutOfBandMembers\n // where null means out of band members haven't been stored yet for this room\n const markerObject = {\n room_id: roomId,\n oob_written: true,\n state_key: 0,\n };\n store.put(markerObject);\n await txnAsPromise(tx);\n logger.log(`LL: backend done storing for ${roomId}!`);\n }\n\n public async clearOutOfBandMembers(roomId: string): Promise<void> {\n // the approach to delete all members for a room\n // is to get the min and max state key from the index\n // for that room, and then delete between those\n // keys in the store.\n // this should be way faster than deleting every member\n // individually for a large room.\n const readTx = this.db!.transaction([\"oob_membership_events\"], \"readonly\");\n const store = readTx.objectStore(\"oob_membership_events\");\n const roomIndex = store.index(\"room\");\n const roomRange = IDBKeyRange.only(roomId);\n\n const minStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, \"next\")).then(\n (cursor) => (<IDBValidKey[]>cursor?.primaryKey)[1],\n );\n const maxStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, \"prev\")).then(\n (cursor) => (<IDBValidKey[]>cursor?.primaryKey)[1],\n );\n const [minStateKey, maxStateKey] = await Promise.all([minStateKeyProm, maxStateKeyProm]);\n\n const writeTx = this.db!.transaction([\"oob_membership_events\"], \"readwrite\");\n const writeStore = writeTx.objectStore(\"oob_membership_events\");\n const membersKeyRange = IDBKeyRange.bound([roomId, minStateKey], [roomId, maxStateKey]);\n\n logger.log(\n `LL: Deleting all users + marker in storage for room ${roomId}, with key range:`,\n [roomId, minStateKey],\n [roomId, maxStateKey],\n );\n await reqAsPromise(writeStore.delete(membersKeyRange));\n }\n\n /**\n * Clear the entire database. This should be used when logging out of a client\n * to prevent mixing data between accounts. Closes the database.\n * @returns Resolved when the database is cleared.\n */\n public clearDatabase(): Promise<void> {\n return new Promise((resolve) => {\n logger.log(`Removing indexeddb instance: ${this.dbName}`);\n\n // Close the database first to avoid firing unexpected close events\n this.db?.close();\n\n const req = this.indexedDB.deleteDatabase(this.dbName);\n\n req.onblocked = (): void => {\n logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`);\n };\n\n req.onerror = (): void => {\n // in firefox, with indexedDB disabled, this fails with a\n // DOMError. We treat this as non-fatal, so that we can still\n // use the app.\n logger.warn(`unable to delete js-sdk store indexeddb: ${req.error?.name}`);\n resolve();\n };\n\n req.onsuccess = (): void => {\n logger.log(`Removed indexeddb instance: ${this.dbName}`);\n resolve();\n };\n });\n }\n\n /**\n * @param copy - If false, the data returned is from internal\n * buffers and must not be mutated. Otherwise, a copy is made before\n * returning such that the data can be safely mutated. Default: true.\n *\n * @returns Promise which resolves with a sync response to restore the\n * client state to where it was at the last save, or null if there\n * is no saved sync data.\n */\n public getSavedSync(copy = true): Promise<ISavedSync | null> {\n const data = this.syncAccumulator.getJSON();\n if (!data.nextBatch) return Promise.resolve(null);\n if (copy) {\n // We must deep copy the stored data so that the /sync processing code doesn't\n // corrupt the internal state of the sync accumulator (it adds non-clonable keys)\n return Promise.resolve(deepCopy(data));\n } else {\n return Promise.resolve(data);\n }\n }\n\n public getNextBatchToken(): Promise<string> {\n return Promise.resolve(this.syncAccumulator.getNextBatchToken());\n }\n\n public setSyncData(syncData: ISyncResponse): Promise<void> {\n return Promise.resolve().then(() => {\n this.syncAccumulator.accumulate(syncData);\n });\n }\n\n /**\n * Sync users and all accumulated sync data to the database.\n * If a previous sync is in flight, the new data will be added to the\n * next sync and the current sync's promise will be returned.\n * @param userTuples - The user tuples\n * @returns Promise which resolves if the data was persisted.\n */\n public async syncToDatabase(userTuples: UserTuple[]): Promise<void> {\n if (this.syncToDatabasePromise) {\n logger.warn(\"Skipping syncToDatabase() as persist already in flight\");\n this.pendingUserPresenceData.push(...userTuples);\n return this.syncToDatabasePromise;\n }\n userTuples.unshift(...this.pendingUserPresenceData);\n this.syncToDatabasePromise = this.doSyncToDatabase(userTuples);\n return this.syncToDatabasePromise;\n }\n\n private async doSyncToDatabase(userTuples: UserTuple[]): Promise<void> {\n try {\n const syncData = this.syncAccumulator.getJSON(true);\n await Promise.all([\n this.persistUserPresenceEvents(userTuples),\n this.persistAccountData(syncData.accountData),\n this.persistSyncData(syncData.nextBatch, syncData.roomsData),\n ]);\n } finally {\n this.syncToDatabasePromise = undefined;\n }\n }\n\n /**\n * Persist rooms /sync data along with the next batch token.\n * @param nextBatch - The next_batch /sync value.\n * @param roomsData - The 'rooms' /sync data from a SyncAccumulator\n * @returns Promise which resolves if the data was persisted.\n */\n private persistSyncData(nextBatch: string, roomsData: ISyncResponse[\"rooms\"]): Promise<void> {\n logger.log(\"Persisting sync data up to\", nextBatch);\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"sync\"], \"readwrite\");\n const store = txn.objectStore(\"sync\");\n store.put({\n clobber: \"-\", // constant key so will always clobber\n nextBatch,\n roomsData,\n }); // put == UPSERT\n return txnAsPromise(txn).then(() => {\n logger.log(\"Persisted sync data up to\", nextBatch);\n });\n });\n }\n\n /**\n * Persist a list of account data events. Events with the same 'type' will\n * be replaced.\n * @param accountData - An array of raw user-scoped account data events\n * @returns Promise which resolves if the events were persisted.\n */\n private persistAccountData(accountData: IMinimalEvent[]): Promise<void> {\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"accountData\"], \"readwrite\");\n const store = txn.objectStore(\"accountData\");\n for (const event of accountData) {\n store.put(event); // put == UPSERT\n }\n return txnAsPromise(txn).then();\n });\n }\n\n /**\n * Persist a list of [user id, presence event] they are for.\n * Users with the same 'userId' will be replaced.\n * Presence events should be the event in its raw form (not the Event\n * object)\n * @param tuples - An array of [userid, event] tuples\n * @returns Promise which resolves if the users were persisted.\n */\n private persistUserPresenceEvents(tuples: UserTuple[]): Promise<void> {\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"users\"], \"readwrite\");\n const store = txn.objectStore(\"users\");\n for (const tuple of tuples) {\n store.put({\n userId: tuple[0],\n event: tuple[1],\n }); // put == UPSERT\n }\n return txnAsPromise(txn).then();\n });\n }\n\n /**\n * Load all user presence events from the database. This is not cached.\n * FIXME: It would probably be more sensible to store the events in the\n * sync.\n * @returns A list of presence events in their raw form.\n */\n public getUserPresenceEvents(): Promise<UserTuple[]> {\n return promiseTry<UserTuple[]>(() => {\n const txn = this.db!.transaction([\"users\"], \"readonly\");\n const store = txn.objectStore(\"users\");\n return selectQuery(store, undefined, (cursor) => {\n return [cursor.value.userId, cursor.value.event];\n });\n });\n }\n\n /**\n * Load all the account data events from the database. This is not cached.\n * @returns A list of raw global account events.\n */\n private loadAccountData(): Promise<IMinimalEvent[]> {\n logger.log(`LocalIndexedDBStoreBackend: loading account data...`);\n return promiseTry<IMinimalEvent[]>(() => {\n const txn = this.db!.transaction([\"accountData\"], \"readonly\");\n const store = txn.objectStore(\"accountData\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value;\n }).then((result: IMinimalEvent[]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded account data`);\n return result;\n });\n });\n }\n\n /**\n * Load the sync data from the database.\n * @returns An object with \"roomsData\" and \"nextBatch\" keys.\n */\n private loadSyncData(): Promise<ISyncData> {\n logger.log(`LocalIndexedDBStoreBackend: loading sync data...`);\n return promiseTry<ISyncData>(() => {\n const txn = this.db!.transaction([\"sync\"], \"readonly\");\n const store = txn.objectStore(\"sync\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value;\n }).then((results: ISyncData[]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded sync data`);\n if (results.length > 1) {\n logger.warn(\"loadSyncData: More than 1 sync row found.\");\n }\n return results.length > 0 ? results[0] : ({} as ISyncData);\n });\n });\n }\n\n public getClientOptions(): Promise<IStoredClientOpts | undefined> {\n return Promise.resolve().then(() => {\n const txn = this.db!.transaction([\"client_options\"], \"readonly\");\n const store = txn.objectStore(\"client_options\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value?.options;\n }).then((results) => results[0]);\n });\n }\n\n public async storeClientOptions(options: IStoredClientOpts): Promise<void> {\n const txn = this.db!.transaction([\"client_options\"], \"readwrite\");\n const store = txn.objectStore(\"client_options\");\n store.put({\n clobber: \"-\", // constant key so will always clobber\n options: options,\n }); // put == UPSERT\n await txnAsPromise(txn);\n }\n\n public async saveToDeviceBatches(batches: ToDeviceBatchWithTxnId[]): Promise<void> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readwrite\");\n const store = txn.objectStore(\"to_device_queue\");\n for (const batch of batches) {\n store.add(batch);\n }\n await txnAsPromise(txn);\n }\n\n public async getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readonly\");\n const store = txn.objectStore(\"to_device_queue\");\n const cursor = await reqAsCursorPromise(store.openCursor());\n if (!cursor) return null;\n\n const resultBatch = cursor.value as ToDeviceBatchWithTxnId;\n\n return {\n id: cursor.key as number,\n txnId: resultBatch.txnId,\n eventType: resultBatch.eventType,\n batch: resultBatch.batch,\n };\n }\n\n public async removeToDeviceBatch(id: number): Promise<void> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readwrite\");\n const store = txn.objectStore(\"to_device_queue\");\n store.delete(id);\n await txnAsPromise(txn);\n }\n\n /*\n * Close the database\n */\n public async destroy(): Promise<void> {\n this.db?.close();\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"indexeddb-local-backend.js","names":["SyncAccumulator","deepCopy","promiseTry","exists","idbExists","logger","DB_MIGRATIONS","db","createObjectStore","keyPath","oobMembersStore","createIndex","autoIncrement","VERSION","length","selectQuery","store","keyRange","resultMapper","query","openCursor","Promise","resolve","reject","results","onerror","Error","concat","name","cause","error","onsuccess","cursor","result","push","continue","txnAsPromise","txn","oncomplete","event","reqAsEventPromise","req","reqAsPromise","err","reqAsCursorPromise","then","LocalIndexedDBStoreBackend","indexedDB","dbName","constructor","arguments","undefined","_defineProperty","syncAccumulator","connect","onClose","_this","disconnected","log","open","onupgradeneeded","ev","oldVersion","_isNewlyCreated","forEach","migration","index","onblocked","_asyncToGenerator","onversionchange","_this$db","close","onclose","init","isNewlyCreated","all","loadAccountData","loadSyncData","_ref2","accountData","syncData","accumulate","next_batch","nextBatch","rooms","roomsData","account_data","events","getOutOfBandMembers","roomId","tx","transaction","objectStore","roomIndex","range","IDBKeyRange","only","request","membershipEvents","oobWritten","record","value","oob_written","setOutOfBandMembers","_this2","e","put","markerObject","room_id","state_key","clearOutOfBandMembers","_this3","readTx","roomRange","minStateKeyProm","openKeyCursor","primaryKey","maxStateKeyProm","minStateKey","maxStateKey","writeTx","writeStore","membersKeyRange","bound","delete","clearDatabase","_this$db2","deleteDatabase","_req$error","warn","getSavedSync","copy","data","getJSON","getNextBatchToken","setSyncData","syncToDatabase","userTuples","_this4","syncToDatabasePromise","pendingUserPresenceData","unshift","doSyncToDatabase","_this5","persistUserPresenceEvents","persistAccountData","persistSyncData","clobber","tuples","tuple","userId","getUserPresenceEvents","getClientOptions","_cursor$value","options","storeClientOptions","_this6","saveToDeviceBatches","batches","_this7","batch","add","getOldestToDeviceBatch","_this8","resultBatch","id","key","txnId","eventType","removeToDeviceBatch","_this9","destroy","_this0","_this0$db"],"sources":["../../src/store/indexeddb-local-backend.ts"],"sourcesContent":["/*\nCopyright 2017 - 2021 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\nimport { type IMinimalEvent, type ISyncData, type ISyncResponse, SyncAccumulator } from \"../sync-accumulator.ts\";\nimport { deepCopy, promiseTry } from \"../utils.ts\";\nimport { exists as idbExists } from \"../indexeddb-helpers.ts\";\nimport { logger } from \"../logger.ts\";\nimport { type IStateEventWithRoomId, type IStoredClientOpts } from \"../matrix.ts\";\nimport { type ISavedSync } from \"./index.ts\";\nimport { type IIndexedDBBackend, type UserTuple } from \"./indexeddb-backend.ts\";\nimport { type IndexedToDeviceBatch, type ToDeviceBatchWithTxnId } from \"../models/ToDeviceMessage.ts\";\n\ntype DbMigration = (db: IDBDatabase) => void;\nconst DB_MIGRATIONS: DbMigration[] = [\n (db): void => {\n // Make user store, clobber based on user ID. (userId property of User objects)\n db.createObjectStore(\"users\", { keyPath: [\"userId\"] });\n\n // Make account data store, clobber based on event type.\n // (event.type property of MatrixEvent objects)\n db.createObjectStore(\"accountData\", { keyPath: [\"type\"] });\n\n // Make /sync store (sync tokens, room data, etc), always clobber (const key).\n db.createObjectStore(\"sync\", { keyPath: [\"clobber\"] });\n },\n (db): void => {\n const oobMembersStore = db.createObjectStore(\"oob_membership_events\", {\n keyPath: [\"room_id\", \"state_key\"],\n });\n oobMembersStore.createIndex(\"room\", \"room_id\");\n },\n (db): void => {\n db.createObjectStore(\"client_options\", { keyPath: [\"clobber\"] });\n },\n (db): void => {\n db.createObjectStore(\"to_device_queue\", { autoIncrement: true });\n },\n // Expand as needed.\n];\nconst VERSION = DB_MIGRATIONS.length;\n\n/**\n * Helper method to collect results from a Cursor and promiseify it.\n * @param store - The store to perform openCursor on.\n * @param keyRange - Optional key range to apply on the cursor.\n * @param resultMapper - A function which is repeatedly called with a\n * Cursor.\n * Return the data you want to keep.\n * @returns Promise which resolves to an array of whatever you returned from\n * resultMapper.\n * @throws If there was an error completing the query.\n */\nfunction selectQuery<T>(\n store: IDBObjectStore,\n keyRange: IDBKeyRange | IDBValidKey | undefined,\n resultMapper: (cursor: IDBCursorWithValue) => T,\n): Promise<T[]> {\n const query = store.openCursor(keyRange);\n return new Promise((resolve, reject) => {\n const results: T[] = [];\n query.onerror = (): void => {\n reject(new Error(`selectQuery failed for ${store.name}`, { cause: query.error }));\n };\n // collect results\n query.onsuccess = (): void => {\n const cursor = query.result;\n if (!cursor) {\n resolve(results);\n return; // end of results\n }\n results.push(resultMapper(cursor));\n cursor.continue();\n };\n });\n}\n\nfunction txnAsPromise(txn: IDBTransaction): Promise<Event> {\n return new Promise((resolve, reject) => {\n txn.oncomplete = function (event): void {\n resolve(event);\n };\n txn.onerror = function (): void {\n reject(txn.error);\n };\n });\n}\n\nfunction reqAsEventPromise(req: IDBRequest): Promise<Event> {\n return new Promise((resolve, reject) => {\n req.onsuccess = function (event): void {\n resolve(event);\n };\n req.onerror = function (): void {\n reject(req.error);\n };\n });\n}\n\nfunction reqAsPromise(req: IDBRequest): Promise<IDBRequest> {\n return new Promise((resolve, reject) => {\n req.onsuccess = (): void => resolve(req);\n req.onerror = (err): void => reject(err);\n });\n}\n\nfunction reqAsCursorPromise<T>(req: IDBRequest<T>): Promise<T> {\n return reqAsEventPromise(req).then((event) => req.result);\n}\n\nexport class LocalIndexedDBStoreBackend implements IIndexedDBBackend {\n public static exists(indexedDB: IDBFactory, dbName: string): Promise<boolean> {\n dbName = \"matrix-js-sdk:\" + (dbName || \"default\");\n return idbExists(indexedDB, dbName);\n }\n\n private readonly dbName: string;\n private readonly syncAccumulator: SyncAccumulator;\n private db?: IDBDatabase;\n private disconnected = true;\n private _isNewlyCreated = false;\n private syncToDatabasePromise?: Promise<void>;\n private pendingUserPresenceData: UserTuple[] = [];\n\n /**\n * Does the actual reading from and writing to the indexeddb\n *\n * Construct a new Indexed Database store backend. This requires a call to\n * `connect()` before this store can be used.\n * @param indexedDB - The Indexed DB interface e.g\n * `window.indexedDB`\n * @param dbName - Optional database name. The same name must be used\n * to open the same database.\n */\n public constructor(\n private readonly indexedDB: IDBFactory,\n dbName = \"default\",\n ) {\n this.dbName = \"matrix-js-sdk:\" + dbName;\n this.syncAccumulator = new SyncAccumulator();\n }\n\n /**\n * Attempt to connect to the database. This can fail if the user does not\n * grant permission.\n * @returns Promise which resolves if successfully connected.\n */\n public connect(onClose?: () => void): Promise<void> {\n if (!this.disconnected) {\n logger.log(`LocalIndexedDBStoreBackend.connect: already connected or connecting`);\n return Promise.resolve();\n }\n\n this.disconnected = false;\n\n logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`);\n const req = this.indexedDB.open(this.dbName, VERSION);\n req.onupgradeneeded = (ev): void => {\n const db = req.result;\n const oldVersion = ev.oldVersion;\n logger.log(`LocalIndexedDBStoreBackend.connect: upgrading from ${oldVersion}`);\n if (oldVersion < 1) {\n // The database did not previously exist\n this._isNewlyCreated = true;\n }\n DB_MIGRATIONS.forEach((migration, index) => {\n if (oldVersion <= index) migration(db);\n });\n };\n\n req.onblocked = (): void => {\n logger.log(`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`);\n };\n\n logger.log(`LocalIndexedDBStoreBackend.connect: awaiting connection...`);\n return reqAsEventPromise(req).then(async () => {\n logger.log(`LocalIndexedDBStoreBackend.connect: connected`);\n this.db = req.result;\n\n // add a poorly-named listener for when deleteDatabase is called\n // so we can close our db connections.\n this.db.onversionchange = (): void => {\n this.db?.close(); // this does not call onclose\n this.disconnected = true;\n this.db = undefined;\n };\n this.db.onclose = (): void => {\n this.disconnected = true;\n this.db = undefined;\n onClose?.();\n };\n\n await this.init();\n });\n }\n\n /** @returns whether or not the database was newly created in this session. */\n public isNewlyCreated(): Promise<boolean> {\n return Promise.resolve(this._isNewlyCreated);\n }\n\n /**\n * Having connected, load initial data from the database and prepare for use\n * @returns Promise which resolves on success\n */\n private init(): Promise<unknown> {\n return Promise.all([this.loadAccountData(), this.loadSyncData()]).then(([accountData, syncData]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded initial data`);\n this.syncAccumulator.accumulate(\n {\n next_batch: syncData.nextBatch,\n rooms: syncData.roomsData,\n account_data: {\n events: accountData,\n },\n },\n true,\n );\n });\n }\n\n /**\n * Returns the out-of-band membership events for this room that\n * were previously loaded.\n * @returns the events, potentially an empty array if OOB loading didn't yield any new members\n * @returns in case the members for this room haven't been stored yet\n */\n public getOutOfBandMembers(roomId: string): Promise<IStateEventWithRoomId[] | null> {\n return new Promise<IStateEventWithRoomId[] | null>((resolve, reject) => {\n const tx = this.db!.transaction([\"oob_membership_events\"], \"readonly\");\n const store = tx.objectStore(\"oob_membership_events\");\n const roomIndex = store.index(\"room\");\n const range = IDBKeyRange.only(roomId);\n const request = roomIndex.openCursor(range);\n\n const membershipEvents: IStateEventWithRoomId[] = [];\n // did we encounter the oob_written marker object\n // amongst the results? That means OOB member\n // loading already happened for this room\n // but there were no members to persist as they\n // were all known already\n let oobWritten = false;\n\n request.onsuccess = (): void => {\n const cursor = request.result;\n if (!cursor) {\n // Unknown room\n if (!membershipEvents.length && !oobWritten) {\n return resolve(null);\n }\n return resolve(membershipEvents);\n }\n const record = cursor.value;\n if (record.oob_written) {\n oobWritten = true;\n } else {\n membershipEvents.push(record);\n }\n cursor.continue();\n };\n request.onerror = (err): void => {\n reject(err);\n };\n }).then((events) => {\n logger.log(`LL: got ${events?.length} membershipEvents from storage for room ${roomId} ...`);\n return events;\n });\n }\n\n /**\n * Stores the out-of-band membership events for this room. Note that\n * it still makes sense to store an empty array as the OOB status for the room is\n * marked as fetched, and getOutOfBandMembers will return an empty array instead of null\n * @param membershipEvents - the membership events to store\n */\n public async setOutOfBandMembers(roomId: string, membershipEvents: IStateEventWithRoomId[]): Promise<void> {\n logger.log(`LL: backend about to store ${membershipEvents.length}` + ` members for ${roomId}`);\n const tx = this.db!.transaction([\"oob_membership_events\"], \"readwrite\");\n const store = tx.objectStore(\"oob_membership_events\");\n membershipEvents.forEach((e) => {\n store.put(e);\n });\n // aside from all the events, we also write a marker object to the store\n // to mark the fact that OOB members have been written for this room.\n // It's possible that 0 members need to be written as all where previously know\n // but we still need to know whether to return null or [] from getOutOfBandMembers\n // where null means out of band members haven't been stored yet for this room\n const markerObject = {\n room_id: roomId,\n oob_written: true,\n state_key: 0,\n };\n store.put(markerObject);\n await txnAsPromise(tx);\n logger.log(`LL: backend done storing for ${roomId}!`);\n }\n\n public async clearOutOfBandMembers(roomId: string): Promise<void> {\n // the approach to delete all members for a room\n // is to get the min and max state key from the index\n // for that room, and then delete between those\n // keys in the store.\n // this should be way faster than deleting every member\n // individually for a large room.\n const readTx = this.db!.transaction([\"oob_membership_events\"], \"readonly\");\n const store = readTx.objectStore(\"oob_membership_events\");\n const roomIndex = store.index(\"room\");\n const roomRange = IDBKeyRange.only(roomId);\n\n const minStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, \"next\")).then(\n (cursor) => (<IDBValidKey[]>cursor?.primaryKey)[1],\n );\n const maxStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, \"prev\")).then(\n (cursor) => (<IDBValidKey[]>cursor?.primaryKey)[1],\n );\n const [minStateKey, maxStateKey] = await Promise.all([minStateKeyProm, maxStateKeyProm]);\n\n const writeTx = this.db!.transaction([\"oob_membership_events\"], \"readwrite\");\n const writeStore = writeTx.objectStore(\"oob_membership_events\");\n const membersKeyRange = IDBKeyRange.bound([roomId, minStateKey], [roomId, maxStateKey]);\n\n logger.log(\n `LL: Deleting all users + marker in storage for room ${roomId}, with key range:`,\n [roomId, minStateKey],\n [roomId, maxStateKey],\n );\n await reqAsPromise(writeStore.delete(membersKeyRange));\n }\n\n /**\n * Clear the entire database. This should be used when logging out of a client\n * to prevent mixing data between accounts. Closes the database.\n * @returns Resolved when the database is cleared.\n */\n public clearDatabase(): Promise<void> {\n return new Promise((resolve) => {\n logger.log(`Removing indexeddb instance: ${this.dbName}`);\n\n // Close the database first to avoid firing unexpected close events\n this.db?.close();\n\n const req = this.indexedDB.deleteDatabase(this.dbName);\n\n req.onblocked = (): void => {\n logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`);\n };\n\n req.onerror = (): void => {\n // in firefox, with indexedDB disabled, this fails with a\n // DOMError. We treat this as non-fatal, so that we can still\n // use the app.\n logger.warn(`unable to delete js-sdk store indexeddb: ${req.error?.name}`);\n resolve();\n };\n\n req.onsuccess = (): void => {\n logger.log(`Removed indexeddb instance: ${this.dbName}`);\n resolve();\n };\n });\n }\n\n /**\n * @param copy - If false, the data returned is from internal\n * buffers and must not be mutated. Otherwise, a copy is made before\n * returning such that the data can be safely mutated. Default: true.\n *\n * @returns Promise which resolves with a sync response to restore the\n * client state to where it was at the last save, or null if there\n * is no saved sync data.\n */\n public getSavedSync(copy = true): Promise<ISavedSync | null> {\n const data = this.syncAccumulator.getJSON();\n if (!data.nextBatch) return Promise.resolve(null);\n if (copy) {\n // We must deep copy the stored data so that the /sync processing code doesn't\n // corrupt the internal state of the sync accumulator (it adds non-clonable keys)\n return Promise.resolve(deepCopy(data));\n } else {\n return Promise.resolve(data);\n }\n }\n\n public getNextBatchToken(): Promise<string> {\n return Promise.resolve(this.syncAccumulator.getNextBatchToken());\n }\n\n public setSyncData(syncData: ISyncResponse): Promise<void> {\n return Promise.resolve().then(() => {\n this.syncAccumulator.accumulate(syncData);\n });\n }\n\n /**\n * Sync users and all accumulated sync data to the database.\n * If a previous sync is in flight, the new data will be added to the\n * next sync and the current sync's promise will be returned.\n * @param userTuples - The user tuples\n * @returns Promise which resolves if the data was persisted.\n */\n public async syncToDatabase(userTuples: UserTuple[]): Promise<void> {\n if (this.syncToDatabasePromise) {\n logger.warn(\"Skipping syncToDatabase() as persist already in flight\");\n this.pendingUserPresenceData.push(...userTuples);\n return this.syncToDatabasePromise;\n }\n userTuples.unshift(...this.pendingUserPresenceData);\n this.syncToDatabasePromise = this.doSyncToDatabase(userTuples);\n return this.syncToDatabasePromise;\n }\n\n private async doSyncToDatabase(userTuples: UserTuple[]): Promise<void> {\n try {\n const syncData = this.syncAccumulator.getJSON(true);\n await Promise.all([\n this.persistUserPresenceEvents(userTuples),\n this.persistAccountData(syncData.accountData),\n this.persistSyncData(syncData.nextBatch, syncData.roomsData),\n ]);\n } finally {\n this.syncToDatabasePromise = undefined;\n }\n }\n\n /**\n * Persist rooms /sync data along with the next batch token.\n * @param nextBatch - The next_batch /sync value.\n * @param roomsData - The 'rooms' /sync data from a SyncAccumulator\n * @returns Promise which resolves if the data was persisted.\n */\n private persistSyncData(nextBatch: string, roomsData: ISyncResponse[\"rooms\"]): Promise<void> {\n logger.log(\"Persisting sync data up to\", nextBatch);\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"sync\"], \"readwrite\");\n const store = txn.objectStore(\"sync\");\n store.put({\n clobber: \"-\", // constant key so will always clobber\n nextBatch,\n roomsData,\n }); // put == UPSERT\n return txnAsPromise(txn).then(() => {\n logger.log(\"Persisted sync data up to\", nextBatch);\n });\n });\n }\n\n /**\n * Persist a list of account data events. Events with the same 'type' will\n * be replaced.\n * @param accountData - An array of raw user-scoped account data events\n * @returns Promise which resolves if the events were persisted.\n */\n private persistAccountData(accountData: IMinimalEvent[]): Promise<void> {\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"accountData\"], \"readwrite\");\n const store = txn.objectStore(\"accountData\");\n for (const event of accountData) {\n store.put(event); // put == UPSERT\n }\n return txnAsPromise(txn).then();\n });\n }\n\n /**\n * Persist a list of [user id, presence event] they are for.\n * Users with the same 'userId' will be replaced.\n * Presence events should be the event in its raw form (not the Event\n * object)\n * @param tuples - An array of [userid, event] tuples\n * @returns Promise which resolves if the users were persisted.\n */\n private persistUserPresenceEvents(tuples: UserTuple[]): Promise<void> {\n return promiseTry<void>(() => {\n const txn = this.db!.transaction([\"users\"], \"readwrite\");\n const store = txn.objectStore(\"users\");\n for (const tuple of tuples) {\n store.put({\n userId: tuple[0],\n event: tuple[1],\n }); // put == UPSERT\n }\n return txnAsPromise(txn).then();\n });\n }\n\n /**\n * Load all user presence events from the database. This is not cached.\n * FIXME: It would probably be more sensible to store the events in the\n * sync.\n * @returns A list of presence events in their raw form.\n */\n public getUserPresenceEvents(): Promise<UserTuple[]> {\n return promiseTry<UserTuple[]>(() => {\n const txn = this.db!.transaction([\"users\"], \"readonly\");\n const store = txn.objectStore(\"users\");\n return selectQuery(store, undefined, (cursor) => {\n return [cursor.value.userId, cursor.value.event];\n });\n });\n }\n\n /**\n * Load all the account data events from the database. This is not cached.\n * @returns A list of raw global account events.\n */\n private loadAccountData(): Promise<IMinimalEvent[]> {\n logger.log(`LocalIndexedDBStoreBackend: loading account data...`);\n return promiseTry<IMinimalEvent[]>(() => {\n const txn = this.db!.transaction([\"accountData\"], \"readonly\");\n const store = txn.objectStore(\"accountData\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value;\n }).then((result: IMinimalEvent[]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded account data`);\n return result;\n });\n });\n }\n\n /**\n * Load the sync data from the database.\n * @returns An object with \"roomsData\" and \"nextBatch\" keys.\n */\n private loadSyncData(): Promise<ISyncData> {\n logger.log(`LocalIndexedDBStoreBackend: loading sync data...`);\n return promiseTry<ISyncData>(() => {\n const txn = this.db!.transaction([\"sync\"], \"readonly\");\n const store = txn.objectStore(\"sync\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value;\n }).then((results: ISyncData[]) => {\n logger.log(`LocalIndexedDBStoreBackend: loaded sync data`);\n if (results.length > 1) {\n logger.warn(\"loadSyncData: More than 1 sync row found.\");\n }\n return results.length > 0 ? results[0] : ({} as ISyncData);\n });\n });\n }\n\n public getClientOptions(): Promise<IStoredClientOpts | undefined> {\n return Promise.resolve().then(() => {\n const txn = this.db!.transaction([\"client_options\"], \"readonly\");\n const store = txn.objectStore(\"client_options\");\n return selectQuery(store, undefined, (cursor) => {\n return cursor.value?.options;\n }).then((results) => results[0]);\n });\n }\n\n public async storeClientOptions(options: IStoredClientOpts): Promise<void> {\n const txn = this.db!.transaction([\"client_options\"], \"readwrite\");\n const store = txn.objectStore(\"client_options\");\n store.put({\n clobber: \"-\", // constant key so will always clobber\n options: options,\n }); // put == UPSERT\n await txnAsPromise(txn);\n }\n\n public async saveToDeviceBatches(batches: ToDeviceBatchWithTxnId[]): Promise<void> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readwrite\");\n const store = txn.objectStore(\"to_device_queue\");\n for (const batch of batches) {\n store.add(batch);\n }\n await txnAsPromise(txn);\n }\n\n public async getOldestToDeviceBatch(): Promise<IndexedToDeviceBatch | null> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readonly\");\n const store = txn.objectStore(\"to_device_queue\");\n const cursor = await reqAsCursorPromise(store.openCursor());\n if (!cursor) return null;\n\n const resultBatch = cursor.value as ToDeviceBatchWithTxnId;\n\n return {\n id: cursor.key as number,\n txnId: resultBatch.txnId,\n eventType: resultBatch.eventType,\n batch: resultBatch.batch,\n };\n }\n\n public async removeToDeviceBatch(id: number): Promise<void> {\n const txn = this.db!.transaction([\"to_device_queue\"], \"readwrite\");\n const store = txn.objectStore(\"to_device_queue\");\n store.delete(id);\n await txnAsPromise(txn);\n }\n\n /*\n * Close the database\n */\n public async destroy(): Promise<void> {\n this.db?.close();\n }\n}\n"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAAiEA,eAAe,QAAQ,wBAAwB;AAChH,SAASC,QAAQ,EAAEC,UAAU,QAAQ,aAAa;AAClD,SAASC,MAAM,IAAIC,SAAS,QAAQ,yBAAyB;AAC7D,SAASC,MAAM,QAAQ,cAAc;AAOrC,IAAMC,aAA4B,GAAG,CAChCC,EAAE,IAAW;EACV;EACAA,EAAE,CAACC,iBAAiB,CAAC,OAAO,EAAE;IAAEC,OAAO,EAAE,CAAC,QAAQ;EAAE,CAAC,CAAC;;EAEtD;EACA;EACAF,EAAE,CAACC,iBAAiB,CAAC,aAAa,EAAE;IAAEC,OAAO,EAAE,CAAC,MAAM;EAAE,CAAC,CAAC;;EAE1D;EACAF,EAAE,CAACC,iBAAiB,CAAC,MAAM,EAAE;IAAEC,OAAO,EAAE,CAAC,SAAS;EAAE,CAAC,CAAC;AAC1D,CAAC,EACAF,EAAE,IAAW;EACV,IAAMG,eAAe,GAAGH,EAAE,CAACC,iBAAiB,CAAC,uBAAuB,EAAE;IAClEC,OAAO,EAAE,CAAC,SAAS,EAAE,WAAW;EACpC,CAAC,CAAC;EACFC,eAAe,CAACC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC;AAClD,CAAC,EACAJ,EAAE,IAAW;EACVA,EAAE,CAACC,iBAAiB,CAAC,gBAAgB,EAAE;IAAEC,OAAO,EAAE,CAAC,SAAS;EAAE,CAAC,CAAC;AACpE,CAAC,EACAF,EAAE,IAAW;EACVA,EAAE,CAACC,iBAAiB,CAAC,iBAAiB,EAAE;IAAEI,aAAa,EAAE;EAAK,CAAC,CAAC;AACpE;AACA;AAAA,CACH;AACD,IAAMC,OAAO,GAAGP,aAAa,CAACQ,MAAM;;AAEpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,WAAWA,CAChBC,KAAqB,EACrBC,QAA+C,EAC/CC,YAA+C,EACnC;EACZ,IAAMC,KAAK,GAAGH,KAAK,CAACI,UAAU,CAACH,QAAQ,CAAC;EACxC,OAAO,IAAII,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;IACpC,IAAMC,OAAY,GAAG,EAAE;IACvBL,KAAK,CAACM,OAAO,GAAG,MAAY;MACxBF,MAAM,CAAC,IAAIG,KAAK,2BAAAC,MAAA,CAA2BX,KAAK,CAACY,IAAI,GAAI;QAAEC,KAAK,EAAEV,KAAK,CAACW;MAAM,CAAC,CAAC,CAAC;IACrF,CAAC;IACD;IACAX,KAAK,CAACY,SAAS,GAAG,MAAY;MAC1B,IAAMC,MAAM,GAAGb,KAAK,CAACc,MAAM;MAC3B,IAAI,CAACD,MAAM,EAAE;QACTV,OAAO,CAACE,OAAO,CAAC;QAChB,OAAO,CAAC;MACZ;MACAA,OAAO,CAACU,IAAI,CAAChB,YAAY,CAACc,MAAM,CAAC,CAAC;MAClCA,MAAM,CAACG,QAAQ,CAAC,CAAC;IACrB,CAAC;EACL,CAAC,CAAC;AACN;AAEA,SAASC,YAAYA,CAACC,GAAmB,EAAkB;EACvD,OAAO,IAAIhB,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;IACpCc,GAAG,CAACC,UAAU,GAAG,UAAUC,KAAK,EAAQ;MACpCjB,OAAO,CAACiB,KAAK,CAAC;IAClB,CAAC;IACDF,GAAG,CAACZ,OAAO,GAAG,YAAkB;MAC5BF,MAAM,CAACc,GAAG,CAACP,KAAK,CAAC;IACrB,CAAC;EACL,CAAC,CAAC;AACN;AAEA,SAASU,iBAAiBA,CAACC,GAAe,EAAkB;EACxD,OAAO,IAAIpB,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;IACpCkB,GAAG,CAACV,SAAS,GAAG,UAAUQ,KAAK,EAAQ;MACnCjB,OAAO,CAACiB,KAAK,CAAC;IAClB,CAAC;IACDE,GAAG,CAAChB,OAAO,GAAG,YAAkB;MAC5BF,MAAM,CAACkB,GAAG,CAACX,KAAK,CAAC;IACrB,CAAC;EACL,CAAC,CAAC;AACN;AAEA,SAASY,YAAYA,CAACD,GAAe,EAAuB;EACxD,OAAO,IAAIpB,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;IACpCkB,GAAG,CAACV,SAAS,GAAG,MAAYT,OAAO,CAACmB,GAAG,CAAC;IACxCA,GAAG,CAAChB,OAAO,GAAIkB,GAAG,IAAWpB,MAAM,CAACoB,GAAG,CAAC;EAC5C,CAAC,CAAC;AACN;AAEA,SAASC,kBAAkBA,CAAIH,GAAkB,EAAc;EAC3D,OAAOD,iBAAiB,CAACC,GAAG,CAAC,CAACI,IAAI,CAAEN,KAAK,IAAKE,GAAG,CAACR,MAAM,CAAC;AAC7D;AAEA,OAAO,MAAMa,0BAA0B,CAA8B;EACjE,OAAc3C,MAAMA,CAAC4C,SAAqB,EAAEC,MAAc,EAAoB;IAC1EA,MAAM,GAAG,gBAAgB,IAAIA,MAAM,IAAI,SAAS,CAAC;IACjD,OAAO5C,SAAS,CAAC2C,SAAS,EAAEC,MAAM,CAAC;EACvC;EAUA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACWC,WAAWA,CACGF,SAAqB,EAExC;IAAA,IADEC,MAAM,GAAAE,SAAA,CAAApC,MAAA,QAAAoC,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,SAAS;IAAA,KADDH,SAAqB,GAArBA,SAAqB;IAAAK,eAAA;IAAAA,eAAA;IAAAA,eAAA;IAAAA,eAAA,uBAhBnB,IAAI;IAAAA,eAAA,0BACD,KAAK;IAAAA,eAAA;IAAAA,eAAA,kCAEgB,EAAE;IAgB7C,IAAI,CAACJ,MAAM,GAAG,gBAAgB,GAAGA,MAAM;IACvC,IAAI,CAACK,eAAe,GAAG,IAAIrD,eAAe,CAAC,CAAC;EAChD;;EAEA;AACJ;AACA;AACA;AACA;EACWsD,OAAOA,CAACC,OAAoB,EAAiB;IAAA,IAAAC,KAAA;IAChD,IAAI,CAAC,IAAI,CAACC,YAAY,EAAE;MACpBpD,MAAM,CAACqD,GAAG,sEAAsE,CAAC;MACjF,OAAOrC,OAAO,CAACC,OAAO,CAAC,CAAC;IAC5B;IAEA,IAAI,CAACmC,YAAY,GAAG,KAAK;IAEzBpD,MAAM,CAACqD,GAAG,oDAAoD,CAAC;IAC/D,IAAMjB,GAAG,GAAG,IAAI,CAACM,SAAS,CAACY,IAAI,CAAC,IAAI,CAACX,MAAM,EAAEnC,OAAO,CAAC;IACrD4B,GAAG,CAACmB,eAAe,GAAIC,EAAE,IAAW;MAChC,IAAMtD,EAAE,GAAGkC,GAAG,CAACR,MAAM;MACrB,IAAM6B,UAAU,GAAGD,EAAE,CAACC,UAAU;MAChCzD,MAAM,CAACqD,GAAG,uDAAA/B,MAAA,CAAuDmC,UAAU,CAAE,CAAC;MAC9E,IAAIA,UAAU,GAAG,CAAC,EAAE;QAChB;QACA,IAAI,CAACC,eAAe,GAAG,IAAI;MAC/B;MACAzD,aAAa,CAAC0D,OAAO,CAAC,CAACC,SAAS,EAAEC,KAAK,KAAK;QACxC,IAAIJ,UAAU,IAAII,KAAK,EAAED,SAAS,CAAC1D,EAAE,CAAC;MAC1C,CAAC,CAAC;IACN,CAAC;IAEDkC,GAAG,CAAC0B,SAAS,GAAG,MAAY;MACxB9D,MAAM,CAACqD,GAAG,yEAAyE,CAAC;IACxF,CAAC;IAEDrD,MAAM,CAACqD,GAAG,6DAA6D,CAAC;IACxE,OAAOlB,iBAAiB,CAACC,GAAG,CAAC,CAACI,IAAI,cAAAuB,iBAAA,CAAC,aAAY;MAC3C/D,MAAM,CAACqD,GAAG,gDAAgD,CAAC;MAC3DF,KAAI,CAACjD,EAAE,GAAGkC,GAAG,CAACR,MAAM;;MAEpB;MACA;MACAuB,KAAI,CAACjD,EAAE,CAAC8D,eAAe,GAAG,MAAY;QAAA,IAAAC,QAAA;QAClC,CAAAA,QAAA,GAAAd,KAAI,CAACjD,EAAE,cAAA+D,QAAA,eAAPA,QAAA,CAASC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClBf,KAAI,CAACC,YAAY,GAAG,IAAI;QACxBD,KAAI,CAACjD,EAAE,GAAG4C,SAAS;MACvB,CAAC;MACDK,KAAI,CAACjD,EAAE,CAACiE,OAAO,GAAG,MAAY;QAC1BhB,KAAI,CAACC,YAAY,GAAG,IAAI;QACxBD,KAAI,CAACjD,EAAE,GAAG4C,SAAS;QACnBI,OAAO,aAAPA,OAAO,eAAPA,OAAO,CAAG,CAAC;MACf,CAAC;MAED,MAAMC,KAAI,CAACiB,IAAI,CAAC,CAAC;IACrB,CAAC,EAAC;EACN;;EAEA;EACOC,cAAcA,CAAA,EAAqB;IACtC,OAAOrD,OAAO,CAACC,OAAO,CAAC,IAAI,CAACyC,eAAe,CAAC;EAChD;;EAEA;AACJ;AACA;AACA;EACYU,IAAIA,CAAA,EAAqB;IAC7B,OAAOpD,OAAO,CAACsD,GAAG,CAAC,CAAC,IAAI,CAACC,eAAe,CAAC,CAAC,EAAE,IAAI,CAACC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAChC,IAAI,CAACiC,KAAA,IAA6B;MAAA,IAA5B,CAACC,WAAW,EAAEC,QAAQ,CAAC,GAAAF,KAAA;MAC3FzE,MAAM,CAACqD,GAAG,kDAAkD,CAAC;MAC7D,IAAI,CAACL,eAAe,CAAC4B,UAAU,CAC3B;QACIC,UAAU,EAAEF,QAAQ,CAACG,SAAS;QAC9BC,KAAK,EAAEJ,QAAQ,CAACK,SAAS;QACzBC,YAAY,EAAE;UACVC,MAAM,EAAER;QACZ;MACJ,CAAC,EACD,IACJ,CAAC;IACL,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACWS,mBAAmBA,CAACC,MAAc,EAA2C;IAChF,OAAO,IAAIpE,OAAO,CAAiC,CAACC,OAAO,EAAEC,MAAM,KAAK;MACpE,IAAMmE,EAAE,GAAG,IAAI,CAACnF,EAAE,CAAEoF,WAAW,CAAC,CAAC,uBAAuB,CAAC,EAAE,UAAU,CAAC;MACtE,IAAM3E,KAAK,GAAG0E,EAAE,CAACE,WAAW,CAAC,uBAAuB,CAAC;MACrD,IAAMC,SAAS,GAAG7E,KAAK,CAACkD,KAAK,CAAC,MAAM,CAAC;MACrC,IAAM4B,KAAK,GAAGC,WAAW,CAACC,IAAI,CAACP,MAAM,CAAC;MACtC,IAAMQ,OAAO,GAAGJ,SAAS,CAACzE,UAAU,CAAC0E,KAAK,CAAC;MAE3C,IAAMI,gBAAyC,GAAG,EAAE;MACpD;MACA;MACA;MACA;MACA;MACA,IAAIC,UAAU,GAAG,KAAK;MAEtBF,OAAO,CAAClE,SAAS,GAAG,MAAY;QAC5B,IAAMC,MAAM,GAAGiE,OAAO,CAAChE,MAAM;QAC7B,IAAI,CAACD,MAAM,EAAE;UACT;UACA,IAAI,CAACkE,gBAAgB,CAACpF,MAAM,IAAI,CAACqF,UAAU,EAAE;YACzC,OAAO7E,OAAO,CAAC,IAAI,CAAC;UACxB;UACA,OAAOA,OAAO,CAAC4E,gBAAgB,CAAC;QACpC;QACA,IAAME,MAAM,GAAGpE,MAAM,CAACqE,KAAK;QAC3B,IAAID,MAAM,CAACE,WAAW,EAAE;UACpBH,UAAU,GAAG,IAAI;QACrB,CAAC,MAAM;UACHD,gBAAgB,CAAChE,IAAI,CAACkE,MAAM,CAAC;QACjC;QACApE,MAAM,CAACG,QAAQ,CAAC,CAAC;MACrB,CAAC;MACD8D,OAAO,CAACxE,OAAO,GAAIkB,GAAG,IAAW;QAC7BpB,MAAM,CAACoB,GAAG,CAAC;MACf,CAAC;IACL,CAAC,CAAC,CAACE,IAAI,CAAE0C,MAAM,IAAK;MAChBlF,MAAM,CAACqD,GAAG,YAAA/B,MAAA,CAAY4D,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEzE,MAAM,8CAAAa,MAAA,CAA2C8D,MAAM,SAAM,CAAC;MAC5F,OAAOF,MAAM;IACjB,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACiBgB,mBAAmBA,CAACd,MAAc,EAAES,gBAAyC,EAAiB;IAAA,IAAAM,MAAA;IAAA,OAAApC,iBAAA;MACvG/D,MAAM,CAACqD,GAAG,CAAC,8BAAA/B,MAAA,CAA8BuE,gBAAgB,CAACpF,MAAM,oBAAAa,MAAA,CAAqB8D,MAAM,CAAE,CAAC;MAC9F,IAAMC,EAAE,GAAGc,MAAI,CAACjG,EAAE,CAAEoF,WAAW,CAAC,CAAC,uBAAuB,CAAC,EAAE,WAAW,CAAC;MACvE,IAAM3E,KAAK,GAAG0E,EAAE,CAACE,WAAW,CAAC,uBAAuB,CAAC;MACrDM,gBAAgB,CAAClC,OAAO,CAAEyC,CAAC,IAAK;QAC5BzF,KAAK,CAAC0F,GAAG,CAACD,CAAC,CAAC;MAChB,CAAC,CAAC;MACF;MACA;MACA;MACA;MACA;MACA,IAAME,YAAY,GAAG;QACjBC,OAAO,EAAEnB,MAAM;QACfa,WAAW,EAAE,IAAI;QACjBO,SAAS,EAAE;MACf,CAAC;MACD7F,KAAK,CAAC0F,GAAG,CAACC,YAAY,CAAC;MACvB,MAAMvE,YAAY,CAACsD,EAAE,CAAC;MACtBrF,MAAM,CAACqD,GAAG,iCAAA/B,MAAA,CAAiC8D,MAAM,MAAG,CAAC;IAAC;EAC1D;EAEaqB,qBAAqBA,CAACrB,MAAc,EAAiB;IAAA,IAAAsB,MAAA;IAAA,OAAA3C,iBAAA;MAC9D;MACA;MACA;MACA;MACA;MACA;MACA,IAAM4C,MAAM,GAAGD,MAAI,CAACxG,EAAE,CAAEoF,WAAW,CAAC,CAAC,uBAAuB,CAAC,EAAE,UAAU,CAAC;MAC1E,IAAM3E,KAAK,GAAGgG,MAAM,CAACpB,WAAW,CAAC,uBAAuB,CAAC;MACzD,IAAMC,SAAS,GAAG7E,KAAK,CAACkD,KAAK,CAAC,MAAM,CAAC;MACrC,IAAM+C,SAAS,GAAGlB,WAAW,CAACC,IAAI,CAACP,MAAM,CAAC;MAE1C,IAAMyB,eAAe,GAAGtE,kBAAkB,CAACiD,SAAS,CAACsB,aAAa,CAACF,SAAS,EAAE,MAAM,CAAC,CAAC,CAACpE,IAAI,CACtFb,MAAM,IAAK,CAAgBA,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEoF,UAAU,EAAE,CAAC,CACrD,CAAC;MACD,IAAMC,eAAe,GAAGzE,kBAAkB,CAACiD,SAAS,CAACsB,aAAa,CAACF,SAAS,EAAE,MAAM,CAAC,CAAC,CAACpE,IAAI,CACtFb,MAAM,IAAK,CAAgBA,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEoF,UAAU,EAAE,CAAC,CACrD,CAAC;MACD,IAAM,CAACE,WAAW,EAAEC,WAAW,CAAC,SAASlG,OAAO,CAACsD,GAAG,CAAC,CAACuC,eAAe,EAAEG,eAAe,CAAC,CAAC;MAExF,IAAMG,OAAO,GAAGT,MAAI,CAACxG,EAAE,CAAEoF,WAAW,CAAC,CAAC,uBAAuB,CAAC,EAAE,WAAW,CAAC;MAC5E,IAAM8B,UAAU,GAAGD,OAAO,CAAC5B,WAAW,CAAC,uBAAuB,CAAC;MAC/D,IAAM8B,eAAe,GAAG3B,WAAW,CAAC4B,KAAK,CAAC,CAAClC,MAAM,EAAE6B,WAAW,CAAC,EAAE,CAAC7B,MAAM,EAAE8B,WAAW,CAAC,CAAC;MAEvFlH,MAAM,CAACqD,GAAG,wDAAA/B,MAAA,CACiD8D,MAAM,wBAC7D,CAACA,MAAM,EAAE6B,WAAW,CAAC,EACrB,CAAC7B,MAAM,EAAE8B,WAAW,CACxB,CAAC;MACD,MAAM7E,YAAY,CAAC+E,UAAU,CAACG,MAAM,CAACF,eAAe,CAAC,CAAC;IAAC;EAC3D;;EAEA;AACJ;AACA;AACA;AACA;EACWG,aAAaA,CAAA,EAAkB;IAClC,OAAO,IAAIxG,OAAO,CAAEC,OAAO,IAAK;MAAA,IAAAwG,SAAA;MAC5BzH,MAAM,CAACqD,GAAG,iCAAA/B,MAAA,CAAiC,IAAI,CAACqB,MAAM,CAAE,CAAC;;MAEzD;MACA,CAAA8E,SAAA,OAAI,CAACvH,EAAE,cAAAuH,SAAA,eAAPA,SAAA,CAASvD,KAAK,CAAC,CAAC;MAEhB,IAAM9B,GAAG,GAAG,IAAI,CAACM,SAAS,CAACgF,cAAc,CAAC,IAAI,CAAC/E,MAAM,CAAC;MAEtDP,GAAG,CAAC0B,SAAS,GAAG,MAAY;QACxB9D,MAAM,CAACqD,GAAG,+BAAA/B,MAAA,CAA+B,IAAI,CAACqB,MAAM,kCAA+B,CAAC;MACxF,CAAC;MAEDP,GAAG,CAAChB,OAAO,GAAG,MAAY;QAAA,IAAAuG,UAAA;QACtB;QACA;QACA;QACA3H,MAAM,CAAC4H,IAAI,6CAAAtG,MAAA,EAAAqG,UAAA,GAA6CvF,GAAG,CAACX,KAAK,cAAAkG,UAAA,uBAATA,UAAA,CAAWpG,IAAI,CAAE,CAAC;QAC1EN,OAAO,CAAC,CAAC;MACb,CAAC;MAEDmB,GAAG,CAACV,SAAS,GAAG,MAAY;QACxB1B,MAAM,CAACqD,GAAG,gCAAA/B,MAAA,CAAgC,IAAI,CAACqB,MAAM,CAAE,CAAC;QACxD1B,OAAO,CAAC,CAAC;MACb,CAAC;IACL,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACW4G,YAAYA,CAAA,EAA0C;IAAA,IAAzCC,IAAI,GAAAjF,SAAA,CAAApC,MAAA,QAAAoC,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,IAAI;IAC3B,IAAMkF,IAAI,GAAG,IAAI,CAAC/E,eAAe,CAACgF,OAAO,CAAC,CAAC;IAC3C,IAAI,CAACD,IAAI,CAACjD,SAAS,EAAE,OAAO9D,OAAO,CAACC,OAAO,CAAC,IAAI,CAAC;IACjD,IAAI6G,IAAI,EAAE;MACN;MACA;MACA,OAAO9G,OAAO,CAACC,OAAO,CAACrB,QAAQ,CAACmI,IAAI,CAAC,CAAC;IAC1C,CAAC,MAAM;MACH,OAAO/G,OAAO,CAACC,OAAO,CAAC8G,IAAI,CAAC;IAChC;EACJ;EAEOE,iBAAiBA,CAAA,EAAoB;IACxC,OAAOjH,OAAO,CAACC,OAAO,CAAC,IAAI,CAAC+B,eAAe,CAACiF,iBAAiB,CAAC,CAAC,CAAC;EACpE;EAEOC,WAAWA,CAACvD,QAAuB,EAAiB;IACvD,OAAO3D,OAAO,CAACC,OAAO,CAAC,CAAC,CAACuB,IAAI,CAAC,MAAM;MAChC,IAAI,CAACQ,eAAe,CAAC4B,UAAU,CAACD,QAAQ,CAAC;IAC7C,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;EACiBwD,cAAcA,CAACC,UAAuB,EAAiB;IAAA,IAAAC,MAAA;IAAA,OAAAtE,iBAAA;MAChE,IAAIsE,MAAI,CAACC,qBAAqB,EAAE;QAC5BtI,MAAM,CAAC4H,IAAI,CAAC,wDAAwD,CAAC;QACrES,MAAI,CAACE,uBAAuB,CAAC1G,IAAI,CAAC,GAAGuG,UAAU,CAAC;QAChD,OAAOC,MAAI,CAACC,qBAAqB;MACrC;MACAF,UAAU,CAACI,OAAO,CAAC,GAAGH,MAAI,CAACE,uBAAuB,CAAC;MACnDF,MAAI,CAACC,qBAAqB,GAAGD,MAAI,CAACI,gBAAgB,CAACL,UAAU,CAAC;MAC9D,OAAOC,MAAI,CAACC,qBAAqB;IAAC;EACtC;EAEcG,gBAAgBA,CAACL,UAAuB,EAAiB;IAAA,IAAAM,MAAA;IAAA,OAAA3E,iBAAA;MACnE,IAAI;QACA,IAAMY,QAAQ,GAAG+D,MAAI,CAAC1F,eAAe,CAACgF,OAAO,CAAC,IAAI,CAAC;QACnD,MAAMhH,OAAO,CAACsD,GAAG,CAAC,CACdoE,MAAI,CAACC,yBAAyB,CAACP,UAAU,CAAC,EAC1CM,MAAI,CAACE,kBAAkB,CAACjE,QAAQ,CAACD,WAAW,CAAC,EAC7CgE,MAAI,CAACG,eAAe,CAAClE,QAAQ,CAACG,SAAS,EAAEH,QAAQ,CAACK,SAAS,CAAC,CAC/D,CAAC;MACN,CAAC,SAAS;QACN0D,MAAI,CAACJ,qBAAqB,GAAGxF,SAAS;MAC1C;IAAC;EACL;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACY+F,eAAeA,CAAC/D,SAAiB,EAAEE,SAAiC,EAAiB;IACzFhF,MAAM,CAACqD,GAAG,CAAC,4BAA4B,EAAEyB,SAAS,CAAC;IACnD,OAAOjF,UAAU,CAAO,MAAM;MAC1B,IAAMmC,GAAG,GAAG,IAAI,CAAC9B,EAAE,CAAEoF,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;MACvD,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,MAAM,CAAC;MACrC5E,KAAK,CAAC0F,GAAG,CAAC;QACNyC,OAAO,EAAE,GAAG;QAAE;QACdhE,SAAS;QACTE;MACJ,CAAC,CAAC,CAAC,CAAC;MACJ,OAAOjD,YAAY,CAACC,GAAG,CAAC,CAACQ,IAAI,CAAC,MAAM;QAChCxC,MAAM,CAACqD,GAAG,CAAC,2BAA2B,EAAEyB,SAAS,CAAC;MACtD,CAAC,CAAC;IACN,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACY8D,kBAAkBA,CAAClE,WAA4B,EAAiB;IACpE,OAAO7E,UAAU,CAAO,MAAM;MAC1B,IAAMmC,GAAG,GAAG,IAAI,CAAC9B,EAAE,CAAEoF,WAAW,CAAC,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC;MAC9D,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,aAAa,CAAC;MAC5C,KAAK,IAAMrD,KAAK,IAAIwC,WAAW,EAAE;QAC7B/D,KAAK,CAAC0F,GAAG,CAACnE,KAAK,CAAC,CAAC,CAAC;MACtB;MACA,OAAOH,YAAY,CAACC,GAAG,CAAC,CAACQ,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;EACYmG,yBAAyBA,CAACI,MAAmB,EAAiB;IAClE,OAAOlJ,UAAU,CAAO,MAAM;MAC1B,IAAMmC,GAAG,GAAG,IAAI,CAAC9B,EAAE,CAAEoF,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;MACxD,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,OAAO,CAAC;MACtC,KAAK,IAAMyD,KAAK,IAAID,MAAM,EAAE;QACxBpI,KAAK,CAAC0F,GAAG,CAAC;UACN4C,MAAM,EAAED,KAAK,CAAC,CAAC,CAAC;UAChB9G,KAAK,EAAE8G,KAAK,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC,CAAC;MACR;MACA,OAAOjH,YAAY,CAACC,GAAG,CAAC,CAACQ,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACW0G,qBAAqBA,CAAA,EAAyB;IACjD,OAAOrJ,UAAU,CAAc,MAAM;MACjC,IAAMmC,GAAG,GAAG,IAAI,CAAC9B,EAAE,CAAEoF,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;MACvD,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,OAAO,CAAC;MACtC,OAAO7E,WAAW,CAACC,KAAK,EAAEmC,SAAS,EAAGnB,MAAM,IAAK;QAC7C,OAAO,CAACA,MAAM,CAACqE,KAAK,CAACiD,MAAM,EAAEtH,MAAM,CAACqE,KAAK,CAAC9D,KAAK,CAAC;MACpD,CAAC,CAAC;IACN,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;EACYqC,eAAeA,CAAA,EAA6B;IAChDvE,MAAM,CAACqD,GAAG,sDAAsD,CAAC;IACjE,OAAOxD,UAAU,CAAkB,MAAM;MACrC,IAAMmC,GAAG,GAAG,IAAI,CAAC9B,EAAE,CAAEoF,WAAW,CAAC,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC;MAC7D,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,aAAa,CAAC;MAC5C,OAAO7E,WAAW,CAACC,KAAK,EAAEmC,SAAS,EAAGnB,MAAM,IAAK;QAC7C,OAAOA,MAAM,CAACqE,KAAK;MACvB,CAAC,CAAC,CAACxD,IAAI,CAAEZ,MAAuB,IAAK;QACjC5B,MAAM,CAACqD,GAAG,kDAAkD,CAAC;QAC7D,OAAOzB,MAAM;MACjB,CAAC,CAAC;IACN,CAAC,CAAC;EACN;;EAEA;AACJ;AACA;AACA;EACY4C,YAAYA,CAAA,EAAuB;IACvCxE,MAAM,CAACqD,GAAG,mDAAmD,CAAC;IAC9D,OAAOxD,UAAU,CAAY,MAAM;MAC/B,IAAMmC,GAAG,GAAG,IAAI,CAAC9B,EAAE,CAAEoF,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;MACtD,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,MAAM,CAAC;MACrC,OAAO7E,WAAW,CAACC,KAAK,EAAEmC,SAAS,EAAGnB,MAAM,IAAK;QAC7C,OAAOA,MAAM,CAACqE,KAAK;MACvB,CAAC,CAAC,CAACxD,IAAI,CAAErB,OAAoB,IAAK;QAC9BnB,MAAM,CAACqD,GAAG,+CAA+C,CAAC;QAC1D,IAAIlC,OAAO,CAACV,MAAM,GAAG,CAAC,EAAE;UACpBT,MAAM,CAAC4H,IAAI,CAAC,2CAA2C,CAAC;QAC5D;QACA,OAAOzG,OAAO,CAACV,MAAM,GAAG,CAAC,GAAGU,OAAO,CAAC,CAAC,CAAC,GAAI,CAAC,CAAe;MAC9D,CAAC,CAAC;IACN,CAAC,CAAC;EACN;EAEOgI,gBAAgBA,CAAA,EAA2C;IAC9D,OAAOnI,OAAO,CAACC,OAAO,CAAC,CAAC,CAACuB,IAAI,CAAC,MAAM;MAChC,IAAMR,GAAG,GAAG,IAAI,CAAC9B,EAAE,CAAEoF,WAAW,CAAC,CAAC,gBAAgB,CAAC,EAAE,UAAU,CAAC;MAChE,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,gBAAgB,CAAC;MAC/C,OAAO7E,WAAW,CAACC,KAAK,EAAEmC,SAAS,EAAGnB,MAAM,IAAK;QAAA,IAAAyH,aAAA;QAC7C,QAAAA,aAAA,GAAOzH,MAAM,CAACqE,KAAK,cAAAoD,aAAA,uBAAZA,aAAA,CAAcC,OAAO;MAChC,CAAC,CAAC,CAAC7G,IAAI,CAAErB,OAAO,IAAKA,OAAO,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC;EACN;EAEamI,kBAAkBA,CAACD,OAA0B,EAAiB;IAAA,IAAAE,MAAA;IAAA,OAAAxF,iBAAA;MACvE,IAAM/B,GAAG,GAAGuH,MAAI,CAACrJ,EAAE,CAAEoF,WAAW,CAAC,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC;MACjE,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,gBAAgB,CAAC;MAC/C5E,KAAK,CAAC0F,GAAG,CAAC;QACNyC,OAAO,EAAE,GAAG;QAAE;QACdO,OAAO,EAAEA;MACb,CAAC,CAAC,CAAC,CAAC;MACJ,MAAMtH,YAAY,CAACC,GAAG,CAAC;IAAC;EAC5B;EAEawH,mBAAmBA,CAACC,OAAiC,EAAiB;IAAA,IAAAC,MAAA;IAAA,OAAA3F,iBAAA;MAC/E,IAAM/B,GAAG,GAAG0H,MAAI,CAACxJ,EAAE,CAAEoF,WAAW,CAAC,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;MAClE,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,iBAAiB,CAAC;MAChD,KAAK,IAAMoE,KAAK,IAAIF,OAAO,EAAE;QACzB9I,KAAK,CAACiJ,GAAG,CAACD,KAAK,CAAC;MACpB;MACA,MAAM5H,YAAY,CAACC,GAAG,CAAC;IAAC;EAC5B;EAEa6H,sBAAsBA,CAAA,EAAyC;IAAA,IAAAC,MAAA;IAAA,OAAA/F,iBAAA;MACxE,IAAM/B,GAAG,GAAG8H,MAAI,CAAC5J,EAAE,CAAEoF,WAAW,CAAC,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;MACjE,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,iBAAiB,CAAC;MAChD,IAAM5D,MAAM,SAASY,kBAAkB,CAAC5B,KAAK,CAACI,UAAU,CAAC,CAAC,CAAC;MAC3D,IAAI,CAACY,MAAM,EAAE,OAAO,IAAI;MAExB,IAAMoI,WAAW,GAAGpI,MAAM,CAACqE,KAA+B;MAE1D,OAAO;QACHgE,EAAE,EAAErI,MAAM,CAACsI,GAAa;QACxBC,KAAK,EAAEH,WAAW,CAACG,KAAK;QACxBC,SAAS,EAAEJ,WAAW,CAACI,SAAS;QAChCR,KAAK,EAAEI,WAAW,CAACJ;MACvB,CAAC;IAAC;EACN;EAEaS,mBAAmBA,CAACJ,EAAU,EAAiB;IAAA,IAAAK,MAAA;IAAA,OAAAtG,iBAAA;MACxD,IAAM/B,GAAG,GAAGqI,MAAI,CAACnK,EAAE,CAAEoF,WAAW,CAAC,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;MAClE,IAAM3E,KAAK,GAAGqB,GAAG,CAACuD,WAAW,CAAC,iBAAiB,CAAC;MAChD5E,KAAK,CAAC4G,MAAM,CAACyC,EAAE,CAAC;MAChB,MAAMjI,YAAY,CAACC,GAAG,CAAC;IAAC;EAC5B;;EAEA;AACJ;AACA;EACiBsI,OAAOA,CAAA,EAAkB;IAAA,IAAAC,MAAA;IAAA,OAAAxG,iBAAA;MAAA,IAAAyG,SAAA;MAClC,CAAAA,SAAA,GAAAD,MAAI,CAACrK,EAAE,cAAAsK,SAAA,eAAPA,SAAA,CAAStG,KAAK,CAAC,CAAC;IAAC;EACrB;AACJ","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matrix-js-sdk",
3
- "version": "41.3.0",
3
+ "version": "41.4.0",
4
4
  "description": "Matrix Client-Server SDK for Javascript",
5
5
  "engines": {
6
6
  "node": ">=22.0.0"
@@ -18,8 +18,8 @@
18
18
  "lint:types": "tsc --noEmit",
19
19
  "lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'",
20
20
  "lint:knip": "knip",
21
- "test": "vitest",
22
- "test:watch": "vitest --watch",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest watch",
23
23
  "coverage": "pnpm test --coverage"
24
24
  },
25
25
  "repository": {
@@ -48,7 +48,7 @@
48
48
  ],
49
49
  "dependencies": {
50
50
  "@babel/runtime": "^7.12.5",
51
- "@matrix-org/matrix-sdk-crypto-wasm": "^18.0.0",
51
+ "@matrix-org/matrix-sdk-crypto-wasm": "^18.1.0",
52
52
  "another-json": "^0.2.0",
53
53
  "bs58": "^6.0.0",
54
54
  "content-type": "^1.0.4",
@@ -57,7 +57,7 @@
57
57
  "matrix-events-sdk": "0.0.1",
58
58
  "matrix-widget-api": "^1.16.1",
59
59
  "oidc-client-ts": "^3.0.1",
60
- "p-retry": "7",
60
+ "p-retry": "8",
61
61
  "sdp-transform": "^3.0.0",
62
62
  "unhomoglyph": "^1.0.6",
63
63
  "uuid": "13"
@@ -109,7 +109,7 @@
109
109
  "knip": "^6.0.0",
110
110
  "lint-staged": "^16.0.0",
111
111
  "matrix-mock-request": "^2.5.0",
112
- "prettier": "3.8.1",
112
+ "prettier": "3.8.3",
113
113
  "typedoc": "^0.28.1",
114
114
  "typedoc-plugin-coverage": "^4.0.0",
115
115
  "typedoc-plugin-mdn-links": "^5.0.0",
@@ -118,9 +118,6 @@
118
118
  "vitest": "^4.0.17",
119
119
  "vitest-sonar-reporter": "^3.0.0"
120
120
  },
121
- "resolutions": {
122
- "expect": "30.3.0"
123
- },
124
121
  "pnpm": {
125
122
  "peerDependencyRules": {
126
123
  "allowedVersions": {
@@ -129,7 +126,14 @@
129
126
  },
130
127
  "allowedDeprecatedVersions": {
131
128
  "eslint": "8"
129
+ },
130
+ "overrides": {
131
+ "expect": "30.3.0",
132
+ "flatted@<=3.4.1": "^3.4.2",
133
+ "picomatch@>=4.0.0 <4.0.4": "^4.0.4",
134
+ "yaml@>=2.0.0 <2.8.3": "^2.8.3",
135
+ "vite": "7.3.2"
132
136
  }
133
137
  },
134
- "packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be"
138
+ "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
135
139
  }
@@ -416,9 +416,12 @@ export interface AccountDataEvents extends SecretStorageAccountDataEvents {
416
416
  [EventType.Direct]: { [userId: string]: string[] };
417
417
  [EventType.IgnoredUserList]: { ignored_users: { [userId: string]: EmptyObject } };
418
418
  "m.secret_storage.default_key": { key: string };
419
- // Flag set by the rust SDK (Element X) and also used by us to mark that the user opted out of backup
420
- // (I don't know why it's m.org.matrix...)
419
+
420
+ // MSC4287: Sharing key backup preference between clients - used to mark that the user opted out of key storage
421
+ "m.key_backup": { enabled: boolean };
422
+ // MSC4287 unstable prefix (note the boolean property has the opposite sense)
421
423
  "m.org.matrix.custom.backup_disabled": { disabled: boolean };
424
+
422
425
  "m.identity_server": { base_url: string | null };
423
426
  [key: `${typeof LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${string}`]: LocalNotificationSettings;
424
427
  [key: `m.secret_storage.key.${string}`]: SecretStorageKeyDescription;
@@ -428,6 +431,15 @@ export interface AccountDataEvents extends SecretStorageAccountDataEvents {
428
431
  [POLICIES_ACCOUNT_EVENT_TYPE.altName]: { [key: string]: any };
429
432
 
430
433
  [EventType.InvitePermissionConfig]: { default_action?: string };
434
+
435
+ // List of recently used reaction emojis
436
+ // https://spec.matrix.org/v1.18/client-server-api/#mrecent_emoji
437
+ "m.recent_emoji": {
438
+ recent_emoji: Array<{
439
+ emoji: string;
440
+ total: number;
441
+ }>;
442
+ };
431
443
  }
432
444
 
433
445
  /**
@@ -188,7 +188,9 @@ export interface CryptoApi {
188
188
  /**
189
189
  * Check if the given user has published cross-signing keys.
190
190
  *
191
- * - If the user is tracked, a `/keys/query` request is made to update locally the cross signing keys.
191
+ * - If the user is this user, a `/keys/query` request is made to update locally the cross signing keys.
192
+ * - If the user is tracked, any current `/keys/query` requests are awaited (with a timeout) and then
193
+ * the locally cached information is used.
192
194
  * - If the user is not tracked locally and downloadUncached is set to true,
193
195
  * a `/keys/query` request is made to the server to retrieve the cross signing keys.
194
196
  * - Otherwise, return false
@@ -205,7 +207,10 @@ export interface CryptoApi {
205
207
  * Get the device information for the given list of users.
206
208
  *
207
209
  * For any users whose device lists are cached (due to sharing an encrypted room with the user), the
208
- * cached device data is returned.
210
+ * cached device data is returned, unless it is stale.
211
+ *
212
+ * If there are users with stale cached entries, wait (with some timeout) for any in-progress
213
+ * `/keys/query` request to complete.
209
214
  *
210
215
  * If there are uncached users, and the `downloadUncached` parameter is set to `true`,
211
216
  * a `/keys/query` request is made to the server to retrieve these devices.
@@ -626,7 +631,6 @@ export interface CryptoApi {
626
631
  * * Disables 4S, deleting the info for the default key, the default key pointer itself and any
627
632
  * known 4S data (cross-signing keys and the megolm key backup key).
628
633
  * * Deletes any dehydrated devices.
629
- * * Sets the "m.org.matrix.custom.backup_disabled" account data flag to indicate that the user has disabled backups.
630
634
  */
631
635
  disableKeyStorage(): Promise<void>;
632
636
 
@@ -857,6 +861,25 @@ export interface BootstrapCrossSigningOpts {
857
861
  * Represents the ways in which we trust a user
858
862
  */
859
863
  export class UserVerificationStatus {
864
+ /**
865
+ * Indicates if we have saved a known identity for this user. Typically, this means that we share a
866
+ * room with them (or have done in the past).
867
+ *
868
+ * If this is `false`, then the other flags ({@link isCrossSigningVerified}, {@link wasCrossSigningVerified},
869
+ * {@link needsUserApproval}) will also be `false`. This means that we haven't seen this user before.
870
+ *
871
+ * If this is `true`, then there are further possibilities:
872
+ *
873
+ * - If {@link isCrossSigningVerified} returns `true`, then we have cryptographically verified the current
874
+ * identity of this user: that is the highest form of trust we have.
875
+ *
876
+ * - If {@link needsUserApproval} is `true`, that means that the user has changed their identity.
877
+ *
878
+ * - Otherwise, the user is "TOFU trusted": we have a record of their identity, and, typically, will share
879
+ * encrypted content with them as long as they retain that identity.
880
+ */
881
+ public readonly known: boolean;
882
+
860
883
  /**
861
884
  * Indicates if the identity has changed in a way that needs user approval.
862
885
  *
@@ -872,12 +895,14 @@ export class UserVerificationStatus {
872
895
  */
873
896
  public readonly needsUserApproval: boolean;
874
897
 
898
+ /** @internal */
875
899
  public constructor(
876
900
  private readonly crossSigningVerified: boolean,
877
901
  private readonly crossSigningVerifiedBefore: boolean,
878
- private readonly tofu: boolean,
902
+ known: boolean,
879
903
  needsUserApproval: boolean = false,
880
904
  ) {
905
+ this.known = known;
881
906
  this.needsUserApproval = needsUserApproval;
882
907
  }
883
908
 
@@ -909,7 +934,7 @@ export class UserVerificationStatus {
909
934
  * @deprecated No longer supported, with the Rust crypto stack.
910
935
  */
911
936
  public isTofu(): boolean {
912
- return this.tofu;
937
+ return false;
913
938
  }
914
939
  }
915
940
 
package/src/embedded.ts CHANGED
@@ -806,7 +806,7 @@ export class RoomWidgetClient extends MatrixClient {
806
806
  // Sliding Sync
807
807
  await this.syncApi!.injectRoomEvents(this.room!, [event]);
808
808
  }
809
- logger.info(`Updated state entry ${event.getType()} ${event.getStateKey()} to ${event.getId()}`);
809
+ logger.debug(`Updated state entry ${event.getType()} ${event.getStateKey()} to ${event.getId()}`);
810
810
  } else {
811
811
  const { event_id: eventId, room_id: roomId } = ev.detail.data;
812
812
  logger.info(`Received state entry ${eventId} for a different room ${roomId}; discarding`);
@@ -863,7 +863,8 @@ function quickFilterNonRelevantContents(content: IContent, logger: Logger): bool
863
863
  // We have a MSC4143 event membership event with a proper joined content
864
864
  return true;
865
865
  } else if (eventKeysCount === 1 && "memberships" in content) {
866
- logger.warn(`Legacy event found. Those are ignored, they do not contribute to the MatrixRTC session`);
866
+ // Events used to have this format in the past, but are now deprecated.
867
+ // Given that state events ~cannot be deleted, there can be some remaining events in the room, just ignore them.
867
868
  return false;
868
869
  } else {
869
870
  // Invalid or left content
@@ -20,7 +20,7 @@ import type { RelationType } from "../../types.ts";
20
20
  import { type RtcSlotEventContent, type Transport } from "../types.ts";
21
21
  import { MatrixRTCMembershipParseError } from "./common.ts";
22
22
  import { sha256 } from "../../digest.ts";
23
- import { encodeUnpaddedBase64Url } from "../../base64.ts";
23
+ import { encodeUnpaddedBase64 } from "../../base64.ts";
24
24
  import { slotIdToDescription } from "../utils.ts";
25
25
 
26
26
  /**
@@ -149,8 +149,9 @@ export const checkRtcMembershipData = (data: IContent, sender: string): data is
149
149
  };
150
150
 
151
151
  export async function computeRtcIdentityRaw(userId: string, deviceId: string, memberId: string): Promise<string> {
152
- const hashInput = `${userId}|${deviceId}|${memberId}`;
153
- const hashBuffer = await sha256(hashInput);
154
- const hashedString = encodeUnpaddedBase64Url(hashBuffer);
152
+ // canonical JSON serialization (Matrix canonical JSON for arrays)
153
+ const jsonStr = JSON.stringify([userId, deviceId, memberId]);
154
+ const hashBuffer = await sha256(jsonStr);
155
+ const hashedString = encodeUnpaddedBase64(hashBuffer);
155
156
  return hashedString;
156
157
  }
@@ -14,7 +14,15 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
16
 
17
- import { type IdTokenClaims, Log, OidcClient, SigninResponse, SigninState, WebStorageStateStore } from "oidc-client-ts";
17
+ import {
18
+ type IdTokenClaims,
19
+ Log,
20
+ OidcClient,
21
+ type SigninRequestCreateArgs,
22
+ SigninResponse,
23
+ SigninState,
24
+ WebStorageStateStore,
25
+ } from "oidc-client-ts";
18
26
 
19
27
  import { logger } from "../logger.ts";
20
28
  import { secureRandomString } from "../randomstring.ts";
@@ -127,6 +135,8 @@ export const generateAuthorizationUrl = async (
127
135
  * @param urlState - value to append to the opaque state identifier to uniquely identify the callback
128
136
  * @param loginHint - value to send as the `login_hint` to the OP, giving a hint about the login identifier the user might use to log in.
129
137
  * See {@link https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest OIDC core 3.1.2.1}.
138
+ * @param responseMode - value to send as the `response_mode` to the OP, selecting how auth is passed back during redirect.
139
+ * See {@link https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest OIDC core 3.1.2.1}.
130
140
  * @returns a Promise with the url as a string
131
141
  */
132
142
  export const generateOidcAuthorizationUrl = async ({
@@ -139,6 +149,7 @@ export const generateOidcAuthorizationUrl = async ({
139
149
  prompt,
140
150
  urlState,
141
151
  loginHint,
152
+ responseMode = "query",
142
153
  }: {
143
154
  clientId: string;
144
155
  metadata: ValidatedAuthMetadata;
@@ -149,6 +160,7 @@ export const generateOidcAuthorizationUrl = async ({
149
160
  prompt?: string;
150
161
  urlState?: string;
151
162
  loginHint?: string;
163
+ responseMode?: SigninRequestCreateArgs["response_mode"];
152
164
  }): Promise<string> => {
153
165
  const scope = generateScope();
154
166
  const oidcClient = new OidcClient({
@@ -156,7 +168,7 @@ export const generateOidcAuthorizationUrl = async ({
156
168
  client_id: clientId,
157
169
  redirect_uri: redirectUri,
158
170
  authority: metadata.issuer,
159
- response_mode: "query",
171
+ response_mode: responseMode,
160
172
  response_type: "code",
161
173
  scope,
162
174
  stateStore: new WebStorageStateStore({ prefix: "mx_oidc_", store: window.sessionStorage }),
@@ -200,7 +212,8 @@ const normalizeBearerTokenResponseTokenType = (response: SigninResponse): Bearer
200
212
  * request to the Token Endpoint, to obtain the access token, refresh token, etc.
201
213
  *
202
214
  * @param code - authorization code as returned by OP during authorization
203
- * @param storedAuthorizationParams - stored params from start of oidc login flow
215
+ * @param state - authorization state param as returned by OP during authorization
216
+ * @param responseMode - the response mode used for authentication
204
217
  * @returns valid bearer token response
205
218
  * @throws An `Error` with `message` set to an entry in {@link OidcError},
206
219
  * when the request fails, or the returned token response is invalid.
@@ -208,6 +221,7 @@ const normalizeBearerTokenResponseTokenType = (response: SigninResponse): Bearer
208
221
  export const completeAuthorizationCodeGrant = async (
209
222
  code: string,
210
223
  state: string,
224
+ responseMode: SigninRequestCreateArgs["response_mode"] = "query",
211
225
  ): Promise<{
212
226
  oidcClientSettings: { clientId: string; issuer: string };
213
227
  tokenResponse: BearerTokenResponse;
@@ -221,13 +235,18 @@ export const completeAuthorizationCodeGrant = async (
221
235
  * so that oidc-client can parse it
222
236
  */
223
237
  const reconstructedUrl = new URL(window.location.origin);
224
- reconstructedUrl.searchParams.append("code", code);
225
- reconstructedUrl.searchParams.append("state", state);
238
+
239
+ const params = new URLSearchParams({ code, state });
240
+ if (responseMode === "query") {
241
+ reconstructedUrl.search = params.toString();
242
+ } else {
243
+ reconstructedUrl.hash = `#${params.toString()}`;
244
+ }
226
245
 
227
246
  // set oidc-client to use our logger
228
247
  Log.setLogger(logger);
229
248
  try {
230
- const response = new SigninResponse(reconstructedUrl.searchParams);
249
+ const response = new SigninResponse(params);
231
250
 
232
251
  const stateStore = new WebStorageStateStore({ prefix: "mx_oidc_", store: window.sessionStorage });
233
252
 
@@ -62,6 +62,6 @@ export const validateAuthMetadataAndKeys = async (authMetadata: unknown): Promis
62
62
 
63
63
  return {
64
64
  ...validatedIssuerConfig,
65
- signingKeys: await metadataService.getSigningKeys(),
65
+ signingKeys: validatedIssuerConfig.jwks_uri ? await metadataService.getSigningKeys() : null,
66
66
  };
67
67
  };