import type { DriveStorage } from "@suaveplan/drive"; import type { ChunkLayout } from "../types/chunks.types.js"; export function createChunkKeysLayout(storage: DriveStorage): ChunkLayout { return { name: "chunk-keys", async putChunk(fileId, chunkId, rawBytes) { const key = chunkKey(fileId, chunkId); await storage.set(key, rawBytes); }, async getChunk(fileId, chunkId) { const key = chunkKey(fileId, chunkId); return storage.get(key); }, async hasChunks(fileId) { const prefix = `chunks/${hex(fileId)}/`; const result = await storage.list({ prefix }); const maxChunkId = result.keys.reduce( (max: number, key: string) => { const id = Number.parseInt(key.slice(prefix.length), 10); return Math.max(max, id); }, -1 ); const bits = new Array(maxChunkId + 1).fill(false); for (const key of result.keys) { const id = Number.parseInt(key.slice(prefix.length), 10); bits[id] = true; } return bits; }, async availableChunks(fileId) { const bits = await this.hasChunks(fileId); const ids: number[] = []; for (let i = 0; i < bits.length; i++) { if (bits[i]) ids.push(i); } return ids; }, }; } function chunkKey(fileId: Uint8Array, chunkId: number): string { return `chunks/${hex(fileId)}/${chunkId}`; } function hex(bytes: Uint8Array): string { return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(""); }