first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
# chunk-keys
## Purpose
Implements the `chunk-keys` layout strategy that stores each chunk under a discrete storage key (`chunks/<fileIdHex>/<chunkId>`). 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<void>`.
- `getChunk(fileId, chunkId): Promise<Uint8Array | undefined>`.
- `hasChunks(fileId): Promise<boolean[]>` — `bits.length === maxChunkId + 1`; uses `-1` sentinel when no chunks exist (yields empty array).
- `availableChunks(fileId): Promise<number[]>`.
## 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.