0.1.3•Updated 17 days ago
import { join } from "https://deno.land/std@0.216.0/path/mod.ts";
import { existsSync } from "https://deno.land/std@0.216.0/fs/mod.ts";
import { AssetStoreBase, type FileStats, type UploadableDataTypes } from "./asset_store_base.ts";
export interface FileStoreOptions {
root_path: string
}
export class FileStore extends AssetStoreBase {
readonly root_path: string
constructor(namespace: string, options: FileStoreOptions) {
super(namespace);
this.root_path = options.root_path;
}
private cleaned_key(key: string) {
if(key.includes('../')) throw new Error("Can't traverse upwards in a file store");
return this.stripped_key(key);
}
override Get(key: string) {
key = this.cleaned_key(key);
const path = join(this.root_path, key);
if(this.cache.has(key)) return this.cache.get(key);
if(!existsSync(path, { isFile: true })) return null;
return this.cache.set(key, Deno.readFileSync(path).buffer);
}
override async Upload(key: string, data: UploadableDataTypes) {
key = this.cleaned_key(key);
const path = join(this.root_path, key);
const array_buffer = await this.ToArrayBuffer(key, data);
if(existsSync(path, { isDirectory: true })) return this.namespaced_key(key);
if(array_buffer) Deno.writeFileSync(path, new Uint8Array(array_buffer));
return this.namespaced_key(key);
}
override Info(key: string): FileStats | Promise<FileStats> {
key = this.cleaned_key(key);
const path = join(this.root_path, key);
if(!existsSync(path)) return {
size: 0,
etag: key,
lastModified: new Date(0),
type: "null"
};
const stats = Deno.statSync(path);
return {
size: stats.size,
lastModified: stats.mtime!,
type: "file",
etag: stats.uid!.toString()
}
}
override Delete(key: string): void | Promise<void> {
key = this.cleaned_key(key);
const path = join(this.root_path, key);
if(!existsSync(path, { isFile: true })) return;
Deno.removeSync(path);
}
};