NormalizedCache class
Entity-normalized store: { "ROOT_QUERY": {...}, "Launch:launch-181": {...} }.
Operation roots are entities too (ROOT_QUERY, ROOT_MUTATION), so one
walk serves every read. Non-identifiable objects live inline in their
parent, exactly like the path-addressed cache this replaces.
- Implemented types
Constructors
-
NormalizedCache({Normalization normalization = const Normalization(), Map<
String, Object?> ? initial}) -
NormalizedCache.adopt(Map<
String, Map< entities, {Normalization normalization = const Normalization()})String, Object?> > -
A cache hydrated from
entities(the snapshot format) without copying them: the maps and lists are taken over and converted in place ({"__ref": key}maps become refs), so the caller must not touch them afterwards. For a persistence layer that just decoded them (jsonDecodeoutput is mutable);Cache(initial:)copies.
Properties
-
entityKeys
→ Iterable<
String> -
Keys of every stored entity, operation roots included.
no setteroverride
- hashCode → int
-
The hash code for this object.
no setterinherited
- normalization → Normalization
-
final
-
onChange
→ Stream<
Set< String> > -
Fires once per change — a write outside a batch, or a whole batch —
with the dependency keys (
entity.field, seedepKey, plusentity.field[i]/entity.field[length]for inline lists) it touched, synchronously. Nothing fires when nothing changed (a refetch returning the same data).no setteroverride - runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
snapshot
→ Map<
String, Object?> -
JSON-able deep copy of the whole store (refs as
{"__ref": key}). Entities are merged in place by later writes, so it is a copy, not a view; changesSince copies only what changed.no setteroverride - version → int
-
Change counter: bumped once per change that altered an entity (see
batch). 0 for a new cache and for a hydrated one —
Cache(initial:)is the persisted baseline.no setteroverride
Methods
-
batch<
T> (T body()) → T -
Runs
bodyas one change: the writes it makes (nested batches included) fire onChange once, with every key they touched, and bump version once, when the outermost batch returns or throws. The client batches each response, mutation, subscription event and optimistic callback, list-rule edits included; batch several manual writes with it.override -
changesSince(
int version) → CacheDelta -
The entities changed or removed since
version(an earlier value of Cache.version), as JSON copies of those entities only (for the operation roots: of the fields that changed, see CacheDelta.changedFields). Store it, then ask again from CacheDelta.version.override -
clear(
) → void -
Removes everything (sign-out): every scope's data reads as missing
again and is refetched on its next run; onChange reports every key
and the next changesSince is a CacheDelta.full delta.
override
-
compact(
{required int upTo}) → void -
Forgets the change records up to
upTo, a version the persisted copy holds (the CacheDelta.version just stored): the removals and per-entity stamps at or before it are dropped, so they are not scanned again by changesSince. A cache that was never compacted forgets its removals once they pass a thousand (and the entity count, e.g. after a large gc) and answers older versions with a CacheDelta.full delta (a store rewrites every entity); once compacted, only a far larger pile (a store that stopped saving) is.override -
entity(
String key) → Map< String, Object?> ? -
Read-only view of one entity (
ROOT_QUERY,Launch:launch-181, …).override -
evict(
String key) → Set< String> -
Removes an entity and every reference to it (list elements are dropped,
object fields become missing so they are re-fetched on next read).
override
-
fetchedAt(
String depKey) → DateTime? -
When
depKey(entity.field) was last written by a server response, ornullif never: hydrated snapshots, optimistic writes and manual writes carry no stamp, so they count as stale formaxAge. An elementDepKey / lengthDepKey answers for the field holding the list.override -
gc(
{Iterable< String> retain = const []}) → Set<String> -
Removes entities not reachable from any operation root nor from one of
the
retained entity keys (extra roots:SlingClient.gcpasses the entities live scopes read). Returns the removed keys. No scope reads a removed entity, so the client rebuilds nothing; onChange still reports the removed entities' fields (a persistence layer drops them).override -
hasEntity(
String key) → bool -
True when the store holds the entity (or operation root)
key(Launch:launch-181,ROOT_QUERY).override -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
read(
String operation, List< Object> path, {Set<String> ? deps}) → Object? -
Reads the value at
pathunderoperation's root, following entity references transparently. Returns missing when the path does not exist. -
readField(
String operation, List< Object> path, String field, {Set<String> ? deps}) → Object? -
read of
[...path, field]without allocating the joined path: the accessors' hot path (one call per generated getter). -
readListField(
String operation, List< Object> path, String field, {Set<String> ? deps}) → Object? -
readField for a caller that uses only the length of the list it
returns (
Accessor.listof inline objects: its elements are read through their own paths). Whenfieldis an entity field holding a list,depsgets its lengthDepKey instead of itsdepKey. -
remove(
String operation, List< Object> path) → Set<String> -
Removes the value at
path(a map field or a list element) so it reads as missing again. Returns the dependency keys touched. -
toString(
) → String -
A string representation of this object.
inherited
-
write(
String operation, List< Object> path, Object? value) → Set<String> - Writes an optimistic/manual value at a path, creating containers as needed. Returns the dependency keys touched.
-
writeResponse(
String operation, Map< String, Object?> data, {DateTime? at}) → Set<String> -
Merges a GraphQL response
dataobject. Objects the Normalization identifies are stored once as entities and referenced; the rest is merged inline. Returns the dependency keys touched (the ones whose value changed). Whenatis given, every key the response wrote — changed or not — is stamped with it (see fetchedAt).
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited