From b71ca25bf40df9f9f42ce3b29a95e7928dce8629 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 15 Apr 2025 17:34:49 -0300 Subject: [PATCH 1/7] Refactor drive method parameters to use object destructuring for improved readability and maintainability --- .prettierrc.js | 2 +- examples/get-state.ts | 4 +- examples/handlers/handle-add.ts | 5 +- examples/handlers/handle-change-size.ts | 11 +- examples/handlers/handle-dehydrate.ts | 4 +- examples/handlers/handle-hydrate.ts | 4 +- examples/register.ts | 13 +- examples/utils/generate-random-file-tree.ts | 9 +- .../utils/generate-random-tree.unit.test.ts | 32 +++- .../PlaceHolderInfo.cpp | 18 +- .../placeholders_interface/Planceholders.cpp | 4 +- package.json | 2 +- src/queue/queue-manager.ts | 17 +- src/queue/queue-manager.unit.test.ts | 2 +- src/virtual-drive.ts | 176 +++++++++++------- src/virtual-drive.unit.test.ts | 10 +- 16 files changed, 207 insertions(+), 106 deletions(-) diff --git a/.prettierrc.js b/.prettierrc.js index d4c4a4aa..56d7ef99 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -7,7 +7,7 @@ module.exports = { importOrderParserPlugins: ["typescript", "decorators-legacy"], importOrderSeparation: true, plugins: [require.resolve("@trivago/prettier-plugin-sort-imports")], - printWidth: 140, + printWidth: 120, proseWrap: "never", semi: true, singleQuote: false, diff --git a/examples/get-state.ts b/examples/get-state.ts index bf761251..80df9acc 100644 --- a/examples/get-state.ts +++ b/examples/get-state.ts @@ -18,7 +18,9 @@ const { data } = z.object({ file: z.string() }).safeParse(argv); if (data) { const path = data.file; - const state = drive.getPlaceholderState(path); + const state = drive.getPlaceholderState({ + path, + }); logger.info({ state }); } else { logger.error("Por favor especifica un archivo con --file "); diff --git a/examples/handlers/handle-add.ts b/examples/handlers/handle-add.ts index 267525ad..9ecea632 100644 --- a/examples/handlers/handle-add.ts +++ b/examples/handlers/handle-add.ts @@ -8,7 +8,10 @@ export const handleAdd = async (task: QueueItem) => { try { logger.info({ fn: "handleAdd", task }); const id = task.isFolder ? v4() : addInfoItem(task.path); - drive.convertToPlaceholder(task.path, id); + drive.convertToPlaceholder({ + itemPath: task.path, + id, + }); } catch (error) { logger.error("handleAdd", error); } diff --git a/examples/handlers/handle-change-size.ts b/examples/handlers/handle-change-size.ts index f3206cc4..a288d288 100644 --- a/examples/handlers/handle-change-size.ts +++ b/examples/handlers/handle-change-size.ts @@ -7,8 +7,15 @@ export const handleChangeSize = async (task: QueueItem) => { try { logger.info({ fn: "handleChangeSize", path: task.path }); const id = v4(); - drive.convertToPlaceholder(task.path, id); - drive.updateFileIdentity(task.path, id, false); + drive.convertToPlaceholder({ + itemPath: task.path, + id, + }); + drive.updateFileIdentity({ + itemPath: task.path, + id, + isDirectory: task.isFolder, + }); } catch (error) { logger.error("handleChangeSize", error); } diff --git a/examples/handlers/handle-dehydrate.ts b/examples/handlers/handle-dehydrate.ts index 4b5e05a9..1b154890 100644 --- a/examples/handlers/handle-dehydrate.ts +++ b/examples/handlers/handle-dehydrate.ts @@ -5,7 +5,9 @@ import { QueueItem } from "@/queue/queueManager"; export const handleDehydrate = async (task: QueueItem) => { try { logger.info({ fn: "handleDehydrate", path: task.path }); - drive.dehydrateFile(task.path); + drive.dehydrateFile({ + itemPath: task.path, + }); } catch (error) { logger.error("handleDehydrate", error); } diff --git a/examples/handlers/handle-hydrate.ts b/examples/handlers/handle-hydrate.ts index 192dbd52..1a8e7d9b 100644 --- a/examples/handlers/handle-hydrate.ts +++ b/examples/handlers/handle-hydrate.ts @@ -5,7 +5,9 @@ import { QueueItem } from "@/queue/queueManager"; export const handleHydrate = async (task: QueueItem) => { try { logger.info({ fn: "handleHydrate", path: task.path }); - await drive.hydrateFile(task.path); + await drive.hydrateFile({ + itemPath: task.path, + }); } catch (error) { logger.error("handleHydrate", error); } diff --git a/examples/register.ts b/examples/register.ts index 108bff7d..b4a865c4 100644 --- a/examples/register.ts +++ b/examples/register.ts @@ -1,5 +1,4 @@ import { QueueManager } from "@/queue/queue-manager"; -import VirtualDrive from "@/virtual-drive"; import { cancelFetchDataCallback } from "./callbacks/cancel-fetch-data.callback"; import { notifyDeleteCallback } from "./callbacks/notify-delete.callback"; @@ -17,15 +16,19 @@ import settings from "./settings"; const callbacks = { notifyDeleteCallback, notifyRenameCallback, fetchDataCallback, cancelFetchDataCallback, notifyMessageCallback }; const handlers = { handleAdd, handleHydrate, handleDehydrate, handleChangeSize }; -const notify = { onTaskSuccess: async () => undefined, onTaskProcessing: async () => undefined }; -const queueManager = new QueueManager(handlers, notify, settings.queuePersistPath); +const queueManager = new QueueManager({ handlers, persistPath: settings.queuePersistPath }); -drive.registerSyncRoot(settings.driveName, settings.driveVersion, callbacks, settings.iconPath); +drive.registerSyncRoot({ + providerName: settings.driveName, + providerVersion: settings.driveVersion, + callbacks, + logoPath: settings.iconPath, +}); drive.connectSyncRoot(); try { initInfoItems(); - drive.watchAndWait(settings.syncRootPath, queueManager, settings.watcherLogPath); + drive.watchAndWait({ queueManager }); } catch (error) { logger.error(error); drive.disconnectSyncRoot(); diff --git a/examples/utils/generate-random-file-tree.ts b/examples/utils/generate-random-file-tree.ts index 42b7fc94..c28b5807 100644 --- a/examples/utils/generate-random-file-tree.ts +++ b/examples/utils/generate-random-file-tree.ts @@ -53,7 +53,7 @@ async function createStructureRecursively( const createdAt = Date.now() - (timeOffset || 0); const updatedAt = Date.now() - (timeOffset || 0) + 2000; - drive.createFileByPath(fullPath, fileId, fileSize, createdAt, updatedAt); + drive.createFileByPath({ relativePath: fullPath, itemId: fileId, size: fileSize, creationTime: createdAt, lastWriteTime: updatedAt }); result[fileId] = fullPath; } @@ -66,7 +66,12 @@ async function createStructureRecursively( const createdAt = Date.now() - (timeOffset || 0) - 10000; // Ejemplo const updatedAt = Date.now() - (timeOffset || 0); - drive.createFolderByPath(newFolderPath, folderId, 1000, createdAt, updatedAt); + drive.createFolderByPath({ + relativePath: newFolderPath, + itemId: folderId, + creationTime: createdAt, + lastWriteTime: updatedAt, + }); await createStructureRecursively(drive, newFolderPath, level - 1, options, result); } diff --git a/examples/utils/generate-random-tree.unit.test.ts b/examples/utils/generate-random-tree.unit.test.ts index 06d906bf..1031c193 100644 --- a/examples/utils/generate-random-tree.unit.test.ts +++ b/examples/utils/generate-random-tree.unit.test.ts @@ -6,12 +6,36 @@ class MockVirtualDrive implements Partial { private files: Record = {}; private folders: Record = {}; - createFileByPath(path: string, id: string, size: number, createdAt: number, updatedAt: number): void { - this.files[path] = { id, size, createdAt, updatedAt }; + createFileByPath({ + relativePath, + itemId, + size = 0, + creationTime = Date.now(), + lastWriteTime = Date.now(), + }: { + relativePath: string; + itemId: string; + size?: number; + creationTime?: number; + lastWriteTime?: number; + }): void { + this.files[relativePath] = { itemId, size, creationTime, lastWriteTime }; } - createFolderByPath(path: string, id: string, size: number, createdAt: number, updatedAt: number): void { - this.folders[path] = { id, size, createdAt, updatedAt }; + createFolderByPath({ + relativePath, + itemId, + size = 0, + creationTime = Date.now(), + lastWriteTime = Date.now(), + }: { + relativePath: string; + itemId: string; + size?: number; + creationTime?: number; + lastWriteTime?: number; + }): void { + this.folders[relativePath] = { itemId, size, creationTime, lastWriteTime }; } getFiles(): Record { diff --git a/native-src/placeholders_interface/PlaceHolderInfo.cpp b/native-src/placeholders_interface/PlaceHolderInfo.cpp index 2c77c2b7..250bfc61 100644 --- a/native-src/placeholders_interface/PlaceHolderInfo.cpp +++ b/native-src/placeholders_interface/PlaceHolderInfo.cpp @@ -163,13 +163,7 @@ FileHandle handleForPath(const std::wstring &wPath) return {}; } - // Convertir std::wstring a std::string - std::wstring_convert> converter; - std::string path = converter.to_bytes(wPath); - - LPCSTR pPath = path.c_str(); - - std::filesystem::path pathFs(path); + std::filesystem::path pathFs(wPath); // Use wPath directly to create path if (!std::filesystem::exists(pathFs)) { return {}; @@ -186,13 +180,16 @@ FileHandle handleForPath(const std::wstring &wPath) } else { + // Convert only for logging purposes + std::wstring_convert> converter; + std::string path = converter.to_bytes(wPath); printf("Could not CfOpenFileWithOplock for path: %s with error: %ld\n", path.c_str(), openResult); } } else if (std::filesystem::is_regular_file(pathFs)) { - HANDLE handle = CreateFile( - pPath, + HANDLE handle = CreateFileW( + wPath.c_str(), // Use wide string path directly FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, @@ -206,6 +203,9 @@ FileHandle handleForPath(const std::wstring &wPath) } else { + // Convert only for logging purposes + std::wstring_convert> converter; + std::string path = converter.to_bytes(wPath); printf("Could not CreateFile for path: %s with error: %ld\n", path.c_str(), GetLastError()); } } diff --git a/native-src/placeholders_interface/Planceholders.cpp b/native-src/placeholders_interface/Planceholders.cpp index 20346922..c8de198f 100644 --- a/native-src/placeholders_interface/Planceholders.cpp +++ b/native-src/placeholders_interface/Planceholders.cpp @@ -226,7 +226,8 @@ bool Placeholders::ConvertToPlaceholder(const std::wstring &fullPath, const std: if (FAILED(hr)) { // Manejar el error al convertir a marcador de posición - if (hr != 0x8007017C) { + if (hr != 0x8007017C) + { wprintf(L"[ConvertToPlaceholder] Error converting to placeholder, ConvertToPlaceholder failed with HRESULT 0x%X\n", hr); } @@ -287,6 +288,7 @@ void Placeholders::UpdateSyncStatus(const std::wstring &filePath, bool inputSync if (fileHandle == INVALID_HANDLE_VALUE) { wprintf(L"[UpdateSyncStatus] Error al abrir el archivo: %d\n", GetLastError()); + CloseHandle(fileHandle); return; } diff --git a/package.json b/package.json index edfe8b24..4afd9d00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@internxt/node-win", - "version": "1.0.8", + "version": "1.0.9", "description": "Drive desktop node addon", "main": "dist/index.ts", "types": "dist/index.d.ts", diff --git a/src/queue/queue-manager.ts b/src/queue/queue-manager.ts index 69ab7aad..11515bd5 100644 --- a/src/queue/queue-manager.ts +++ b/src/queue/queue-manager.ts @@ -12,6 +12,9 @@ export type QueueHandler = { handleChangeSize: HandleAction; }; +/** + * * @deprecated + */ export type QueueManagerCallback = { onTaskSuccess: () => Promise; onTaskProcessing: () => Promise; @@ -37,13 +40,13 @@ export class QueueManager { private enqueueTimeout: NodeJS.Timeout | null = null; private enqueueDelay = 2000; - private readonly notify: QueueManagerCallback; + // private readonly notify: QueueManagerCallback; private readonly persistPath: string; logger?: Logger; actions: HandleActions; - constructor(handlers: QueueHandler, notify: QueueManagerCallback, persistPath: string) { + constructor({ handlers, persistPath }: { handlers: QueueHandler; persistPath: string }) { this.actions = { add: handlers.handleAdd, hydrate: handlers.handleHydrate, @@ -51,7 +54,7 @@ export class QueueManager { changeSize: handlers.handleChangeSize, change: handlers.handleChange || (() => Promise.resolve()), }; - this.notify = notify; + // this.notify = notify; this.persistPath = persistPath; if (!fs.existsSync(this.persistPath)) { fs.writeFileSync(this.persistPath, JSON.stringify(this.queues)); @@ -165,7 +168,7 @@ export class QueueManager { const chunks = lodashChunk(this.queues[type], chunkSize); for (const chunk of chunks) { - await this.notify.onTaskProcessing(); + // await this.notify.onTaskProcessing(); await Promise.all(chunk.map((task) => this.processTask(type, task))); this.queues[type] = this.queues[type].slice(chunk.length); } @@ -173,7 +176,7 @@ export class QueueManager { private async processSequentially(type: typeQueue): Promise { while (this.queues[type].length > 0) { - await this.notify.onTaskProcessing(); + // await this.notify.onTaskProcessing(); const task = this.queues[type].shift(); this.saveQueueStateToFile(); @@ -195,8 +198,8 @@ export class QueueManager { public async processAll(): Promise { this.logger?.debug({ fn: "processAll" }); const taskTypes = Object.keys(this.queues) as typeQueue[]; - await this.notify.onTaskProcessing(); + // await this.notify.onTaskProcessing(); await Promise.all(taskTypes.map((type: typeQueue) => this.processQueue(type))); - await this.notify.onTaskSuccess(); + // await this.notify.onTaskSuccess(); } } diff --git a/src/queue/queue-manager.unit.test.ts b/src/queue/queue-manager.unit.test.ts index dc3265b9..52ac8001 100644 --- a/src/queue/queue-manager.unit.test.ts +++ b/src/queue/queue-manager.unit.test.ts @@ -16,7 +16,7 @@ describe("QueueManager", () => { beforeEach(() => { vi.clearAllMocks(); - queueManager = new QueueManager(mockHandlers, mockCallbacks, persistPath); + queueManager = new QueueManager({ handlers: mockHandlers, persistPath }); }); it("should add a task to the queue and sort it correctly", async () => { diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 8c4db925..3605b029 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -37,11 +37,11 @@ class VirtualDrive { this.logger = createLogger(loggerPath); } - convertToWindowsTime(jsTime: number) { + private convertToWindowsTime(jsTime: number) { return BigInt(jsTime) * 10000n + 116444736000000000n; } - convertToWindowsPath(path: string) { + private convertToWindowsPath(path: string) { return path.replaceAll("/", win32.sep); } @@ -58,7 +58,7 @@ class VirtualDrive { this.addon.addLogger({ logPath }); } - getPlaceholderState(path: string) { + getPlaceholderState({ path }: { path: string }) { return this.addon.getPlaceholderState({ path: this.fixPath(path) }); } @@ -72,12 +72,12 @@ class VirtualDrive { } } - getFileIdentity(relativePath: string) { - return this.addon.getFileIdentity({ path: this.fixPath(relativePath) }); + getFileIdentity({ path }: { path: string }) { + return this.addon.getFileIdentity({ path: this.fixPath(path) }); } - async deleteFileSyncRoot(relativePath: string) { - return this.addon.deleteFileSyncRoot({ path: this.fixPath(relativePath) }); + async deleteFileSyncRoot({ path }: { path: string }) { + return this.addon.deleteFileSyncRoot({ path: this.fixPath(path) }); } connectSyncRoot() { @@ -95,16 +95,25 @@ class VirtualDrive { this.addon.disconnectSyncRoot({ syncRootPath: this.syncRootPath }); } - createPlaceholderFile( - fileName: string, - fileId: string, - fileSize: number, - fileAttributes: number, - creationTime: number, - lastWriteTime: number, - lastAccessTime: number, - basePath: string, - ): any { + private createPlaceholderFile({ + fileName, + fileId, + fileSize, + fileAttributes, + creationTime, + lastWriteTime, + lastAccessTime, + basePath = this.syncRootPath, + }: { + fileName: string; + fileId: string; + fileSize: number; + fileAttributes: number; + creationTime: number; + lastWriteTime: number; + lastAccessTime: number; + basePath?: string; + }): any { const creationTimeStr = this.convertToWindowsTime(creationTime).toString(); const lastWriteTimeStr = this.convertToWindowsTime(lastWriteTime).toString(); const lastAccessTimeStr = this.convertToWindowsTime(lastAccessTime).toString(); @@ -121,17 +130,27 @@ class VirtualDrive { }); } - createPlaceholderDirectory( - itemName: string, - itemId: string, - isDirectory: boolean, - itemSize: number, - fileAttributes: number, - creationTime: number, - lastWriteTime: number, - lastAccessTime: number, - path: string, - ) { + private createPlaceholderDirectory({ + itemName, + itemId, + isDirectory, + itemSize, + fileAttributes, + creationTime, + lastWriteTime, + lastAccessTime, + path = this.syncRootPath, + }: { + itemName: string; + itemId: string; + isDirectory: boolean; + itemSize: number; + fileAttributes: number; + creationTime: number; + lastWriteTime: number; + lastAccessTime: number; + path?: string; + }) { const creationTimeStr = this.convertToWindowsTime(creationTime).toString(); const lastWriteTimeStr = this.convertToWindowsTime(lastWriteTime).toString(); const lastAccessTimeStr = this.convertToWindowsTime(lastAccessTime).toString(); @@ -149,7 +168,17 @@ class VirtualDrive { }); } - async registerSyncRoot(providerName: string, providerVersion: string, callbacks: Callbacks, logoPath: string): Promise { + async registerSyncRoot({ + providerName, + providerVersion, + callbacks, + logoPath, + }: { + providerName: string; + providerVersion: string; + callbacks: Callbacks; + logoPath: string; + }): Promise { this.callbacks = callbacks; this.logger.debug({ msg: "Registering sync root", syncRootPath: this.syncRootPath }); return this.addon.registerSyncRoot({ @@ -172,7 +201,7 @@ class VirtualDrive { return DependencyInjectionAddonProvider.get().unregisterSyncRoot({ providerId }); } - watchAndWait(path: string, queueManager: QueueManager, loggerPath: string): void { + watchAndWait({ queueManager }: { queueManager: QueueManager }): void { this.watcher.addon = this.addon; this.watcher.queueManager = queueManager; this.watcher.logger = this.logger; @@ -193,13 +222,19 @@ class VirtualDrive { this.watcher.watchAndWait(); } - createFileByPath( - relativePath: string, - itemId: string, - size: number = 0, - creationTime: number = Date.now(), - lastWriteTime: number = Date.now(), - ) { + createFileByPath({ + relativePath, + itemId, + size = 0, + creationTime = Date.now(), + lastWriteTime = Date.now(), + }: { + relativePath: string; + itemId: string; + size?: number; + creationTime?: number; + lastWriteTime?: number; + }) { const fullPath = path.join(this.syncRootPath, relativePath); const splitPath = relativePath.split("/").filter((p) => p); const directoryPath = path.resolve(this.syncRootPath); @@ -212,29 +247,35 @@ class VirtualDrive { currentPath = path.join(currentPath, dir); } // last element is the file - this.createPlaceholderFile( - path.basename(fullPath), - itemId, - size, - PLACEHOLDER_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, + this.createPlaceholderFile({ + fileName: path.basename(fullPath), + fileId: itemId, + fileSize: size, + fileAttributes: PLACEHOLDER_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, creationTime, lastWriteTime, - Date.now(), - currentPath, - ); + lastAccessTime: Date.now(), + basePath: currentPath, + }); } catch (error) { //@ts-ignore console.error(`Error al crear placeholder: ${error.message}`); } } - createFolderByPath( - relativePath: string, - itemId: string, - size: number = 0, - creationTime: number = Date.now(), - lastWriteTime: number = Date.now(), - ) { + createFolderByPath({ + relativePath, + itemId, + size = 0, + creationTime = Date.now(), + lastWriteTime = Date.now(), + }: { + relativePath: string; + itemId: string; + size?: number; + creationTime?: number; + lastWriteTime?: number; + }) { const splitPath = relativePath.split("/").filter((p) => p); const directoryPath = path.resolve(this.syncRootPath); let currentPath = directoryPath; @@ -244,39 +285,40 @@ class VirtualDrive { const last = i === splitPath.length - 1; if (last) { if (fs.existsSync(currentPath)) { - this.createPlaceholderDirectory( - dir, + this.createPlaceholderDirectory({ + itemName: dir, itemId, - true, - size, - PLACEHOLDER_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, - creationTime, - lastWriteTime, - Date.now(), - currentPath, - ); + isDirectory: true, + itemSize: size, + fileAttributes: PLACEHOLDER_ATTRIBUTES.FOLDER_ATTRIBUTE_READONLY, + creationTime: creationTime, + lastWriteTime: lastWriteTime, + lastAccessTime: Date.now(), + path: currentPath, + }); } } currentPath = path.join(currentPath, dir); } } - updateSyncStatus(itemPath: string, isDirectory: boolean, sync: boolean = true) { + updateSyncStatus({ itemPath, isDirectory, sync = true }: { itemPath: string; isDirectory: boolean; sync?: boolean }) { return this.addon.updateSyncStatus({ path: this.fixPath(itemPath), isDirectory, sync }); } - convertToPlaceholder(itemPath: string, id: string) { + convertToPlaceholder({ itemPath, id }: { itemPath: string; id: string }) { return this.addon.convertToPlaceholder({ path: this.fixPath(itemPath), id }); } - updateFileIdentity(itemPath: string, id: string, isDirectory: boolean) { + + updateFileIdentity({ itemPath, id, isDirectory }: { itemPath: string; id: string; isDirectory: boolean }) { return this.addon.updateFileIdentity({ path: this.fixPath(itemPath), id, isDirectory }); } - dehydrateFile(itemPath: string) { + dehydrateFile({ itemPath }: { itemPath: string }) { return this.addon.dehydrateFile({ path: this.fixPath(itemPath) }); } - hydrateFile(itemPath: string) { + hydrateFile({ itemPath }: { itemPath: string }) { return this.addon.hydrateFile({ path: this.fixPath(itemPath) }); } } diff --git a/src/virtual-drive.unit.test.ts b/src/virtual-drive.unit.test.ts index 712d6366..cb242250 100644 --- a/src/virtual-drive.unit.test.ts +++ b/src/virtual-drive.unit.test.ts @@ -128,7 +128,13 @@ describe("VirtualDrive", () => { const drive = new VirtualDrive(syncRootPath, providerId, logPath); // Act - drive.createFileByPath("folder/subfolder/file.txt", "file-id", 1234, 1660000000000, 1660000001000); + drive.createFileByPath({ + relativePath: "folder/subfolder/file.txt", + itemId: "file-id", + size: 1234, + creationTime: 1660000000000, + lastWriteTime: 1660000001000, + }); // Assert expect(addon.createPlaceholderFile).toHaveBeenCalledWith( @@ -156,7 +162,7 @@ describe("VirtualDrive", () => { // Act expect(drive.callbacks).toBe(undefined); - await drive.registerSyncRoot(providerName, providerVersion, callbacks, logoPath); + await drive.registerSyncRoot({ providerName, providerVersion, callbacks, logoPath }); // Assert expect(drive.callbacks).not.toBe(undefined); From de04d835443a0af216424719453728a784317c8b Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 15 Apr 2025 17:51:27 -0300 Subject: [PATCH 2/7] Refactor convertToWindowsPath to accept an object for improved consistency and readability --- src/virtual-drive.ts | 8 ++++---- src/virtual-drive.unit.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 3605b029..db0e48c2 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -26,8 +26,8 @@ class VirtualDrive { constructor(syncRootPath: string, providerId: string, loggerPath: string) { this.addon = DependencyInjectionAddonProvider.get(); - this.syncRootPath = this.convertToWindowsPath(syncRootPath); - loggerPath = this.convertToWindowsPath(loggerPath); + this.syncRootPath = this.convertToWindowsPath({ path: syncRootPath }); + loggerPath = this.convertToWindowsPath({ path: loggerPath }); this.providerId = providerId; this.addon.syncRootPath = this.syncRootPath; @@ -41,12 +41,12 @@ class VirtualDrive { return BigInt(jsTime) * 10000n + 116444736000000000n; } - private convertToWindowsPath(path: string) { + convertToWindowsPath({ path }: { path: string }) { return path.replaceAll("/", win32.sep); } fixPath(path: string) { - path = this.convertToWindowsPath(path); + path = this.convertToWindowsPath({ path }); if (path.includes(this.syncRootPath)) { return path; } else { diff --git a/src/virtual-drive.unit.test.ts b/src/virtual-drive.unit.test.ts index cb242250..4b8ac498 100644 --- a/src/virtual-drive.unit.test.ts +++ b/src/virtual-drive.unit.test.ts @@ -36,13 +36,13 @@ describe("VirtualDrive", () => { it("When unix path, then convert to windows path", () => { // Assert - const result = drive.convertToWindowsPath("C:/test-drive/test.txt"); + const result = drive.convertToWindowsPath({ path: "C:/test-drive/test.txt" }); expect(result).toBe("C:\\test-drive\\test.txt"); }); it("When windows path, then do not modify it", () => { // Assert - const result = drive.convertToWindowsPath("C:\\test-drive\\test.txt"); + const result = drive.convertToWindowsPath({ path: "C:\\test-drive\\test.txt" }); expect(result).toBe("C:\\test-drive\\test.txt"); }); }); From cb8564fb4b802ce77c7854182b673588ceb452f5 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 15 Apr 2025 17:55:22 -0300 Subject: [PATCH 3/7] Add pull request types to workflow configuration for clarity --- .github/workflows/pull-request.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 6c616d8b..81ebe49c 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -2,6 +2,7 @@ name: Pull request checks on: pull_request: + types: [opened, synchronize, reopened] jobs: checks: From 4fdb5595436e947312f92b5a5d0759b40048769b Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 15 Apr 2025 17:58:47 -0300 Subject: [PATCH 4/7] Refactor code for improved readability by formatting function parameters and object properties across multiple files --- examples/callbacks/notify-message.callback.ts | 7 +++++- examples/register.ts | 8 ++++++- examples/utils/generate-random-file-tree.ts | 13 +++++++++-- index.ts | 13 ++++++++++- src/addon-wrapper.ts | 23 +++++++++++++++++-- src/types/callbacks.type.ts | 6 ++++- src/virtual-drive.unit.test.ts | 8 ++++++- src/watcher/events/on-add-dir.service.ts | 6 ++++- src/watcher/events/on-add.service.ts | 6 ++++- 9 files changed, 79 insertions(+), 11 deletions(-) diff --git a/examples/callbacks/notify-message.callback.ts b/examples/callbacks/notify-message.callback.ts index 4357f993..e6af86ab 100644 --- a/examples/callbacks/notify-message.callback.ts +++ b/examples/callbacks/notify-message.callback.ts @@ -1,6 +1,11 @@ import { logger } from "examples/drive"; -export const notifyMessageCallback = (message: string, action: string, errorName: string, callback: (response: boolean) => void) => { +export const notifyMessageCallback = ( + message: string, + action: string, + errorName: string, + callback: (response: boolean) => void, +) => { logger.info({ event: "notifyMessageCallback", message, action, errorName }); callback(true); }; diff --git a/examples/register.ts b/examples/register.ts index b4a865c4..a60d7b49 100644 --- a/examples/register.ts +++ b/examples/register.ts @@ -13,7 +13,13 @@ import { handleHydrate } from "./handlers/handle-hydrate"; import { initInfoItems } from "./info-items-manager"; import settings from "./settings"; -const callbacks = { notifyDeleteCallback, notifyRenameCallback, fetchDataCallback, cancelFetchDataCallback, notifyMessageCallback }; +const callbacks = { + notifyDeleteCallback, + notifyRenameCallback, + fetchDataCallback, + cancelFetchDataCallback, + notifyMessageCallback, +}; const handlers = { handleAdd, handleHydrate, handleDehydrate, handleChangeSize }; const queueManager = new QueueManager({ handlers, persistPath: settings.queuePersistPath }); diff --git a/examples/utils/generate-random-file-tree.ts b/examples/utils/generate-random-file-tree.ts index c28b5807..fa4c798f 100644 --- a/examples/utils/generate-random-file-tree.ts +++ b/examples/utils/generate-random-file-tree.ts @@ -53,7 +53,13 @@ async function createStructureRecursively( const createdAt = Date.now() - (timeOffset || 0); const updatedAt = Date.now() - (timeOffset || 0) + 2000; - drive.createFileByPath({ relativePath: fullPath, itemId: fileId, size: fileSize, creationTime: createdAt, lastWriteTime: updatedAt }); + drive.createFileByPath({ + relativePath: fullPath, + itemId: fileId, + size: fileSize, + creationTime: createdAt, + lastWriteTime: updatedAt, + }); result[fileId] = fullPath; } @@ -77,7 +83,10 @@ async function createStructureRecursively( } } -async function generateRandomFilesAndFolders(drive: VirtualDrive, options: GenerateOptions): Promise> { +async function generateRandomFilesAndFolders( + drive: VirtualDrive, + options: GenerateOptions, +): Promise> { const { rootPath } = options; const result: Record = {}; diff --git a/index.ts b/index.ts index 2657e993..dd8d060f 100644 --- a/index.ts +++ b/index.ts @@ -5,4 +5,15 @@ import { Callbacks } from "@/types/callbacks.type"; import { PinState, SyncState } from "@/types/placeholder.type"; import VirtualDrive from "@/virtual-drive"; -export { Addon, VirtualDrive, QueueItem, typeQueue, HandleAction, HandleActions, QueueManager, Callbacks, PinState, SyncState }; +export { + Addon, + VirtualDrive, + QueueItem, + typeQueue, + HandleAction, + HandleActions, + QueueManager, + Callbacks, + PinState, + SyncState, +}; diff --git a/src/addon-wrapper.ts b/src/addon-wrapper.ts index 967216cf..fa38af56 100644 --- a/src/addon-wrapper.ts +++ b/src/addon-wrapper.ts @@ -89,7 +89,16 @@ export class Addon { lastAccessTime: string; basePath: string; }) { - return addon.createPlaceholderFile(fileName, fileId, fileSize, fileAttributes, creationTime, lastWriteTime, lastAccessTime, basePath); + return addon.createPlaceholderFile( + fileName, + fileId, + fileSize, + fileAttributes, + creationTime, + lastWriteTime, + lastAccessTime, + basePath, + ); } createPlaceholderDirectory({ @@ -113,7 +122,17 @@ export class Addon { lastAccessTime: string; path: string; }) { - return addon.createEntry(itemName, itemId, isDirectory, itemSize, fileAttributes, creationTime, lastWriteTime, lastAccessTime, path); + return addon.createEntry( + itemName, + itemId, + isDirectory, + itemSize, + fileAttributes, + creationTime, + lastWriteTime, + lastAccessTime, + path, + ); } /** diff --git a/src/types/callbacks.type.ts b/src/types/callbacks.type.ts index 7e3be7d4..8b4f1160 100644 --- a/src/types/callbacks.type.ts +++ b/src/types/callbacks.type.ts @@ -6,7 +6,11 @@ export type FilePlaceholderId = `${FilePlaceholderIdPrefixType}${string}`; export type TFetchDataCallback = ( id: FilePlaceholderId, - callback: (data: boolean, path: string, errorHandler?: () => void) => Promise<{ finished: boolean; progress: number }>, + callback: ( + data: boolean, + path: string, + errorHandler?: () => void, + ) => Promise<{ finished: boolean; progress: number }>, ) => void; export type InputSyncCallbacks = { diff --git a/src/virtual-drive.unit.test.ts b/src/virtual-drive.unit.test.ts index 4b8ac498..70f18199 100644 --- a/src/virtual-drive.unit.test.ts +++ b/src/virtual-drive.unit.test.ts @@ -166,7 +166,13 @@ describe("VirtualDrive", () => { // Assert expect(drive.callbacks).not.toBe(undefined); - expect(addon.registerSyncRoot).toHaveBeenCalledWith(syncRootPath, providerName, providerVersion, providerId, logoPath); + expect(addon.registerSyncRoot).toHaveBeenCalledWith( + syncRootPath, + providerName, + providerVersion, + providerId, + logoPath, + ); }); }); }); diff --git a/src/watcher/events/on-add-dir.service.ts b/src/watcher/events/on-add-dir.service.ts index 0705ff40..7fc2f828 100644 --- a/src/watcher/events/on-add-dir.service.ts +++ b/src/watcher/events/on-add-dir.service.ts @@ -11,7 +11,11 @@ export class OnAddDirService { const status = self.addon.getPlaceholderState({ path }); self.logger.info({ fn: "onAddDir", path, status }); - if (status.pinState === PinState.AlwaysLocal || status.pinState === PinState.OnlineOnly || status.syncState === SyncState.InSync) { + if ( + status.pinState === PinState.AlwaysLocal || + status.pinState === PinState.OnlineOnly || + status.syncState === SyncState.InSync + ) { return; } diff --git a/src/watcher/events/on-add.service.ts b/src/watcher/events/on-add.service.ts index 3dde04fd..dc698b1d 100644 --- a/src/watcher/events/on-add.service.ts +++ b/src/watcher/events/on-add.service.ts @@ -29,7 +29,11 @@ export class OnAddService { isMovedFile = true; } - if (status.pinState === PinState.AlwaysLocal || status.pinState === PinState.OnlineOnly || status.syncState === SyncState.InSync) { + if ( + status.pinState === PinState.AlwaysLocal || + status.pinState === PinState.OnlineOnly || + status.syncState === SyncState.InSync + ) { return; } From a1fb02bc5b7f61669d268fe75dc4aefb6c677501 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 16 Apr 2025 07:50:26 -0300 Subject: [PATCH 5/7] Refactor fileAttributes to folderAttributes for consistency in Addon and VirtualDrive classes --- src/addon-wrapper.ts | 6 +++--- src/virtual-drive.ts | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/addon-wrapper.ts b/src/addon-wrapper.ts index fa38af56..e245d28f 100644 --- a/src/addon-wrapper.ts +++ b/src/addon-wrapper.ts @@ -106,7 +106,7 @@ export class Addon { itemId, isDirectory, itemSize, - fileAttributes, + folderAttributes, creationTime, lastWriteTime, lastAccessTime, @@ -116,7 +116,7 @@ export class Addon { itemId: string; isDirectory: boolean; itemSize: number; - fileAttributes: number; + folderAttributes: number; creationTime: string; lastWriteTime: string; lastAccessTime: string; @@ -127,7 +127,7 @@ export class Addon { itemId, isDirectory, itemSize, - fileAttributes, + folderAttributes, creationTime, lastWriteTime, lastAccessTime, diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index db0e48c2..fe183ee7 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -2,12 +2,18 @@ import fs from "fs"; import path, { join, win32 } from "path"; import winston from "winston"; + + import { Addon, DependencyInjectionAddonProvider } from "./addon-wrapper"; import { createLogger } from "./logger"; import { QueueManager } from "./queue/queue-manager"; import { Callbacks } from "./types/callbacks.type"; import { Watcher } from "./watcher/watcher"; + + + + const PLACEHOLDER_ATTRIBUTES = { FILE_ATTRIBUTE_READONLY: 0x1, FILE_ATTRIBUTE_HIDDEN: 0x2, @@ -135,7 +141,7 @@ class VirtualDrive { itemId, isDirectory, itemSize, - fileAttributes, + folderAttributes, creationTime, lastWriteTime, lastAccessTime, @@ -145,7 +151,7 @@ class VirtualDrive { itemId: string; isDirectory: boolean; itemSize: number; - fileAttributes: number; + folderAttributes: number; creationTime: number; lastWriteTime: number; lastAccessTime: number; @@ -160,7 +166,7 @@ class VirtualDrive { itemId, isDirectory, itemSize, - fileAttributes, + folderAttributes, creationTime: creationTimeStr, lastWriteTime: lastWriteTimeStr, lastAccessTime: lastAccessTimeStr, @@ -290,8 +296,8 @@ class VirtualDrive { itemId, isDirectory: true, itemSize: size, - fileAttributes: PLACEHOLDER_ATTRIBUTES.FOLDER_ATTRIBUTE_READONLY, - creationTime: creationTime, + folderAttributes: PLACEHOLDER_ATTRIBUTES.FOLDER_ATTRIBUTE_READONLY, + creationTime, lastWriteTime: lastWriteTime, lastAccessTime: Date.now(), path: currentPath, @@ -323,4 +329,4 @@ class VirtualDrive { } } -export default VirtualDrive; +export default VirtualDrive; \ No newline at end of file From 337f8844db98f13fec9e9175262fc4beb4406d76 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 16 Apr 2025 08:23:06 -0300 Subject: [PATCH 6/7] Remove unnecessary blank lines for improved code cleanliness in VirtualDrive class --- src/virtual-drive.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index fe183ee7..7195a012 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -2,18 +2,12 @@ import fs from "fs"; import path, { join, win32 } from "path"; import winston from "winston"; - - import { Addon, DependencyInjectionAddonProvider } from "./addon-wrapper"; import { createLogger } from "./logger"; import { QueueManager } from "./queue/queue-manager"; import { Callbacks } from "./types/callbacks.type"; import { Watcher } from "./watcher/watcher"; - - - - const PLACEHOLDER_ATTRIBUTES = { FILE_ATTRIBUTE_READONLY: 0x1, FILE_ATTRIBUTE_HIDDEN: 0x2, @@ -329,4 +323,4 @@ class VirtualDrive { } } -export default VirtualDrive; \ No newline at end of file +export default VirtualDrive; From d3fca28498caf363567d55ace615aaaf783a41f9 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 16 Apr 2025 09:29:08 -0300 Subject: [PATCH 7/7] Optimize handleForPath by using wPath directly to enhance performance and ensure Unicode support --- .../placeholders_interface/PlaceHolderInfo.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/native-src/placeholders_interface/PlaceHolderInfo.cpp b/native-src/placeholders_interface/PlaceHolderInfo.cpp index 250bfc61..a690eeb3 100644 --- a/native-src/placeholders_interface/PlaceHolderInfo.cpp +++ b/native-src/placeholders_interface/PlaceHolderInfo.cpp @@ -163,7 +163,20 @@ FileHandle handleForPath(const std::wstring &wPath) return {}; } - std::filesystem::path pathFs(wPath); // Use wPath directly to create path + /** + * v1.0.9 Jonathan Arce + * + * We directly use the wPath parameter in handleForPath for several important reasons: + * + * 1. Performance optimization: Using wPath directly avoids unnecessary string conversions + * between wide strings and UTF-8/ANSI, which would be costly for file operations. + * + * 2. Unicode support: Windows APIs like CfOpenFileWithOplock and CreateFileW require wide + * character strings (wchar_t) to properly handle Unicode paths with international + * characters, spaces, and special symbols. + */ + + std::filesystem::path pathFs(wPath); if (!std::filesystem::exists(pathFs)) { return {};