import { extensionMimeType } from "../FileMeta/ExtensionMimeType"; import { FileSystemSource, VirtualFile, VirtualDirectory } from "./types"; export type NginxFsConfig = { name: string; rootUrl: string; auth?: { username: string; password: string; }; } type DateString = string & {}; interface NginxFile { name: string; type: 'file' mtime: DateString; size: number; } interface NginxDirectory { name: string; type: 'directory'; mtime: DateString; } export class NginxFS implements FileSystemSource { constructor(private options: NginxFsConfig) {} get name() { return this.options.name; } get root():VirtualDirectory { return { type: 'directory', source: this.options.name, path: [], name: this.options.name } } private get sanitizedRootUrl() { return this.options.rootUrl.endsWith("/") ? this.options.rootUrl : this.options.rootUrl + "/"; } private get authHeaders(): {Authorization: string}|{} { return this.options.auth ? { Authorization: `Basic ${btoa(`${this.options.auth.username}:${this.options.auth.password}`)}` } : {} } async listDir(dir: VirtualDirectory): Promise<(VirtualDirectory|VirtualFile)[]> { const response = await fetch(`${this.sanitizedRootUrl}${dir.path.map((x) => `${x}/`).join("")}`, { headers: { ...this.authHeaders, } }); if (!response.ok) { console.error("Failed to list directory", response); return []; } const data = await response.json() as Array; return data.map((item) => { if (item.type === "directory") { return { type: "directory", source: this.options.name, path: [...dir.path, item.name], name: item.name } } else { return { type: "file", source: this.options.name, path: [...dir.path, item.name], name: item.name, mimeType: extensionMimeType(item.name), } } }); } async download(file: VirtualFile): Promise { const response = await fetch(`${this.sanitizedRootUrl}${file.path.join("/")}`); if (!response.ok) { throw new Error("Failed to download file"); } return new File([await response.blob()], file.name, { type: file.mimeType }); } getConfig() { return { ...this.options, type: "nginx", } as const; } }