ob_dump_reader 0.1.0-beta.1
ob_dump_reader: ^0.1.0-beta.1 copied to clipboard
Minimal ObjectBox LMDB reader toolkit
ob_dump_reader #
Minimal ObjectBox LMDB reader toolkit for Dart. Its core job: walk a
data.mdb file and hand you each stored object's raw FlatBuffers table
bytes, plus its entity id and object id — no per-field FlatBuffers or
schema knowledge for that part, just a small purpose-built dart:ffi
binding over vendored LMDB C source (see "Why this shape" below).
It also covers the handful of things flatc --dart output can't: ToMany
relations (a separate LMDB structure, not a table field) and Flex/
ExternalPropertyType fields (flatc only knows the base FlatBuffers
type, not ObjectBox's semantic annotation on top) — see "Beyond flatc"
below.
Decoding those raw bytes into typed objects is left to the official
flatc --dart compiler — not this package, and not ob-dump's own
C++ core either. This is a deliberate toolkit split, not a missing feature:
see the parent project's docs/BACKLOG.md
for the reasoning.
Using this from a Flutter app? Depend on
../flutter (ob_dump_reader_flutter) instead of this
package directly — same API, but it's a real Flutter plugin (ffiPlugin: true) that compiles and bundles the native LMDB library for you on every
platform (Android/iOS/Linux/macOS/Windows). This package on its own only
gives you dart run ob_dump_reader:build (see below), which is enough for
a plain Dart script/CLI but not for a shipped Flutter app.
Building the native library (plain Dart) #
dart run ob_dump_reader:build
Compiles the vendored LMDB source (src/lmdb/) into a shared library for
the current desktop platform, via a plain CMake configure+build — no
network access, no FetchContent, no prebuilt binary download. Only needed
if you're using this package directly from a plain Dart project (script,
CLI, server); ob_dump_reader_flutter builds and bundles its own copy
automatically as part of flutter build/flutter run.
Workflow #
# 1. Generate a schema JSON (entityId -> table name/shape) and a .fbs from
# your ObjectBox model, using the ob_dump CLI (see ../README.md):
ob_dump --schema objectbox-model.json -o schema.json
ob_dump --fbs objectbox-model.json -o schema.fbs
# 2. Generate typed Dart classes with the *official* FlatBuffers compiler.
# (This is `flatc`, not `flatcc` — flatcc is a separate, C-only
# implementation with no Dart backend.) flatc always names its output
# `<input>_generated.dart`; rename to the `.g.dart` suffix Dart tooling
# conventionally uses for generated code (e.g. so a `*.g.dart` entry in
# .gitignore or an analyzer exclusion rule already covers it).
flatc --dart -o lib/generated schema.fbs
mv lib/generated/schema_generated.dart lib/generated/schema.g.dart
import 'package:ob_dump_reader/ob_dump_reader.dart';
import 'generated/schema.g.dart'; // from flatc --dart, see step 2 above
const ammoEntityId = 1; // from schema.json
Future<void> main() async {
// Walks data.mdb, calling this callback once per stored ObjectBox object
// with its raw (still-undecoded) FlatBuffers bytes — see [ObRecord].
await readObjectBoxRecords('/path/to/objectbox/dir', (record) {
if (record.entityId == ammoEntityId) {
final ammo = Ammo(record.data); // flatc-generated class decodes the bytes
print('${ammo.name}: ${ammo.bcG1}');
// ... insert into whatever your new database is.
}
});
}
Reads are in place, no copy #
readObjectBoxRecords reads data.mdb/lock.mdb directly, with no
temporary copy step — it opens the LMDB environment itself MDB_RDONLY
(matching ob-dump's own C++ LmdbReader), so it never needs a
write-capable handle. This is exactly what LMDB's MVCC design is for: any
number of readers can safely run alongside one concurrent writer, in any
process, with zero risk to the original data — even while a live
ObjectBox process has the same store open.
Beyond flatc: ToMany relations and Flex/ExternalPropertyType fields #
ob_dump --schema lists each property's externalType and each entity's
relations (id, name, target entity) when present — use that to know
which of your fields need one of these:
import 'package:ob_dump_reader/ob_dump_reader.dart';
// ToMany: not part of the FlatBuffers table at all, so flatc has no
// accessor for it — relationId/sourceObjectId come from `ob_dump --schema`
// and the record you're looking at (record.objectId).
final authorIds = await readToManyTargets(dbDir, relationId, record.objectId);
// Flex: flatc gives you the raw bytes (a List<int>/Uint8List field) —
// decode with decodeFlex.
final value = decodeFlex(ammo.someFlexField);
// ExternalPropertyType: flatc gives you the base type's plain value
// (a byte list for Uuid/Int128/Decimal128/Bson, a string for
// Json/JavaScript/JsonToNative) — decode with the matching helper.
final uuid = bytesToUuidString(ammo.someUuidField);
final blob = bytesToHex(ammo.someBsonField);
final parsed = tryParseJsonString(ammo.someJsonField);
Every one of these mirrors ob-dump's own C++ decode (src/fb_decode.cpp)
exactly — same hex/UUID formatting, same JSON-parse-with-string-fallback
for JavaScript, same forward-only relation direction (see
docs/BACKLOG.md "ToMany relations" for why: the backward direction is an
auto-maintained index for ObjectBox's own query engine, not needed for a
one-directional dump).
Why this shape #
The alternative — an FFI wrapper around ob-dump's full C++ core — would
mean vendoring/building that much larger codebase from a pub.dev package
for every platform. Not needed: LMDB itself is a single small C library
(src/lmdb/, vendored from the same upstream commit ob-dump's own C++
core builds), so this package binds directly to it via a purpose-built
dart:ffi layer (lib/src/lmdb_bindings.dart), and flatc --dart already
gives an officially generated, correct FlatBuffers decoder. This package is
only the small piece connecting the two — LMDB traversal and the
ObjectBox key format (docs/BACKLOG.md in the parent project) — and stays
that small on purpose.
An earlier version of this package depended on
dart_lmdb2 instead of vendoring
LMDB directly. Dropped because its native-library path resolution
(Isolate.resolvePackageUriSync()) throws UnsupportedError outright in
any compiled AOT release build — confirmed empirically against a real
flutter build linux --release, run from an isolated copy of just the
output bundle — and because it required a write-capable LMDB environment
just to open a store, forcing a copy-to-temp step this package no longer
needs (see "Reads are in place, no copy" above).
Verified end-to-end #
Confirmed against a real ObjectBox database, independent of every other
verification already done in this repo (the Dart PoC this was ported from,
the C++ decoder, and a C++ flatc-generated consumer): generated schema.fbs
from the real model, ran flatc --dart on it, read a real record with
readObjectBoxRecords, decoded it with the generated Ammo class — every
field matched exactly.
Integrity & Licensing #
ob-dump was developed as an independent implementation for reading data stored in the ObjectBox format. It adheres to a "Clean Room Design" approach regarding binary software:
- Purpose-Limited: Built solely to support data recovery and migration to another database, for projects whose own license is incompatible with
objectbox-c's (a closed-source binary — see "Why this exists" in the parent project'sdocs/BACKLOG.md). Not intended as, and not pursued as, a competing product to ObjectBox itself — no write support, no query engine, no ongoing-database use case, strictly a one-time read-only export path out of an existing store. - No Reverse Engineering: We have performed no decompilation, disassembly, or any other analysis of the closed-source
objectbox-cbinary. - Open Specification: Data parsing is based exclusively on public formats (LMDB and FlatBuffers) and the open-source code of the official schema generator (
objectbox_generator, licensed under Apache 2.0). - Model-Driven: The decoding process is driven by the user-provided
objectbox-model.jsonfile, which is an open, user-accessible schema definition.
This approach ensures full licensing integrity: ob-dump is an independent software project that contains no proprietary or misappropriated code, making it suitable for integration into projects with any licensing requirements.
License #
MIT — see LICENSE.