npm rxdb 17.6.0

3 hours ago

JavaScript Database

  • ADD getConnectionHandlerNostr() to the WebRTC replication plugin. Peers find each other over Nostr relays instead of a signaling server. Signals are sent as signed, NIP-44 encrypted ephemeral events, and getNostrPublicKeyOfPeer() returns the verified public key of a peer for use in isPeerValid(). Added tests for the Nostr signaling with multiple relays, peer validation and unreachable relays.
  • FIX DenoKV RxStorage: a query without a limit passed Infinity to Deno.Kv.list(), which throws Limit must be a positive integer since Deno 2.9. Unlimited queries no longer pass a limit at all.
  • FIX DocumentCache: a document that is re-inserted after the cleanup purged its tombstone was no longer found by findOne() and by primary key queries, because the new revision chain starts at height 1 and the out-of-order protection kept the cached tombstone. #8948
  • FIX typos in the dev-mode error messages: DB6 had the docs URL glued to the sentence (Read thishttps://...), GDR18 said exxeeded instead of exceeded, and MQ4 said instanceof instead of instance of.
  • FIX IncrementalWriteQueue: ensure storage bulkWrite errors are properly caught and reset queue runner state so the queue does not wedge on failure.
  • FIX schema migration finalized with Promise.all([oldStorage.remove(), metaStorage.remove()]) which removed both storage instances at the same time. Storages like SQLite share a single connection between all storage instances of one database, so the two DROP TABLE statements were sent to the same connection concurrently and async single-connection adapters like expo-sqlite failed with SQLITE_LOCKED ("database is locked"). The storages are now removed one after another and the DROP TABLE of the SQLite RxStorage runs inside of a transaction so that it goes through TX_QUEUE_BY_DATABASE. Added a test case that tracks overlapping statements on a single SQLite connection. Fixes #9024.
  • FIX schema migration with multiInstance: true blocked addCollections() in every tab forever when the tab that won the leader election of the migration was frozen, throttled or discarded by the browser. The migration leader now writes a heartbeat into the migration status document and waiting tabs take over the migration when the status document was not written for 60 seconds (configurable with setMigrationLeaderTiming()). Fixes #9191.
  • FIX flaky preact-signals reactivity test that asserted the signal value before the change event of the remote storage arrived #9172
  • FIX query-builder: .where({ age: { $gt: 3 } }) on a query whose selector had a shorthand value for the same field (for example find({ selector: { age: 7 } })) threw TypeError: Cannot create property '$gt' on number '7'. In the other direction, .where({ age: 7 }) silently dropped an existing operator like { $lt: 7 }. The shorthand value is now converted to $eq so both conditions are merged. Added a test case in test/unit/query-builder.test.ts.
  • FIX replication: when the first start() of a replication rejected, the error was an unhandled rejection that was not emitted on error$, and every later start(), pause() and remove() rejected with the same error because the startQueue stayed rejected, so the replication could not be started again without a page reload. A failed start is now emitted on error$ as RC_START and a later start() retries it. The internal start() calls of autoStart and toggleOnDocumentVisible no longer create unhandled rejections. Added a test case for it in test/unit/replication.test.ts. Fixes #9127.
  • FIX replication-protocol: the upstream initial sync could call getChangedDocumentsSince() on the fork RxStorageInstance after the replication was canceled, because it did not re-check the canceled state after it throttled on the running persistToMaster() promises. With a fast storage (rxdb-premium IndexedDB) this happened when a schema migration was interrupted via RxMigrationState.cancel() which closes the old storage, so the "instance is closed" error ended up as an unhandled rejection. Added a testcase for it in test/unit/replication-protocol.test.ts.
  • FIX addCollections() threw DB6 for an unchanged schema after the device or app language changed. sortObject() uses localeCompare(), so in Czech and Slovak ("ch" sorts after "h") the schema hash differed. When the hashes differ, the stored schema is now compared with deepEqual() and no error is thrown when the content is equal. #9128
  • FIX queries that sort by a nested field (for example sort: [{ 'address.city': 'asc' }]) threw TypeError: Cannot read properties of null when a document had null as the value of the parent object (address: null). The nested path lookup now treats a null parent like a missing one. Added a test case in test/unit/rx-query.test.ts.
  • FIX react plugin useRxDocument starting with loading: false instead of loading: true when valid collection and primaryKey are provided. This caused a false "not found" flash on the first render before the subscription resolved. Added equivalent tests to the existing react-hooks test suite. Fixes #8965.
  • FIX webmcp plugin causing an unhandled promise rejection when a collection is closed directly after registerWebMCP() on a spec-conformant modelContext whose registerTool() returns a promise #9172
  • FIX WebRTC replication was flaky and could spin or stop syncing:
    • The simple-peer connection handler reconnected to the signaling server in a tight loop without delay and crashed in Node.js when the server was not reachable. Reconnects now use an exponential backoff.
    • A failed peer connection was recreated in an endless loop. Peer connections now have a connect timeout, reconnect with a backoff, and signals of outdated connection attempts are ignored instead of throwing.
    • The first replication request of a peer could get lost when it arrived before the own handshake was done, which made the sync hang forever. Requests are now answered independently of the handshake state.
    • Requests to a disconnected peer never resolved. They now fail on disconnect, on timeout (new requestTimeout option) and when the remote peer throws, so the replication retries.
    • With three or more peers, change stream events of one master were applied to the replications of all other masters.
    • Messages bigger than the data channel size limit failed. They are now split into chunks.
    • The signaling server now tells the other peers of a room when a peer leaves.
    • Re-enabled the WebRTC replication tests and added tests for an unreachable signaling server, a signaling server restart and big documents with three peers.
    • RxWebRTCReplicationPool.cancel() now awaits the cancelation of all replications, so they do not write to the storage after the database was closed.
  • FIX replication-protocol: when the upstream had push conflicts, persistToMaster() wrote the resolved conflicts to the fork and meta instance even when the replication was canceled while the conflicts were resolved. This caused "already closed" errors when a database was closed during a replication.
  • IMPROVE performance of findByIds(): the query cache key is no longer built from a sorted copy of all ids. With 3000 ids, find-by-ids in the memory performance test went from 4.80ms to 3.26ms. Queries with the same ids in a different order now get their own cache entry, so each result Map keeps the order of its own ids.
  • IMPROVE performance of the DocumentCache: RxDocuments are cached by their revision, and the _meta.lwt is compared on lookup instead of being converted to a string for the cache key. find-by-query went from 3.32ms to 2.60ms.
  • IMPROVE performance of nested property access on RxDocuments: the nested value is no longer looked up again from the document root on each access. property-access went from 6.57ms to 4.02ms.
  • IMPROVE query planner: string and number fields that are matched with $eq are ignored when checking whether the index order matches the sort order, as was already done for boolean and enum fields. The storage no longer has to re-sort these query results. find-by-query-parallel-4 went from 3.63ms to 2.87ms.
  • IMPROVE performance of database and collection creation: schema hashes are cached, so the same schema is not hashed again for each collection or database. time-to-first-insert went from 1.40ms to 1.22ms.
  • FIX flaky attachments.test.ts encryption test that decoded binary ciphertext as base64 and failed about 1 in 4 runs with storages that store the encrypted attachment data as binary #9193
  • FIX the storage test should clean up all deleted documents when multiple are deleted failed from time to time when the storage uses another instance of now() than the test, like the premium storages in their integration tests. The test now waits until the deletion time is in the past before it runs cleanup(0).
  • ADD tests that parallel bulkWrite() calls and a schema migration with multiple batches keep all documents when multiInstance: false is used. See #9145
  • FIX webmcp.test.ts failed in browsers with native WebMCP support (like Chromium 154) because the polyfill does not install its testing shim when document.modelContext already exists. The test now removes the native getter while it runs and restores it afterwards.

RxDB Server

  • FIX the replication test create read update delete did not cancel its live replication before it closed the databases. The replication kept pulling from the closed server and ensureReplicationHasNoErrors() threw fetch failed while the next test (should give a 426 error on outdated versions) was running, which made that test fail from time to time.

RxDB Premium

  • FIX (storage-filesystem-node, storage-opfs and all other filesystem based storages) Multiple writes within the same write-run all wrote to changes.json at offset 0 instead of appending, which left invalid JSON on disk while the run was in flight. When the process was killed in that window, the database could no longer be opened (SyntaxError: Expected ',' or ']' after array element in JSON).
  • FIX (storage-filesystem-node, storage-opfs and all other filesystem based storages) When the process died during a cleanup after the index files were written but before the changelog.txt was emptied, the next start applied the changelog operations a second time on top of the already updated index files. This corrupted the index state (lost documents, duplicated rows with stale byte positions) and the next cleanup or read failed with SyntaxError: Expected ',' or ']' after array element in JSON at position .... The changelog now starts with an epoch header and the index files remember the epoch and the amount of operations they already contain, so operations are never applied twice. Index and changelog files of older versions are still readable.
  • FIX (storage-memory-mapped) Fixed a bug where bulkUpsert of an existing document would not survive a database reopen. The background persistence flush used return instead of continue inside the write-tasks loop, causing any remaining batched writes to be silently dropped whenever one write task produced no written documents (e.g. when a conflicting insert yields an empty result). See rxdb-premium-issues#24
  • FIX (storage-indexeddb) With multiInstance: false, parallel bulkWrite() calls with more than 16 documents overwrote each other's WAL content, so whole batches were lost without an error. This dropped documents during schema migrations that needed three or more batches. See #9145
  • FIX (storage-indexeddb) Eliminated unhandled TransactionInactiveError rejections that occurred during bulk replication pulls when concurrent reads hit the WAL flush window. See #8497

NOTICE: An overview about all releases can be found at the changelog

Join RxDB:

Don't miss a new rxdb release

NewReleases is sending notifications on new releases.