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})

Properties

entityKeys → Iterable<String>
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, see depKey, plus entity.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 body as 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. Store it, then ask again from CacheDelta.version.
override
clear() → void
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, or null if never: hydrated snapshots, optimistic writes and manual writes carry no stamp, so they count as stale for maxAge. 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.gc passes 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
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 path under operation'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.list of inline objects: its elements are read through their own paths). When field is an entity field holding a list, deps gets its lengthDepKey instead of its depKey.
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 data object. 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). When at is given, every key the response wrote — changed or not — is stamped with it (see fetchedAt).

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Methods

isRootKey(String key) → bool
rootKey(String operation) → String