Rebasely Beta: data may be purged

examples/storefront Public

TypeScript · 51 lines · 1.8 KiB · at 8b37e66

// An R2 stand-in kept in memory: put, get, head, delete, and the parts of R2Object the// storefront reads (body, httpEtag, httpMetadata, writeHttpMetadata).type Stored = { bytes: Uint8Array; httpMetadata: R2HTTPMetadata; etag: string };export class TestR2 {  readonly objects = new Map<string, Stored>();  async put(key: string, value: ArrayBuffer | ArrayBufferView | string, options: R2PutOptions = {}) {    const bytes = typeof value === "string" ? new TextEncoder().encode(value) : new Uint8Array(ArrayBuffer.isView(value) ? value.buffer : value);    const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));    const etag = [...digest.slice(0, 16)].map((b) => b.toString(16).padStart(2, "0")).join("");    this.objects.set(key, { bytes, httpMetadata: (options.httpMetadata ?? {}) as R2HTTPMetadata, etag });    return this.view(key)!;  }  async head(key: string) {    return this.view(key);  }  async get(key: string) {    const v = this.view(key);    if (!v) return null;    const bytes = this.objects.get(key)!.bytes;    return { ...v, body: new Blob([bytes]).stream() };  }  async delete(keys: string | string[]) {    for (const k of Array.isArray(keys) ? keys : [keys]) this.objects.delete(k);  }  private view(key: string) {    const o = this.objects.get(key);    if (!o) return null;    return {      key,      size: o.bytes.byteLength,      etag: o.etag,      httpEtag: `"${o.etag}"`,      httpMetadata: o.httpMetadata,      writeHttpMetadata(headers: Headers) {        if (o.httpMetadata.contentType) headers.set("content-type", o.httpMetadata.contentType);        if (o.httpMetadata.cacheControl) headers.set("cache-control", o.httpMetadata.cacheControl);      },    };  }}export function testBucket(): R2Bucket {  return new TestR2() as unknown as R2Bucket;}