Repository navigation
Conversation
Adds Collection.observeRecord(id), a failsafe version of findAndObserve(id). It emits null while the record is missing, the record once it exists or is created, and null again instead of completing when it is deleted, and keeps observing throughout. Relations get a failsafe option that makes observe() use observeRecord, and @experimentalFailsafe sets it, so failsafe relations recover when a missing related record is created. Model and Collection now notify a copy of their subscriber lists, so subscribers can unsubscribe while being notified. In TypeScript, Relation accepts a nullable record type. Refs Nozbe#1257 and Nozbe#1719. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Hi @joker-777, thank you for this, it's a really nice addition! I maintain NitromelonDB, a maintained fork of WatermelonDB (New Architecture, Nitro Modules). We recently shipped What we don't have yet is the If you don't have the time or would rather not, no worries at all, I'm happy to port it myself. Just let me know. Thanks a lot! |
Summary
Adds
Collection.observeRecord(id), a failsafe version offindAndObserve(id)for records that may not exist (yet), and makes@experimentalFailsaferelations use it so they recover when the related record appears.Refs #1257 and #1719.
Problem
findAndObserve(id)callsobserver.error()when the record does not exist andobserver.complete()when it is deleted.withObservablesrethrows that error inrender()and ignores completion. In practice:Relation.observe()goes throughfindAndObserve, so relations pointing at missing records behave the same way.@experimentalFailsafewrapsobserve()incatchError(() => of(fallback)). That emits the fallback once and completes, so the relation never recovers either.Changes
Collection.observeRecord(id)emits:nullwhile the record is missing;createdchange for that id arrives on the collection;nullagain instead of completing when the record is deleted, and keeps observing after that.It still errors for invalid ids such as
null, likefind(). It reuses the existing plumbing:_fetchRecordnow delegates to a new_fetchRecordIfExiststhat returnsnullinstead of throwing, and creation is detected withCollection.experimentalSubscribe. There are no new dependencies. The behaviour offindAndObserveandfindis unchanged.Relationaccepts a newfailsafeoption. When it is set,observe()usesobserveRecordinstead offindAndObserve, for both mutable and immutable relations.@experimentalFailsafemarks the decorated relation as failsafe. A missing related record is mapped to the decorator's fallback value, while a relation whose id isnullstill emitsnull. The observable now recovers when the record is created.catchErrorstays in place for other errors and for non-relation values.Flow types and the hand-maintained
.d.tsforCollectionandRelation.Docs in
CRUD.md,Components.mdandRelation.md, plus a line inCHANGELOG-Unreleased.md.I picked a separate method rather than
findAndObserve(id, { failsafe: true })because the emitted type differs (Observable<?Record>vsObservable<Record>). A separate name keeps both signatures precise in Flow and TypeScript.Tests
src/Collection/test.js: the first tests forfindAndObserve, covering emit, update, complete on delete, and error when missing.observeRecordcases cover missing →null, created later → record, deleted →nullwithout completing, then re-created → record, and an uncached record whose id contains colons (12:Quiz:hand). There are also tests for a creation racing with the initial fetch, invalid ids, and cleanup on unsubscribe.src/Relation/test.js: a non-failsafe relation still errors. Failsafe mutable and immutable relations emitnulland recover on create, update, delete and re-point.src/decorators/experimentalFailsafe/test.js(new): relations are marked failsafe,fetch()falls back, andobserve()emits the fallback and then recovers. Anullid staysnull, and arbitrary observables still getcatchError.src/react/withObservables/withObservables.test.js: anullprop fromobserveRecordrenders without throwing and re-renders when the record is created or deleted. Observable errors are still rethrown in render.Jest for
src/Collection src/Relation src/decorators src/react src/observationpasses, as do eslint, tslint andflow check.Example
🤖 Generated with Claude Code