diff --git a/frontend/sync-client/src/persistence/database.ts b/frontend/sync-client/src/persistence/database.ts index a5daf876..981780e8 100644 --- a/frontend/sync-client/src/persistence/database.ts +++ b/frontend/sync-client/src/persistence/database.ts @@ -74,7 +74,6 @@ export class Database { this.documents.forEach((doc) => { this.lastSeenUpdateIds.add(doc.metadata?.parentVersionId); }); - } public get length(): number { @@ -104,7 +103,7 @@ export class Database { i === 0 ? false : records[i - 1].parallelVersion === - current.parallelVersion + current.parallelVersion ) ) { throw new Error( @@ -282,7 +281,6 @@ export class Database { candidate.isDeleted = true; } - public getLastSeenUpdateId(): VaultUpdateId { return this.lastSeenUpdateIds.min; } @@ -317,7 +315,7 @@ export class Database { ...metadata! // `resolvedDocuments` only returns docs with metadata set }) ), - lastSeenUpdateId: this.lastSeenUpdateIds.min, + lastSeenUpdateId: this.lastSeenUpdateIds.min }); } @@ -341,7 +339,7 @@ export class Database { if (duplicates.length > 0) { throw new Error( "Document IDs are not unique, found duplicates: " + - duplicates.join("; ") + duplicates.join("; ") ); } } diff --git a/frontend/sync-client/src/services/sync-service.ts b/frontend/sync-client/src/services/sync-service.ts index 82303bce..ce4d125a 100644 --- a/frontend/sync-client/src/services/sync-service.ts +++ b/frontend/sync-client/src/services/sync-service.ts @@ -157,7 +157,8 @@ export class SyncService { (await response.json()) as DocumentUpdateResponse; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion this.logger.debug( - `Updated document ${JSON.stringify(result)} with id ${result.documentId + `Updated document ${JSON.stringify(result)} with id ${ + result.documentId }}` ); @@ -209,7 +210,8 @@ export class SyncService { (await response.json()) as DocumentUpdateResponse; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion this.logger.debug( - `Updated document ${JSON.stringify(result)} with id ${result.documentId + `Updated document ${JSON.stringify(result)} with id ${ + result.documentId }}` ); @@ -336,7 +338,7 @@ export class SyncService { return this.retryForever(async () => { this.logger.debug( "Getting all documents" + - (since != null ? ` since ${since}` : "") + (since != null ? ` since ${since}` : "") ); const url = new URL(this.getUrl("/documents")); diff --git a/frontend/sync-client/src/services/websocket-manager.ts b/frontend/sync-client/src/services/websocket-manager.ts index 266047ce..27ef7084 100644 --- a/frontend/sync-client/src/services/websocket-manager.ts +++ b/frontend/sync-client/src/services/websocket-manager.ts @@ -40,7 +40,7 @@ export class WebSocketManager { private readonly logger: Logger, private readonly settings: Settings, private readonly webSocketFactoryImplementation: typeof globalThis.WebSocket = WebSocket - ) { } + ) {} public get isWebSocketConnected(): boolean { return ( @@ -260,10 +260,9 @@ export class WebSocketManager { this.resolveDisconnectingPromise?.(); this.resolveDisconnectingPromise = null; } else { - const delay = this.settings.getSettings().webSocketRetryIntervalMs; - this.logger.info( - `Reconnecting to WebSocket in ${delay}ms...` - ); + const delay = + this.settings.getSettings().webSocketRetryIntervalMs; + this.logger.info(`Reconnecting to WebSocket in ${delay}ms...`); this.reconnectTimeoutId = setTimeout(() => { this.reconnectTimeoutId = undefined; this.initializeWebSocket(); diff --git a/frontend/sync-client/src/sync-client.ts b/frontend/sync-client/src/sync-client.ts index dfcfc3e4..e7ae3baa 100644 --- a/frontend/sync-client/src/sync-client.ts +++ b/frontend/sync-client/src/sync-client.ts @@ -56,7 +56,7 @@ export class SyncClient { database: Partial; }> > - ) { } + ) {} public get documentCount(): number { return this.database.length; diff --git a/frontend/sync-client/src/sync-operations/syncer.ts b/frontend/sync-client/src/sync-operations/syncer.ts index e4017ca5..62f104b3 100644 --- a/frontend/sync-client/src/sync-operations/syncer.ts +++ b/frontend/sync-client/src/sync-operations/syncer.ts @@ -166,7 +166,7 @@ export class Syncer { // in that case, we mustn't move it again. if ( this.database.getLatestDocumentByRelativePath(relativePath) === - undefined || + undefined || this.database.getLatestDocumentByRelativePath(relativePath) ?.isDeleted === true ) { @@ -484,6 +484,5 @@ export class Syncer { return this.syncLocallyDeletedFile(relativePath); }) ); - } } diff --git a/frontend/sync-client/src/sync-operations/unrestricted-syncer.ts b/frontend/sync-client/src/sync-operations/unrestricted-syncer.ts index 4ea1eda0..52ffcc6f 100644 --- a/frontend/sync-client/src/sync-operations/unrestricted-syncer.ts +++ b/frontend/sync-client/src/sync-operations/unrestricted-syncer.ts @@ -87,7 +87,7 @@ export class UnrestrictedSyncer { forceMerge: true }); - this.handleMaybeMergingResponse({ + await this.handleMaybeMergingResponse({ document, response, contentHash, @@ -159,14 +159,14 @@ export class UnrestrictedSyncer { const updateDetails: SyncUpdateDetails | SyncMovedDetails = oldPath !== undefined ? { - type: SyncType.MOVE, - relativePath: document.relativePath, - movedFrom: oldPath - } + type: SyncType.MOVE, + relativePath: document.relativePath, + movedFrom: oldPath + } : { - type: SyncType.UPDATE, - relativePath: document.relativePath - }; + type: SyncType.UPDATE, + relativePath: document.relativePath + }; await this.executeSync(updateDetails, async () => { const originalRelativePath = document.relativePath; @@ -181,7 +181,7 @@ export class UnrestrictedSyncer { const contentBytes = await this.operations.read( document.relativePath ); // this can throw FileNotFoundError - let contentHash = hash(contentBytes); + const contentHash = hash(contentBytes); const areThereLocalChanges = !( document.metadata.hash === contentHash && oldPath === undefined @@ -205,22 +205,22 @@ export class UnrestrictedSyncer { response = isText && cachedVersion !== undefined ? await this.syncService.putText({ - documentId: document.metadata.documentId, - parentVersionId: - document.metadata.parentVersionId, - relativePath: document.relativePath, - content: diff( - new TextDecoder().decode(cachedVersion), - new TextDecoder().decode(contentBytes) - ) - }) + documentId: document.metadata.documentId, + parentVersionId: + document.metadata.parentVersionId, + relativePath: document.relativePath, + content: diff( + new TextDecoder().decode(cachedVersion), + new TextDecoder().decode(contentBytes) + ) + }) : await this.syncService.putBinary({ - documentId: document.metadata.documentId, - parentVersionId: - document.metadata.parentVersionId, - relativePath: document.relativePath, - contentBytes - }); + documentId: document.metadata.documentId, + parentVersionId: + document.metadata.parentVersionId, + relativePath: document.relativePath, + contentBytes + }); } else { if (!force) { this.logger.debug( @@ -234,10 +234,9 @@ export class UnrestrictedSyncer { }); } - - this.handleMaybeMergingResponse({ + await this.handleMaybeMergingResponse({ document, - response: response!, + response: response, contentHash, originalRelativePath, originalContentBytes: contentBytes @@ -255,16 +254,16 @@ export class UnrestrictedSyncer { const actualUpdateDetails: SyncUpdateDetails | SyncMovedDetails = oldPath !== undefined || - response.relativePath != originalRelativePath + response.relativePath != originalRelativePath ? { - type: SyncType.MOVE, - relativePath: response.relativePath, - movedFrom: oldPath ?? originalRelativePath - } + type: SyncType.MOVE, + relativePath: response.relativePath, + movedFrom: oldPath ?? originalRelativePath + } : { - type: SyncType.UPDATE, - relativePath: response.relativePath - }; + type: SyncType.UPDATE, + relativePath: response.relativePath + }; if (areThereLocalChanges) { this.history.addHistoryEntry({ @@ -288,7 +287,8 @@ export class UnrestrictedSyncer { type: SyncType.DELETE, relativePath: document.relativePath }, - message: "File has been deleted remotely, so we deleted it locally", + message: + "File has been deleted remotely, so we deleted it locally", author: response.userId, timestamp: new Date(response.updatedDate) }); @@ -460,24 +460,21 @@ export class UnrestrictedSyncer { } } - private async handleMaybeMergingResponse( - { - document, - response, - contentHash, - originalRelativePath, - originalContentBytes - }: { - document: DocumentRecord; - response: DocumentVersion | DocumentUpdateResponse, - contentHash: string, - originalRelativePath: string, - originalContentBytes: Uint8Array - } - ): Promise { - + private async handleMaybeMergingResponse({ + document, + response, + contentHash, + originalRelativePath, + originalContentBytes + }: { + document: DocumentRecord; + response: DocumentVersion | DocumentUpdateResponse; + contentHash: string; + originalRelativePath: string; + originalContentBytes: Uint8Array; + }): Promise { // `document` is mutable and reflects the latest state in the local database - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (document.isDeleted) { this.logger.info( `Document ${document.relativePath} has been deleted before we could finish updating it` @@ -572,8 +569,9 @@ export class UnrestrictedSyncer { type: SyncType.SKIPPED, relativePath }, - message: `File size of ${sizeInMB} MB exceeds the maximum file size limit of ${maxFileSizeMB - } MB` + message: `File size of ${sizeInMB} MB exceeds the maximum file size limit of ${ + maxFileSizeMB + } MB` }; } } @@ -598,8 +596,6 @@ export class UnrestrictedSyncer { document: DocumentRecord, response: DocumentVersion | DocumentUpdateResponse ): Promise { - - this.database.delete(document.relativePath); this.database.updateDocumentMetadata( { diff --git a/frontend/test-client/src/agent/mock-client.ts b/frontend/test-client/src/agent/mock-client.ts index 240869bb..84ef4f18 100644 --- a/frontend/test-client/src/agent/mock-client.ts +++ b/frontend/test-client/src/agent/mock-client.ts @@ -102,13 +102,13 @@ export class MockClient implements FileSystemOperations { .map((part) => part.trim()); const newParts = newContent.split(" ").map((part) => part.trim()); existingParts.forEach((part) => - // all changes should be additive - { - assert( - newParts.includes(part), - `Part ${part} not found in new content: ${newContent}` - ); - } + // all changes should be additive + { + assert( + newParts.includes(part), + `Part ${part} not found in new content: ${newContent}` + ); + } ); } diff --git a/sync-server/config-e2e.yml b/sync-server/config-e2e.yml index 1f235b01..e9d47559 100644 --- a/sync-server/config-e2e.yml +++ b/sync-server/config-e2e.yml @@ -9,24 +9,24 @@ server: max_clients_per_vault: 256 response_timeout: 30m mergeable_file_extensions: - - md - - txt + - md + - txt users: user_configs: - - name: admin - token: test-token-change-me - vault_access: - type: allow_access_to_all - - name: other-admin - token: test-token-change-me2 - vault_access: - type: allow_access_to_all - - name: test - token: other-test-token - vault_access: - type: allow_list - allowed: - - default + - name: admin + token: test-token-change-me + vault_access: + type: allow_access_to_all + - name: other-admin + token: test-token-change-me2 + vault_access: + type: allow_access_to_all + - name: test + token: other-test-token + vault_access: + type: allow_list + allowed: + - default logging: log_directory: logs log_rotation: 7days diff --git a/sync-server/src/server/update_document.rs b/sync-server/src/server/update_document.rs index 7bee7b60..b5d9bf0a 100644 --- a/sync-server/src/server/update_document.rs +++ b/sync-server/src/server/update_document.rs @@ -249,7 +249,7 @@ pub async fn merge_with_stored_version( }; // We can only update the relative path if we're the first one to do so - let new_relative_path = if parent_document_path == &latest_version.relative_path + let new_relative_path = if parent_document_path == latest_version.relative_path && latest_version.relative_path != sanitized_relative_path { let new_path = find_first_available_path( diff --git a/sync-server/src/utils/find_first_available_path.rs b/sync-server/src/utils/find_first_available_path.rs index 937eecae..20a0a656 100644 --- a/sync-server/src/utils/find_first_available_path.rs +++ b/sync-server/src/utils/find_first_available_path.rs @@ -1,7 +1,7 @@ use crate::app_state::database::models::VaultId; use crate::{app_state::database::Transaction, utils::dedup_paths::dedup_paths}; use anyhow::Result; -use log::{debug, info}; +use log::info; pub async fn find_first_available_path( vault_id: &VaultId,