sounds, better files

This commit is contained in:
2024-08-18 19:11:41 +00:00
parent 9ed2f70701
commit 08489ed67b
86 changed files with 4226 additions and 86 deletions

View File

@@ -0,0 +1,129 @@
import { FileSystemSource, ListDirOptions, VirtualDirectory, VirtualFile } from "./types";
import { NginxFS } from "./NginxFS";
import { FileStashFs } from "./FileStashFs";
import { CachePolicy, NoCacheEntryError } from "./FsCache";
type Config<T> = T extends FileSystemSource<any> ? ReturnType<T['getConfig']> : never;
const CACHE = Symbol('Cache');
export interface Fs {
get root(): VirtualDirectory[];
download(file: VirtualFile): Promise<File>;
listDir(dir: VirtualDirectory, options?: ListDirOptions): Promise<(VirtualDirectory|VirtualFile)[]>;
}
export class MountedFs implements Fs {
private filesystems: Map<string, FileSystemSource<any>> = new Map();
public readonly name: string = 'root';
constructor(filesystems: (Config<NginxFS> | Config<FileStashFs>)[]) {
for (const fsOptions of filesystems) {
if (fsOptions.type === 'nginx') {
this.filesystems.set(fsOptions.name, new NginxFS(fsOptions));
} else if (fsOptions.type === 'filestash') {
this.filesystems.set(fsOptions.name, new FileStashFs(fsOptions));
}
}
}
get root() {
return [...this.filesystems.values()].map(fs => fs.root);
}
download(file: VirtualFile) {
const fs = this.filesystems.get(file.source);
if (!fs) {
throw new Error(`Filesystem ${file.source} not found`);
}
return fs.download(file);
}
async listDir(dir: VirtualDirectory, options?: ListDirOptions) {
const fs = this.filesystems.get(dir.source);
if (!fs) {
throw new Error(`Filesystem ${dir.source} not found`);
}
const result = await fs.listDir(dir, options);
return result;
}
async *search(query: string, cancelToken?: AbortSignal) {
query = query.toLocaleLowerCase();
for (const fs of this.filesystems.values()) {
const dirQueue = [fs.root];
while (dirQueue.length > 0) {
const dir = dirQueue.shift()!;
try {
const children = await this.listDir(dir, {cache: CachePolicy.onlyCache});
for (const child of children) {
if (cancelToken?.aborted) {
return;
}
if (child.type === 'directory') {
dirQueue.push(child);
} else if (child.name.toLocaleLowerCase().includes(query)) {
yield child;
}
}
} catch (err) {
if (!(err instanceof NoCacheEntryError)) {
console.warn(`Failed to list directory ${dir.path.join('/')}`, err);
}
continue;
}
}
}
}
async *buildIndex() {
let counter = 0;
for (const fs of this.filesystems.values()) {
const dirQueue = [fs.root];
while (dirQueue.length > 0) {
const dir = dirQueue.shift()!;
for (const child of await this.listDir(dir)) {
if (child.type === 'directory') {
dirQueue.push(child);
}
counter++;
}
yield counter
}
}
}
}
// export class SearchableFilesystem implements Fs {
// public allFiles: VirtualFile[] = [];
// constructor(private fs: MountedFs) {}
// async precacheDir(dir: VirtualDirectory) {
// for (const child of await this.fs.listDir(dir, {cache: CachePolicy.useCache})) {
// if (child.type === 'file') {
// this.allFiles.push(child);
// } else {
// await this.precacheDir(child as VirtualDirectory);
// }
// }
// }
// async search(query: string) {
// await Promise.all(this.fs.root.map((root) => this.precacheDir(root)));
// }
// get root() {
// return this.fs.root;
// }
// async listDir(dir: VirtualDirectory) {
// return this.fs.listDir(dir);
// }
// async download(file: VirtualFile) {
// return this.fs.download(file);
// }
// }