# chunk-keys ## Purpose Implements the `chunk-keys` layout strategy that stores each chunk under a discrete storage key (`chunks//`). This is the simplest layout — every chunk is a separate `set/get` operation, no preallocation, no offset arithmetic — and it works on any `DriveStorage` whose `set` and `list` methods are implemented. ## Features - `createChunkKeysLayout(storage): ChunkLayout` — factory returning a `ChunkLayout` with `name: "chunk-keys"`. - `putChunk(fileId, chunkId, rawBytes)` — single `storage.set` call. - `getChunk(fileId, chunkId)` — single `storage.get` call returning `undefined` for missing chunks (no error). - `hasChunks(fileId)` — returns a sparse `boolean[]` indexed by chunkId, derived from `storage.list({ prefix })`. - `availableChunks(fileId)` — flattens `hasChunks` into the list of present indices. ## Usage: Basic Example ```ts import { Drive } from "@suaveplan/drive"; import { chunksPlugin } from "@suaveplan/drive-plugin-chunks"; import { MemoryStorage } from "@suaveplan/storage/memory"; const storage = Object.assign(new MemoryStorage(), { id: "default" }); const drive = new Drive(storage); await drive.initialize(); const chunks = await drive.usePlugin( chunksPlugin({ serverPrivKey, serverPubKey, layout: "chunk-keys" }) ); ``` ## Usage: Advanced Example ```ts import { createChunkKeysLayout } from "@suaveplan/drive-plugin-chunks"; const layout = createChunkKeysLayout(storage); await layout.putChunk(fileId, 0, raw); const present = await layout.hasChunks(fileId); const available = await layout.availableChunks(fileId); console.log(`have ${available.length}/${present.length}`); ``` ## API Reference - `createChunkKeysLayout(storage: DriveStorage): ChunkLayout`. - `ChunkLayout.name === "chunk-keys"`. - `putChunk(fileId, chunkId, rawBytes): Promise`. - `getChunk(fileId, chunkId): Promise`. - `hasChunks(fileId): Promise` — `bits.length === maxChunkId + 1`; uses `-1` sentinel when no chunks exist (yields empty array). - `availableChunks(fileId): Promise`. ## Implementation Notes The `hex` helper formats `fileId` to lowercase hex with leading zeros, identical to the formatting in `plugin.ts` so stored chunks remain addressable across plugin and layout boundaries. `hasChunks` uses `storage.list({ prefix })` once and then computes the bit array client-side, which is O(n) over present chunks and avoids `n` storage round trips. Missing chunks correspond to `false` slots in the bit array; gaps are explicit, not implicit.