2025-10-02 10:10:57 +00:00
|
|
|
import type AIAgentPlugin from "main";
|
2025-10-05 12:06:05 +00:00
|
|
|
import { TAbstractFile, TFile, TFolder, type Vault } from "obsidian";
|
2025-09-30 20:20:24 +00:00
|
|
|
import { Resolve } from "./DependencyService";
|
|
|
|
|
import { Services } from "./Services";
|
|
|
|
|
import { isValidJson } from "Helpers/Helpers";
|
2025-10-12 20:26:01 +00:00
|
|
|
import { Path } from "Enums/Path";
|
|
|
|
|
import type { VaultService } from "./VaultService";
|
2025-09-30 20:20:24 +00:00
|
|
|
|
|
|
|
|
export class FileSystemService {
|
2025-10-12 20:26:01 +00:00
|
|
|
|
|
|
|
|
private readonly vaultService: VaultService;
|
2025-09-30 20:20:24 +00:00
|
|
|
|
|
|
|
|
public constructor() {
|
2025-10-12 20:26:01 +00:00
|
|
|
this.vaultService = Resolve<VaultService>(Services.VaultService);
|
2025-09-30 20:20:24 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-08 21:06:25 +00:00
|
|
|
public getVaultFileListForMarkDown() {
|
2025-10-12 20:26:01 +00:00
|
|
|
const files: TFile[] = this.vaultService.getMarkdownFiles();
|
2025-10-08 21:06:25 +00:00
|
|
|
return files.map(file => {
|
|
|
|
|
return file.path.replace(/\.md$/, "");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-05 12:06:05 +00:00
|
|
|
public async readFile(filePath: string): Promise<string | null> {
|
2025-10-12 20:26:01 +00:00
|
|
|
const file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath);
|
2025-09-30 20:20:24 +00:00
|
|
|
if (file && file instanceof TFile) {
|
2025-10-12 20:26:01 +00:00
|
|
|
return await this.vaultService.read(file);
|
2025-09-30 20:20:24 +00:00
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-05 12:06:05 +00:00
|
|
|
public async writeFile(filePath: string, content: string): Promise<boolean> {
|
2025-09-30 20:20:24 +00:00
|
|
|
try {
|
2025-10-12 20:26:01 +00:00
|
|
|
let file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath);
|
2025-10-05 12:06:05 +00:00
|
|
|
if (file == null || !(file instanceof TFile)) {
|
2025-10-12 20:26:01 +00:00
|
|
|
await this.createDirectories(this.vaultService, filePath);
|
|
|
|
|
await this.vaultService.create(filePath, content);
|
2025-10-05 12:06:05 +00:00
|
|
|
return true;
|
2025-09-30 20:20:24 +00:00
|
|
|
}
|
2025-10-12 20:26:01 +00:00
|
|
|
await this.vaultService.modify(file as TFile, content);
|
2025-09-30 20:20:24 +00:00
|
|
|
return true;
|
2025-10-05 12:06:05 +00:00
|
|
|
}
|
|
|
|
|
catch (error) {
|
|
|
|
|
console.error("Error writing file:", error);
|
2025-09-30 20:20:24 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-03 21:14:30 +00:00
|
|
|
public async deleteFile(filePath: string): Promise<boolean> {
|
|
|
|
|
try {
|
2025-10-12 20:26:01 +00:00
|
|
|
const file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath);
|
2025-10-03 21:14:30 +00:00
|
|
|
|
|
|
|
|
if (file && file instanceof TFile) {
|
2025-10-12 20:26:01 +00:00
|
|
|
await this.vaultService.delete(file);
|
2025-10-03 21:14:30 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error deleting file:", error);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-05 12:06:05 +00:00
|
|
|
public async listFilesInDirectory(dirPath: string, recursive: boolean = true): Promise<TFile[]> {
|
2025-10-12 20:26:01 +00:00
|
|
|
const dir: TAbstractFile | null = this.vaultService.getAbstractFileByPath(dirPath);
|
2025-10-05 12:06:05 +00:00
|
|
|
|
|
|
|
|
if (dir == null || !(dir instanceof TFolder)) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let files: TFile[] = [];
|
|
|
|
|
for (let child of dir.children) {
|
|
|
|
|
if (child instanceof TFile) {
|
|
|
|
|
files.push(child);
|
|
|
|
|
} else if (child instanceof TFolder && recursive) {
|
|
|
|
|
const childFiles = await this.listFilesInDirectory(child.path, recursive);
|
|
|
|
|
files = files.concat(childFiles);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return files;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async readObjectFromFile(filePath: string): Promise<object | null> {
|
2025-10-12 20:26:01 +00:00
|
|
|
const file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath);
|
2025-10-05 12:06:05 +00:00
|
|
|
if (file && file instanceof TFile) {
|
2025-10-12 20:26:01 +00:00
|
|
|
const content = await this.vaultService.read(file);
|
2025-10-05 12:06:05 +00:00
|
|
|
if (isValidJson(content) === true) {
|
|
|
|
|
return JSON.parse(content);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async writeObjectToFile(filePath: string, data: object): Promise<boolean> {
|
|
|
|
|
try {
|
2025-10-12 20:26:01 +00:00
|
|
|
let file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath);
|
2025-10-05 12:06:05 +00:00
|
|
|
|
|
|
|
|
if (file && file instanceof TFile) {
|
2025-10-12 20:26:01 +00:00
|
|
|
await this.vaultService.modify(file, JSON.stringify(data, null, 4));
|
2025-10-05 12:06:05 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2025-10-12 20:26:01 +00:00
|
|
|
await this.createDirectories(this.vaultService, filePath);
|
|
|
|
|
await this.vaultService.create(filePath, JSON.stringify(data, null, 4));
|
2025-10-05 12:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error writing JSON file:", error);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-12 20:26:01 +00:00
|
|
|
private async createDirectories(vaultService: VaultService, filePath: string) {
|
2025-09-30 20:20:24 +00:00
|
|
|
const dirPath: string = filePath.substring(0, filePath.lastIndexOf('/'));
|
|
|
|
|
|
|
|
|
|
const dirs: string[] = dirPath.split('/');
|
|
|
|
|
|
|
|
|
|
let currentPath = "";
|
|
|
|
|
for (const dir of dirs) {
|
|
|
|
|
if (dir) {
|
|
|
|
|
currentPath = currentPath ? `${currentPath}/${dir}` : dir;
|
2025-10-12 20:26:01 +00:00
|
|
|
if (vaultService.getAbstractFileByPath(currentPath) == null) {
|
|
|
|
|
await vaultService.createFolder(currentPath);
|
2025-09-30 20:20:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|