From c2a297608070aea36f5df11769f8582d855c8388 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 11 Feb 2025 20:49:30 -0300 Subject: [PATCH 1/7] Refactor sync root management to use drive instance for unregistering and disconnecting --- examples/register.ts | 2 +- examples/unregister.ts | 4 +- include/sync_root_interface/SyncRoot.h | 6 +- native-src/sync_root_interface/SyncRoot.cpp | 49 ++++----- native-src/virtual_drive/Wrappers.cpp | 4 +- src/addon-wrapper.ts | 6 +- src/virtual-drive.ts | 109 +++++++++++--------- 7 files changed, 96 insertions(+), 84 deletions(-) diff --git a/examples/register.ts b/examples/register.ts index 5ed00fbe..c0c0d3fc 100644 --- a/examples/register.ts +++ b/examples/register.ts @@ -29,5 +29,5 @@ try { } catch (error) { logger.error(error); drive.disconnectSyncRoot(); - VirtualDrive.unregisterSyncRoot(settings.syncRootPath); + drive.unregisterSyncRoot(); } diff --git a/examples/unregister.ts b/examples/unregister.ts index 6c57ca89..b5446fcd 100644 --- a/examples/unregister.ts +++ b/examples/unregister.ts @@ -1,7 +1,7 @@ import VirtualDrive from "@/virtual-drive"; +import { drive } from "./drive"; import { deleteInfoItems } from "./info-items-manager"; -import settings from "./settings"; -VirtualDrive.unregisterSyncRoot(settings.syncRootPath); +drive.unregisterSyncRoot(); deleteInfoItems(); diff --git a/include/sync_root_interface/SyncRoot.h b/include/sync_root_interface/SyncRoot.h index 25238e3c..d8842999 100644 --- a/include/sync_root_interface/SyncRoot.h +++ b/include/sync_root_interface/SyncRoot.h @@ -16,11 +16,13 @@ class SyncRoot public: static HRESULT RegisterSyncRoot(const wchar_t *syncRootPath, const wchar_t *providerName, const wchar_t *providerVersion, const GUID &providerId, const wchar_t *logoPath); static HRESULT ConnectSyncRoot(const wchar_t *syncRootPath, InputSyncCallbacks syncCallbacks, napi_env env, CF_CONNECTION_KEY *connectionKey); - static HRESULT DisconnectSyncRoot(); + static HRESULT DisconnectSyncRoot(const wchar_t *syncRootPath); static HRESULT UnregisterSyncRoot(); - static std::list GetItemsSyncRoot(const wchar_t *syncRootPath); static std::string GetFileIdentity(const wchar_t *path); static void HydrateFile(const wchar_t *filePath); static void DehydrateFile(const wchar_t *filePath); static void DeleteFileSyncRoot(const wchar_t *path); + +private: + CF_CONNECTION_KEY connectionKey; }; \ No newline at end of file diff --git a/native-src/sync_root_interface/SyncRoot.cpp b/native-src/sync_root_interface/SyncRoot.cpp index 04125741..f7a62e6a 100644 --- a/native-src/sync_root_interface/SyncRoot.cpp +++ b/native-src/sync_root_interface/SyncRoot.cpp @@ -1,6 +1,6 @@ -#include "stdafx.h" -#include "SyncRoot.h" #include "Callbacks.h" +#include "SyncRoot.h" +#include "stdafx.h" #include #include #include @@ -9,6 +9,7 @@ namespace fs = std::filesystem; // variable to disconect CF_CONNECTION_KEY gloablConnectionKey; +std::map connectionMap; void TransformInputCallbacksToSyncCallbacks(napi_env env, InputSyncCallbacks input) { @@ -115,16 +116,17 @@ HRESULT SyncRoot::RegisterSyncRoot(const wchar_t *syncRootPath, const wchar_t *p { try { - auto syncRootID = providerId; + // Convert GUID to string for syncRootID + wchar_t syncRootID[39]; + StringFromGUID2(providerId, syncRootID, 39); winrt::StorageProviderSyncRootInfo info; - info.Id(L"syncRootID"); + info.Id(syncRootID); auto folder = winrt::StorageFolder::GetFolderFromPathAsync(syncRootPath).get(); info.Path(folder); // The string can be in any form acceptable to SHLoadIndirectString. - info.DisplayNameResource(providerName); std::wstring completeIconResource = std::wstring(logoPath) + L",0"; @@ -135,7 +137,7 @@ HRESULT SyncRoot::RegisterSyncRoot(const wchar_t *syncRootPath, const wchar_t *p info.HydrationPolicyModifier(winrt::StorageProviderHydrationPolicyModifier::None); info.PopulationPolicy(winrt::StorageProviderPopulationPolicy::AlwaysFull); info.InSyncPolicy(winrt::StorageProviderInSyncPolicy::FileCreationTime | winrt::StorageProviderInSyncPolicy::DirectoryCreationTime); - info.Version(L"1.0.0"); + info.Version(providerVersion); info.ShowSiblingsAsGroup(false); info.HardlinkPolicy(winrt::StorageProviderHardlinkPolicy::None); @@ -145,9 +147,8 @@ HRESULT SyncRoot::RegisterSyncRoot(const wchar_t *syncRootPath, const wchar_t *p // Context std::wstring syncRootIdentity(syncRootPath); syncRootIdentity.append(L"->"); - syncRootIdentity.append(L"TestProvider"); + syncRootIdentity.append(providerName); - wchar_t const contextString[] = L"TestProviderContextString"; winrt::IBuffer contextBuffer = winrt::CryptographicBuffer::ConvertStringToBinary(syncRootIdentity.data(), winrt::BinaryStringEncoding::Utf8); info.Context(contextBuffer); @@ -165,6 +166,7 @@ HRESULT SyncRoot::RegisterSyncRoot(const wchar_t *syncRootPath, const wchar_t *p catch (...) { wprintf(L"Could not register the sync root, hr %08x\n", static_cast(winrt::to_hresult())); + return E_FAIL; } } @@ -179,6 +181,7 @@ HRESULT SyncRoot::UnregisterSyncRoot() catch (...) { wprintf(L"Could not unregister the sync root, hr %08x\n", static_cast(winrt::to_hresult())); + return E_FAIL; } } @@ -205,38 +208,38 @@ HRESULT SyncRoot::ConnectSyncRoot(const wchar_t *syncRootPath, InputSyncCallback CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO | CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, connectionKey); wprintf(L"Connection key: %llu\n", *connectionKey); - gloablConnectionKey = *connectionKey; + if (SUCCEEDED(hr)) + { + connectionMap[syncRootPath] = *connectionKey; + } return hr; } catch (const std::exception &e) { wprintf(L"Excepción capturada: %hs\n", e.what()); - // Aquí puedes decidir si retornar un código de error específico o mantener el E_FAIL. + return E_FAIL; } catch (...) { wprintf(L"Excepción desconocida capturada\n"); - // Igualmente, puedes decidir el código de error a retornar. + return E_FAIL; } } // disconection sync root -HRESULT SyncRoot::DisconnectSyncRoot() +HRESULT SyncRoot::DisconnectSyncRoot(const wchar_t *syncRootPath) { - Logger::getInstance().log("Disconnecting sync root.", LogLevel::INFO); - try + auto it = connectionMap.find(syncRootPath); + if (it != connectionMap.end()) { - HRESULT hr = CfDisconnectSyncRoot(gloablConnectionKey); + HRESULT hr = CfDisconnectSyncRoot(it->second); + if (SUCCEEDED(hr)) + { + connectionMap.erase(it); + } return hr; } - catch (const std::exception &e) - { - Logger::getInstance().log("Exception caught: " + std::string(e.what()), LogLevel::ERROR); - } - catch (...) - { - Logger::getInstance().log("Unknown exception caught.", LogLevel::ERROR); - } + return E_FAIL; } // struct diff --git a/native-src/virtual_drive/Wrappers.cpp b/native-src/virtual_drive/Wrappers.cpp index a81e57e1..d75d6383 100644 --- a/native-src/virtual_drive/Wrappers.cpp +++ b/native-src/virtual_drive/Wrappers.cpp @@ -429,8 +429,8 @@ napi_value DisconnectSyncRootWrapper(napi_env env, napi_callback_info args) syncRootPath = new WCHAR[pathLength + 1]; napi_get_value_string_utf16(env, argv[0], reinterpret_cast(const_cast(syncRootPath)), pathLength + 1, nullptr); - HRESULT result = SyncRoot::DisconnectSyncRoot(); - // wprintf(L"DisconnectSyncRootWrapper: %08x\n", static_cast(result)); + HRESULT result = SyncRoot::DisconnectSyncRoot(syncRootPath); + delete[] syncRootPath; napi_value napiResult; diff --git a/src/addon-wrapper.ts b/src/addon-wrapper.ts index 5e39f33a..5b55017a 100644 --- a/src/addon-wrapper.ts +++ b/src/addon-wrapper.ts @@ -27,7 +27,7 @@ export class Addon { return this.parseAddonZod("registerSyncRoot", result); } - connectSyncRoot({ callbacks }: { callbacks: Callbacks }) { + connectSyncRoot({ callbacks }: { callbacks: Callbacks; syncRootPath: string }) { const result = addon.connectSyncRoot(this.syncRootPath, callbacks); return this.parseAddonZod("connectSyncRoot", result); } @@ -37,8 +37,8 @@ export class Addon { return this.parseAddonZod("unregisterSyncRoot", result); } - disconnectSyncRoot() { - return addon.disconnectSyncRoot(this.syncRootPath); + disconnectSyncRoot({ syncRootPath }: { syncRootPath: string }) { + return addon.disconnectSyncRoot(syncRootPath); } addLogger({ logPath }: { logPath: string }) { diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 3b881b24..17f96e2f 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -1,14 +1,12 @@ -import path, { join, win32 } from "path"; import fs from "fs"; -import { Watcher } from "./watcher/watcher"; -import { Callbacks } from "./types/callbacks.type"; -import { IQueueManager } from "./queue/queueManager"; - -import { createLogger } from "./logger"; -import { Addon } from "./addon-wrapper"; +import path, { join, win32 } from "path"; import winston from "winston"; -const addon = new Addon(); +import { Addon } from "./addon-wrapper"; +import { createLogger } from "./logger"; +import { IQueueManager } from "./queue/queueManager"; +import { Callbacks } from "./types/callbacks.type"; +import { Watcher } from "./watcher/watcher"; const PLACEHOLDER_ATTRIBUTES = { FILE_ATTRIBUTE_READONLY: 0x1, @@ -22,12 +20,16 @@ class VirtualDrive { callbacks?: Callbacks; watcher = new Watcher(); logger: winston.Logger; + connections: Map = new Map(); + + addon: Addon; constructor(syncRootPath: string, loggerPath: string) { + this.addon = new Addon(); this.syncRootPath = this.convertToWindowsPath(syncRootPath); loggerPath = this.convertToWindowsPath(loggerPath); - addon.syncRootPath = this.syncRootPath; + this.addon.syncRootPath = this.syncRootPath; this.createSyncRootFolder(); this.addLoggerPath(loggerPath); @@ -52,15 +54,15 @@ class VirtualDrive { } addLoggerPath(logPath: string) { - addon.addLogger({ logPath }); + this.addon.addLogger({ logPath }); } getPlaceholderState(path: string) { - return addon.getPlaceholderState({ path: this.fixPath(path) }); + return this.addon.getPlaceholderState({ path: this.fixPath(path) }); } getPlaceholderWithStatePending() { - return addon.getPlaceholderWithStatePending(); + return this.addon.getPlaceholderWithStatePending(); } createSyncRootFolder() { @@ -70,11 +72,11 @@ class VirtualDrive { } getFileIdentity(relativePath: string) { - return addon.getFileIdentity({ path: this.fixPath(relativePath) }); + return this.addon.getFileIdentity({ path: this.fixPath(relativePath) }); } async deleteFileSyncRoot(relativePath: string) { - return addon.deleteFileSyncRoot({ path: this.fixPath(relativePath) }); + return this.addon.deleteFileSyncRoot({ path: this.fixPath(relativePath) }); } connectSyncRoot() { @@ -82,7 +84,23 @@ class VirtualDrive { throw new Error("Callbacks are not defined"); } - return addon.connectSyncRoot({ callbacks: this.callbacks }); + console.log("Connecting to sync root: ", this.syncRootPath); + + const connectionKey = this.addon.connectSyncRoot({ syncRootPath: this.syncRootPath, callbacks: this.callbacks }); + + console.log("Connection key: ", connectionKey); + this.connections.set(this.syncRootPath, connectionKey); + return connectionKey; + } + + disconnectSyncRoot() { + const connectionKey = this.connections.get(this.syncRootPath); + if (connectionKey) { + this.addon.disconnectSyncRoot({ syncRootPath: this.syncRootPath }); + this.connections.delete(this.syncRootPath); + } else { + throw new Error(`No connection found for syncRootPath: ${this.syncRootPath}`); + } } createPlaceholderFile( @@ -93,13 +111,13 @@ class VirtualDrive { creationTime: number, lastWriteTime: number, lastAccessTime: number, - basePath: string + basePath: string, ): any { const creationTimeStr = this.convertToWindowsTime(creationTime).toString(); const lastWriteTimeStr = this.convertToWindowsTime(lastWriteTime).toString(); const lastAccessTimeStr = this.convertToWindowsTime(lastAccessTime).toString(); - return addon.createPlaceholderFile({ + return this.addon.createPlaceholderFile({ fileName, fileId, fileSize, @@ -107,7 +125,7 @@ class VirtualDrive { creationTime: creationTimeStr, lastWriteTime: lastWriteTimeStr, lastAccessTime: lastAccessTimeStr, - basePath + basePath, }); } @@ -120,13 +138,13 @@ class VirtualDrive { creationTime: number, lastWriteTime: number, lastAccessTime: number, - path: string + path: string, ) { const creationTimeStr = this.convertToWindowsTime(creationTime).toString(); const lastWriteTimeStr = this.convertToWindowsTime(lastWriteTime).toString(); const lastAccessTimeStr = this.convertToWindowsTime(lastAccessTime).toString(); - - return addon.createPlaceholderDirectory({ + + return this.addon.createPlaceholderDirectory({ itemName, itemId, isDirectory, @@ -135,7 +153,7 @@ class VirtualDrive { creationTime: creationTimeStr, lastWriteTime: lastWriteTimeStr, lastAccessTime: lastAccessTimeStr, - path + path, }); } @@ -144,27 +162,24 @@ class VirtualDrive { providerVersion: string, providerId: string, callbacks: Callbacks, - logoPath: string + logoPath: string, ): Promise { this.callbacks = callbacks; - return addon.registerSyncRoot({ + console.log("Registering sync root: ", this.syncRootPath); + return this.addon.registerSyncRoot({ providerName, providerVersion, providerId, - logoPath + logoPath, }); } - static unregisterSyncRoot(syncRootPath: string) { - return addon.unregisterSyncRoot({ syncRootPath }); + unregisterSyncRoot() { + return this.addon.unregisterSyncRoot({ syncRootPath: this.syncRootPath }); } - watchAndWait( - path: string, - queueManager: IQueueManager, - loggerPath: string - ): void { - this.watcher.addon = addon; + watchAndWait(path: string, queueManager: IQueueManager, loggerPath: string): void { + this.watcher.addon = this.addon; this.watcher.queueManager = queueManager; this.watcher.logger = this.logger; this.watcher.syncRootPath = this.syncRootPath; @@ -189,7 +204,7 @@ class VirtualDrive { itemId: string, size: number = 0, creationTime: number = Date.now(), - lastWriteTime: number = Date.now() + lastWriteTime: number = Date.now(), ) { const fullPath = path.join(this.syncRootPath, relativePath); const splitPath = relativePath.split("/").filter((p) => p); @@ -211,7 +226,7 @@ class VirtualDrive { creationTime, lastWriteTime, Date.now(), - currentPath + currentPath, ); } catch (error) { //@ts-ignore @@ -224,7 +239,7 @@ class VirtualDrive { itemId: string, size: number = 0, creationTime: number = Date.now(), - lastWriteTime: number = Date.now() + lastWriteTime: number = Date.now(), ) { const splitPath = relativePath.split("/").filter((p) => p); const directoryPath = path.resolve(this.syncRootPath); @@ -244,7 +259,7 @@ class VirtualDrive { creationTime, lastWriteTime, Date.now(), - currentPath + currentPath, ); } } @@ -252,31 +267,23 @@ class VirtualDrive { } } - disconnectSyncRoot() { - return addon.disconnectSyncRoot(); - } - - updateSyncStatus( - itemPath: string, - isDirectory: boolean, - sync: boolean = true - ) { - return addon.updateSyncStatus({ path: this.fixPath(itemPath), isDirectory, sync }); + updateSyncStatus(itemPath: string, isDirectory: boolean, sync: boolean = true) { + return this.addon.updateSyncStatus({ path: this.fixPath(itemPath), isDirectory, sync }); } convertToPlaceholder(itemPath: string, id: string) { - return addon.convertToPlaceholder({ path: this.fixPath(itemPath), id }); + return this.addon.convertToPlaceholder({ path: this.fixPath(itemPath), id }); } updateFileIdentity(itemPath: string, id: string, isDirectory: boolean) { - return addon.updateFileIdentity({ path: this.fixPath(itemPath), id, isDirectory }); + return this.addon.updateFileIdentity({ path: this.fixPath(itemPath), id, isDirectory }); } dehydrateFile(itemPath: string) { - return addon.dehydrateFile({ path: this.fixPath(itemPath) }); + return this.addon.dehydrateFile({ path: this.fixPath(itemPath) }); } hydrateFile(itemPath: string) { - return addon.hydrateFile({ path: this.fixPath(itemPath) }); + return this.addon.hydrateFile({ path: this.fixPath(itemPath) }); } } From 53167e67cbd33d83527eb7e46187598475c5c547 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 11 Feb 2025 21:10:37 -0300 Subject: [PATCH 2/7] Update unregisterSyncRoot to use providerId instead of syncRootPath --- examples/drive.ts | 2 +- include/sync_root_interface/SyncRoot.h | 2 +- native-src/sync_root_interface/SyncRoot.cpp | 8 +++++-- native-src/virtual_drive/Wrappers.cpp | 24 ++++++++++++++------- src/addon-wrapper.ts | 4 ++-- src/virtual-drive.ts | 6 ++++-- 6 files changed, 30 insertions(+), 16 deletions(-) diff --git a/examples/drive.ts b/examples/drive.ts index 3322737f..5d47137e 100644 --- a/examples/drive.ts +++ b/examples/drive.ts @@ -3,5 +3,5 @@ import VirtualDrive from "@/virtual-drive"; import settings from "./settings"; -export const drive = new VirtualDrive(settings.syncRootPath, settings.defaultLogPath); +export const drive = new VirtualDrive(settings.syncRootPath, settings.providerid, settings.defaultLogPath); export const logger = createLogger(settings.defaultLogPath); diff --git a/include/sync_root_interface/SyncRoot.h b/include/sync_root_interface/SyncRoot.h index d8842999..6d74f738 100644 --- a/include/sync_root_interface/SyncRoot.h +++ b/include/sync_root_interface/SyncRoot.h @@ -17,7 +17,7 @@ class SyncRoot static HRESULT RegisterSyncRoot(const wchar_t *syncRootPath, const wchar_t *providerName, const wchar_t *providerVersion, const GUID &providerId, const wchar_t *logoPath); static HRESULT ConnectSyncRoot(const wchar_t *syncRootPath, InputSyncCallbacks syncCallbacks, napi_env env, CF_CONNECTION_KEY *connectionKey); static HRESULT DisconnectSyncRoot(const wchar_t *syncRootPath); - static HRESULT UnregisterSyncRoot(); + static HRESULT UnregisterSyncRoot(const GUID &providerId); static std::string GetFileIdentity(const wchar_t *path); static void HydrateFile(const wchar_t *filePath); static void DehydrateFile(const wchar_t *filePath); diff --git a/native-src/sync_root_interface/SyncRoot.cpp b/native-src/sync_root_interface/SyncRoot.cpp index f7a62e6a..3cb6c7b6 100644 --- a/native-src/sync_root_interface/SyncRoot.cpp +++ b/native-src/sync_root_interface/SyncRoot.cpp @@ -170,12 +170,16 @@ HRESULT SyncRoot::RegisterSyncRoot(const wchar_t *syncRootPath, const wchar_t *p } } -HRESULT SyncRoot::UnregisterSyncRoot() +HRESULT SyncRoot::UnregisterSyncRoot(const GUID &providerId) { try { + // Convert GUID to string for syncRootID + wchar_t syncRootID[39]; + StringFromGUID2(providerId, syncRootID, 39); + Logger::getInstance().log("Unregistering sync root.", LogLevel::INFO); - winrt::StorageProviderSyncRootManager::Unregister(L"syncRootID"); + winrt::StorageProviderSyncRootManager::Unregister(syncRootID); return S_OK; } catch (...) diff --git a/native-src/virtual_drive/Wrappers.cpp b/native-src/virtual_drive/Wrappers.cpp index d75d6383..e8ba0e6e 100644 --- a/native-src/virtual_drive/Wrappers.cpp +++ b/native-src/virtual_drive/Wrappers.cpp @@ -112,19 +112,27 @@ napi_value UnregisterSyncRootWrapper(napi_env env, napi_callback_info args) if (argc < 1) { - napi_throw_error(env, nullptr, "The sync root path is required for UnregisterSyncRoot"); + napi_throw_error(env, nullptr, "The provider ID is required for UnregisterSyncRoot"); return nullptr; } - LPCWSTR syncRootPath; - size_t pathLength; - napi_get_value_string_utf16(env, argv[0], nullptr, 0, &pathLength); - syncRootPath = new WCHAR[pathLength + 1]; - napi_get_value_string_utf16(env, argv[0], reinterpret_cast(const_cast(syncRootPath)), pathLength + 1, nullptr); + GUID providerId; + LPCWSTR providerIdStr; + size_t providerIdStrLength; + napi_get_value_string_utf16(env, argv[0], nullptr, 0, &providerIdStrLength); + providerIdStr = new WCHAR[providerIdStrLength + 1]; + napi_get_value_string_utf16(env, argv[0], reinterpret_cast(const_cast(providerIdStr)), providerIdStrLength + 1, nullptr); - HRESULT result = SyncRoot::UnregisterSyncRoot(); + if (FAILED(CLSIDFromString(providerIdStr, &providerId))) + { + napi_throw_error(env, nullptr, "Invalid GUID format"); + delete[] providerIdStr; + return nullptr; + } - delete[] syncRootPath; + HRESULT result = SyncRoot::UnregisterSyncRoot(providerId); + + delete[] providerIdStr; napi_value napiResult; napi_create_int32(env, static_cast(result), &napiResult); diff --git a/src/addon-wrapper.ts b/src/addon-wrapper.ts index 5b55017a..7c77c4a2 100644 --- a/src/addon-wrapper.ts +++ b/src/addon-wrapper.ts @@ -32,8 +32,8 @@ export class Addon { return this.parseAddonZod("connectSyncRoot", result); } - unregisterSyncRoot({ syncRootPath }: { syncRootPath: string }) { - const result = addon.unregisterSyncRoot(syncRootPath); + unregisterSyncRoot({ providerId }: { providerId: string }) { + const result = addon.unregisterSyncRoot(providerId); return this.parseAddonZod("unregisterSyncRoot", result); } diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 17f96e2f..153ef649 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -17,6 +17,7 @@ const PLACEHOLDER_ATTRIBUTES = { class VirtualDrive { syncRootPath: string; + providerId: string; callbacks?: Callbacks; watcher = new Watcher(); logger: winston.Logger; @@ -24,10 +25,11 @@ class VirtualDrive { addon: Addon; - constructor(syncRootPath: string, loggerPath: string) { + constructor(syncRootPath: string, providerId: string, loggerPath: string) { this.addon = new Addon(); this.syncRootPath = this.convertToWindowsPath(syncRootPath); loggerPath = this.convertToWindowsPath(loggerPath); + this.providerId = providerId; this.addon.syncRootPath = this.syncRootPath; @@ -175,7 +177,7 @@ class VirtualDrive { } unregisterSyncRoot() { - return this.addon.unregisterSyncRoot({ syncRootPath: this.syncRootPath }); + return this.addon.unregisterSyncRoot({ providerId: this.providerId }); } watchAndWait(path: string, queueManager: IQueueManager, loggerPath: string): void { From 976468b44d85a36fd544f9efa0e7b55a6061b0fa Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 11 Feb 2025 21:16:22 -0300 Subject: [PATCH 3/7] Refactor registerSyncRoot to use providerId from instance and update related tests --- 3758a9e6-de8b-4e1e-a4fe-53300d078e99 | 0 examples/register.ts | 2 +- src/virtual-drive.ts | 10 ++-------- src/virtual-drive.unit.test.ts | 30 +++++++++++++++++++--------- 4 files changed, 24 insertions(+), 18 deletions(-) create mode 100644 3758a9e6-de8b-4e1e-a4fe-53300d078e99 diff --git a/3758a9e6-de8b-4e1e-a4fe-53300d078e99 b/3758a9e6-de8b-4e1e-a4fe-53300d078e99 new file mode 100644 index 00000000..e69de29b diff --git a/examples/register.ts b/examples/register.ts index c0c0d3fc..108bff7d 100644 --- a/examples/register.ts +++ b/examples/register.ts @@ -20,7 +20,7 @@ const handlers = { handleAdd, handleHydrate, handleDehydrate, handleChangeSize } const notify = { onTaskSuccess: async () => undefined, onTaskProcessing: async () => undefined }; const queueManager = new QueueManager(handlers, notify, settings.queuePersistPath); -drive.registerSyncRoot(settings.driveName, settings.driveVersion, settings.providerid, callbacks, settings.iconPath); +drive.registerSyncRoot(settings.driveName, settings.driveVersion, callbacks, settings.iconPath); drive.connectSyncRoot(); try { diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 153ef649..b0029d1a 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -159,19 +159,13 @@ class VirtualDrive { }); } - async registerSyncRoot( - providerName: string, - providerVersion: string, - providerId: string, - callbacks: Callbacks, - logoPath: string, - ): Promise { + async registerSyncRoot(providerName: string, providerVersion: string, callbacks: Callbacks, logoPath: string): Promise { this.callbacks = callbacks; console.log("Registering sync root: ", this.syncRootPath); return this.addon.registerSyncRoot({ providerName, providerVersion, - providerId, + providerId: this.providerId, logoPath, }); } diff --git a/src/virtual-drive.unit.test.ts b/src/virtual-drive.unit.test.ts index 14c9c711..af736ca6 100644 --- a/src/virtual-drive.unit.test.ts +++ b/src/virtual-drive.unit.test.ts @@ -29,8 +29,10 @@ describe("VirtualDrive", () => { }); describe("When convertToWindowsPath is called", () => { + const providerId = v4(); + // Arrange - const drive = new VirtualDrive(syncRootPath, logPath); + const drive = new VirtualDrive(syncRootPath, providerId, logPath); it("When unix path, then convert to windows path", () => { // Assert @@ -46,8 +48,10 @@ describe("VirtualDrive", () => { }); describe("When fixPath is called", () => { + const providerId = v4(); + // Arrange - const drive = new VirtualDrive(syncRootPath, logPath); + const drive = new VirtualDrive(syncRootPath, providerId, logPath); it("When absolute windows path, then do not modify it", () => { // Assert @@ -80,8 +84,10 @@ describe("VirtualDrive", () => { // Arrange mockExistsSync.mockReturnValue(false); + const providerId = v4(); + // Act - new VirtualDrive(syncRootPath, logPath); + new VirtualDrive(syncRootPath, providerId, logPath); // Assert expect(fs.mkdirSync).toHaveBeenCalledWith(syncRootPath, { @@ -93,8 +99,10 @@ describe("VirtualDrive", () => { // Arrange mockExistsSync.mockReturnValue(true); + const providerId = v4(); + // Act - new VirtualDrive(syncRootPath, logPath); + new VirtualDrive(syncRootPath, providerId, logPath); // Assert expect(fs.mkdirSync).not.toHaveBeenCalled(); @@ -102,7 +110,9 @@ describe("VirtualDrive", () => { it("Then it calls addon.addLoggerPath with logPath provided", () => { // Act - new VirtualDrive(syncRootPath, logPath); + const providerId = v4(); + + new VirtualDrive(syncRootPath, providerId, logPath); // Assert expect(addon.addLoggerPath).toHaveBeenCalledWith(logPath); @@ -113,7 +123,9 @@ describe("VirtualDrive", () => { it("Then it calls addon.createPlaceholderFile", () => { // Arrange mockExistsSync.mockReturnValue(true); - const drive = new VirtualDrive(syncRootPath, logPath); + const providerId = v4(); + + const drive = new VirtualDrive(syncRootPath, logPath, providerId); // Act drive.createFileByPath("folder/subfolder/file.txt", "file-id", 1234, 1660000000000, 1660000001000); @@ -135,16 +147,16 @@ describe("VirtualDrive", () => { describe("When call registerSyncRoot", () => { it("Then it assigns callbacks and calls addon.registerSyncRoot", async () => { // Arrange - const drive = new VirtualDrive(syncRootPath, logPath); + const providerId = v4(); + const drive = new VirtualDrive(syncRootPath, providerId, logPath); const providerName = "MyProvider"; const providerVersion = "1.0.0"; - const providerId = v4(); const logoPath = "C:\\iconPath"; const callbacks = mockDeep(); // Act expect(drive.callbacks).toBe(undefined); - await drive.registerSyncRoot(providerName, providerVersion, providerId, callbacks, logoPath); + await drive.registerSyncRoot(providerName, providerVersion, callbacks, logoPath); // Assert expect(drive.callbacks).not.toBe(undefined); From 850e4c32eda5051c014655a520689d970e050539 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 12 Feb 2025 09:37:57 -0300 Subject: [PATCH 4/7] Remove connections map from VirtualDrive and simplify disconnectSyncRoot method --- src/virtual-drive.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index b0029d1a..1ca3564c 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -21,7 +21,6 @@ class VirtualDrive { callbacks?: Callbacks; watcher = new Watcher(); logger: winston.Logger; - connections: Map = new Map(); addon: Addon; @@ -91,18 +90,11 @@ class VirtualDrive { const connectionKey = this.addon.connectSyncRoot({ syncRootPath: this.syncRootPath, callbacks: this.callbacks }); console.log("Connection key: ", connectionKey); - this.connections.set(this.syncRootPath, connectionKey); return connectionKey; } disconnectSyncRoot() { - const connectionKey = this.connections.get(this.syncRootPath); - if (connectionKey) { - this.addon.disconnectSyncRoot({ syncRootPath: this.syncRootPath }); - this.connections.delete(this.syncRootPath); - } else { - throw new Error(`No connection found for syncRootPath: ${this.syncRootPath}`); - } + this.addon.disconnectSyncRoot({ syncRootPath: this.syncRootPath }); } createPlaceholderFile( From 693be0ca9842ceea43706ea389f8597dbf93a9dd Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 12 Feb 2025 12:30:46 -0300 Subject: [PATCH 5/7] Add FilePlaceholderId type for improved type safety in TFetchDataCallback --- src/types/callbacks.type.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/types/callbacks.type.ts b/src/types/callbacks.type.ts index 96b09a5d..7e3be7d4 100644 --- a/src/types/callbacks.type.ts +++ b/src/types/callbacks.type.ts @@ -1,7 +1,11 @@ export type NapiCallbackFunction = (...args: any[]) => any; +export type FilePlaceholderIdPrefixType = "FILE:"; + +export type FilePlaceholderId = `${FilePlaceholderIdPrefixType}${string}`; + export type TFetchDataCallback = ( - id: string, + id: FilePlaceholderId, callback: (data: boolean, path: string, errorHandler?: () => void) => Promise<{ finished: boolean; progress: number }>, ) => void; From 326ad37366b6deb323f8b5f305a68317929c58c1 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Thu, 13 Feb 2025 12:22:03 -0300 Subject: [PATCH 6/7] Remove syncRootPath parameter from connectSyncRoot method for cleaner API usage --- src/addon-wrapper.ts | 2 +- src/virtual-drive.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/addon-wrapper.ts b/src/addon-wrapper.ts index 7c77c4a2..14a2097b 100644 --- a/src/addon-wrapper.ts +++ b/src/addon-wrapper.ts @@ -27,7 +27,7 @@ export class Addon { return this.parseAddonZod("registerSyncRoot", result); } - connectSyncRoot({ callbacks }: { callbacks: Callbacks; syncRootPath: string }) { + connectSyncRoot({ callbacks }: { callbacks: Callbacks }) { const result = addon.connectSyncRoot(this.syncRootPath, callbacks); return this.parseAddonZod("connectSyncRoot", result); } diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 1ca3564c..86fadb42 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -87,7 +87,7 @@ class VirtualDrive { console.log("Connecting to sync root: ", this.syncRootPath); - const connectionKey = this.addon.connectSyncRoot({ syncRootPath: this.syncRootPath, callbacks: this.callbacks }); + const connectionKey = this.addon.connectSyncRoot({ callbacks: this.callbacks }); console.log("Connection key: ", connectionKey); return connectionKey; From 5d68993c44dcb0497b9d60de58dd13a33ef3e5d4 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Thu, 13 Feb 2025 14:45:21 -0300 Subject: [PATCH 7/7] Refactor VirtualDrive to use logger for connection debug information and update constructor parameter order --- src/virtual-drive.ts | 5 ++--- src/virtual-drive.unit.test.ts | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 86fadb42..4c68b25c 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -1,3 +1,4 @@ +import { logger } from "examples/drive"; import fs from "fs"; import path, { join, win32 } from "path"; import winston from "winston"; @@ -85,11 +86,9 @@ class VirtualDrive { throw new Error("Callbacks are not defined"); } - console.log("Connecting to sync root: ", this.syncRootPath); - const connectionKey = this.addon.connectSyncRoot({ callbacks: this.callbacks }); - console.log("Connection key: ", connectionKey); + this.logger.debug({ fn: "connectSyncRoot", connectionKey }); return connectionKey; } diff --git a/src/virtual-drive.unit.test.ts b/src/virtual-drive.unit.test.ts index af736ca6..712d6366 100644 --- a/src/virtual-drive.unit.test.ts +++ b/src/virtual-drive.unit.test.ts @@ -125,7 +125,7 @@ describe("VirtualDrive", () => { mockExistsSync.mockReturnValue(true); const providerId = v4(); - const drive = new VirtualDrive(syncRootPath, logPath, providerId); + const drive = new VirtualDrive(syncRootPath, providerId, logPath); // Act drive.createFileByPath("folder/subfolder/file.txt", "file-id", 1234, 1660000000000, 1660000001000);