Refactored: changed the implementation from using overrides to injecting an adapter.

This commit is contained in:
vorotamoroz
2026-03-02 09:06:23 +00:00
parent 28e06a21e4
commit f3e83d4045
19 changed files with 430 additions and 385 deletions
@@ -0,0 +1,18 @@
import type { UXFileInfoStub, UXFolderInfo } from "@/lib/src/common/types";
import type { IConversionAdapter } from "@/lib/src/serviceModules/adapters";
import { TFileToUXFileInfoStub, TFolderToUXFileInfoStub } from "@/modules/coreObsidian/storageLib/utilObsidian";
import type { TFile, TFolder } from "obsidian";
/**
* Conversion adapter implementation for Obsidian
*/
export class ObsidianConversionAdapter implements IConversionAdapter<TFile, TFolder> {
nativeFileToUXFileInfoStub(file: TFile): UXFileInfoStub {
return TFileToUXFileInfoStub(file);
}
nativeFolderToUXFolder(folder: TFolder): UXFolderInfo {
return TFolderToUXFileInfoStub(folder);
}
}
@@ -0,0 +1,64 @@
import type { FilePath, UXStat } from "@/lib/src/common/types";
import type {
IFileSystemAdapter,
IPathAdapter,
ITypeGuardAdapter,
IConversionAdapter,
IStorageAdapter,
IVaultAdapter,
} from "@/lib/src/serviceModules/adapters";
import type { TAbstractFile, TFile, TFolder, Stat, App } from "obsidian";
import { ObsidianConversionAdapter } from "./ObsidianConversionAdapter";
import { ObsidianPathAdapter } from "./ObsidianPathAdapter";
import { ObsidianStorageAdapter } from "./ObsidianStorageAdapter";
import { ObsidianTypeGuardAdapter } from "./ObsidianTypeGuardAdapter";
import { ObsidianVaultAdapter } from "./ObsidianVaultAdapter";
declare module "obsidian" {
interface Vault {
getAbstractFileByPathInsensitive(path: string): TAbstractFile | null;
}
interface DataAdapter {
reconcileInternalFile?(path: string): Promise<void>;
}
}
/**
* Complete file system adapter implementation for Obsidian
*/
export class ObsidianFileSystemAdapter implements IFileSystemAdapter<TAbstractFile, TFile, TFolder, Stat> {
readonly path: IPathAdapter<TAbstractFile>;
readonly typeGuard: ITypeGuardAdapter<TFile, TFolder>;
readonly conversion: IConversionAdapter<TFile, TFolder>;
readonly storage: IStorageAdapter<Stat>;
readonly vault: IVaultAdapter<TFile>;
constructor(private app: App) {
this.path = new ObsidianPathAdapter();
this.typeGuard = new ObsidianTypeGuardAdapter();
this.conversion = new ObsidianConversionAdapter();
this.storage = new ObsidianStorageAdapter(app);
this.vault = new ObsidianVaultAdapter(app);
}
getAbstractFileByPath(path: FilePath | string): TAbstractFile | null {
return this.app.vault.getAbstractFileByPath(path);
}
getAbstractFileByPathInsensitive(path: FilePath | string): TAbstractFile | null {
return this.app.vault.getAbstractFileByPathInsensitive(path);
}
getFiles(): TFile[] {
return this.app.vault.getFiles();
}
statFromNative(file: TFile): Promise<UXStat> {
return Promise.resolve({ ...file.stat, type: "file" });
}
async reconcileInternalFile(path: string): Promise<void> {
return await Promise.resolve(this.app.vault.adapter.reconcileInternalFile?.(path));
}
}
@@ -0,0 +1,16 @@
import { type TAbstractFile, normalizePath } from "@/deps";
import type { FilePath } from "@lib/common/types";
import type { IPathAdapter } from "@lib/serviceModules/adapters";
/**
* Path adapter implementation for Obsidian
*/
export class ObsidianPathAdapter implements IPathAdapter<TAbstractFile> {
getPath(file: string | TAbstractFile): FilePath {
return (typeof file === "string" ? file : file.path) as FilePath;
}
normalisePath(path: string): string {
return normalizePath(path);
}
}
@@ -0,0 +1,57 @@
import type { UXDataWriteOptions } from "@/lib/src/common/types";
import type { IStorageAdapter } from "@/lib/src/serviceModules/adapters";
import { toArrayBuffer } from "@/lib/src/serviceModules/FileAccessBase";
import type { Stat, App } from "obsidian";
/**
* Storage adapter implementation for Obsidian
*/
export class ObsidianStorageAdapter implements IStorageAdapter<Stat> {
constructor(private app: App) {}
async exists(path: string): Promise<boolean> {
return await this.app.vault.adapter.exists(path);
}
async trystat(path: string): Promise<Stat | null> {
if (!(await this.app.vault.adapter.exists(path))) return null;
return await this.app.vault.adapter.stat(path);
}
async stat(path: string): Promise<Stat | null> {
return await this.app.vault.adapter.stat(path);
}
async mkdir(path: string): Promise<void> {
await this.app.vault.adapter.mkdir(path);
}
async remove(path: string): Promise<void> {
await this.app.vault.adapter.remove(path);
}
async read(path: string): Promise<string> {
return await this.app.vault.adapter.read(path);
}
async readBinary(path: string): Promise<ArrayBuffer> {
return await this.app.vault.adapter.readBinary(path);
}
async write(path: string, data: string, options?: UXDataWriteOptions): Promise<void> {
return await this.app.vault.adapter.write(path, data, options);
}
async writeBinary(path: string, data: ArrayBuffer, options?: UXDataWriteOptions): Promise<void> {
return await this.app.vault.adapter.writeBinary(path, toArrayBuffer(data), options);
}
async append(path: string, data: string, options?: UXDataWriteOptions): Promise<void> {
return await this.app.vault.adapter.append(path, data, options);
}
list(basePath: string): Promise<{ files: string[]; folders: string[] }> {
return Promise.resolve(this.app.vault.adapter.list(basePath));
}
}
@@ -0,0 +1,16 @@
import type { ITypeGuardAdapter } from "@/lib/src/serviceModules/adapters";
import { TFile, TFolder } from "obsidian";
/**
* Type guard adapter implementation for Obsidian
*/
export class ObsidianTypeGuardAdapter implements ITypeGuardAdapter<TFile, TFolder> {
isFile(file: any): file is TFile {
return file instanceof TFile;
}
isFolder(item: any): item is TFolder {
return item instanceof TFolder;
}
}
@@ -0,0 +1,51 @@
import type { UXDataWriteOptions } from "@/lib/src/common/types";
import type { IVaultAdapter } from "@/lib/src/serviceModules/adapters";
import { toArrayBuffer } from "@/lib/src/serviceModules/FileAccessBase";
import type { TFile, App, TFolder } from "obsidian";
/**
* Vault adapter implementation for Obsidian
*/
export class ObsidianVaultAdapter implements IVaultAdapter<TFile> {
constructor(private app: App) {}
async read(file: TFile): Promise<string> {
return await this.app.vault.read(file);
}
async cachedRead(file: TFile): Promise<string> {
return await this.app.vault.cachedRead(file);
}
async readBinary(file: TFile): Promise<ArrayBuffer> {
return await this.app.vault.readBinary(file);
}
async modify(file: TFile, data: string, options?: UXDataWriteOptions): Promise<void> {
return await this.app.vault.modify(file, data, options);
}
async modifyBinary(file: TFile, data: ArrayBuffer, options?: UXDataWriteOptions): Promise<void> {
return await this.app.vault.modifyBinary(file, toArrayBuffer(data), options);
}
async create(path: string, data: string, options?: UXDataWriteOptions): Promise<TFile> {
return await this.app.vault.create(path, data, options);
}
async createBinary(path: string, data: ArrayBuffer, options?: UXDataWriteOptions): Promise<TFile> {
return await this.app.vault.createBinary(path, toArrayBuffer(data), options);
}
async delete(file: TFile | TFolder, force = false): Promise<void> {
return await this.app.vault.delete(file, force);
}
async trash(file: TFile | TFolder, force = false): Promise<void> {
return await this.app.vault.trash(file, force);
}
trigger(name: string, ...data: any[]): any {
return this.app.vault.trigger(name, ...data);
}
}