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: 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/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/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..a60d7b49 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"; @@ -14,18 +13,28 @@ 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 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..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(fullPath, fileId, fileSize, createdAt, updatedAt); + drive.createFileByPath({ + relativePath: fullPath, + itemId: fileId, + size: fileSize, + creationTime: createdAt, + lastWriteTime: updatedAt, + }); result[fileId] = fullPath; } @@ -66,13 +72,21 @@ 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); } } -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/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/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/native-src/placeholders_interface/PlaceHolderInfo.cpp b/native-src/placeholders_interface/PlaceHolderInfo.cpp index 2c77c2b7..a690eeb3 100644 --- a/native-src/placeholders_interface/PlaceHolderInfo.cpp +++ b/native-src/placeholders_interface/PlaceHolderInfo.cpp @@ -163,13 +163,20 @@ 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); + /** + * 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 {}; @@ -186,13 +193,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 +216,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/addon-wrapper.ts b/src/addon-wrapper.ts index 967216cf..e245d28f 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({ @@ -97,7 +106,7 @@ export class Addon { itemId, isDirectory, itemSize, - fileAttributes, + folderAttributes, creationTime, lastWriteTime, lastAccessTime, @@ -107,13 +116,23 @@ export class Addon { itemId: string; isDirectory: boolean; itemSize: number; - fileAttributes: number; + folderAttributes: number; creationTime: string; lastWriteTime: string; lastAccessTime: string; path: string; }) { - return addon.createEntry(itemName, itemId, isDirectory, itemSize, fileAttributes, creationTime, lastWriteTime, lastAccessTime, path); + return addon.createEntry( + itemName, + itemId, + isDirectory, + itemSize, + folderAttributes, + creationTime, + lastWriteTime, + lastAccessTime, + path, + ); } /** 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/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.ts b/src/virtual-drive.ts index 8c4db925..7195a012 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; @@ -37,16 +37,16 @@ class VirtualDrive { this.logger = createLogger(loggerPath); } - convertToWindowsTime(jsTime: number) { + private convertToWindowsTime(jsTime: number) { return BigInt(jsTime) * 10000n + 116444736000000000n; } - 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 { @@ -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, + folderAttributes, + creationTime, + lastWriteTime, + lastAccessTime, + path = this.syncRootPath, + }: { + itemName: string; + itemId: string; + isDirectory: boolean; + itemSize: number; + folderAttributes: 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(); @@ -141,7 +160,7 @@ class VirtualDrive { itemId, isDirectory, itemSize, - fileAttributes, + folderAttributes, creationTime: creationTimeStr, lastWriteTime: lastWriteTimeStr, lastAccessTime: lastAccessTimeStr, @@ -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, + isDirectory: true, + itemSize: size, + folderAttributes: PLACEHOLDER_ATTRIBUTES.FOLDER_ATTRIBUTE_READONLY, creationTime, - lastWriteTime, - Date.now(), - currentPath, - ); + 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..70f18199 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"); }); }); @@ -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,11 +162,17 @@ 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); - 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; }