0.2.0 • Published 3 years ago
@canvas-js/okra-browser v0.2.0
@canvas-js/okra-browser
Pure JS/IndexedDB okra implementation.
Table of Contents
Installation
npm i @canvas-js/okra-browserimport * as okra from "@canvas-js/okra-browser"
const tree = await okra.Tree.open("example")
const toHex = (hash) => ([...hash]).map((byte) => byte.toString(16).padStart(2, "0")).join("")
// all reads and writes take place within transaction callbacks
await tree.read(async (txn) => {
const root = await txn.getRoot();
console.log(root) // Object { level: 0, key: null, hash: Uint8Array(16) }
console.log(toHex(root.hash)) // af1349b9f5f9a1a6a0404dea36dcc949
})
const encoder = new TextEncoder()
await tree.write(async (txn) => {
await txn.set(encoder.encode("a"), encoder.encode("foo"))
await txn.set(encoder.encode("b"), encoder.encode("bar"))
await txn.set(encoder.encode("c"), encoder.encode("baz"))
const root = await txn.getRoot();
console.log(root) // Object { level: 1, key: null, hash: Uint8Array(16) }
console.log(toHex(root.hash)) // 6246b94074d09feb644be1a1c12c1f50
})API
The basic interfaces are Tree, ReadOnlyTransaction, and ReadWriteTransaction. Trees and transactions form a classical key/value store interface: you can open a tree, use the tree.read((txn) => { ... }) and tree.write((txn) => { ... }) callbacks to open managed transactions, and use the transaction to get, set, and delete key/value entries. Don't create or close transactions directly.
Transactions also have getRoot, getNode, and getChildren methods to access the internal merkle tree. These methods return Node objects. node.key === null for anchor nodes, and node.value === undefined if level > 0 || key === null.
class Tree<T = Uint8Array> {
public static open<T = Uint8Array>(
name: string,
options?: { dbs?: string[]; getID?: (value: T) => Uint8Array },
): Promise<Tree<T>>;
// Open a read-only transaction. Acquires a shared lock that is released when the callback resolves.
public read<R = void>(
callback: (txn: ReadOnlyTransaction<T>) => Promise<R> | R,
options?: { dbi?: string },
): Promise<R>;
// Open a read-write transaction. Acquire an exclusive lock that is released when the callback resolves.
public write<R = void>(
callback: (txn: ReadWriteTransaction<T>) => Promise<R> | R,
options?: { dbi?: string },
): Promise<R>;
public close(): void;
}Transactions
type Node<T = Uint8Array> = {
level: number;
key: Key;
hash: Uint8Array;
value?: T;
};interface ReadOnlyTransaction<T> {
// get a leaf key/value entry
public get(key: Uint8Array): Promise<T | null>
// get internal merkle tree nodes
public getRoot(): Promise<Node<T>>
public getNode(level: number, key: Key): Promise<Node>
public getChildren(level: number, key: Key): Promise<Node<T>[]>
public seek(level: number, key: Key): Promise<Node<T> | null>
}
interface ReadWriteTransaction<T> extends ReadOnlyTransaction<T> {
// set a leaf key/value entry
public set(key: Uint8Array, value: T): Promise<void>
// delete a leaf key/value entry
public delete(key: Uint8Array): Promise<void>
}