BREAKING CHANGE(SmartFileFactory): Refactor to in-memory file API and introduce SmartFileFactory; delegate filesystem operations to @push.rocks/smartfs; bump to 12.0.0

This commit is contained in:
2025-11-22 13:18:32 +00:00
parent 16d47ea348
commit ad33cb6d73
24 changed files with 1552 additions and 1789 deletions

View File

@@ -1,6 +1,5 @@
import { SmartFile } from './classes.smartfile.js';
import * as plugins from './plugins.js';
import * as fs from './fs.js';
export interface IVirtualDirectoryConstructorOptions {
mode: '';
@@ -8,46 +7,149 @@ export interface IVirtualDirectoryConstructorOptions {
/**
* a virtual directory exposes a fs api
* Use SmartFileFactory to create instances of this class
*/
export class VirtualDirectory {
consstructor(options = {}) {}
// STATIC
public static async fromFsDirPath(
pathArg: string,
smartFs?: any,
factory?: any
): Promise<VirtualDirectory> {
const newVirtualDir = new VirtualDirectory();
newVirtualDir.addSmartfiles(await fs.fileTreeToObject(pathArg, '**/*'));
if (!smartFs || !factory) {
throw new Error('No SmartFs/Factory instance available. Create VirtualDirectory through SmartFileFactory.');
}
const newVirtualDir = new VirtualDirectory(smartFs, factory);
// Use smartFs to list directory and factory to create SmartFiles
const entries = await smartFs.directory(pathArg).list({ recursive: true });
const smartfiles = await Promise.all(
entries
.filter((entry: any) => entry.isFile)
.map((entry: any) => factory.fromFilePath(entry.path, pathArg))
);
newVirtualDir.addSmartfiles(smartfiles);
return newVirtualDir;
}
public static async fromVirtualDirTransferableObject(
virtualDirTransferableObjectArg: plugins.smartfileInterfaces.VirtualDirTransferableObject,
smartFs?: any,
factory?: any
): Promise<VirtualDirectory> {
const newVirtualDir = new VirtualDirectory();
const newVirtualDir = new VirtualDirectory(smartFs, factory);
for (const fileArg of virtualDirTransferableObjectArg.files) {
newVirtualDir.addSmartfiles([
SmartFile.enfoldFromJson(fileArg) as SmartFile,
]);
const smartFile = SmartFile.enfoldFromJson(fileArg) as SmartFile;
// Update smartFs reference if available
if (smartFs) {
(smartFile as any).smartFs = smartFs;
}
newVirtualDir.addSmartfiles([smartFile]);
}
return newVirtualDir;
}
public static fromFileArray(files: SmartFile[], smartFs?: any, factory?: any): VirtualDirectory {
const vdir = new VirtualDirectory(smartFs, factory);
vdir.addSmartfiles(files);
return vdir;
}
public static empty(smartFs?: any, factory?: any): VirtualDirectory {
return new VirtualDirectory(smartFs, factory);
}
// INSTANCE
public smartfileArray: SmartFile[] = [];
private smartFs?: any;
private factory?: any;
constructor() {}
constructor(smartFs?: any, factory?: any) {
this.smartFs = smartFs;
this.factory = factory;
}
// ============================================
// Collection Mutations
// ============================================
public addSmartfiles(smartfileArrayArg: SmartFile[]) {
this.smartfileArray = this.smartfileArray.concat(smartfileArrayArg);
}
public async getFileByPath(pathArg: string) {
for (const smartfile of this.smartfileArray) {
if (smartfile.path === pathArg) {
return smartfile;
public addSmartfile(smartfileArg: SmartFile): void {
this.smartfileArray.push(smartfileArg);
}
public removeByPath(pathArg: string): boolean {
const initialLength = this.smartfileArray.length;
this.smartfileArray = this.smartfileArray.filter(f => f.path !== pathArg);
return this.smartfileArray.length < initialLength;
}
public clear(): void {
this.smartfileArray = [];
}
public merge(otherVDir: VirtualDirectory): void {
this.addSmartfiles(otherVDir.smartfileArray);
}
// ============================================
// Collection Queries
// ============================================
public exists(pathArg: string): boolean {
return this.smartfileArray.some(f => f.path === pathArg);
}
public has(pathArg: string): boolean {
return this.exists(pathArg);
}
public async getFileByPath(pathArg: string): Promise<SmartFile | undefined> {
return this.smartfileArray.find(f => f.path === pathArg);
}
public listFiles(): SmartFile[] {
return [...this.smartfileArray];
}
public listDirectories(): string[] {
const dirs = new Set<string>();
for (const file of this.smartfileArray) {
const dir = plugins.path.dirname(file.path);
if (dir !== '.') {
dirs.add(dir);
}
}
return Array.from(dirs).sort();
}
public filter(predicate: (file: SmartFile) => boolean): VirtualDirectory {
const newVDir = new VirtualDirectory(this.smartFs, this.factory);
newVDir.addSmartfiles(this.smartfileArray.filter(predicate));
return newVDir;
}
public map(fn: (file: SmartFile) => SmartFile): VirtualDirectory {
const newVDir = new VirtualDirectory(this.smartFs, this.factory);
newVDir.addSmartfiles(this.smartfileArray.map(fn));
return newVDir;
}
public find(predicate: (file: SmartFile) => boolean): SmartFile | undefined {
return this.smartfileArray.find(predicate);
}
public size(): number {
return this.smartfileArray.length;
}
public isEmpty(): boolean {
return this.smartfileArray.length === 0;
}
public async toVirtualDirTransferableObject(): Promise<plugins.smartfileInterfaces.VirtualDirTransferableObject> {
@@ -69,7 +171,7 @@ export class VirtualDirectory {
}
public async shiftToSubdirectory(subDir: string): Promise<VirtualDirectory> {
const newVirtualDir = new VirtualDirectory();
const newVirtualDir = new VirtualDirectory(this.smartFs, this.factory);
for (const file of this.smartfileArray) {
if (file.path.startsWith(subDir)) {
const adjustedFilePath = plugins.path.relative(subDir, file.path);
@@ -80,6 +182,13 @@ export class VirtualDirectory {
return newVirtualDir;
}
public async loadFromDisk(dirArg: string): Promise<void> {
// Load from disk, replacing current collection
this.clear();
const loaded = await VirtualDirectory.fromFsDirPath(dirArg, this.smartFs, this.factory);
this.addSmartfiles(loaded.smartfileArray);
}
public async addVirtualDirectory(
virtualDir: VirtualDirectory,
newRoot: string,