FlureeStore — Fluree time-travel ledger (HTTP/JSON)
Read this page in the documentation
FlureeStore — Fluree time-travel ledger (HTTP/JSON) Overview Fluree is an immutable, time-travel ledger database: every transaction is appended as a set of cryptographically-hashed "flakes" into a blockchain-like log, so no data is ever overwritten and any past state (by block or time) is queryable. It speaks a JSON query/transaction API (FlureeQL) over HTTP, not SQL. Fluree is not a SQL Dialect, so FlureeStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch — plus the shared ledger surface (append/get/history/verify/query). Identity: Property | Value | --------- | ---------- | name | 'fluree' | library | 'fetch' | No canonical driver — HTTP over fetch Fluree has no single canonical npm client; it is an HTTP/JSON API. Rather than a lazy-required driver, this store talks to the server with the global fetch — so library === 'fetch' — via a tiny FlureeHttpClient (a single post(path, body) method returning parsed JSON). connect() builds a fetch-backed client with createFlureeFetchClient(baseURL, headers); there is no external package to install. The fetch client POSTs JSON (Content-Type: application/json plus any configured headers) and throws Error("HTTP <status> <statusText>") on a non-OK response. Injected client FlureeStoreOptions accepts a pre-built client (any FlureeHttpClient). When provided, connect() uses it directly and baseURL is ignored. This is how the test suite injects an in-memory mock client (no network) that records each POST and returns canned responses. Connection Build a store from connection options and call connect(). A ledger name is required — the constructor throws a DatabaseError (code: 'INVALIDCONNECTION') without one. Option | Type | Purpose | --------- | ------------------------ | ----------------------------------------------------------------------- | ledger | string | Required. Ledger (network/db) name, e.g. 'my/ledger'. | baseURL | string | Fluree server base URL. Defaults to 'http://localhost:8090'. Ignored when client is provided. | headers | Record<string, string> | Extra HTTP headers (e.g. an auth bearer). | client | FlureeHttpClient | A pre-built HTTP client. When set, baseURL is ignored. | Injected-client form Methods Every ledger method POSTs to /fdb/<ledger>/<op> and wraps failures in a DatabaseError (via DatabaseError.from, prefixing the message with the failing action). Using any method before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | ------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Uses an injected client if provided, otherwise builds a fetch-backed client from baseURL/headers. Idempotent. | disconnect | disconnect(): Promise<void> | Clears the client and connected state (no network call). | isConnected | isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): FlureeHttpClient | Returns the underlying (internal or injected) HTTP client. Throws ConnectionError if not connected. | Ledger surface Method | Signature | HTTP endpoint | Request body | ---------- | -------------------------------------------------------------- | -------------------------------- | -------------------------------------------------------------- | append | append(collection: string, data: Record<string, unknown>): Promise<unknown> | POST /fdb/<ledger>/transact | [{ id: collection, ...data }] — returns the transaction response (block, flakes, temp-id map, block hash). | get | get(collection: string, id: string \| number): Promise<unknown> | POST /fdb/<ledger>/query | { select: [''], from: [['<collection>/id', id]] } | history | history(collection: string, id: string \| number): Promise<unknown> | POST /fdb/<ledger>/history | { history: [['<collection>/id', id]] } | verify | verify(collection: string, id: string \| number): Promise<unknown> | POST /fdb/<ledger>/history | { history: [['<collection>/id', id]], meta: true } — the meta flag returns block metadata (hash + instant) that anchors each revision. | query | query(flureeql: unknown): Promise<unknown> | POST /fdb/<ledger>/query | the raw FlureeQL query object, verbatim. | transact | transact(transaction: unknown): Promise<unknown> | POST /fdb/<ledger>/transact | the raw FlureeQL transaction, verbatim. | Note: verify returns the flake history with block metadata (meta: true) — the block hash is the tamper-evidence proof. The store does not itself re-derive or check that hash. Example Verification status Unit / mock-verified only. The tests in tests/nosql/fluree.test.ts inject an in-memory mock FlureeHttpClient via FlureeStoreOptions.client, so no network is touched. The mock records every POST (path + body) and returns canned responses. What this proves: Each method POSTs to the correct endpoint (/fdb/my/db/transact, .../query, .../history) with the exact body shape ([{ id, ...data }], { select, from }, { history }, { history, meta: true }, or the raw query verbatim). Responses are returned to the caller unchanged. Lifecycle: isConnected() false before connect(), connecting via injected client, disconnect(), and ConnectionError from getClient() / reads before connect(). Constructor requires a ledger; error handling wraps client failures in DatabaseError. What this does not prove: live execution against a real Fluree server, or the correctness of the block-hash tamper-evidence proof. The request/response shape is verified against Fluree's documented HTTP contract, but execution over the wire has not been exercised here. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories