Commit c809e09
feat(solid-query): rewrite the adapter onto Solid 2.0's native async model (#11308)
* feat(solid-query): rewrite the adapter onto Solid 2's native async model
Reads become a single async memo over the query cache (suspends into
<Loading>, holds previous data through refetches, routes rejections to
<Errored>, serializes settled values for streaming hydration); mutations
ride Solid core's `action` primitive with transactional settle and
optimistic overlays; cross-cache hooks share a dual-write aggregate
with a hydration latch. The observer notification/store layer
(createStore/reconcile, tracking proxies, notifyManager batching) is
deleted — QueryObserver/MutationObserver remain as lifecycle/policy
engines with noop listeners.
Breaking: result `data` is non-optional (reads suspend instead of
returning undefined), mutateAsync is removed (mutate returns a
promise), and the reconcile/suspense/deferStream options are removed.
SSR contracts pinned by the fixture suite: settled-only serialization
for every exposed field, hydration id parity, no fetches inside the
hydration/restore windows, and hydration-latched cross-cache
aggregates. Validated against solid-js 2.0.0-rc.0 and rc.3, including
an end-to-end template run with single-flight mutations.
Co-authored-by: Cursor <cursoragent@cursor.com>
* ci: apply automated fixes
* feat(solid-query): wire deferStream through to Solid's per-computation SSR option
deferStream was declared in the option types on this line but wired to
nothing. Solid 2 exposes it as a creation-time memo option, so pass it
straight through to the data node: the server holds the stream flush
until the query resolves instead of flushing the surrounding boundary's
fallback. Server-only; ignored on the client.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(solid-query): serve data through an auto-reconciling store projection
Solid 2 projections auto-reconcile their returns by key, so the data face
becomes a store: deep reads are fine-grained and item identity survives
across refetches (keyed by the new `reconcile` option, default 'id').
The async memo remains the SSR/hydration spine underneath; the projection
derive is inert on the server — server projections run eagerly at
creation, so a live derive would fetch at hook creation and serialize a
duplicate payload, and the serialized entry would latch the hydrating
client's projection for the whole stream. With nothing serialized the
client projection computes live through the hydration window.
Rewrites the structural-sharing test to the stronger store contract and
adds leaf-granularity, custom-key, and primitive-data semantics tests.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(solid-query): green up CI for the native rewrite
- align @solidjs/web, babel-preset-solid and solid-js dev ranges across the
solid packages (sherif flagged the split, and devtools/persist-client were
resolving a second solid-js copy)
- drop the unused `export` on the internal BaseQueryLayer seam (knip)
- port the PersistQueryClientProvider suite to the 2.0 read layer: a query
with nothing cached now suspends for the whole restore window, so the
tests assert the visible fallback -> restored -> refreshed transitions
and the fetch/callback bookkeeping instead of observer result snapshots
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* refactor(solid-query): unify the data node into a single hybrid projection
Collapse the three-node data face (serialized async memo + transparent
hydration memo + client-only projection) into one createProjection with
an identical derive on both sides — the Solid Router feed-query-into-
projection shape. The engine owns SSR serialization (deferStream rides
the projection now), suspense, hydration adoption, and keyed
reconciliation. ssrSource 'hybrid' keeps hydrated components live: the
serialized value claims the DOM and the derive re-takes over from the
live cache per hydrated region. A per-hook `primed` signal gates the
pull-model fetch so the hydration takeover recompute cannot race data
the channel is about to deliver (SSR-errored queries fall through and
fetch normally once the channel declines them).
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(solid-query): default ('server') hydration semantics for the data node
Drop ssrSource 'hybrid' from the data projection: query data IS
server-serialized truth, so the serialized value owns the DOM for the
whole hydration window. Mid-stream cache writes commit when the stream
closes through Solid's hydration-end divergence takeover (solid-js >
2.0.0-rc.3 — earlier engines lose a latched node's mid-stream divergence
instead of deferring it). Network activity is unchanged: observers
attach per-query as the channel primes, so mid-stream invalidations
still refetch immediately; only the DOM commit defers to hydration end.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(solid-query): single-channel hydration — the node payload is the transport
Delete the provider-owned dehydration channel and its coordinator. The
data projection's serialized root now carries the cache facts hydration
needs ({ value, t: dataUpdatedAt, raw?: pre-select data }); on a hydrated
mount each hook peeks its projection's node id, loads that entry itself,
primes the query cache through query-core hydrate() (staleness intact,
newer-wins, silent under external pre-priming), and attaches its observer
per query as chunks land. One serialization story, engine-owned; ~240
lines deleted. Requires solid-js > 2.0.0-rc.3 (peekNextChildId export).
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore(solid-query): drop internal porting notes from the tree
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(solid-query): content-addressed hydration transfer (router query() pattern)
Serialize cache entries under sq:<queryHash> at fetch-dispatch time
(provider-side, promise-valued so streaming settles ride the payload)
instead of tying transfer to a rendered node's positional id. Client
hooks look their own hash up and prime through query-core hydrate();
the registry outlives the hydration window, so prefetched-never-rendered
queries transfer and late mounts (lazy routes, post-hydration navigation)
adopt the server payload instead of refetching — restoring full
cache-level dehydration coverage with less machinery. Priming moved ahead
of the attach render effect (its effect half runs synchronously inside an
active flush, and mount policy against a cold cache would refetch).
Drops the peekNextChildId dependency; the data root reverts to { value }.
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore(solid-query): drop internal porting notes from the tree
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(solid-query)!: remove create* aliases, completing the #8950 deprecation
The create*/Create* names were kept as a migration bridge when v5 made
use* canonical (#8950 deprecated them). This major already rewrites every
callsite's semantics, so the bridge retires: use* is the only naming,
matching the docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
* ci: apply automated fixes
* refactor(solid-query)!: drop isInitialLoading (deprecated alias of isLoading)
Core deprecated it in favor of isLoading; the adapter's getter was
byte-identical. Result types now omit it (distributively over the
Defined result unions so status discriminants survive), and useBaseQuery
declares the adapter's own result face instead of the core union.
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore(solid-query): require solid-js >= 2.0.0-rc.4
rc.4 is published and carries the hydration-end divergence takeover the
adapter's streaming hydration relies on. Bump the peer range and dev dep
off the locally-built solid and onto the released bits; full suite (344
adapter + 7 persist-client tests, typecheck) green against published rc.4.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Brenley Dueck <brenleydueck@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent 606d09d commit c809e09
41 files changed
Lines changed: 5523 additions & 6130 deletions
File tree
- .changeset
- packages
- solid-query-devtools
- solid-query-persist-client
- src/__tests__
- solid-query
- src
- __tests__
- fixtures/hydration
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
73 | | - | |
| 73 | + | |
74 | 74 | | |
75 | | - | |
| 75 | + | |
76 | 76 | | |
77 | | - | |
| 77 | + | |
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
73 | | - | |
| 73 | + | |
74 | 74 | | |
75 | 75 | | |
76 | | - | |
| 76 | + | |
77 | 77 | | |
78 | | - | |
| 78 | + | |
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| |||
0 commit comments