Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 22 additions & 115 deletions src/virtual-drive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class VirtualDrive {
this.logger = createLogger(loggerPath);
}

addLoggerPath(logPath: string) {
addon.addLogger({ logPath });
convertToWindowsTime(jsTime: number) {
return BigInt(jsTime) * 10000n + 116444736000000000n;
}

convertToWindowsPath(path: string) {
Expand All @@ -51,11 +51,15 @@ class VirtualDrive {
}
}

addLoggerPath(logPath: string) {
addon.addLogger({ logPath });
}

getPlaceholderState(path: string) {
return addon.getPlaceholderState({ path: this.fixPath(path) });
}

getPlaceholderWithStatePending(): any {
getPlaceholderWithStatePending() {
return addon.getPlaceholderWithStatePending();
}

Expand All @@ -65,19 +69,15 @@ class VirtualDrive {
}
}

convertToWindowsTime(jsTime: number): bigint {
return BigInt(jsTime) * 10000n + 116444736000000000n;
}

getFileIdentity(relativePath: string) {
return addon.getFileIdentity({ path: this.fixPath(relativePath) });
}

async deleteFileSyncRoot(relativePath: string): Promise<void> {
async deleteFileSyncRoot(relativePath: string) {
return addon.deleteFileSyncRoot({ path: this.fixPath(relativePath) });
}

async connectSyncRoot() {
connectSyncRoot() {
if (this.callbacks === undefined) {
throw new Error("Callbacks are not defined");
}
Expand Down Expand Up @@ -139,14 +139,6 @@ class VirtualDrive {
});
}

private isValidFolderPath(path: string) {
return path.startsWith("/") && path.endsWith("/") && !path.includes(".");
}

private isValidFilePath(path: string) {
return path.includes(".");
}

async registerSyncRoot(
providerName: string,
providerVersion: string,
Expand All @@ -163,25 +155,19 @@ class VirtualDrive {
});
}

static unregisterSyncRoot(syncRootPath: string): any {
const result = addon.unregisterSyncRoot({ syncRootPath });
return result;
static unregisterSyncRoot(syncRootPath: string) {
return addon.unregisterSyncRoot({ syncRootPath });
}

watchAndWait(
path: string,
queueManager: IQueueManager,
loggerPath: string
): void {
if (this.callbacks === undefined) {
throw new Error("Callbacks are not defined");
}

this.watcher.addon = addon;
this.watcher.queueManager = queueManager;

this.watcher.logger = this.logger;

this.watcher.syncRootPath = path;
this.watcher.syncRootPath = this.syncRootPath;
this.watcher.options = {
ignored: /(^|[\/\\])\../,
persistent: true,
Expand All @@ -195,8 +181,6 @@ class VirtualDrive {
usePolling: true,
};

this.watcher.addon = addon;

this.watcher.watchAndWait();
}

Expand All @@ -206,7 +190,7 @@ class VirtualDrive {
size: number = 0,
creationTime: number = Date.now(),
lastWriteTime: number = Date.now()
): void {
) {
const fullPath = path.join(this.syncRootPath, relativePath);
const splitPath = relativePath.split("/").filter((p) => p);
const directoryPath = path.resolve(this.syncRootPath);
Expand Down Expand Up @@ -241,7 +225,7 @@ class VirtualDrive {
size: number = 0,
creationTime: number = Date.now(),
lastWriteTime: number = Date.now()
): void {
) {
const splitPath = relativePath.split("/").filter((p) => p);
const directoryPath = path.resolve(this.syncRootPath);
let currentPath = directoryPath;
Expand All @@ -268,107 +252,30 @@ class VirtualDrive {
}
}

createItemByPath(
relativePath: string,
itemId: string,
size: number = 0,
creationTime: number = Date.now(),
lastWriteTime: number = Date.now()
): void {
const fullPath = path.join(this.syncRootPath, relativePath);
const splitPath = relativePath.split("/").filter((p) => p);
const directoryPath = path.resolve(this.syncRootPath);
let currentPath = directoryPath;
if (this.isValidFolderPath(relativePath)) {
// Es un directorio

for (const dir of splitPath) {
if (fs.existsSync(currentPath)) {
try {
this.createPlaceholderDirectory(
dir,
itemId,
true,
size,
PLACEHOLDER_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL,
creationTime,
lastWriteTime,
Date.now(),
currentPath
);
} catch (error) {
//@ts-ignore
console.error(`Error while creating directory: ${error.message}`);
}
}
currentPath = path.join(currentPath, dir);
}
} else if (this.isValidFilePath(relativePath)) {
// Es un archivo

try {
for (let i = 0; i < splitPath.length - 1; i++) {
// everything except last element
const dir = splitPath[i];
if (fs.existsSync(currentPath)) {
this.createPlaceholderDirectory(
dir,
itemId,
true,
0,
PLACEHOLDER_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL,
Date.now(),
Date.now(),
Date.now(),
currentPath
);
}
currentPath = path.join(currentPath, dir);
}
// last element is the file
this.createPlaceholderFile(
path.basename(fullPath),
itemId,
size,
PLACEHOLDER_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL,
creationTime,
lastWriteTime,
Date.now(),
currentPath
);
} catch (error) {
//@ts-ignore
console.error(`Error al crear placeholder: ${error.message}`);
}
} else {
console.error("Invalid path");
}
}

disconnectSyncRoot() {
return addon.disconnectSyncRoot();
}

async updateSyncStatus(
updateSyncStatus(
itemPath: string,
isDirectory: boolean,
sync: boolean = true
) {
return await addon.updateSyncStatus({ path: this.fixPath(itemPath), isDirectory, sync });
return addon.updateSyncStatus({ path: this.fixPath(itemPath), isDirectory, sync });
}

convertToPlaceholder(itemPath: string, id: string): boolean {
convertToPlaceholder(itemPath: string, id: string) {
return addon.convertToPlaceholder({ path: this.fixPath(itemPath), id });
}
updateFileIdentity(itemPath: string, id: string, isDirectory: boolean): void {
addon.updateFileIdentity({ path: this.fixPath(itemPath), id, isDirectory });
updateFileIdentity(itemPath: string, id: string, isDirectory: boolean) {
return addon.updateFileIdentity({ path: this.fixPath(itemPath), id, isDirectory });
}

async dehydrateFile(itemPath: string) {
dehydrateFile(itemPath: string) {
return addon.dehydrateFile({ path: this.fixPath(itemPath) });
}

async hydrateFile(itemPath: string): Promise<void> {
hydrateFile(itemPath: string) {
return addon.hydrateFile({ path: this.fixPath(itemPath) });
}
}
Expand Down
24 changes: 5 additions & 19 deletions src/watcher/events/on-add.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,29 @@ import { PinState, SyncState } from "@/types/placeholder.type";
import { Watcher } from "../watcher";

export class OnAddService {
execute({ self, path, stats }: TProps) {
execute({ self, path, stats }: { self: Watcher; path: string; stats: Stats }) {
try {
const ext = path.split(".").pop();
const { size, birthtime, mtime } = stats;
const itemId = self.addon.getFileIdentity({ path });

self.logger.info({ fn: "onAdd", path, ext, size, birthtime, mtime, itemId });

if (!ext || size === 0 || size > 20 * 1024 * 1024 * 1024) return;
if (size === 0 || size > 20 * 1024 * 1024 * 1024) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove the !ext validation? In theory, we shouldn't allow files without extensions to be uploaded.


const itemId = self.addon.getFileIdentity({ path });
const status = self.addon.getPlaceholderState({ path });
self.logger.info({ fn: "onAdd", path, status });

// Verificar tiempos de creación y modificación
self.logger.info({ fn: "onAdd", path, size, birthtime, mtime, itemId, status });

const creationTime = new Date(birthtime).getTime();
const modificationTime = new Date(mtime).getTime();
const currentTime = Date.now();

let isNewFile = false;
let isMovedFile = false;

if (!itemId) {
// El archivo fue creado recientemente (dentro de los últimos 60 segundos)
isNewFile = true;
} else if (creationTime !== modificationTime) {
// El archivo fue movido (o modificado)
isMovedFile = true;
}

// Procesar el archivo según su estado
if (status.pinState === PinState.AlwaysLocal || status.pinState === PinState.OnlineOnly || status.syncState === SyncState.InSync) {
return;
}
Expand All @@ -45,16 +38,9 @@ export class OnAddService {
self.queueManager.enqueue({ path, type: typeQueue.add, isFolder: false });
} else if (isMovedFile) {
self.logger.info({ fn: "onAdd", msg: "File moved", path });
// Procesar archivo movido según sea necesario
}
} catch (error) {
self.logger.error("onAddService", error);
}
}
}

type TProps = {
self: Watcher;
path: string;
stats: Stats;
};
14 changes: 0 additions & 14 deletions src/watcher/events/on-all.service.ts

This file was deleted.

23 changes: 7 additions & 16 deletions src/watcher/watcher.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import * as chokidar from "chokidar";
import { watch, WatchOptions, FSWatcher } from "chokidar";
import { Stats } from "fs";
import { Logger } from "winston";

import { Addon } from "@/addon-wrapper";
import { QueueManager } from "@/queue/queue-manager";
import { IQueueManager } from "@/queue/queueManager";

import { OnAddDirService } from "./events/on-add-dir.service";
import { OnAddService } from "./events/on-add.service";
import { OnAllService } from "./events/on-all.service";
import { OnRawService } from "./events/on-raw.service";
import { Addon } from "@/addon-wrapper";

export namespace Watcher {
export type TOptions = chokidar.WatchOptions;
export type TOptions = WatchOptions;
}

export class Watcher {
Expand All @@ -22,21 +21,15 @@ export class Watcher {
queueManager!: IQueueManager;
logger!: Logger;
fileInDevice = new Set<string>();
chokidar?: FSWatcher;

constructor(
private readonly onAll: OnAllService = new OnAllService(),
private readonly onAdd: OnAddService = new OnAddService(),
private readonly onAddDir: OnAddDirService = new OnAddDirService(),
private readonly onRaw: OnRawService = new OnRawService(),
) {}

init(
queueManager: QueueManager,
syncRootPath: string,
options: chokidar.WatchOptions,
logger: Logger,
addon: Addon,
) {
init(queueManager: QueueManager, syncRootPath: string, options: WatchOptions, logger: Logger, addon: Addon) {
this.queueManager = queueManager;
this.syncRootPath = syncRootPath;
this.options = options;
Expand All @@ -58,10 +51,8 @@ export class Watcher {

public watchAndWait() {
try {
const watcher = chokidar.watch(this.syncRootPath, this.options);

watcher
.on("all", (event, path, stats) => this.onAll.execute({ self: this, event, path, stats }))
this.chokidar = watch(this.syncRootPath, this.options);
this.chokidar
.on("add", (path, stats) => this.onAdd.execute({ self: this, path, stats: stats! }))
.on("change", this.onChange)
.on("addDir", (path, stats) => this.onAddDir.execute({ self: this, path, stats: stats! }))
Expand Down
Loading