fix(plugins): clean matrix lint types

This commit is contained in:
Vincent Koc
2026-04-06 15:16:55 +01:00
parent 878c208844
commit e6df924a34
5 changed files with 90 additions and 72 deletions

View File

@@ -22,7 +22,7 @@ export type MatrixCryptoFacade = {
leftDeviceLists: unknown,
) => Promise<void>;
isRoomEncrypted: (roomId: string) => Promise<boolean>;
requestOwnUserVerification: () => Promise<unknown | null>;
requestOwnUserVerification: () => Promise<MatrixVerificationSummary | null>;
encryptMedia: (buffer: Buffer) => Promise<{ buffer: Buffer; file: Omit<EncryptedFile, "url"> }>;
decryptMedia: (
file: EncryptedFile,
@@ -111,7 +111,7 @@ export function createMatrixCryptoFacade(deps: {
return false;
}
},
requestOwnUserVerification: async (): Promise<unknown | null> => {
requestOwnUserVerification: async () => {
const crypto = deps.client.getCrypto() as MatrixVerificationCryptoApi | undefined;
return await deps.verificationManager.requestOwnUserVerification(crypto);
},

View File

@@ -8,9 +8,9 @@ export async function clearAllIndexedDbState(): Promise<void> {
(name) =>
new Promise<void>((resolve, reject) => {
const req = indexedDB.deleteDatabase(name);
req.onsuccess = () => resolve();
req.onerror = () => reject(req.error);
req.onblocked = () => resolve();
req.addEventListener("success", () => resolve(), { once: true });
req.addEventListener("error", () => reject(req.error), { once: true });
req.addEventListener("blocked", () => resolve(), { once: true });
}),
),
);
@@ -24,26 +24,26 @@ export async function seedDatabase(params: {
}): Promise<void> {
await new Promise<void>((resolve, reject) => {
const req = indexedDB.open(params.name, params.version ?? 1);
req.onupgradeneeded = () => {
req.addEventListener("upgradeneeded", () => {
const db = req.result;
if (!db.objectStoreNames.contains(params.storeName)) {
db.createObjectStore(params.storeName);
}
};
req.onsuccess = () => {
});
req.addEventListener("success", () => {
const db = req.result;
const tx = db.transaction(params.storeName, "readwrite");
const store = tx.objectStore(params.storeName);
for (const record of params.records) {
store.put(record.value, record.key);
}
tx.oncomplete = () => {
tx.addEventListener("complete", () => {
db.close();
resolve();
};
tx.onerror = () => reject(tx.error);
};
req.onerror = () => reject(req.error);
});
tx.addEventListener("error", () => reject(tx.error), { once: true });
});
req.addEventListener("error", () => reject(req.error), { once: true });
});
}
@@ -54,7 +54,7 @@ export async function readDatabaseRecords(params: {
}): Promise<Array<{ key: IDBValidKey; value: unknown }>> {
return await new Promise((resolve, reject) => {
const req = indexedDB.open(params.name, params.version ?? 1);
req.onsuccess = () => {
req.addEventListener("success", () => {
const db = req.result;
const tx = db.transaction(params.storeName, "readonly");
const store = tx.objectStore(params.storeName);
@@ -72,17 +72,17 @@ export async function readDatabaseRecords(params: {
resolve(keys.map((key, index) => ({ key, value: resolvedValues[index] })));
};
keysReq.onsuccess = () => {
keysReq.addEventListener("success", () => {
keys = keysReq.result;
maybeResolve();
};
valuesReq.onsuccess = () => {
});
valuesReq.addEventListener("success", () => {
values = valuesReq.result;
maybeResolve();
};
keysReq.onerror = () => reject(keysReq.error);
valuesReq.onerror = () => reject(valuesReq.error);
};
req.onerror = () => reject(req.error);
});
keysReq.addEventListener("error", () => reject(keysReq.error), { once: true });
valuesReq.addEventListener("error", () => reject(valuesReq.error), { once: true });
});
req.addEventListener("error", () => reject(req.error), { once: true });
});
}

View File

@@ -96,8 +96,8 @@ function parseSnapshotPayload(data: string): IdbDatabaseSnapshot[] | null {
function idbReq<T>(req: IDBRequest<T>): Promise<T> {
return new Promise((resolve, reject) => {
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
req.addEventListener("success", () => resolve(req.result), { once: true });
req.addEventListener("error", () => reject(req.error), { once: true });
});
}
@@ -116,8 +116,8 @@ async function dumpIndexedDatabases(databasePrefix?: string): Promise<IdbDatabas
}
const db: IDBDatabase = await new Promise((resolve, reject) => {
const r = idb.open(name, version);
r.onsuccess = () => resolve(r.result);
r.onerror = () => reject(r.error);
r.addEventListener("success", () => resolve(r.result), { once: true });
r.addEventListener("error", () => reject(r.error), { once: true });
});
const stores: IdbStoreSnapshot[] = [];
@@ -156,7 +156,7 @@ async function restoreIndexedDatabases(snapshot: IdbDatabaseSnapshot[]): Promise
for (const dbSnap of snapshot) {
await new Promise<void>((resolve, reject) => {
const r = idb.open(dbSnap.name, dbSnap.version);
r.onupgradeneeded = () => {
r.addEventListener("upgradeneeded", () => {
const db = r.result;
for (const storeSnap of dbSnap.stores) {
const opts: IDBObjectStoreParameters = {};
@@ -174,34 +174,36 @@ async function restoreIndexedDatabases(snapshot: IdbDatabaseSnapshot[]): Promise
});
}
}
};
r.onsuccess = async () => {
try {
const db = r.result;
for (const storeSnap of dbSnap.stores) {
if (storeSnap.records.length === 0) {
continue;
}
const tx = db.transaction(storeSnap.name, "readwrite");
const store = tx.objectStore(storeSnap.name);
for (const rec of storeSnap.records) {
if (storeSnap.keyPath !== null) {
store.put(rec.value);
} else {
store.put(rec.value, rec.key);
});
r.addEventListener(
"success",
() => {
void (async () => {
const db = r.result;
for (const storeSnap of dbSnap.stores) {
if (storeSnap.records.length === 0) {
continue;
}
const tx = db.transaction(storeSnap.name, "readwrite");
const store = tx.objectStore(storeSnap.name);
for (const rec of storeSnap.records) {
if (storeSnap.keyPath !== null) {
store.put(rec.value);
} else {
store.put(rec.value, rec.key);
}
}
await new Promise<void>((res) => {
tx.addEventListener("complete", () => res(), { once: true });
});
}
await new Promise<void>((res) => {
tx.oncomplete = () => res();
});
}
db.close();
resolve();
} catch (err) {
reject(err);
}
};
r.onerror = () => reject(r.error);
db.close();
resolve();
})().catch(reject);
},
{ once: true },
);
r.addEventListener("error", () => reject(r.error), { once: true });
});
}
}

View File

@@ -200,7 +200,7 @@ export type MatrixCryptoBootstrapApi = {
}) => Promise<void>;
createRecoveryKeyFromPassphrase?: (password?: string) => Promise<MatrixGeneratedSecretStorageKey>;
getSecretStorageStatus?: () => Promise<MatrixSecretStorageStatus>;
requestOwnUserVerification: () => Promise<unknown | null>;
requestOwnUserVerification: () => Promise<MatrixVerificationRequestLike | null>;
findVerificationRequestDMInProgress?: (
roomId: string,
userId: string,

View File

@@ -6,6 +6,23 @@ import {
import { VerificationMethod } from "matrix-js-sdk/lib/types.js";
export type MatrixVerificationMethod = "sas" | "show-qr" | "scan-qr";
type MatrixVerificationPhase = VerificationPhase | -1;
const MATRIX_VERIFICATION_PHASES = new Set<MatrixVerificationPhase>([
-1,
VerificationPhase.Unsent,
VerificationPhase.Requested,
VerificationPhase.Ready,
VerificationPhase.Started,
VerificationPhase.Cancelled,
VerificationPhase.Done,
]);
function isMatrixVerificationPhase(value: unknown): value is MatrixVerificationPhase {
return (
typeof value === "number" && MATRIX_VERIFICATION_PHASES.has(value as MatrixVerificationPhase)
);
}
export type MatrixVerificationSummary = {
id: string;
@@ -82,7 +99,7 @@ export type MatrixVerificationRequestLike = {
};
export type MatrixVerificationCryptoApi = {
requestOwnUserVerification: () => Promise<unknown | null>;
requestOwnUserVerification: () => Promise<MatrixVerificationRequestLike | null>;
findVerificationRequestDMInProgress?: (
roomId: string,
userId: string,
@@ -137,9 +154,17 @@ export class MatrixVerificationManager {
}
}
private readVerificationPhase(
request: MatrixVerificationRequestLike,
fallback: MatrixVerificationPhase,
): MatrixVerificationPhase {
const phase = this.readRequestValue<unknown>(request, () => request.phase, fallback);
return isMatrixVerificationPhase(phase) ? phase : fallback;
}
private pruneVerificationSessions(nowMs: number): void {
for (const [id, session] of this.verificationSessions) {
const phase = this.readRequestValue(session.request, () => session.request.phase, -1);
const phase = this.readVerificationPhase(session.request, -1);
const isTerminal = phase === VerificationPhase.Done || phase === VerificationPhase.Cancelled;
if (isTerminal && nowMs - session.updatedAtMs > TERMINAL_SESSION_RETENTION_MS) {
this.verificationSessions.delete(id);
@@ -162,7 +187,7 @@ export class MatrixVerificationManager {
}
}
private getVerificationPhaseName(phase: number): string {
private getVerificationPhaseName(phase: MatrixVerificationPhase): string {
switch (phase) {
case VerificationPhase.Unsent:
return "unsent";
@@ -203,7 +228,7 @@ export class MatrixVerificationManager {
private buildVerificationSummary(session: MatrixVerificationSession): MatrixVerificationSummary {
const request = session.request;
const phase = this.readRequestValue(request, () => request.phase, VerificationPhase.Requested);
const phase = this.readVerificationPhase(request, VerificationPhase.Requested);
const accepting = this.readRequestValue(request, () => request.accepting, false);
const declining = this.readRequestValue(request, () => request.declining, false);
const pending = this.readRequestValue(request, () => request.pending, false);
@@ -287,7 +312,7 @@ export class MatrixVerificationManager {
false,
);
const initiatedByMe = this.readRequestValue(request, () => request.initiatedByMe, false);
const phase = this.readRequestValue(request, () => request.phase, VerificationPhase.Requested);
const phase = this.readVerificationPhase(request, VerificationPhase.Requested);
const accepting = this.readRequestValue(request, () => request.accepting, false);
const declining = this.readRequestValue(request, () => request.declining, false);
if (isSelfVerification || initiatedByMe) {
@@ -320,11 +345,7 @@ export class MatrixVerificationManager {
if (!this.readRequestValue(session.request, () => session.request.isSelfVerification, false)) {
return;
}
const phase = this.readRequestValue(
session.request,
() => session.request.phase,
VerificationPhase.Requested,
);
const phase = this.readVerificationPhase(session.request, VerificationPhase.Requested);
if (phase < VerificationPhase.Ready || phase >= VerificationPhase.Cancelled) {
return;
}
@@ -416,11 +437,7 @@ export class MatrixVerificationManager {
// we send our MAC and finish our side of the SAS flow.
session.sasAutoConfirmTimer = setTimeout(() => {
session.sasAutoConfirmTimer = undefined;
const phase = this.readRequestValue(
session.request,
() => session.request.phase,
VerificationPhase.Requested,
);
const phase = this.readVerificationPhase(session.request, VerificationPhase.Requested);
if (phase >= VerificationPhase.Cancelled) {
return;
}
@@ -514,8 +531,7 @@ export class MatrixVerificationManager {
if (!crypto) {
return null;
}
const request =
(await crypto.requestOwnUserVerification()) as MatrixVerificationRequestLike | null;
const request = await crypto.requestOwnUserVerification();
if (!request) {
return null;
}
@@ -544,7 +560,7 @@ export class MatrixVerificationManager {
}
let request: MatrixVerificationRequestLike | null = null;
if (params.ownUser) {
request = (await crypto.requestOwnUserVerification()) as MatrixVerificationRequestLike | null;
request = await crypto.requestOwnUserVerification();
} else if (params.userId && params.deviceId && crypto.requestDeviceVerification) {
request = await crypto.requestDeviceVerification(params.userId, params.deviceId);
} else if (params.userId && params.roomId && crypto.requestVerificationDM) {