Repository navigation
v0.5.0
npm install better-content@0.5.0One change, kept on its own rather than batched with features, so that a
behavior change has exactly one suspect.
createWithId now means the same thing on every adapter
It meant two opposite things depending on the backend:
| Before | After | |
|---|---|---|
| Firestore | set — overwrote the existing document |
rejects |
| Postgres | insert — threw a unique violation |
rejects (unchanged) |
The same call, against the same seam, did opposite things depending on which
adapter was underneath. That is exactly what the adapter seam exists to
prevent, and neither behavior was pinned by a test, so it was unspecified
rather than a deliberate difference.
Firestore now issues create instead of set, so the rejection is enforced
by Firestore itself with no read-then-write race. The Postgres adapter was
already correct and does not change.
Breaking
Code relying on Firestore's createWithId silently overwriting will now see
it reject.
- To write regardless of what is there, use
upsert. - To replace a document wholesale,
deletethencreateWithId.
There is deliberately no single "replace this document" call. Neither verb
expresses it portably, since upsert merges rather than replaces.
The write contract, now specified and tested
It is stated on the DataAdapter type, in the adapter guide, and pinned by
tests on both shipped adapters.
| Method | On an id that already exists |
|---|---|
createWithId |
rejects; never overwrites |
upsert |
writes, merging; omitted fields are kept |
update |
patches the given fields |
delete |
succeeds even when the id does not exist |
If you maintain your own DataAdapter, check it against that table. The
in-memory adapter in the playground and the "write your own adapter" snippet
both overwrote silently and have been corrected.
Docs
The adapter guide told authors to "treat upsert as create-or-replace", when
both shipped adapters merge, so the guidance contradicted the implementations
it described. Corrected, with the write contract added to the core and
adapters API pages, the how-it-works guide and the README.
Also documented, found while investigating this: reads order by createdAt by
default and Firestore omits documents that lack the ordering field, so records
written only through upsert, which does not stamp createdAt, can be missing
from an unfiltered read.
Full detail in CHANGELOG.md.