1
0
silverbullet/common/spaces/deno_kv_space_primitives.ts
2023-08-20 17:51:00 +02:00

84 lines
2.2 KiB
TypeScript

/// <reference lib="deno.unstable" />
import { FileMeta } from "$sb/types.ts";
import type { SpacePrimitives } from "./space_primitives.ts";
import { mime } from "https://deno.land/x/mimetypes@v1.0.0/mod.ts";
export class DenoKVSpacePrimitives implements SpacePrimitives {
private kv!: Deno.Kv;
private dataAttribute = "file";
private metaAttribute = "meta";
async init(path?: string) {
this.kv = await Deno.openKv(path);
}
close() {
this.kv.close();
}
async fetchFileList(): Promise<FileMeta[]> {
const results: FileMeta[] = [];
for await (
const result of this.kv.list({
prefix: [this.metaAttribute],
})
) {
results.push(result.value as FileMeta);
}
return results;
}
async readFile(name: string): Promise<{ data: Uint8Array; meta: FileMeta }> {
const [meta, data] = await this.kv.getMany([[this.metaAttribute, name], [
this.dataAttribute,
name,
]]);
if (!meta.value) {
throw new Error("Not found");
}
return {
data: data.value as Uint8Array,
meta: meta.value as FileMeta,
};
}
async getFileMeta(name: string): Promise<FileMeta> {
const result = await this.kv.get([this.metaAttribute, name]);
if (result.value) {
return result.value as FileMeta;
} else {
throw new Error("Not found");
}
}
async writeFile(
name: string,
data: Uint8Array,
_selfUpdate?: boolean | undefined,
suggestedMeta?: FileMeta | undefined,
): Promise<FileMeta> {
const meta: FileMeta = {
name,
lastModified: suggestedMeta?.lastModified || Date.now(),
contentType: mime.getType(name) || "application/octet-stream",
size: data.byteLength,
perm: suggestedMeta?.perm || "rw",
};
const res = await this.kv.atomic()
.set([this.dataAttribute, name], data)
.set([this.metaAttribute, name], meta)
.commit();
if (!res.ok) {
throw res;
}
return meta;
}
async deleteFile(name: string): Promise<void> {
const res = await this.kv.atomic()
.delete([this.dataAttribute, name])
.delete([this.metaAttribute, name])
.commit();
if (!res.ok) {
throw res;
}
}
}