107 lines
2.5 KiB
TypeScript
107 lines
2.5 KiB
TypeScript
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<NginxFsConfig> {
|
|
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<NginxFile | NginxDirectory>;
|
|
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<File> {
|
|
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 });
|
|
}
|
|
|
|
async downloadThumbnail(file: VirtualFile): Promise<File> {
|
|
return this.download(file);
|
|
}
|
|
|
|
getConfig() {
|
|
return {
|
|
...this.options,
|
|
type: "nginx",
|
|
} as const;
|
|
}
|
|
}
|
|
|