Lint & format
This commit is contained in:
parent
7e3f972531
commit
57b2b76932
21 changed files with 89 additions and 74 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { Editor } from "obsidian";
|
||||
import type { Editor } from "obsidian";
|
||||
import { lineAndColumnToPosition } from "./line-and-column-to-position";
|
||||
|
||||
export interface Cursor {
|
||||
|
|
|
|||
9
frontend/obsidian-plugin/src/utils/get-random-color.ts
Normal file
9
frontend/obsidian-plugin/src/utils/get-random-color.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
export function getRandomColor(name: string): string {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
hash = (hash << 5) - hash + name.charCodeAt(i);
|
||||
hash |= 0; // Convert to 32bit integer
|
||||
}
|
||||
const normalised = hash / 0x7fffffff;
|
||||
return `hsl(${Math.abs(normalised * 360)}, 70%, 30%)`; // HSL color
|
||||
}
|
||||
|
|
@ -9,13 +9,13 @@ import type { Settings } from "../persistence/settings";
|
|||
import type { ConnectionStatus } from "./connection-status";
|
||||
import { sleep } from "../utils/sleep";
|
||||
import { SyncResetError } from "./sync-reset-error";
|
||||
import { SerializedError } from "./types/SerializedError";
|
||||
import { DocumentVersionWithoutContent } from "./types/DocumentVersionWithoutContent";
|
||||
import { DocumentUpdateResponse } from "./types/DocumentUpdateResponse";
|
||||
import { DocumentVersion } from "./types/DocumentVersion";
|
||||
import { FetchLatestDocumentsResponse } from "./types/FetchLatestDocumentsResponse";
|
||||
import { PingResponse } from "./types/PingResponse";
|
||||
import { DeleteDocumentVersion } from "./types/DeleteDocumentVersion";
|
||||
import type { SerializedError } from "./types/SerializedError";
|
||||
import type { DocumentVersionWithoutContent } from "./types/DocumentVersionWithoutContent";
|
||||
import type { DocumentUpdateResponse } from "./types/DocumentUpdateResponse";
|
||||
import type { DocumentVersion } from "./types/DocumentVersion";
|
||||
import type { FetchLatestDocumentsResponse } from "./types/FetchLatestDocumentsResponse";
|
||||
import type { PingResponse } from "./types/PingResponse";
|
||||
import type { DeleteDocumentVersion } from "./types/DeleteDocumentVersion";
|
||||
|
||||
export interface CheckConnectionResult {
|
||||
isSuccessful: boolean;
|
||||
|
|
@ -24,8 +24,8 @@ export interface CheckConnectionResult {
|
|||
|
||||
export class SyncService {
|
||||
private static readonly NETWORK_RETRY_INTERVAL_MS = 1000;
|
||||
private client: typeof globalThis.fetch;
|
||||
private pingClient: typeof globalThis.fetch;
|
||||
private readonly client: typeof globalThis.fetch;
|
||||
private readonly pingClient: typeof globalThis.fetch;
|
||||
|
||||
public constructor(
|
||||
private readonly deviceId: string,
|
||||
|
|
@ -35,7 +35,7 @@ export class SyncService {
|
|||
fetchImplementation: typeof globalThis.fetch = globalThis.fetch
|
||||
) {
|
||||
// ensure that if it's called a method, `this` won't be bound to the instance
|
||||
const unboundFetch: typeof globalThis.fetch = (...args) =>
|
||||
const unboundFetch: typeof globalThis.fetch = async (...args) =>
|
||||
fetchImplementation(...args);
|
||||
|
||||
this.client = this.connectionStatus.getFetchImplementation(
|
||||
|
|
@ -45,12 +45,6 @@ export class SyncService {
|
|||
this.pingClient = unboundFetch;
|
||||
}
|
||||
|
||||
private getUrl(path: string): string {
|
||||
let { vaultName, remoteUri } = this.settings.getSettings();
|
||||
remoteUri = remoteUri.replace(/\/+$/, "");
|
||||
return `${remoteUri}/vaults/${vaultName}${path}`;
|
||||
}
|
||||
|
||||
private static formatError(error: SerializedError): string {
|
||||
let result = error.message;
|
||||
if (error.causes.length > 0) {
|
||||
|
|
@ -85,7 +79,9 @@ export class SyncService {
|
|||
});
|
||||
|
||||
const result: SerializedError | DocumentVersionWithoutContent =
|
||||
await response.json();
|
||||
(await response.json()) as // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||
| SerializedError
|
||||
| DocumentVersionWithoutContent;
|
||||
|
||||
if ("errorType" in result) {
|
||||
throw new Error(
|
||||
|
|
@ -133,7 +129,9 @@ export class SyncService {
|
|||
);
|
||||
|
||||
const result: SerializedError | DocumentUpdateResponse =
|
||||
await response.json();
|
||||
(await response.json()) as // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||
| SerializedError
|
||||
| DocumentUpdateResponse;
|
||||
|
||||
if ("errorType" in result) {
|
||||
throw new Error(
|
||||
|
|
@ -175,7 +173,9 @@ export class SyncService {
|
|||
);
|
||||
|
||||
const result: SerializedError | DocumentVersionWithoutContent =
|
||||
await response.json();
|
||||
(await response.json()) as // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||
| SerializedError
|
||||
| DocumentVersionWithoutContent;
|
||||
|
||||
if ("errorType" in result) {
|
||||
throw new Error(
|
||||
|
|
@ -205,7 +205,7 @@ export class SyncService {
|
|||
);
|
||||
|
||||
const result: SerializedError | DocumentVersion =
|
||||
await response.json();
|
||||
(await response.json()) as SerializedError | DocumentVersion; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||
|
||||
if ("errorType" in result) {
|
||||
throw new Error(
|
||||
|
|
@ -234,7 +234,9 @@ export class SyncService {
|
|||
});
|
||||
|
||||
const result: SerializedError | FetchLatestDocumentsResponse =
|
||||
await response.json();
|
||||
(await response.json()) as // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||
| SerializedError
|
||||
| FetchLatestDocumentsResponse;
|
||||
|
||||
if ("errorType" in result) {
|
||||
throw new Error(
|
||||
|
|
@ -256,7 +258,7 @@ export class SyncService {
|
|||
headers: this.getDefaultHeaders()
|
||||
});
|
||||
const result: PingResponse | SerializedError =
|
||||
await response.json();
|
||||
(await response.json()) as PingResponse | SerializedError; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
||||
|
||||
if ("errorType" in result) {
|
||||
throw new Error(
|
||||
|
|
@ -283,6 +285,12 @@ export class SyncService {
|
|||
}
|
||||
}
|
||||
|
||||
private getUrl(path: string): string {
|
||||
const { vaultName, remoteUri } = this.settings.getSettings();
|
||||
const safeRemoteUri = remoteUri.replace(/\/+$/, "");
|
||||
return `${safeRemoteUri}/vaults/${vaultName}${path}`;
|
||||
}
|
||||
|
||||
private getDefaultHeaders(): Record<string, string> {
|
||||
return {
|
||||
"device-id": this.deviceId,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { CursorSpan } from "./CursorSpan";
|
||||
|
||||
export type ClientCursors = { userName: string, deviceId: string, cursors: { [key in string]?: Array<CursorSpan> }, };
|
||||
export interface ClientCursors { userName: string, deviceId: string, cursors: Partial<Record<string, CursorSpan[]>>, }
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type CreateDocumentVersion = {
|
||||
export interface CreateDocumentVersion {
|
||||
/**
|
||||
* The client can decide the document id (if it wishes to) in order
|
||||
* to help with syncing. If the client does not provide a document id,
|
||||
* the server will generate one. If the client provides a document id
|
||||
* it must not already exist in the database.
|
||||
*/
|
||||
document_id: string | null, relative_path: string, content: Array<number>, };
|
||||
document_id: string | null, relative_path: string, content: number[], }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { CursorSpan } from "./CursorSpan";
|
||||
|
||||
export type CursorPositionFromClient = { documentToCursors: { [key in string]?: Array<CursorSpan> }, };
|
||||
export interface CursorPositionFromClient { documentToCursors: Partial<Record<string, CursorSpan[]>>, }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ClientCursors } from "./ClientCursors";
|
||||
|
||||
export type CursorPositionFromServer = { clients: Array<ClientCursors>, };
|
||||
export interface CursorPositionFromServer { clients: ClientCursors[], }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type CursorSpan = { start: number, end: number, };
|
||||
export interface CursorSpan { start: number, end: number, }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type DeleteDocumentVersion = { relativePath: string, };
|
||||
export interface DeleteDocumentVersion { relativePath: string, }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type DocumentVersion = { vaultUpdateId: number, documentId: string, relativePath: string, updatedDate: string, contentBase64: string, isDeleted: boolean, userId: string, deviceId: string, };
|
||||
export interface DocumentVersion { vaultUpdateId: number, documentId: string, relativePath: string, updatedDate: string, contentBase64: string, isDeleted: boolean, userId: string, deviceId: string, }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type DocumentVersionWithoutContent = { vaultUpdateId: number, documentId: string, relativePath: string, updatedDate: string, isDeleted: boolean, userId: string, deviceId: string, contentSize: number, };
|
||||
export interface DocumentVersionWithoutContent { vaultUpdateId: number, documentId: string, relativePath: string, updatedDate: string, isDeleted: boolean, userId: string, deviceId: string, contentSize: number, }
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type { DocumentVersionWithoutContent } from "./DocumentVersionWithoutCont
|
|||
/**
|
||||
* Response to a fetch latest documents request.
|
||||
*/
|
||||
export type FetchLatestDocumentsResponse = { latestDocuments: Array<DocumentVersionWithoutContent>,
|
||||
export interface FetchLatestDocumentsResponse { latestDocuments: DocumentVersionWithoutContent[],
|
||||
/**
|
||||
* The update ID of the latest document in the response.
|
||||
*/
|
||||
lastUpdateId: bigint, };
|
||||
lastUpdateId: bigint, }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
* Response to a ping request.
|
||||
*/
|
||||
export type PingResponse = {
|
||||
export interface PingResponse {
|
||||
/**
|
||||
* Semantic version of the server.
|
||||
*/
|
||||
|
|
@ -12,4 +12,4 @@ serverVersion: string,
|
|||
* Whether the client is authenticated based on the sent Authorization
|
||||
* header.
|
||||
*/
|
||||
isAuthenticated: boolean, };
|
||||
isAuthenticated: boolean, }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SerializedError = { errorType: string, message: string, causes: Array<string>, };
|
||||
export interface SerializedError { errorType: string, message: string, causes: string[], }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type UpdateDocumentVersion = { parent_version_id: bigint, relative_path: string, content: Array<number>, };
|
||||
export interface UpdateDocumentVersion { parent_version_id: bigint, relative_path: string, content: number[], }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type WebSocketHandshake = { token: string, deviceId: string, lastSeenVaultUpdateId: number | null, };
|
||||
export interface WebSocketHandshake { token: string, deviceId: string, lastSeenVaultUpdateId: number | null, }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { DocumentVersionWithoutContent } from "./DocumentVersionWithoutContent";
|
||||
|
||||
export type WebSocketVaultUpdate = { documents: Array<DocumentVersionWithoutContent>, isInitialSync: boolean, };
|
||||
export interface WebSocketVaultUpdate { documents: DocumentVersionWithoutContent[], isInitialSync: boolean, }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import type { Database } from "../persistence/database";
|
||||
import type { Logger } from "../tracing/logger";
|
||||
import type { Settings, SyncSettings } from "../persistence/settings";
|
||||
import { WebSocketServerMessage } from "./types/WebSocketServerMessage";
|
||||
import { Syncer } from "../sync-operations/syncer";
|
||||
import { WebSocketClientMessage } from "./types/WebSocketClientMessage";
|
||||
import { CursorPositionFromClient } from "./types/CursorPositionFromClient";
|
||||
import { ClientCursors } from "./types/ClientCursors";
|
||||
import type { WebSocketServerMessage } from "./types/WebSocketServerMessage";
|
||||
import type { Syncer } from "../sync-operations/syncer";
|
||||
import type { WebSocketClientMessage } from "./types/WebSocketClientMessage";
|
||||
import type { CursorPositionFromClient } from "./types/CursorPositionFromClient";
|
||||
import type { ClientCursors } from "./types/ClientCursors";
|
||||
|
||||
export class WebSocketManager {
|
||||
private readonly webSocketStatusChangeListeners: (() => unknown)[] = [];
|
||||
|
|
@ -19,7 +19,6 @@ export class WebSocketManager {
|
|||
|
||||
private readonly webSocketFactoryImplementation: typeof globalThis.WebSocket;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/max-params
|
||||
public constructor(
|
||||
private readonly deviceId: string,
|
||||
private readonly logger: Logger,
|
||||
|
|
@ -90,6 +89,23 @@ export class WebSocketManager {
|
|||
}
|
||||
}
|
||||
|
||||
public updateLocalCursors(cursorPositions: CursorPositionFromClient): void {
|
||||
if (!this.isWebSocketConnected) {
|
||||
this.logger.warn(
|
||||
"WebSocket is not connected, cannot send cursor positions"
|
||||
);
|
||||
return;
|
||||
}
|
||||
const message: WebSocketClientMessage = {
|
||||
type: "cursorPositions",
|
||||
...cursorPositions
|
||||
};
|
||||
this.webSocket?.send(JSON.stringify(message));
|
||||
this.logger.info(
|
||||
`Sent cursor positions: ${JSON.stringify(cursorPositions)}`
|
||||
);
|
||||
}
|
||||
|
||||
private updateWebSocket(settings: SyncSettings): void {
|
||||
try {
|
||||
this.webSocket?.close();
|
||||
|
|
@ -134,6 +150,7 @@ export class WebSocketManager {
|
|||
`Failed to sync remotely updated file: ${e}`
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
} else if (message.type === "cursorPositions") {
|
||||
this.logger.info(
|
||||
`Received cursor positions for ${JSON.stringify(message.clients)}`
|
||||
|
|
@ -159,7 +176,7 @@ export class WebSocketManager {
|
|||
listener();
|
||||
});
|
||||
|
||||
let message: WebSocketClientMessage = {
|
||||
const message: WebSocketClientMessage = {
|
||||
type: "handshake",
|
||||
deviceId: this.deviceId,
|
||||
token: settings.token,
|
||||
|
|
@ -178,23 +195,6 @@ export class WebSocketManager {
|
|||
};
|
||||
}
|
||||
|
||||
public updateLocalCursors(cursorPositions: CursorPositionFromClient): void {
|
||||
if (!this.isWebSocketConnected) {
|
||||
this.logger.warn(
|
||||
"WebSocket is not connected, cannot send cursor positions"
|
||||
);
|
||||
return;
|
||||
}
|
||||
let message: WebSocketClientMessage = {
|
||||
type: "cursorPositions",
|
||||
...cursorPositions
|
||||
};
|
||||
this.webSocket?.send(JSON.stringify(message));
|
||||
this.logger.info(
|
||||
`Sent cursor positions: ${JSON.stringify(cursorPositions)}`
|
||||
);
|
||||
}
|
||||
|
||||
private setWebSocketRefreshInterval(): void {
|
||||
this.refreshWebSocketInterval = setInterval(() => {
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ import type { NetworkConnectionStatus } from "./types/network-connection-status"
|
|||
import { DocumentUpdateStatus } from "./types/document-update-status";
|
||||
import { WebSocketManager } from "./services/websocket-manager";
|
||||
import { createClientId } from "./utils/create-client-id";
|
||||
import { CursorSpan } from "./services/types/CursorSpan";
|
||||
import { ClientCursors } from "./services/types/ClientCursors";
|
||||
import type { CursorSpan } from "./services/types/CursorSpan";
|
||||
import type { ClientCursors } from "./services/types/ClientCursors";
|
||||
|
||||
export class SyncClient {
|
||||
private static readonly MINIMUM_SAVE_INTERVAL_MS = 1000;
|
||||
|
|
@ -275,10 +275,8 @@ export class SyncClient {
|
|||
});
|
||||
}
|
||||
|
||||
public async updateLocalCursors(documentToCursors: {
|
||||
[path: RelativePath]: CursorSpan[];
|
||||
}): Promise<void> {
|
||||
return this.webSocketManager.updateLocalCursors({ documentToCursors });
|
||||
public async updateLocalCursors(documentToCursors: Record<RelativePath, CursorSpan[]>): Promise<void> {
|
||||
this.webSocketManager.updateLocalCursors({ documentToCursors });
|
||||
}
|
||||
|
||||
public addRemoteCursorsUpdateListener(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import type { UnrestrictedSyncer } from "./unrestricted-syncer";
|
|||
import { createPromise } from "../utils/create-promise";
|
||||
import { SyncResetError } from "../services/sync-reset-error";
|
||||
import { Locks } from "../utils/locks";
|
||||
import { DocumentVersionWithoutContent } from "../services/types/DocumentVersionWithoutContent";
|
||||
import type { DocumentVersionWithoutContent } from "../services/types/DocumentVersionWithoutContent";
|
||||
|
||||
export class Syncer {
|
||||
private readonly remoteDocumentsLock: Locks<DocumentId>;
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ import { createPromise } from "../utils/create-promise";
|
|||
import { FileNotFoundError } from "../file-operations/file-not-found-error";
|
||||
import { SyncResetError } from "../services/sync-reset-error";
|
||||
import { globsToRegexes } from "../utils/globs-to-regexes";
|
||||
import { DocumentVersion } from "../services/types/DocumentVersion";
|
||||
import { DocumentUpdateResponse } from "../services/types/DocumentUpdateResponse";
|
||||
import { DocumentVersionWithoutContent } from "../services/types/DocumentVersionWithoutContent";
|
||||
import type { DocumentVersion } from "../services/types/DocumentVersion";
|
||||
import type { DocumentUpdateResponse } from "../services/types/DocumentUpdateResponse";
|
||||
import type { DocumentVersionWithoutContent } from "../services/types/DocumentVersionWithoutContent";
|
||||
|
||||
export class UnrestrictedSyncer {
|
||||
private ignorePatterns: RegExp[];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue