staticql
Version:
Type-safe query engine for static content including Markdown, YAML, JSON, and more.
95 lines (94 loc) • 2.78 kB
JavaScript
/**
* R2Repository: A StorageRepository implementation for Cloudflare R2.
*/
export class R2Repository {
constructor(bucket, prefix) {
this.bucket = bucket;
this.prefix = prefix;
}
/**
* Adds a namespace prefix to keys (if specified).
*/
buildKey(key) {
return this.prefix ? `${this.prefix}/${key}` : key;
}
/**
* Lists file paths in the R2 bucket under a given prefix.
*
* Supports wildcard patterns by trimming after `*`.
*
* @param prefix - Path prefix or glob (e.g. "content/*.md").
* @returns Sorted list of matching object keys.
*/
async listFiles(prefix) {
const path = prefix.replace(/\*.*$/, "");
const list = await this.bucket.list({ prefix: path });
return list.objects.map((obj) => obj.key).sort();
}
/**
* Reads the content of a file from R2.
*
* @param path - Key within the bucket.
* @returns File content as string; empty string if not found.
*/
async readFile(path) {
const fullKey = this.buildKey(path);
const object = await this.bucket.get(fullKey);
if (!object)
return "";
return await object.text();
}
/**
* Opens a file as a ReadableStream from Cloudflare R2.
*
* @param path - Key within the bucket.
* @returns ReadableStream of the file contents.
* @throws Error if the object does not exist.
*/
async openFileStream(path) {
const fullKey = this.buildKey(path);
const object = await this.bucket.get(fullKey);
if (!object || !object.body) {
throw new Error(`Object not found: ${fullKey}`);
}
return object.body;
}
/**
* Writes data to the R2 bucket.
*
* @param path - Key to write.
* @param data - Content to write.
*/
async writeFile(path, data) {
const fullKey = this.buildKey(path);
await this.bucket.put(fullKey, data);
}
/**
* Checks if the specified file exists in the R2 bucket.
*
* @param path - Key to check.
* @returns `true` if it exists, `false` otherwise.
*/
async exists(path) {
const object = await this.bucket.get(this.buildKey(path));
return object !== null;
}
/**
* Deletes the specified file from the R2 bucket.
*
* @param path - Key to delete.
*/
async removeFile(path) {
const fullKey = this.buildKey(path);
await this.bucket.delete(fullKey);
}
/**
* Deletes the specified file from the R2 bucket.
*
* @param path - Key to delete.
*/
async removeDir(path) {
const fullKey = this.buildKey(path);
await this.bucket.delete(fullKey);
}
}