UNPKG

@x5e/gink

Version:

an eventually consistent database

126 lines (117 loc) 4.98 kB
/** * This file contains functions that need to construct generic Containers or convert from a * container of runtime determined type to something else. Typescript has problems with * imports if two classes depend on each other so these functions have been pulled out into * something neither Container nor any of its subclasses need directly. */ import { Muid, Value, AsOf, Entry } from "./typedefs"; import { Container } from "./Container"; import { Directory } from "./Directory"; import { Sequence } from "./Sequence"; import { Box } from "./Box"; import { Group } from "./Group"; import { PairSet } from "./PairSet"; import { PairMap } from "./PairMap"; import { KeySet } from "./KeySet"; import { Database } from "./Database"; import { valueToJson, muidTupleToMuid, rehydrate } from "./utils"; import { Behavior, ContainerBuilder } from "./builders"; import { Property } from "./Property"; import { Vertex } from "./Vertex"; import { EdgeType } from "./EdgeType"; import { Accumulator } from "./Accumulator"; // TODO: maybe make address the first argument, and then database second and optional export async function construct( address: Muid, database?: Database, containerBuilder?: ContainerBuilder, ): Promise<Container | null> { if (database === undefined) { database = Database.recent; } if (address.timestamp === -1) { if (address.offset === Behavior.DIRECTORY) return Directory.get(database, address); if (address.offset === Behavior.SEQUENCE) return Sequence.get(database, address); if (address.offset === Behavior.BOX) return Box.get(database, address); if (address.offset === Behavior.PAIR_MAP) return PairMap.get(database, address); if (address.offset === Behavior.PAIR_SET) return PairSet.get(database, address); if (address.offset === Behavior.KEY_SET) return KeySet.get(database, address); if (address.offset === Behavior.GROUP) return Group.get(database, address); if (address.offset === Behavior.PROPERTY) return Property.get(database, address); if (address.offset === Behavior.VERTEX) return Vertex.get(database, address); if (address.offset === Behavior.ACCUMULATOR) return Accumulator.get(database, address); } if (containerBuilder === undefined) { const containerBytes = await database.store.getContainerBytes(address); if (!containerBytes) { return null; } containerBuilder = <ContainerBuilder>( ContainerBuilder.deserializeBinary(containerBytes) ); } if (containerBuilder.getBehavior() === Behavior.BOX) return Box.get(database, address); if (containerBuilder.getBehavior() === Behavior.SEQUENCE) return Sequence.get(database, address); if (containerBuilder.getBehavior() === Behavior.KEY_SET) return KeySet.get(database, address); if (containerBuilder.getBehavior() === Behavior.DIRECTORY) return Directory.get(database, address); if (containerBuilder.getBehavior() === Behavior.PAIR_SET) return PairSet.get(database, address); if (containerBuilder.getBehavior() === Behavior.PAIR_MAP) return PairMap.get(database, address); if (containerBuilder.getBehavior() === Behavior.VERTEX) return Vertex.get(database, address); if (containerBuilder.getBehavior() === Behavior.EDGE_TYPE) return EdgeType.get(database, address); if (containerBuilder.getBehavior() === Behavior.PROPERTY) return Property.get(database, address); if (containerBuilder.getBehavior() === Behavior.GROUP) return Group.get(database, address); if (containerBuilder.getBehavior() === Behavior.ACCUMULATOR) return Accumulator.get(database, address); throw new Error( `container type not recognized/implemented: ${containerBuilder.getBehavior()}`, ); } export async function interpret( entry: Entry, database: Database, ): Promise<Container | Value | undefined> { if (entry === undefined || entry.deletion) { return undefined; } if (entry.value !== undefined) return entry.value; if (entry.pointeeList.length > 0) { const muid: Muid = rehydrate(entry.pointeeList[0]); return construct(muid, database); } if (Array.isArray(entry.storageKey) && entry.storageKey.length === 3) { // For a MuidTuple effective key return await construct(muidTupleToMuid(entry.storageKey), database); } throw new Error( `don't know how to interpret entry: ${JSON.stringify(entry)}`, ); } export async function toJson( value: Value | Container, indent: number | boolean = false, asOf?: AsOf, seen?: Set<string>, ): Promise<string> { return value instanceof Container ? await value.toJson(indent, asOf, seen) : valueToJson(value); }