Releases: rust-dd/react-native-qdrant-edge
v0.3.1
Patch release — restores Android support by picking up the upstream qdrant-edge 0.7.1 release that contains the WAL flock fix (qdrant/qdrant#9226).
What's fixed
- Android shard creation no longer fails with
try_lock() not supported. Upstreamqdrant-edge0.7.1's WAL initializer now usesfs4::FileExt::try_lock(dir.file())?(a directflock(LOCK_EX | LOCK_NB)syscall, which Android supports) instead of stdlibFile::try_lock(gated to a fixedtarget_oslist that excluded Android, returningErrorKind::Unsupported).
Full Changelog: v0.3.0...v0.3.1
v0.3.0 — qdrant-edge 0.7.0, BM25, hybrid search, facets, snapshots (iOS only)
Major release — qdrant-edge upstream bumped 0.6.0 → 0.7.0 and we now expose every public capability the upstream crate offers. TypeScript API is additive — existing 0.2.x call sites compile and behave unchanged.
⚠️ Android status: the library builds and links on Android, butcreateShard/loadShardcurrently fails at runtime because upstreamqdrant-edge0.7.0 calls Rust stdlibFile::try_lock, and the stdlib gate inlibrary/std/src/sys/fs/unix.rsexcludestarget_os = "android"(returnsErrorKind::Unsupported,"try_lock() not supported"). 0.2.x worked because qdrant-edge 0.6.x usedfs4::try_lock_exclusive(rawflocksyscall) which Android supports. Fix has to land in qdrant-edge upstream; the binding has nothing to patch FFI-side. Use 0.2.x for Android until 0.3.x picks up the upstream patch. iOS is fully verified on this release.
Highlights
- BM25 on-device sparse embedding (
createBm25,embedQuery/embedDocument) — produce sparse vectors from raw text with the full server tokenizer pipeline (language, stopwords, Snowball stemming, ASCII folding, min/max token length). No external embedding model required. - Hybrid search via prefetch + fusion (
rrf/dbsf), with arbitrary nested prefetches and per-source RRF weights. - Sparse and multi-vector upsert + search (the README always claimed these; only the dense path was wired previously).
- Advanced query modes:
recommend(best-score / sum-scores),discover,context,order_by,sample,mmr. - Faceting (
shard.facet({ key, limit?, filter?, exact? })). - Snapshot interop with cloud Qdrant:
snapshotManifest(),unpackSnapshot,recoverPartialSnapshot. - Dynamic vector slots:
createVectorName/deleteVectorNameat runtime. - Runtime config setters:
setHnswConfig,setVectorHnswConfig,setOptimizersConfig. - Mobile-tuned WAL options (
wal_optionsonEdgeConfig, plusmobileWalDefaults()helper). - UUID and u64 point IDs alongside each other;
PointId = number | string. - Filter-based payload ops —
setPayloadOp,overwritePayloadOp,deletePayloadOp,clearPayloadaccept{ payload?, keys?, points?, filter?, key? }. - Three new example screens: BM25 + hybrid demo, facet bar-chart by country, MMR diversity slider.
Fixes
- Runtime crash on FFI errors —
search/query/retrieve/scroll/infopreviously returned{"error": "..."}JSON through the C++ bridge unchanged; the TS layer parsed that as the success type and crashed downstream on.map. Now the Rust side returnsnull+ setslast_error, the C++ throws a JSError, and a newQdrantError/asQdrantErrorpair gives structured access on the TS side. SparseModifierwire format — TS type was'None' | 'Idf'(capitalized); upstream serde format is snake_case'none' | 'idf'. Never triggered in 0.2.x because the example never used sparse vectors.- Android build: macOS strip on ELF archives —
scripts/build-android.shran macOSstripon the Linux/Android.aarchives, corrupting the GNU ar format. Cargo'sprofile.release.strip = "symbols"already does the right thing. - Android build: React Gradle codegen scope — without an explicit
react { libraryName, codegenJavaPackageName, jsRootDir }block, the Gradle plugin scanned every codegen-spec package in the app'snode_modulesand bundled all of them into our AAR, then D8 hit duplicate*ViewManagerDelegatetypes when the real owner (e.g.react-native-screens) also shipped them.
Migration from 0.2.x
Mostly additive on the TS side:
Point.idand IDs indeletePoints/retrievewiden fromnumbertonumber | string. Existing numeric IDs keep working.Point.vectorandSearchRequest.vectorwiden to accept sparse{ indices, values }and multi[[…]]. Dense literals still match.Shard.setPayload(pointId, payload, key?)gains an optional 3rd argument and accepts string IDs. Existing call sites unchanged.
Upstream behavior change: with optimizers.prevent_unoptimized: true, points written to unoptimized segments above indexing_threshold are now persisted as deferred — excluded from reads/search until you call shard.optimize(). Previously the option blocked the write entirely.
Full Changelog: v0.2.0...v0.3.0
v0.2.0
- Full React hooks API:
useShard,useUpsert,useDelete,useSearch,useQuery,useRetrieve,useScroll,useCount,useShardInfo - Example app with 3 tabs: Basic CRUD, Emoji Similarity Search, Benchmark
- Automated Rust build on npm install / expo prebuild / native build
- Prebuilt binaries included in npm package (no Rust toolchain required)
parking_lot::Mutexfor better FFI performance- Auto-generated C headers via cbindgen
v0.1.0
react-native-qdrant-edge v0.1.0
Embedded vector search for React Native powered by Qdrant Edge (Rust) and Nitro Modules.
Highlights
- In-process HNSW vector search on iOS and Android -- no server, fully offline
- Prebuilt native binaries included (no Rust toolchain required)
- Expo and bare React Native support
- Full React hooks API
API
createShard/loadShard-- create or reload persistent vector storesupsert/deletePoints/setPayload-- data operationssearch/query-- nearest-neighbor and advanced search with filteringretrieve/scroll/count-- retrieval and paginationflush/optimize/close-- lifecycle management- React hooks:
useShard,useUpsert,useDelete,useSearch,useQuery,useRetrieve,useScroll,useCount,useShardInfo
Install
npm install react-native-qdrant-edge react-native-nitro-modulesSupported platforms
- iOS arm64 (device) + arm64/x86_64 (simulator)
- Android arm64-v8a + x86_64