vault-link/frontend/local-client-cli/src/file-watcher.ts
Andras Schmelczer 682dc74497
Some checks failed
Check / build (pull_request) Has been cancelled
E2E tests / build (pull_request) Has been cancelled
Publish CLI / publish-docker (pull_request) Has been cancelled
Publish server Docker image / publish-docker (pull_request) Has been cancelled
Update local-client-cli and obsidian-plugin
Pulls the local-client-cli and obsidian-plugin changes from
asch/fix-everything onto a fresh branch off main.
2026-05-09 13:41:51 +01:00

93 lines
2.8 KiB
TypeScript

import Watcher from "watcher";
import * as path from "path";
import type { SyncClient, RelativePath } from "sync-client";
import { toUnixPath, matchesGlob } from "./path-utils";
export class FileWatcher {
private watcher: Watcher | undefined;
private isRunning = false;
private readonly ignorePatterns: string[];
public constructor(
private readonly basePath: string,
private readonly client: SyncClient,
ignorePatterns: string[] = []
) {
this.ignorePatterns = ignorePatterns;
}
public start(): void {
if (this.isRunning) {
return;
}
this.isRunning = true;
this.watcher = new Watcher(this.basePath, {
recursive: true,
renameDetection: true,
renameTimeout: 125,
ignoreInitial: true,
ignore: (filePath: string): boolean => this.shouldIgnore(filePath)
});
this.watcher.on("add", (filePath: string) => {
this.handleCreate(this.toRelativePath(filePath));
});
this.watcher.on("change", (filePath: string) => {
this.handleChange(this.toRelativePath(filePath));
});
this.watcher.on("unlink", (filePath: string) => {
this.handleDelete(this.toRelativePath(filePath));
});
this.watcher.on("rename", (oldPath: string, newPath: string) => {
this.handleRename(
this.toRelativePath(oldPath),
this.toRelativePath(newPath)
);
});
this.client.logger.info("File watcher started");
}
public stop(): void {
if (this.watcher !== undefined) {
this.watcher.close();
this.watcher = undefined;
}
this.isRunning = false;
this.client.logger.info("File watcher stopped");
}
private shouldIgnore(filePath: string): boolean {
const rel = toUnixPath(path.relative(this.basePath, filePath));
return this.ignorePatterns.some((pattern) => matchesGlob(rel, pattern));
}
private handleCreate(relativePath: RelativePath): void {
this.client.syncLocallyCreatedFile(relativePath);
}
private handleChange(relativePath: RelativePath): void {
this.client.syncLocallyUpdatedFile({ relativePath });
}
private handleDelete(relativePath: RelativePath): void {
this.client.syncLocallyDeletedFile(relativePath);
}
private handleRename(oldPath: RelativePath, newPath: RelativePath): void {
this.client.logger.info(`File renamed: ${oldPath} -> ${newPath}`);
this.client.syncLocallyUpdatedFile({
oldPath,
relativePath: newPath
});
}
private toRelativePath(absolutePath: string): RelativePath {
return toUnixPath(path.relative(this.basePath, absolutePath));
}
}