dbinspect_hive

A Hive adapter for dbinspect_bridge, so a desktop client can browse your app's boxes while it runs.

import 'package:dbinspect_bridge/dbinspect_bridge.dart';
import 'package:dbinspect_hive/dbinspect_hive.dart';

await startBridge(
  appName: 'example_app',
  adapters: [
    HiveAdapter(boxes: [settings, sessions], id: 'hive',
        displayName: 'app boxes'),
  ],
);

A box is a key/value store, not a table

Every store is two columns wide — key and value — and the schema is always reported as inferred, because a box has no schema at all. The client shows a key search box rather than a SQL editor or a filter builder.

Keys page in Hive's own ascending order, read by index, so a page of a 100k-entry box costs the page and not the box.

Boxes are handed in, never discovered

BoxBase names a box you already hold, and nothing in Hive lists what an application has open — so you pass the boxes you want inspected. A box that was not passed in is not listed, rather than listed and unopenable. Both Box and LazyBox are accepted.

Values your client has no class for

A box holds whatever your TypeAdapters registered, and the inspecting client has none of those classes. So:

  • a value with a toJson() is sent as that — your own serialisation, rendered as itself;
  • anything else is sent as {"__lossy": "<toString()>", "type": "Order"}, and the client renders it as a description and refuses to edit it.

A description that read as data is how a value gets silently replaced by its own toString(), which is why the flag is on the wire rather than left to the client to guess.

Filtering

The key console sends a filter of prefix, from and to, all optional and all compared as text:

{"prefix": "user:"}
{"from": "user:100", "to": "user:200"}

A filtered page carries no total — counting it means walking every key a second time — and anything else in the filter is refused rather than ignored.

Watching

capabilities.watch is true with watchScope: "engine": Hive's own watch() sees every write in this process, not only this bridge's own.

A BoxEvent carries {key, value, deleted} and cannot tell an insert from an update, so this adapter emits upsert and remove rather than picking one of insert/update and being wrong half the time.

Writing is off unless you say otherwise

HiveAdapter(boxes: [settings], id: 'hive', displayName: 'app boxes',
    allowWrite: true);

That opens the row editor. Three rules it enforces, none of them adjustable:

  • an insert carries its own key in values — a box assigns no identity, so there is nothing to fall back to;
  • an insert onto an occupied key is refused rather than overwriting it;
  • an update never moves an entry to another key, and an update to a key that is no longer there reports changes: 0 instead of quietly creating it.

Values are limited to strings, numbers, booleans and null, which is the protocol's rule for every engine. Editing a TypeAdapter-registered object is not possible through the bridge and will not silently half-work.

hive_ce — unsupported as of 0.1.0, and it fails at compile time

hive_ce is a community fork with the same class names in a different package. Dart identifies a type by its library, so a package:hive_ce Box is not a package:hive BoxBase and cannot be passed to HiveAdapter at all:

error - The element type 'Box<Object?>' can't be assigned to the list type
        'BoxBase<Object?>'.

Tested against hive_ce 2.19.3 on 2026-08-08. This is a build failure, not a runtime surprise, which is the good direction to fail in: nothing half-works and no data is at risk.

There is no workaround inside this package. Supporting the fork means a sibling dbinspect_hive_ce compiled against package:hive_ce — the adapter's logic is identical and only the import changes — and it is not built until someone asks for it.

Licence

Apache-2.0.

Libraries

dbinspect_hive
A Hive adapter for dbinspect_bridge.