nikuda-store is a local, content-addressed store for immutable files, text,
and byte arrays. It deduplicates content chunks and keeps a small SQLite
catalog.
The package is ESM-only and requires Node.js 18 or newer.
npm install nikuda-storeimport{createStore}from'nikuda-store';conststore=createStore({root: './data'});constfileId=awaitstore((connection)=>connection.create({type: 'text',text: 'Hello store!'}));awaitstore(async(connection)=>{awaitconnection.setRoot(fileId);constbytes=awaitconnection.readBytesRoot();console.log(Buffer.from(bytes).toString('utf8'));});createStore returns a context function. Each callback opens the store,
provides a connection, and closes the underlying database when the callback
finishes, including when it throws.
create accepts text, bytes, paths, and Node.js readable streams:
awaitstore(async(connection)=>{awaitconnection.create({type: 'path',path: './document.pdf'});awaitconnection.create({type: 'bytes',bytes: newUint8Array([1,2,3])});});The available source shapes are:
typeContentSource=|{type: 'path';path: string}|{type: 'bytes';bytes: Uint8Array}|{type: 'text';text: string;encoding?: 'utf-8'}|{type: 'stream';stream: NodeJS.ReadableStream};readBytes reads a file into memory. Use read for large content:
awaitstore(async(connection)=>{conststream=awaitconnection.read(fileId);forawait(constchunkofstream){// Process each chunk.}});The optional readBytesLimit prevents accidentally loading large files into
memory:
conststore=createStore({root: './data',readBytesLimit: 16*1024*1024});The default limit is 64 MiB. It applies to readBytes and readBytesRoot, not
to read or readRoot.
One stored file can be assigned as the global root:
awaitstore(async(connection)=>{constfileId=awaitconnection.create({type: 'text',text: 'root'});awaitconnection.setRoot(fileId);constrootBytes=awaitconnection.readBytesRoot();});Every root assignment is appended to the store's global metadata. The public API only exposes the current root for reading.
The package exports:
createStore(options)FileStoreContentSourceCreateFileStoreOptionsFileIdFileRecord
The connection API is intentionally small:
interfaceFileStore{create(content: ContentSource): Promise<FileId>;read(fileId: FileId): Promise<NodeJS.ReadableStream>;readBytes(fileId: FileId): Promise<Uint8Array>;listFiles(): Promise<readonlyFileRecord[]>;setRoot(fileId: FileId): Promise<void>;readRoot(): Promise<NodeJS.ReadableStream>;readBytesRoot(): Promise<Uint8Array>;}The configured root contains the SQLite catalog and content-addressed objects. Keep the entire root together when backing up or moving a store. Do not modify its files while a store operation is running.