Small FE improvements

This commit is contained in:
Andras Schmelczer 2026-09-19 20:03:45 +01:00
commit f2326b846e
7 changed files with 39 additions and 11 deletions

View file

@ -22,13 +22,18 @@ export { Logger, LogLevel, LogLine } from "./tracing/logger";
export { type SyncSettings, DEFAULT_SETTINGS } from "./persistence/settings"; export { type SyncSettings, DEFAULT_SETTINGS } from "./persistence/settings";
export { rateLimit } from "./utils/rate-limit"; export { rateLimit } from "./utils/rate-limit";
export type { RelativePath, StoredDatabase } from "./persistence/database"; export type { RelativePath, StoredDatabase } from "./persistence/database";
export type { FileSystemOperations } from "./file-operations/filesystem-operations"; export type {
FileSystemOperations,
FileSnapshot
} from "./file-operations/filesystem-operations";
export type { PersistenceProvider } from "./persistence/persistence"; export type { PersistenceProvider } from "./persistence/persistence";
export type { CursorSpan } from "./services/types/CursorSpan"; export type { CursorSpan } from "./services/types/CursorSpan";
export type { ClientCursors } from "./services/types/ClientCursors"; export type { ClientCursors } from "./services/types/ClientCursors";
export type { NetworkConnectionStatus } from "./types/network-connection-status"; export type { NetworkConnectionStatus } from "./types/network-connection-status";
export type { ServerVersionMismatchError } from "./services/server-version-mismatch-error"; export type {
export type { AuthenticationError } from "./services/authentication-error"; ServerVersionMismatchError,
AuthenticationError
} from "./errors/errors";
export type { MaybeOutdatedClientCursors } from "./types/maybe-outdated-client-cursors"; export type { MaybeOutdatedClientCursors } from "./types/maybe-outdated-client-cursors";
export { DocumentSyncStatus } from "./types/document-sync-status"; export { DocumentSyncStatus } from "./types/document-sync-status";
export { SyncClient } from "./sync-client"; export { SyncClient } from "./sync-client";
@ -47,3 +52,13 @@ export const utils = {
awaitAll, awaitAll,
removeFromArray removeFromArray
}; };
export type {
FileManifest,
FileManifestEntries,
EventRecord,
EventBatch,
VaultSnapshot,
PutFileContent,
PushFileManifest
} from "./services/protocol";

View file

@ -1,3 +1,7 @@
/** save() atomically replaces the entire value and resolves only after both the
* data and its directory entry are durable across power loss. Failed saves must
* leave either complete value readable; callers retain their recovery journal.
*/
export interface PersistenceProvider<T> { export interface PersistenceProvider<T> {
load: () => Promise<T | undefined>; load: () => Promise<T | undefined>;
save: (data: T) => Promise<void>; save: (data: T) => Promise<void>;

View file

@ -3,7 +3,7 @@ import { describe, it, mock, beforeEach, afterEach } from "node:test";
import assert from "node:assert"; import assert from "node:assert";
import { FetchController } from "./fetch-controller"; import { FetchController } from "./fetch-controller";
import { Logger } from "../tracing/logger"; import { Logger } from "../tracing/logger";
import { SyncResetError } from "./sync-reset-error"; import { SyncResetError } from "../errors/errors";
import { sleep } from "../utils/sleep"; import { sleep } from "../utils/sleep";
describe("FetchController", () => { describe("FetchController", () => {

View file

@ -1,6 +1,6 @@
import type { Logger } from "../tracing/logger"; import type { Logger } from "../tracing/logger";
import { createPromise } from "../utils/create-promise"; import { createPromise } from "../utils/create-promise";
import { SyncResetError } from "./sync-reset-error"; import { SyncResetError } from "../errors/errors";
/** /**
* Offers a resettable fetch implementation that waits until syncing is enabled * Offers a resettable fetch implementation that waits until syncing is enabled

View file

@ -1,6 +1,8 @@
import { SUPPORTED_API_VERSION } from "../consts"; import { SUPPORTED_API_VERSION } from "../consts";
import { AuthenticationError } from "./authentication-error"; import {
import { ServerVersionMismatchError } from "./server-version-mismatch-error"; AuthenticationError,
ServerVersionMismatchError
} from "../errors/errors";
import type { SyncService } from "./sync-service"; import type { SyncService } from "./sync-service";
import type { PingResponse } from "./types/PingResponse"; import type { PingResponse } from "./types/PingResponse";
@ -74,7 +76,12 @@ export class ServerConfig {
public async getConfig(): Promise<ServerConfigData> { public async getConfig(): Promise<ServerConfigData> {
if (!this.config) { if (!this.config) {
this.response ??= this.syncService.ping(); this.response ??= this.syncService.ping();
this.config = await this.response; try {
this.config = await this.response;
} catch (error) {
this.response = undefined;
throw error;
}
} }
ServerConfig.validateConfig(this.config); ServerConfig.validateConfig(this.config);

View file

@ -5,7 +5,7 @@ import type { WebSocketClientMessage } from "./types/WebSocketClientMessage";
import type { CursorPositionFromClient } from "./types/CursorPositionFromClient"; import type { CursorPositionFromClient } from "./types/CursorPositionFromClient";
import type { ClientCursors } from "./types/ClientCursors"; import type { ClientCursors } from "./types/ClientCursors";
import { createPromise } from "../utils/create-promise"; import { createPromise } from "../utils/create-promise";
import type { WebSocketVaultUpdate } from "./types/WebSocketVaultUpdate"; import type { EventBatch } from "./protocol";
import { WEBSOCKET_DISCONNECT_TIMEOUT_IN_S } from "../consts"; import { WEBSOCKET_DISCONNECT_TIMEOUT_IN_S } from "../consts";
import { removeFromArray } from "../utils/remove-from-array"; import { removeFromArray } from "../utils/remove-from-array";
import { EventListeners } from "../utils/data-structures/event-listeners"; import { EventListeners } from "../utils/data-structures/event-listeners";
@ -17,7 +17,7 @@ export class WebSocketManager {
>(); >();
public readonly onRemoteVaultUpdateReceived = new EventListeners< public readonly onRemoteVaultUpdateReceived = new EventListeners<
(update: WebSocketVaultUpdate) => Promise<void> (update: EventBatch) => Promise<void>
>(); >();
public readonly onRemoteCursorsUpdateReceived = new EventListeners< public readonly onRemoteCursorsUpdateReceived = new EventListeners<
@ -252,7 +252,7 @@ export class WebSocketManager {
private async handleWebSocketMessage( private async handleWebSocketMessage(
message: WebSocketServerMessage message: WebSocketServerMessage
): Promise<void> { ): Promise<void> {
if (message.type === "vaultUpdate") { if (message.type === "vaultEvents") {
await this.onRemoteVaultUpdateReceived.triggerAsync(message); await this.onRemoteVaultUpdateReceived.triggerAsync(message);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition

View file

@ -24,11 +24,13 @@ export const setUpTelemetry = (): (() => void) => {
} }
}); });
}; };
window.addEventListener("error", onError); window.addEventListener("error", onError);
const onUnhandledRejection = (event: PromiseRejectionEvent): void => { const onUnhandledRejection = (event: PromiseRejectionEvent): void => {
Sentry.captureException(event.reason); Sentry.captureException(event.reason);
}; };
window.addEventListener("unhandledrejection", onUnhandledRejection); window.addEventListener("unhandledrejection", onUnhandledRejection);
return (): void => { return (): void => {