SHA256
Промежуточный комит для отдачи задания брату
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { WsJsonClient } from './ws-client.js?v=20260330001044';
|
||||
import { WsJsonClient } from './ws-client.js?v=20260330210201';
|
||||
import {
|
||||
deriveEd25519FromPassword,
|
||||
exportEd25519PublicKeyB64,
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
importPkcs8Ed25519,
|
||||
randomBase64,
|
||||
signBase64,
|
||||
} from './crypto-utils.js?v=20260330001044';
|
||||
import { loadSessionMaterial, saveEncryptedUserSecrets, saveSessionMaterial } from './key-vault.js?v=20260330001044';
|
||||
} from './crypto-utils.js?v=20260330210201';
|
||||
import { loadSessionMaterial, saveEncryptedUserSecrets, saveSessionMaterial } from './key-vault.js?v=20260330210201';
|
||||
|
||||
const BCH_SUFFIX = '001';
|
||||
|
||||
@@ -235,6 +235,15 @@ export class AuthService {
|
||||
return response.payload || {};
|
||||
}
|
||||
|
||||
async reportClientError(details) {
|
||||
try {
|
||||
const response = await this.ws.request('ClientErrorLog', details || {}, 3000);
|
||||
return response?.status === 200;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
this.ws.close();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
decryptJsonWithStoragePwd,
|
||||
encryptJsonWithStoragePwd,
|
||||
} from './crypto-utils.js?v=20260330001044';
|
||||
} from './crypto-utils.js?v=20260330210201';
|
||||
|
||||
const DB_NAME = 'shine-ui-auth';
|
||||
const DB_VERSION = 1;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { captureClientError } from './client-error-reporter.js?v=20260331000100';
|
||||
|
||||
const DEFAULT_TIMEOUT_MS = 12000;
|
||||
|
||||
function buildWsUrl(raw) {
|
||||
@@ -34,6 +36,11 @@ export class WsJsonClient {
|
||||
}, { once: true });
|
||||
|
||||
ws.addEventListener('error', () => {
|
||||
captureClientError({
|
||||
kind: 'ws_open_error',
|
||||
message: `Failed to connect WebSocket ${this.url}`,
|
||||
context: { url: this.url },
|
||||
});
|
||||
reject(new Error(`Не удалось подключиться к ${this.url}`));
|
||||
}, { once: true });
|
||||
|
||||
@@ -59,10 +66,20 @@ export class WsJsonClient {
|
||||
const responsePromise = new Promise((resolve, reject) => {
|
||||
const timer = window.setTimeout(() => {
|
||||
this.pending.delete(requestId);
|
||||
if (op !== 'ClientErrorLog') {
|
||||
captureClientError({
|
||||
kind: 'ws_timeout',
|
||||
message: `Timeout waiting for ${op}`,
|
||||
requestOp: op,
|
||||
requestIdRef: requestId,
|
||||
context: { url: this.url, timeoutMs },
|
||||
});
|
||||
}
|
||||
reject(new Error(`Таймаут ответа для операции ${op}`));
|
||||
}, timeoutMs);
|
||||
|
||||
this.pending.set(requestId, {
|
||||
op,
|
||||
resolve: (value) => {
|
||||
window.clearTimeout(timer);
|
||||
resolve(value);
|
||||
@@ -90,6 +107,11 @@ export class WsJsonClient {
|
||||
try {
|
||||
data = JSON.parse(raw);
|
||||
} catch {
|
||||
captureClientError({
|
||||
kind: 'ws_bad_json',
|
||||
message: 'Received non-JSON message from server',
|
||||
context: { raw: String(raw).slice(0, 1000) },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,6 +125,17 @@ export class WsJsonClient {
|
||||
}
|
||||
|
||||
failPending(message) {
|
||||
const pendingOps = [...this.pending.values()]
|
||||
.map((slot) => slot.op)
|
||||
.filter((op) => op && op !== 'ClientErrorLog');
|
||||
if (pendingOps.length > 0) {
|
||||
captureClientError({
|
||||
kind: 'ws_closed',
|
||||
message,
|
||||
context: { url: this.url, pendingOps },
|
||||
});
|
||||
}
|
||||
|
||||
const error = new Error(message);
|
||||
for (const [, slot] of this.pending.entries()) {
|
||||
slot.reject(error);
|
||||
|
||||
Reference in New Issue
Block a user