Ladybug
Native Node.js bindings for Ladybug, an embeddable Cypher graph database with zero-copy Arrow results.
Repository Health
Technical Analysis
@ladybugdb/core is the official Node.js binding for Ladybug, an embeddable property graph database (formerly known as Kuzu) built for fast analytical queries over large graphs. It ships as a native addon built with node-addon-api and cmake-js, wrapping the C++ query engine directly in-process — no server, no client-server round trip, just an embedded database you require() like any other module.
The package exposes Database, Connection, PreparedStatement, and QueryResult classes with both promise-based and synchronous APIs for every operation, Cypher query support, prepared statement parameter binding, and zero-copy Arrow-backed result retrieval including CSR-format adjacency arrays for graph traversal. Prebuilt binaries for Linux, macOS, and Windows (x64/arm64) are bundled directly in the npm package, so installs don’t require a C++ toolchain unless building from source.
What You Get
- Database and Connection classes with lazy initialization and both async (Promise) and sync method variants for every native call
- Full Cypher query execution via Connection.query()/execute(), plus PreparedStatement for parameterized, reusable queries
- Zero-copy QueryResult and ArrowQueryResult classes, including CSR-format (indptr/indices/edgeIds) adjacency exports for graph algorithms
- Prebuilt native binaries for Linux, macOS, and Windows (x64 and arm64) bundled in the npm package, with a CMake/cmake-js source build as fallback
- TypeScript type definitions (lbug.d.ts) covering NodeID, NodeValue, CSRResult and other graph-native types
Common Use Cases
- Embedding a Cypher-queryable graph database directly inside a Node.js backend without standing up a separate graph DB server
- Running knowledge-graph or code-graph workloads (the project’s own examples target code-knowledge-graph use cases) with full-text and vector indices
- Feeding graph traversal results into JS analytics/ML pipelines via zero-copy Arrow and CSR adjacency arrays
- Building Node.js services that need a fast, file-backed or in-memory graph store with ACID transactions
Under The Hood
Architecture The package is a thin JS facade over a native N-API addon: lbug_native.js loads lbugjs.node (using RTLD_LAZY|RTLD_GLOBAL dlopen flags on Linux so the engine’s own extension loading works), and database.js/connection.js/query_result.js/prepared_statement.js each wrap a native object behind a consistent lazy-init pattern — every class exposes both an async init()/initAsync and a blocking initSync(), with an internal _getDatabase()/_getConnection() accessor guarding closed-state errors. index.js aggregates the four classes plus a json() passthrough helper and static VERSION/STORAGE_VERSION getters. On the native side, node_database.cpp/node_connection.cpp/node_query_result.cpp/node_prepared_statement.cpp bridge directly into the upstream Ladybug C++ engine that lives in the parent monorepo.
Tech Stack Built on node-addon-api for the N-API bridge and cmake-js/CMake for compiling the native module, with apache-arrow as a runtime dependency for zero-copy columnar result exchange. The standalone build script (build.js) links against a sibling Ladybug C++ checkout (LBUG_SOURCE_DIR) or a prebuilt static library. Tests run under mocha/chai. CI (ci.yml) builds and tests across a linux/macos/windows x64/arm64 matrix.
Code Quality An extensive mocha test suite covers connections, data types, parameters, concurrency, Arrow-backed queries, sync-API parity, and versioning (test_connection.js, test_data_type.js, test_parameter.js, test_concurrency.js, test_arrow_query.js, test_sync_api.js). Every public method carries JSDoc with typed parameter and return descriptions, and a companion lbug.d.ts supplies full TypeScript definitions. Error handling follows Node’s callback-first convention internally, wrapped in Promises for the public async surface, with explicit closed-state checks guarding against use-after-close.
API Design Every native operation deliberately exposes a matched sync/async pair, letting consumers pick blocking simplicity or non-blocking throughput without a different API shape. Results can be pulled as ordinary JS objects or, via ArrowQueryResult/CSRResult, as zero-copy BigUint64Array adjacency data for graph-analytics code that wants to avoid per-row marshalling. A dedicated json() wrapper disambiguates raw JSON string values from Ladybug’s native JSON column type. Binary distribution follows the prebuildify pattern — all supported platform binaries ship inside the single published tarball rather than triggering a postinstall download.