UNPKG

@orbitdb/ordered-keyvalue-db

Version:

Ordered keyvalue database type for orbit-db.

125 lines 4.04 kB
import { Database, } from "@orbitdb/core"; const type = "ordered-keyvalue"; const OrderedKeyValue = () => async ({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate, }) => { const database = await Database({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate, }); const { addOperation, log } = database; const put = async (key, value, position) => { const entryValue = { value, }; if (position !== undefined) { entryValue.position = position; } return addOperation({ op: "PUT", key, value: entryValue }); }; const move = async (key, position) => { return addOperation({ op: "MOVE", key, value: position }); }; const del = async (key) => { return addOperation({ op: "DEL", key, value: null }); }; const get = async (key) => { for await (const entry of log.traverse()) { const { op, key: k, value } = entry.payload; if (op === "PUT" && k === key) { return value; } else if (op === "DEL" && k === key) { return undefined; } } return undefined; }; const iterator = async function* ({ amount, } = {}) { let count = 0; const orderedLogEntries = []; for await (const entry of log.traverse()) { orderedLogEntries.unshift(entry); } let finalEntries = []; for (const entry of orderedLogEntries) { const { op, key, value } = entry.payload; if (!key) return; if (op === "PUT") { finalEntries = finalEntries.filter((e) => e.key !== key); const putValue = value; const hash = entry.hash; const position = putValue.position !== undefined ? putValue.position : -1; finalEntries.push({ key, value: putValue.value, position, hash, }); count++; } else if (op === "MOVE") { const existingEntry = finalEntries.find((e) => e.key === key); if (existingEntry) { existingEntry.position = value; finalEntries = [ ...finalEntries.filter((e) => e.key !== key), existingEntry, ]; } } else if (op === "DEL") { finalEntries = finalEntries.filter((e) => e.key !== key); } if (amount !== undefined && count >= amount) { break; } } // This is memory inefficient, but I haven't been able to think of a more elegant solution for (const entry of finalEntries) { yield entry; } }; const all = async () => { const entries = []; for await (const entry of iterator()) { entries.push(entry); } const values = []; for (const entry of entries) { const position = entry.position >= 0 ? entry.position : entries.length + entry.position + 1; values.splice(position, 0, { key: entry.key, value: entry.value, hash: entry.hash, }); } return values; }; return { ...database, type, put, set: put, // Alias for put() del, move, get, iterator, all, }; }; OrderedKeyValue.type = type; export default OrderedKeyValue; //# sourceMappingURL=ordered-keyvalue.js.map