new maps

This commit is contained in:
2024-11-24 17:34:41 +00:00
parent eb6abbb97d
commit 641938f7e4
38 changed files with 1241 additions and 228 deletions

View File

@@ -1,3 +1,4 @@
import { CancellationToken } from "typescript";
import { extensionMimeType } from "../FileMeta/ExtensionMimeType";
import { CachePolicy, FsCache } from "./FsCache";
import { VirtualDirectory, VirtualFile, FileSystemSource, ListDirOptions } from "./types";
@@ -40,13 +41,16 @@ export class FileStashFs implements FileSystemSource<FileStashFsConfig> {
}
}
private createUrl(type: 'cat' | 'ls', path: string[]) {
private createUrl(type: 'cat' | 'ls', path: string[], query: Record<string, string> = {}) {
const url = new URL(this.options.domain);
url.pathname = `/api/files/${type}`;
const params = new URLSearchParams();
params.set('share', this.options.share);
params.set('key', this.options.key);
params.set('path', `/${path.join('/')}`);
for (const [key, value] of Object.entries(query)) {
params.set(key, value);
}
url.search = params.toString();
return url;
}
@@ -80,15 +84,46 @@ export class FileStashFs implements FileSystemSource<FileStashFsConfig> {
} else {
throw new Error(`Unknown type ${result.type}`);
}
}).sort((a, b) => {
if (a.type === 'file' && b.type === 'directory') {
return 1;
} else if (a.type === 'directory' && b.type === 'file') {
return -1;
} else if (a.name < b.name) {
return -1;
} else if (a.name > b.name) {
return 1;
}
return 0;
});
}
async download(file: VirtualFile): Promise<File> {
const response = await fetch(this.createUrl('cat', file.path));
async download(file: VirtualFile, {abortSignal}: {abortSignal?: AbortSignal} = {}): Promise<File> {
const response = await fetch(this.createUrl('cat', file.path), {signal: abortSignal});
if (!response.ok) {
throw new Error(`Failed to download file ${file.path.join('/')}`);
}
return new File([await response.blob()], file.name);
return new File([await response.blob()], file.name, {type: file.mimeType});
}
async downloadThumbnail(file: VirtualFile, {abortSignal}: {abortSignal?: AbortSignal} = {}): Promise<File> {
try {
const abortSignals = [AbortSignal.timeout(1000)]
if (abortSignal) {
abortSignals.push(abortSignal);
}
const response = await fetch(this.createUrl('cat', file.path, {thumbnail: 'true'}), {
signal: AbortSignal.any(abortSignals),
});
if (!response.ok) {
throw new Error(`Failed to download file ${file.path.join('/')}`);
}
return new File([await response.blob()], file.name, {type: file.mimeType});
} catch (err) {
if (err !== 'User canceled') {
return this.download(file, {abortSignal});
}
}
}
getConfig() {

View File

@@ -9,6 +9,7 @@ const CACHE = Symbol('Cache');
export interface Fs {
get root(): VirtualDirectory[];
download(file: VirtualFile): Promise<File>;
downloadThumbnail(file: VirtualFile): Promise<File>;
listDir(dir: VirtualDirectory, options?: ListDirOptions): Promise<(VirtualDirectory|VirtualFile)[]>;
}
@@ -38,6 +39,14 @@ export class MountedFs implements Fs {
return fs.download(file);
}
downloadThumbnail(file: VirtualFile, {abortSignal}: {abortSignal?: AbortSignal} = {}) {
const fs = this.filesystems.get(file.source);
if (!fs) {
throw new Error(`Filesystem ${file.source} not found`);
}
return fs.downloadThumbnail(file, {abortSignal});
}
async listDir(dir: VirtualDirectory, options?: ListDirOptions) {
const fs = this.filesystems.get(dir.source);

View File

@@ -92,6 +92,10 @@ export class NginxFS implements FileSystemSource<NginxFsConfig> {
return new File([await response.blob()], file.name, { type: file.mimeType });
}
async downloadThumbnail(file: VirtualFile): Promise<File> {
return this.download(file);
}
getConfig() {
return {
...this.options,

View File

@@ -4,6 +4,7 @@ export interface FileSystemSource<TOptions> {
root: VirtualDirectory;
listDir(dir: VirtualDirectory, options?: ListDirOptions): Promise<(VirtualDirectory|VirtualFile)[]>;
download(file: VirtualFile): Promise<File>;
downloadThumbnail(file: VirtualFile, options?: {abortSignal?: AbortSignal}): Promise<File>;
getConfig(): TOptions & { type: string };
}