From dfafbe91c3af08424931b6a5242579f45ec7a93f Mon Sep 17 00:00:00 2001 From: Ryan Carniato Date: Fri, 28 Aug 2026 23:43:26 -0700 Subject: [PATCH 1/3] feat(solid-query): built-in single-flight consumer via FLIGHT_DATA_SOURCE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Solid's single-flight channel is becoming multi-source (solidjs/solid 653dd41e): mutation responses carry a keyed envelope of per-cache slices, each routed to the consumer subscribed under its source id, so independent caches (Solid Router's route data, the query cache) refresh from one round trip without competing for the single legacy slot. QueryClientProvider now subscribes the query cache's consumer under the exported FLIGHT_DATA_SOURCE id ("sq", matching the sq: hydration-registry namespace): a mutation response carrying that slice — a DehydratedState produced by a server collector registered with registerFlightDataSource(FLIGHT_DATA_SOURCE, hook) — hydrates the provider's client before the mutation's promise resolves. Mounted queries on those keys update with no follow-up refetches, and apps delete the hand-rolled subscribeFlightData/hydrate wiring entirely. Subscribing is inert when no server collector exists (the server folds nothing), client-only (the server registry is cross-request module state), and torn down with the provider. Requires the @solidjs/web release following 2.0.0-rc.4 for the named-source protocol; a typed shim bridges the installed declarations until the peer range bumps. Co-authored-by: Cursor --- .changeset/flight-data-source.md | 5 + .../solid-query/src/QueryClientProvider.tsx | 60 +++++++++- .../src/__tests__/flightData.test.tsx | 110 ++++++++++++++++++ packages/solid-query/src/index.ts | 1 + 4 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 .changeset/flight-data-source.md create mode 100644 packages/solid-query/src/__tests__/flightData.test.tsx diff --git a/.changeset/flight-data-source.md b/.changeset/flight-data-source.md new file mode 100644 index 0000000000..98fe8d4fcb --- /dev/null +++ b/.changeset/flight-data-source.md @@ -0,0 +1,5 @@ +--- +'@tanstack/solid-query': minor +--- + +Built-in single-flight consumer: `QueryClientProvider` now subscribes the query cache's slice of Solid's multi-source single-flight channel under the exported `FLIGHT_DATA_SOURCE` id (`"sq"`). Mutation responses carrying that slice — a `DehydratedState` produced by a server collector registered with `registerFlightDataSource(FLIGHT_DATA_SOURCE, hook)` — hydrate the provider's client before the mutation's promise resolves, so every mounted query on those keys updates with no follow-up refetches and no per-app wiring. Subscribing is inert when no server collector exists. Requires the `@solidjs/web` release following 2.0.0-rc.4 (the named-source single-flight protocol). diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index f615275efc..2bac88b54e 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -1,5 +1,7 @@ import { createContext, onCleanup, sharedConfig, useContext } from 'solid-js' -import type { Query } from '@tanstack/query-core' +import { hydrate } from '@tanstack/query-core' +import { subscribeFlightData } from '@solidjs/web/server-functions' +import type { DehydratedState, Query } from '@tanstack/query-core' import type { QueryClient } from './QueryClient' import type { JSX } from '@solidjs/web' @@ -13,6 +15,40 @@ const isServer = typeof window === 'undefined' */ export const HYDRATION_KEY_PREFIX = 'sq:' +/** + * The query cache's single-flight source id. Mutation responses can fold + * fresh data for multiple caches at once (Solid's multi-source + * single-flight protocol); this is the slice the query cache claims — the + * provider subscribes its consumer under it, and server collectors + * register under it to produce the data: + * + * ```ts + * import { registerFlightDataSource } from '@solidjs/web/server-functions/server' + * import { FLIGHT_DATA_SOURCE, dehydrate } from '@tanstack/solid-query' + * + * registerFlightDataSource(FLIGHT_DATA_SOURCE, async (event, outcome) => { + * // rebuild the data for outcome.targetUrl into a QueryClient, then + * return dehydrate(queryClient) + * }) + * ``` + * + * The slice's payload is a `DehydratedState`; the provider consumes it + * with `hydrate()`, so every mounted query on those keys updates before + * the mutation's promise resolves — no follow-up refetches. + */ +export const FLIGHT_DATA_SOURCE = 'sq' + +// The named-source overload of subscribeFlightData ships in the +// @solidjs/web release after 2.0.0-rc.4 (solidjs/solid#653dd41e); this +// cast bridges the installed types until the peer range bumps. +const subscribeFlightSource = subscribeFlightData as unknown as ( + source: string, + consumer: ( + data: DehydratedState, + context: { response: Response }, + ) => void | Promise, +) => () => void + export const QueryClientContext = createContext<(() => QueryClient) | null>( null, ) @@ -97,15 +133,31 @@ function serializeCacheOnServer(client: QueryClient): void { /** * Provides the QueryClient and manages its mount lifecycle. On the server * it also registers the cache serializer above; on the client, hooks prime - * the cache from their hash-keyed registry entries themselves — see - * `useBaseQuery`. + * the cache from their hash-keyed registry entries themselves (see + * `useBaseQuery`) and the provider subscribes the cache's single-flight + * consumer: mutation responses carrying a `FLIGHT_DATA_SOURCE` slice (a + * `DehydratedState` produced by a server collector registered under the + * same id) hydrate this client before the mutation's promise resolves. + * Subscribing is inert when no server collector exists — the server just + * folds nothing — so it is unconditional. One consumer per source: with + * nested providers, the innermost mounted one owns the slice. */ export const QueryClientProvider = ( props: QueryClientProviderProps, ): JSX.Element => { props.client.mount() onCleanup(() => props.client.unmount()) - if (isServer) serializeCacheOnServer(props.client) + if (isServer) { + serializeCacheOnServer(props.client) + } else { + // Client-only: the server's consumer registry is module state shared + // across requests — registering there would leak between them. + onCleanup( + subscribeFlightSource(FLIGHT_DATA_SOURCE, (data) => { + hydrate(props.client, data) + }), + ) + } return ( props.client}> diff --git a/packages/solid-query/src/__tests__/flightData.test.tsx b/packages/solid-query/src/__tests__/flightData.test.tsx new file mode 100644 index 0000000000..0b764b93aa --- /dev/null +++ b/packages/solid-query/src/__tests__/flightData.test.tsx @@ -0,0 +1,110 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { render } from '@solidjs/testing-library' +import { getFlightDataConsumer } from '@solidjs/web/server-functions' +import { dehydrate } from '@tanstack/query-core' +import { queryKey } from '@tanstack/query-test-utils' +import { + FLIGHT_DATA_SOURCE, + QueryClient, + QueryClientProvider, + useQuery, +} from '..' +import type { DehydratedState } from '@tanstack/query-core' + +// The provider's single-flight consumer: mutation responses carrying a +// FLIGHT_DATA_SOURCE slice hydrate the provider's client. These tests +// drive the registered consumer directly — the wire protocol (request-leg +// header, keyed envelope, slice routing) is @solidjs/web's, tested there. +describe('single-flight data source', () => { + let queryClient: QueryClient + + beforeEach(() => { + vi.useFakeTimers() + queryClient = new QueryClient() + }) + + afterEach(() => { + queryClient.clear() + vi.useRealTimers() + }) + + function flightSlice( + key: ReadonlyArray, + data: unknown, + ): DehydratedState { + const producer = new QueryClient() + producer.setQueryData(key, data) + const state = dehydrate(producer) + producer.clear() + return state + } + + it('registers the consumer for the lifetime of the provider', () => { + expect(getFlightDataConsumer(FLIGHT_DATA_SOURCE)).toBeUndefined() + const result = render(() => ( + +
+ + )) + expect(getFlightDataConsumer(FLIGHT_DATA_SOURCE)).toBeTypeOf('function') + result.unmount() + expect(getFlightDataConsumer(FLIGHT_DATA_SOURCE)).toBeUndefined() + }) + + it('hydrates the slice into the cache and mounted queries update', async () => { + const key = queryKey() + let fetches = 0 + + function Page() { + const state = useQuery(() => ({ + queryKey: key, + queryFn: () => { + fetches++ + return Promise.resolve('stale') + }, + staleTime: Infinity, + })) + return {state.data} + } + + const rendered = render(() => ( + + + + )) + await vi.advanceTimersByTimeAsync(0) + expect(rendered.getByText('stale')).toBeInTheDocument() + expect(fetches).toBe(1) + + // The mutation's data is newer than the mounted query's — hydrate() + // only adopts fresher timestamps, and fake timers freeze Date.now(). + await vi.advanceTimersByTimeAsync(10) + + // What the transport does when a mutation response carries the slice. + const consumer = getFlightDataConsumer(FLIGHT_DATA_SOURCE)! + await consumer(flightSlice(key, 'fresh'), { + response: new Response(null), + }) + await vi.advanceTimersByTimeAsync(0) + + expect(rendered.getByText('fresh')).toBeInTheDocument() + // Seeding, not invalidating: no refetch was triggered. + expect(fetches).toBe(1) + }) + + it('seeds entries no component has mounted', async () => { + const key = queryKey() + render(() => ( + +
+ + )) + + const consumer = getFlightDataConsumer(FLIGHT_DATA_SOURCE)! + await consumer(flightSlice(key, 'prefetched'), { + response: new Response(null), + }) + + expect(queryClient.getQueryData(key)).toBe('prefetched') + }) +}) diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 0ac38c9c03..97f84a9882 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -39,6 +39,7 @@ export type { UndefinedInitialDataOptions, } from './queryOptions' export { + FLIGHT_DATA_SOURCE, QueryClientContext, QueryClientProvider, useQueryClient, From 47f7057a11f11ffdb097ccccb32d276964c7fe2a Mon Sep 17 00:00:00 2001 From: Ryan Carniato Date: Sat, 29 Aug 2026 01:53:09 -0700 Subject: [PATCH 2/3] feat(solid-query): dehydrateSettled, SSR teardown, and dehydrate filtering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fills the gaps the router-ssr-query transport used to cover, natively: - dehydrateSettled(client): the extraction half of a single-flight collector — waits for every in-flight fetch (chased to quiescence) so loaders' fire-and-forget prefetches land before dehydrating. - SSR teardown: the provider cancels and clears the per-request cache on render disposal, so user-configured finite gcTime timers cannot pin the client after the response. - The registry serializer now respects defaultOptions.dehydrate .shouldDehydrateQuery, the same knob apps use on any other transport. Co-authored-by: Cursor --- .../solid-query/src/QueryClientProvider.tsx | 18 ++++ .../src/__tests__/dehydrateSettled.test.tsx | 79 ++++++++++++++ .../hydration/entry-server-stream.tsx | 36 +++++-- .../fixtures/hydration/entry-server.tsx | 100 +++++++++++++----- .../src/__tests__/hydration-utils.ts | 6 ++ .../src/__tests__/hydration.test.tsx | 25 +++++ packages/solid-query/src/dehydrateSettled.ts | 42 ++++++++ packages/solid-query/src/index.ts | 1 + 8 files changed, 274 insertions(+), 33 deletions(-) create mode 100644 packages/solid-query/src/__tests__/dehydrateSettled.test.tsx create mode 100644 packages/solid-query/src/dehydrateSettled.ts diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index 2bac88b54e..e1e092f5fd 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -100,9 +100,18 @@ function serializeCacheOnServer(client: QueryClient): void { if (!ctx || !ctx.async || ctx.noHydrate) return const cache = client.getQueryCache() + // The standard dehydrate filter gates the wire here too, so apps keep + // sensitive or oversized queries out of the HTML with the same option + // they'd pass any other transport. + const shouldDehydrateQuery = + client.getDefaultOptions().dehydrate?.shouldDehydrateQuery const seen = new Set() const serializeQuery = (query: Query) => { if (seen.has(query.queryHash)) return + // Consulted per cache event until it passes, so a filter that rejects + // pending queries (e.g. the core default) still admits the settled + // value if it lands while the request's serialization context is live. + if (shouldDehydrateQuery && !shouldDehydrateQuery(query)) return const state = query.state if (state.status === 'success') { seen.add(query.queryHash) @@ -149,6 +158,15 @@ export const QueryClientProvider = ( onCleanup(() => props.client.unmount()) if (isServer) { serializeCacheOnServer(props.client) + // Render disposal ends the request: abort what's still in flight and + // drop the cache so user-configured finite gcTime timers can't pin + // the per-request client (and whatever its queries closed over) until + // they fire. Serialized promises are already in seroval's hands, so + // clearing here can't affect the streamed payload. + onCleanup(() => { + props.client.cancelQueries().catch(() => undefined) + props.client.clear() + }) } else { // Client-only: the server's consumer registry is module state shared // across requests — registering there would leak between them. diff --git a/packages/solid-query/src/__tests__/dehydrateSettled.test.tsx b/packages/solid-query/src/__tests__/dehydrateSettled.test.tsx new file mode 100644 index 0000000000..a25a60cb3d --- /dev/null +++ b/packages/solid-query/src/__tests__/dehydrateSettled.test.tsx @@ -0,0 +1,79 @@ +import { describe, expect, it } from 'vitest' +import { QueryClient } from '../QueryClient' +import { dehydrateSettled } from '../dehydrateSettled' + +const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) + +describe('dehydrateSettled', () => { + it('waits for in-flight fetches instead of snapshotting mid-fetch', async () => { + const client = new QueryClient() + // Fire-and-forget, the way loaders hint prefetches. + void client.prefetchQuery({ + queryKey: ['slow'], + queryFn: async () => { + await sleep(20) + return 'slow-data' + }, + }) + + const state = await dehydrateSettled(client) + + const query = state.queries.find((q) => q.queryHash === '["slow"]') + expect(query?.state.data).toBe('slow-data') + expect(query?.state.status).toBe('success') + }) + + it('chases fetches dispatched by earlier settlements to quiescence', async () => { + const client = new QueryClient() + void client.prefetchQuery({ + queryKey: ['first'], + queryFn: async () => { + await sleep(10) + // A dependent fetch that only exists once the first one lands. + void client.prefetchQuery({ + queryKey: ['second'], + queryFn: async () => { + await sleep(10) + return 'second-data' + }, + }) + return 'first-data' + }, + }) + + const state = await dehydrateSettled(client) + + expect(state.queries.map((q) => q.queryHash).sort()).toEqual([ + '["first"]', + '["second"]', + ]) + expect( + state.queries.find((q) => q.queryHash === '["second"]')?.state.data, + ).toBe('second-data') + }) + + it('settles failures without rejecting and forwards dehydrate options', async () => { + const client = new QueryClient() + void client.prefetchQuery({ + queryKey: ['ok'], + queryFn: async () => { + await sleep(5) + return 'ok-data' + }, + }) + void client.prefetchQuery({ + queryKey: ['boom'], + retry: false, + queryFn: async () => { + await sleep(5) + throw new Error('nope') + }, + }) + + const state = await dehydrateSettled(client, { + shouldDehydrateQuery: (query) => query.state.status === 'success', + }) + + expect(state.queries.map((q) => q.queryHash)).toEqual(['["ok"]']) + }) +}) diff --git a/packages/solid-query/src/__tests__/fixtures/hydration/entry-server-stream.tsx b/packages/solid-query/src/__tests__/fixtures/hydration/entry-server-stream.tsx index 8dc8d005f7..f88ca7e6a6 100644 --- a/packages/solid-query/src/__tests__/fixtures/hydration/entry-server-stream.tsx +++ b/packages/solid-query/src/__tests__/fixtures/hydration/entry-server-stream.tsx @@ -7,11 +7,29 @@ import { renderToStream } from '@solidjs/web' import { QueryClient } from '@tanstack/solid-query' import { StreamApp } from './StreamApp' +import type { Query } from '@tanstack/solid-query' import type { StreamCounts } from './StreamApp' const client = new QueryClient() const counts: StreamCounts = { header: 0, feed: 0 } +// The provider clears the cache when the render disposes (the SSR +// teardown), so query states are recorded live off cache events rather +// than read back after completion. +const snapshots = new Map< + string, + { queryKey: unknown; queryHash: string; state: unknown } +>() +client.getQueryCache().subscribe((event) => { + if (event.type === 'removed') return + const query: Query = event.query + snapshots.set(query.queryHash, { + queryKey: query.queryKey, + queryHash: query.queryHash, + state: query.state, + }) +}) + const start = Date.now() const chunks: Array<{ t: number; payload: string }> = [] @@ -28,13 +46,13 @@ await new Promise((resolve) => { }) }) -const queries = client - .getQueryCache() - .getAll() - .map((query) => ({ - queryKey: query.queryKey, - queryHash: query.queryHash, - state: query.state, - })) +const cacheEmptyAfterDispose = client.getQueryCache().getAll().length === 0 -console.log(JSON.stringify({ chunks, counts, queries })) +console.log( + JSON.stringify({ + chunks, + counts, + queries: [...snapshots.values()], + cacheEmptyAfterDispose, + }), +) diff --git a/packages/solid-query/src/__tests__/fixtures/hydration/entry-server.tsx b/packages/solid-query/src/__tests__/fixtures/hydration/entry-server.tsx index e96396c264..6a60f1766a 100644 --- a/packages/solid-query/src/__tests__/fixtures/hydration/entry-server.tsx +++ b/packages/solid-query/src/__tests__/fixtures/hydration/entry-server.tsx @@ -7,8 +7,55 @@ import { renderToStream } from '@solidjs/web' import { QueryClient } from '@tanstack/solid-query' import { App } from './App' +import type { Query } from '@tanstack/solid-query' import type { FetchCounts } from './App' +interface QuerySnapshot { + queryKey: unknown + queryHash: string + state: unknown +} + +/** + * The provider clears the cache when the render disposes (the SSR + * teardown), so query states are recorded live off cache events rather + * than read back after completion. States are immutable objects in + * query-core; keeping the latest per hash is an accurate snapshot. + */ +function trackSnapshots(client: QueryClient): Map { + const snapshots = new Map() + const record = (query: Query) => { + snapshots.set(query.queryHash, { + queryKey: query.queryKey, + queryHash: query.queryHash, + state: query.state, + }) + } + client.getQueryCache().subscribe((event) => { + if (event.type !== 'removed') record(event.query) + }) + return snapshots +} + +function renderApp(client: QueryClient, counts: FetchCounts): Promise { + return new Promise((resolve) => { + let out = '' + // Collected through pipe() rather than the thenable form so the fixture + // builds against any solid-js 2 beta (renderToStringAsync was removed + // after beta.29). + renderToStream(() => ( + + )).pipe({ + write(payload: string) { + out += payload + }, + end() { + resolve(out) + }, + }) + }) +} + const client = new QueryClient() const counts: FetchCounts = { fresh: 0, @@ -16,31 +63,36 @@ const counts: FetchCounts = { placeholder: 0, prefetched: 0, } +const snapshots = trackSnapshots(client) +const html = await renderApp(client, counts) -// Fully-settled single-string render. Collected through pipe() rather than -// the thenable form so the fixture builds against any solid-js 2 beta -// (renderToStringAsync was removed after beta.29). -const html = await new Promise((resolve) => { - let out = '' - renderToStream(() => ( - - )).pipe({ - write(payload: string) { - out += payload - }, - end() { - resolve(out) +// The dispose-time teardown must have emptied the per-request cache. +const cacheEmptyAfterDispose = client.getQueryCache().getAll().length === 0 + +// Second pass: same app on a client whose standard dehydrate filter +// excludes the stale query — its registry entry must stay off the wire +// while the others still ship. +const filteredClient = new QueryClient({ + defaultOptions: { + dehydrate: { + shouldDehydrateQuery: (query) => query.queryKey[0] !== 'stale', }, - }) + }, }) +const filteredCounts: FetchCounts = { + fresh: 0, + stale: 0, + placeholder: 0, + prefetched: 0, +} +const filteredHtml = await renderApp(filteredClient, filteredCounts) -const queries = client - .getQueryCache() - .getAll() - .map((query) => ({ - queryKey: query.queryKey, - queryHash: query.queryHash, - state: query.state, - })) - -console.log(JSON.stringify({ html, counts, queries })) +console.log( + JSON.stringify({ + html, + counts, + queries: [...snapshots.values()], + cacheEmptyAfterDispose, + filteredHtml, + }), +) diff --git a/packages/solid-query/src/__tests__/hydration-utils.ts b/packages/solid-query/src/__tests__/hydration-utils.ts index 9b53daad17..648a5f628b 100644 --- a/packages/solid-query/src/__tests__/hydration-utils.ts +++ b/packages/solid-query/src/__tests__/hydration-utils.ts @@ -38,11 +38,17 @@ export interface ServerReport { prefetched: number } queries: Array + /** Whether the provider's dispose-time teardown emptied the cache. */ + cacheEmptyAfterDispose: boolean + /** Same app rendered on a client whose `defaultOptions.dehydrate. + * shouldDehydrateQuery` excludes the stale query. */ + filteredHtml: string } stream: { chunks: Array<{ t: number; payload: string }> counts: { header: number; feed: number } queries: Array + cacheEmptyAfterDispose: boolean } } diff --git a/packages/solid-query/src/__tests__/hydration.test.tsx b/packages/solid-query/src/__tests__/hydration.test.tsx index f62c04d55d..c4271ed7bf 100644 --- a/packages/solid-query/src/__tests__/hydration.test.tsx +++ b/packages/solid-query/src/__tests__/hydration.test.tsx @@ -99,6 +99,31 @@ describe('SSR hydration', () => { ) }) + it('clears the per-request cache when the render disposes', () => { + // The provider's dispose-time teardown (cancel + clear) must leave + // nothing behind: user-configured finite gcTime schedules timers on + // fetched queries, and without the clear those timers pin the + // per-request client (and everything its queries closed over) alive + // until they fire. + expect(harness.report.string.cacheEmptyAfterDispose).toBe(true) + expect(harness.report.stream.cacheEmptyAfterDispose).toBe(true) + }) + + it('keeps filtered queries out of the payload via shouldDehydrateQuery', () => { + const { filteredHtml } = harness.report.string + // The filtered client renders the data into the HTML as usual... + expect(filteredHtml).toContain('stale-server') + // ...but the standard dehydrate filter gates the registry, so the + // stale query's cache entry never ships, + expect(filteredHtml).not.toMatch(/sq:\[\\"stale\\"\]/) + // while unfiltered queries transfer exactly as before — including the + // never-rendered prefetch. + expect(filteredHtml).toMatch( + /sq:\[\\"fresh\\"\]"\]=[^<]*data:"fresh-server"/, + ) + expect(filteredHtml).toMatch(/sq:\[\\"prefetched\\"\]/) + }) + it('hydration primes the query cache and refetches only per staleness rules', async () => { const { string } = harness.report const app = bundle.createApp() diff --git a/packages/solid-query/src/dehydrateSettled.ts b/packages/solid-query/src/dehydrateSettled.ts new file mode 100644 index 0000000000..8c8dc5c9ef --- /dev/null +++ b/packages/solid-query/src/dehydrateSettled.ts @@ -0,0 +1,42 @@ +import { dehydrate } from '@tanstack/query-core' +import type { DehydrateOptions, DehydratedState } from '@tanstack/query-core' +import type { QueryClient } from './QueryClient' + +/** + * Waits for every fetch the client has in flight to settle, then + * dehydrates. This is the extraction half of a single-flight collector: + * after route data functions run for the mutation's target URL, loaders + * commonly kick off prefetches without awaiting them — plain + * `dehydrate()` would snapshot those mid-fetch and ship nothing. + * + * ```ts + * registerFlightDataSource(FLIGHT_DATA_SOURCE, (event, outcome) => + * loadFlightTarget({ + * router, + * event, + * outcome, + * collect: () => dehydrateSettled(queryClient), + * }), + * ) + * ``` + * + * Settling is chased to quiescence — awaiting one batch of fetches can + * dispatch more (dependent queries keyed off a first result) — so an + * unconditionally self-refetching query would keep this pending; that's + * an app bug mirrored, not guarded. + */ +export async function dehydrateSettled( + client: QueryClient, + options?: DehydrateOptions, +): Promise { + const cache = client.getQueryCache() + for (;;) { + const pending = cache + .getAll() + .filter((query) => query.state.fetchStatus !== 'idle') + .map((query) => query.promise) + if (pending.length === 0) break + await Promise.allSettled(pending) + } + return dehydrate(client, options) +} diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 97f84a9882..4325d5aa15 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -45,6 +45,7 @@ export { useQueryClient, } from './QueryClientProvider' export type { QueryClientProviderProps } from './QueryClientProvider' +export { dehydrateSettled } from './dehydrateSettled' export { useIsFetching } from './useIsFetching' export { useInfiniteQuery } from './useInfiniteQuery' export { infiniteQueryOptions } from './infiniteQueryOptions' From 5f2f3fe6d19f9c9b4c13cc367f63ed8c0bfdb0c6 Mon Sep 17 00:00:00 2001 From: Ryan Carniato Date: Wed, 2 Sep 2026 14:22:12 -0700 Subject: [PATCH 3/3] chore(solid-query): require solid 2.0.0-rc.6, drop the subscribe type bridge rc.6 publishes the named flight-data source API with real types, so the subscribeFlightData cast goes away; the peer floor moves to rc.6 because rc.5's settle-walk regression breaks query hydration. Also adds the missing changeset for dehydrateSettled and the SSR teardown work. Co-authored-by: Cursor --- .changeset/dehydrate-settled.md | 5 + .changeset/solid-rc-6-floor.md | 7 + packages/solid-query-devtools/package.json | 6 +- .../solid-query-persist-client/package.json | 4 +- packages/solid-query/package.json | 7 +- .../solid-query/src/QueryClientProvider.tsx | 13 +- pnpm-lock.yaml | 206 +++++------------- 7 files changed, 80 insertions(+), 168 deletions(-) create mode 100644 .changeset/dehydrate-settled.md create mode 100644 .changeset/solid-rc-6-floor.md diff --git a/.changeset/dehydrate-settled.md b/.changeset/dehydrate-settled.md new file mode 100644 index 0000000000..06fcadde6f --- /dev/null +++ b/.changeset/dehydrate-settled.md @@ -0,0 +1,5 @@ +--- +'@tanstack/solid-query': minor +--- + +SSR lifecycle utilities: new `dehydrateSettled` awaits in-flight queries before dehydrating so streamed HTML carries settled data; `QueryClientProvider` tears the client down after server render disposal (`cancelQueries` + `clear`, preventing cross-request leaks) and dehydration now respects `defaultOptions.dehydrate.shouldDehydrateQuery` filtering. diff --git a/.changeset/solid-rc-6-floor.md b/.changeset/solid-rc-6-floor.md new file mode 100644 index 0000000000..3ddcd442c8 --- /dev/null +++ b/.changeset/solid-rc-6-floor.md @@ -0,0 +1,7 @@ +--- +'@tanstack/solid-query': patch +'@tanstack/solid-query-devtools': patch +'@tanstack/solid-query-persist-client': patch +--- + +Require solid-js and @solidjs/web 2.0.0-rc.6+. rc.6 ships the named flight-data source API the single-flight consumer uses, plus the async settle fix the adapter depends on (rc.5's settle-walk regression breaks query hydration). diff --git a/packages/solid-query-devtools/package.json b/packages/solid-query-devtools/package.json index d614405621..471f6caad1 100644 --- a/packages/solid-query-devtools/package.json +++ b/packages/solid-query-devtools/package.json @@ -67,14 +67,14 @@ "devDependencies": { "@babel/core": "^7.28.0", "@babel/preset-typescript": "^7.18.6", - "@solidjs/signals": "^2.0.0-rc.0", + "@solidjs/signals": "^2.0.0-rc.6", "@solidjs/testing-library": "^0.8.10", "@solidjs/vite-plugin": "^3.0.0-next.27", - "@solidjs/web": "^2.0.0-rc.3", + "@solidjs/web": "^2.0.0-rc.6", "@tanstack/solid-query": "workspace:*", "babel-preset-solid": "^2.0.0-rc.2", "npm-run-all2": "^5.0.0", - "solid-js": "^2.0.0-rc.3", + "solid-js": "^2.0.0-rc.6", "tsup-preset-solid": "^2.2.0" }, "peerDependencies": { diff --git a/packages/solid-query-persist-client/package.json b/packages/solid-query-persist-client/package.json index 05dc07041b..5ebfdc02f5 100644 --- a/packages/solid-query-persist-client/package.json +++ b/packages/solid-query-persist-client/package.json @@ -70,12 +70,12 @@ "@babel/preset-typescript": "^7.18.6", "@solidjs/testing-library": "^0.8.10", "@solidjs/vite-plugin": "^3.0.0-next.27", - "@solidjs/web": "^2.0.0-rc.3", + "@solidjs/web": "^2.0.0-rc.6", "@tanstack/query-test-utils": "workspace:*", "@tanstack/solid-query": "workspace:*", "babel-preset-solid": "^2.0.0-rc.2", "npm-run-all2": "^5.0.0", - "solid-js": "^2.0.0-rc.4", + "solid-js": "^2.0.0-rc.6", "tsup-preset-solid": "^2.2.0" }, "peerDependencies": { diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json index 6fc4c4958a..5d1a8f6178 100644 --- a/packages/solid-query/package.json +++ b/packages/solid-query/package.json @@ -72,14 +72,15 @@ "@babel/preset-typescript": "^7.18.6", "@solidjs/testing-library": "^0.8.10", "@solidjs/vite-plugin": "^3.0.0-next.27", - "@solidjs/web": "^2.0.0-rc.3", + "@solidjs/web": "^2.0.0-rc.6", "@tanstack/query-test-utils": "workspace:*", "babel-preset-solid": "^2.0.0-rc.2", "npm-run-all2": "^5.0.0", - "solid-js": "^2.0.0-rc.4", + "solid-js": "^2.0.0-rc.6", "tsup-preset-solid": "^2.2.0" }, "peerDependencies": { - "solid-js": ">=2.0.0-rc.4 <3.0.0" + "@solidjs/web": ">=2.0.0-rc.6 <3.0.0", + "solid-js": ">=2.0.0-rc.6 <3.0.0" } } diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index e1e092f5fd..5d1a247c5c 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -38,17 +38,6 @@ export const HYDRATION_KEY_PREFIX = 'sq:' */ export const FLIGHT_DATA_SOURCE = 'sq' -// The named-source overload of subscribeFlightData ships in the -// @solidjs/web release after 2.0.0-rc.4 (solidjs/solid#653dd41e); this -// cast bridges the installed types until the peer range bumps. -const subscribeFlightSource = subscribeFlightData as unknown as ( - source: string, - consumer: ( - data: DehydratedState, - context: { response: Response }, - ) => void | Promise, -) => () => void - export const QueryClientContext = createContext<(() => QueryClient) | null>( null, ) @@ -171,7 +160,7 @@ export const QueryClientProvider = ( // Client-only: the server's consumer registry is module state shared // across requests — registering there would leak between them. onCleanup( - subscribeFlightSource(FLIGHT_DATA_SOURCE, (data) => { + subscribeFlightData(FLIGHT_DATA_SOURCE, (data) => { hydrate(props.client, data) }), ) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1434b4147d..3b8be6e149 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2955,28 +2955,28 @@ importers: version: 7.28.5(@babel/core@7.29.0) '@solidjs/testing-library': specifier: ^0.8.10 - version: 0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.4))(solid-js@2.0.0-rc.4) + version: 0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.6))(solid-js@2.0.0-rc.6) '@solidjs/vite-plugin': specifier: ^3.0.0-next.27 - version: 3.0.0-next.27(@solidjs/web@2.0.0-rc.3(solid-js@2.0.0-rc.4))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.4)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 3.0.0-next.27(@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.6)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) '@solidjs/web': - specifier: ^2.0.0-rc.3 - version: 2.0.0-rc.3(solid-js@2.0.0-rc.4) + specifier: ^2.0.0-rc.6 + version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) '@tanstack/query-test-utils': specifier: workspace:* version: link:../query-test-utils babel-preset-solid: specifier: ^2.0.0-rc.2 - version: 2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.4) + version: 2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.6) npm-run-all2: specifier: ^5.0.0 version: 5.0.2 solid-js: - specifier: ^2.0.0-rc.4 - version: 2.0.0-rc.4 + specifier: ^2.0.0-rc.6 + version: 2.0.0-rc.6 tsup-preset-solid: specifier: ^2.2.0 - version: 2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.4)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)) + version: 2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.6)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)) packages/solid-query-devtools: dependencies: @@ -2991,32 +2991,32 @@ importers: specifier: ^7.18.6 version: 7.28.5(@babel/core@7.29.0) '@solidjs/signals': - specifier: ^2.0.0-rc.0 - version: 2.0.0-rc.0 + specifier: ^2.0.0-rc.6 + version: 2.0.0-rc.6 '@solidjs/testing-library': specifier: ^0.8.10 - version: 0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.3))(solid-js@2.0.0-rc.3) + version: 0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.6))(solid-js@2.0.0-rc.6) '@solidjs/vite-plugin': specifier: ^3.0.0-next.27 - version: 3.0.0-next.27(@solidjs/web@2.0.0-rc.3(solid-js@2.0.0-rc.3))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 3.0.0-next.27(@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.6)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) '@solidjs/web': - specifier: ^2.0.0-rc.3 - version: 2.0.0-rc.3(solid-js@2.0.0-rc.3) + specifier: ^2.0.0-rc.6 + version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) '@tanstack/solid-query': specifier: workspace:* version: link:../solid-query babel-preset-solid: specifier: ^2.0.0-rc.2 - version: 2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.3) + version: 2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.6) npm-run-all2: specifier: ^5.0.0 version: 5.0.2 solid-js: - specifier: ^2.0.0-rc.3 - version: 2.0.0-rc.3 + specifier: ^2.0.0-rc.6 + version: 2.0.0-rc.6 tsup-preset-solid: specifier: ^2.2.0 - version: 2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.3)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)) + version: 2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.6)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)) packages/solid-query-persist-client: dependencies: @@ -3032,13 +3032,13 @@ importers: version: 7.28.5(@babel/core@7.29.0) '@solidjs/testing-library': specifier: ^0.8.10 - version: 0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.4))(solid-js@2.0.0-rc.4) + version: 0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.6))(solid-js@2.0.0-rc.6) '@solidjs/vite-plugin': specifier: ^3.0.0-next.27 - version: 3.0.0-next.27(@solidjs/web@2.0.0-rc.3(solid-js@2.0.0-rc.4))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.4)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 3.0.0-next.27(@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.6)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) '@solidjs/web': - specifier: ^2.0.0-rc.3 - version: 2.0.0-rc.3(solid-js@2.0.0-rc.4) + specifier: ^2.0.0-rc.6 + version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) '@tanstack/query-test-utils': specifier: workspace:* version: link:../query-test-utils @@ -3047,16 +3047,16 @@ importers: version: link:../solid-query babel-preset-solid: specifier: ^2.0.0-rc.2 - version: 2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.4) + version: 2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.6) npm-run-all2: specifier: ^5.0.0 version: 5.0.2 solid-js: - specifier: ^2.0.0-rc.4 - version: 2.0.0-rc.4 + specifier: ^2.0.0-rc.6 + version: 2.0.0-rc.6 tsup-preset-solid: specifier: ^2.2.0 - version: 2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.4)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)) + version: 2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.6)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)) packages/svelte-query: dependencies: @@ -7228,11 +7228,8 @@ packages: '@solidjs/signals@2.0.0-rc.0': resolution: {integrity: sha512-oKZSfvsCcKw1uJjOGbUkJ+OqlhXLHtZ+rShSyu9KH0lUH7UUwfMfsKeh81JPiQxDDg4YLhEwI38hg0JkwzTdvA==} - '@solidjs/signals@2.0.0-rc.3': - resolution: {integrity: sha512-/yPhTf3xS1FRR4MX8kTYCd4MjsFxzwkO+KyOTfbu35lTEiaJ4Fxy+JL91XonDzt31GV1mYaZ9CGD2TQIzvXuNA==} - - '@solidjs/signals@2.0.0-rc.4': - resolution: {integrity: sha512-l7P0g8+2pnNscaIPOGDMhv0boaidGAsvR8QN66JySIWNMvVnuq2ayv7ZnvP+IR00DJC+RqCNnnTG/UCdxf+h8g==} + '@solidjs/signals@2.0.0-rc.6': + resolution: {integrity: sha512-lPqwZNLPq1Z9CBvgXkMvi1ZFr5OHUiFNz1X40+yehszDWEbJkneZx7BGKIe9eMT/AN1NSL+PMjOiMyZaqVB2xw==} '@solidjs/start@1.3.2': resolution: {integrity: sha512-tasDl3utVbtP0rr4InB3ntBIFV2upvEiFrOOCkRrAA3yBfjx9elpxnc94sJQXo65PNYdAAAkPIC6h93vLrtwHg==} @@ -7265,10 +7262,10 @@ packages: peerDependencies: solid-js: ^2.0.0-rc.0 - '@solidjs/web@2.0.0-rc.3': - resolution: {integrity: sha512-5ckKgOjem1pN5ADycOk6TjHmTtjbbN2fukqxo6RW3Oe3H7z0gaXWAdt8dLISto5/O4Nn8VxprFXFWpfy31+DUg==} + '@solidjs/web@2.0.0-rc.6': + resolution: {integrity: sha512-JgQ2NCjygQpZizZrVjcwPqH3dhIZQZoMRGoGSC6+Tr622cvbuXthDC3pKdNMsjCKCVp19UbT0kkPX15FOdT0pw==} peerDependencies: - solid-js: ^2.0.0-rc.3 + solid-js: ^2.0.0-rc.6 '@speed-highlight/core@1.2.15': resolution: {integrity: sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==} @@ -14818,11 +14815,8 @@ packages: solid-js@2.0.0-rc.0: resolution: {integrity: sha512-3enTJ71VL69nM5p/it2InVBDBt316Cqfij+F0S7VuHZLITc8YV7Rvavjoy52nAKKxYWXM+BcXh2K7KcLTf1zdQ==} - solid-js@2.0.0-rc.3: - resolution: {integrity: sha512-pmW6bRoTvfp/rN4jN7JmLvSaoIpFt7wm0Hi3j508S/smuJqUbRg3dQEjOPTkAwHW+McYnXrMG7cJ4AMNpLevtQ==} - - solid-js@2.0.0-rc.4: - resolution: {integrity: sha512-hSkDmtduesjFtvzjNyqLphrqiSvhSD5+njkPQUR+9YEoR60MMWtuv36SbLL4OucI0Ronof3Jc+AsUp0oWffwMg==} + solid-js@2.0.0-rc.6: + resolution: {integrity: sha512-Z/M8s9ypLBf+6Bl3AAb5upgkYCl73HkpM+UxdUJ5uFGctTwpOQVCM9Gpj3Mjbiaki270HHUfA3Z0Lyn4w+fDtg==} solid-presence@0.1.8: resolution: {integrity: sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA==} @@ -21180,21 +21174,14 @@ snapshots: dependencies: solid-js: 2.0.0-rc.0 - '@solidjs/router@0.15.4(solid-js@2.0.0-rc.3)': + '@solidjs/router@0.15.4(solid-js@2.0.0-rc.6)': dependencies: - solid-js: 2.0.0-rc.3 - optional: true - - '@solidjs/router@0.15.4(solid-js@2.0.0-rc.4)': - dependencies: - solid-js: 2.0.0-rc.4 + solid-js: 2.0.0-rc.6 optional: true '@solidjs/signals@2.0.0-rc.0': {} - '@solidjs/signals@2.0.0-rc.3': {} - - '@solidjs/signals@2.0.0-rc.4': {} + '@solidjs/signals@2.0.0-rc.6': {} '@solidjs/start@1.3.2(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.0)(vinxi@0.5.11(@types/node@22.19.15)(@vercel/functions@2.2.13)(db0@0.3.4)(idb-keyval@6.2.2)(ioredis@5.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: @@ -21227,19 +21214,12 @@ snapshots: optionalDependencies: '@solidjs/router': 0.15.4(solid-js@1.9.12) - '@solidjs/testing-library@0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.3))(solid-js@2.0.0-rc.3)': + '@solidjs/testing-library@0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.6))(solid-js@2.0.0-rc.6)': dependencies: '@testing-library/dom': 10.4.1 - solid-js: 2.0.0-rc.3 + solid-js: 2.0.0-rc.6 optionalDependencies: - '@solidjs/router': 0.15.4(solid-js@2.0.0-rc.3) - - '@solidjs/testing-library@0.8.10(@solidjs/router@0.15.4(solid-js@2.0.0-rc.4))(solid-js@2.0.0-rc.4)': - dependencies: - '@testing-library/dom': 10.4.1 - solid-js: 2.0.0-rc.4 - optionalDependencies: - '@solidjs/router': 0.15.4(solid-js@2.0.0-rc.4) + '@solidjs/router': 0.15.4(solid-js@2.0.0-rc.6) '@solidjs/vite-plugin@3.0.0-next.27(@solidjs/web@2.0.0-rc.0(solid-js@2.0.0-rc.0))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.0)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: @@ -21258,33 +21238,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@solidjs/vite-plugin@3.0.0-next.27(@solidjs/web@2.0.0-rc.3(solid-js@2.0.0-rc.3))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/core': 7.29.0 - '@dom-expressions/compiler': 0.50.0-next.40 - '@solidjs/web': 2.0.0-rc.3(solid-js@2.0.0-rc.3) - '@types/babel__core': 7.20.5 - babel-preset-solid: 2.0.0-beta.33(@babel/core@7.29.0)(solid-js@2.0.0-rc.3) - merge-anything: 5.1.7 - solid-js: 2.0.0-rc.3 - vite: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) - vitefu: 1.1.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) - optionalDependencies: - '@testing-library/jest-dom': 6.9.1 - transitivePeerDependencies: - - supports-color - - '@solidjs/vite-plugin@3.0.0-next.27(@solidjs/web@2.0.0-rc.3(solid-js@2.0.0-rc.4))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.4)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))': + '@solidjs/vite-plugin@3.0.0-next.27(@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6))(@testing-library/jest-dom@6.9.1)(solid-js@2.0.0-rc.6)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@ampproject/remapping': 2.3.0 '@babel/core': 7.29.0 '@dom-expressions/compiler': 0.50.0-next.40 - '@solidjs/web': 2.0.0-rc.3(solid-js@2.0.0-rc.4) + '@solidjs/web': 2.0.0-rc.6(solid-js@2.0.0-rc.6) '@types/babel__core': 7.20.5 - babel-preset-solid: 2.0.0-beta.33(@babel/core@7.29.0)(solid-js@2.0.0-rc.4) + babel-preset-solid: 2.0.0-beta.33(@babel/core@7.29.0)(solid-js@2.0.0-rc.6) merge-anything: 5.1.7 - solid-js: 2.0.0-rc.4 + solid-js: 2.0.0-rc.6 vite: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) vitefu: 1.1.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) optionalDependencies: @@ -21298,17 +21261,11 @@ snapshots: seroval-plugins: 1.5.6(seroval@1.5.6) solid-js: 2.0.0-rc.0 - '@solidjs/web@2.0.0-rc.3(solid-js@2.0.0-rc.3)': - dependencies: - seroval: 1.5.6 - seroval-plugins: 1.5.6(seroval@1.5.6) - solid-js: 2.0.0-rc.3 - - '@solidjs/web@2.0.0-rc.3(solid-js@2.0.0-rc.4)': + '@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6)': dependencies: seroval: 1.5.6 seroval-plugins: 1.5.6(seroval@1.5.6) - solid-js: 2.0.0-rc.4 + solid-js: 2.0.0-rc.6 '@speed-highlight/core@1.2.15': {} @@ -23379,19 +23336,12 @@ snapshots: optionalDependencies: solid-js: 2.0.0-rc.0 - babel-preset-solid@1.9.12(@babel/core@7.29.0)(solid-js@2.0.0-rc.3): + babel-preset-solid@1.9.12(@babel/core@7.29.0)(solid-js@2.0.0-rc.6): dependencies: '@babel/core': 7.29.0 babel-plugin-jsx-dom-expressions: 0.40.6(@babel/core@7.29.0) optionalDependencies: - solid-js: 2.0.0-rc.3 - - babel-preset-solid@1.9.12(@babel/core@7.29.0)(solid-js@2.0.0-rc.4): - dependencies: - '@babel/core': 7.29.0 - babel-plugin-jsx-dom-expressions: 0.40.6(@babel/core@7.29.0) - optionalDependencies: - solid-js: 2.0.0-rc.4 + solid-js: 2.0.0-rc.6 babel-preset-solid@2.0.0-beta.33(@babel/core@7.29.0)(solid-js@2.0.0-rc.0): dependencies: @@ -23400,33 +23350,19 @@ snapshots: optionalDependencies: solid-js: 2.0.0-rc.0 - babel-preset-solid@2.0.0-beta.33(@babel/core@7.29.0)(solid-js@2.0.0-rc.3): - dependencies: - '@babel/core': 7.29.0 - '@dom-expressions/babel-plugin-jsx': 0.50.0-next.41(@babel/core@7.29.0) - optionalDependencies: - solid-js: 2.0.0-rc.3 - - babel-preset-solid@2.0.0-beta.33(@babel/core@7.29.0)(solid-js@2.0.0-rc.4): + babel-preset-solid@2.0.0-beta.33(@babel/core@7.29.0)(solid-js@2.0.0-rc.6): dependencies: '@babel/core': 7.29.0 '@dom-expressions/babel-plugin-jsx': 0.50.0-next.41(@babel/core@7.29.0) optionalDependencies: - solid-js: 2.0.0-rc.4 - - babel-preset-solid@2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.3): - dependencies: - '@babel/core': 7.29.0 - '@dom-expressions/babel-plugin-jsx': 0.50.0-next.44(@babel/core@7.29.0) - optionalDependencies: - solid-js: 2.0.0-rc.3 + solid-js: 2.0.0-rc.6 - babel-preset-solid@2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.4): + babel-preset-solid@2.0.0-rc.2(@babel/core@7.29.0)(solid-js@2.0.0-rc.6): dependencies: '@babel/core': 7.29.0 '@dom-expressions/babel-plugin-jsx': 0.50.0-next.44(@babel/core@7.29.0) optionalDependencies: - solid-js: 2.0.0-rc.4 + solid-js: 2.0.0-rc.6 bail@2.0.2: {} @@ -24978,23 +24914,13 @@ snapshots: transitivePeerDependencies: - supports-color - esbuild-plugin-solid@0.5.0(esbuild@0.27.4)(solid-js@2.0.0-rc.3): + esbuild-plugin-solid@0.5.0(esbuild@0.27.4)(solid-js@2.0.0-rc.6): dependencies: '@babel/core': 7.29.0 '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) - babel-preset-solid: 1.9.12(@babel/core@7.29.0)(solid-js@2.0.0-rc.3) + babel-preset-solid: 1.9.12(@babel/core@7.29.0)(solid-js@2.0.0-rc.6) esbuild: 0.27.4 - solid-js: 2.0.0-rc.3 - transitivePeerDependencies: - - supports-color - - esbuild-plugin-solid@0.5.0(esbuild@0.27.4)(solid-js@2.0.0-rc.4): - dependencies: - '@babel/core': 7.29.0 - '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) - babel-preset-solid: 1.9.12(@babel/core@7.29.0)(solid-js@2.0.0-rc.4) - esbuild: 0.27.4 - solid-js: 2.0.0-rc.4 + solid-js: 2.0.0-rc.6 transitivePeerDependencies: - supports-color @@ -31081,16 +31007,9 @@ snapshots: seroval: 1.5.6 seroval-plugins: 1.5.6(seroval@1.5.6) - solid-js@2.0.0-rc.3: - dependencies: - '@solidjs/signals': 2.0.0-rc.3 - csstype: 3.2.3 - seroval: 1.5.6 - seroval-plugins: 1.5.6(seroval@1.5.6) - - solid-js@2.0.0-rc.4: + solid-js@2.0.0-rc.6: dependencies: - '@solidjs/signals': 2.0.0-rc.4 + '@solidjs/signals': 2.0.0-rc.6 csstype: 3.2.3 seroval: 1.5.6 seroval-plugins: 1.5.6(seroval@1.5.6) @@ -31855,18 +31774,9 @@ snapshots: - solid-js - supports-color - tsup-preset-solid@2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.3)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)): - dependencies: - esbuild-plugin-solid: 0.5.0(esbuild@0.27.4)(solid-js@2.0.0-rc.3) - tsup: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) - transitivePeerDependencies: - - esbuild - - solid-js - - supports-color - - tsup-preset-solid@2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.4)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)): + tsup-preset-solid@2.2.0(esbuild@0.27.4)(solid-js@2.0.0-rc.6)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3)): dependencies: - esbuild-plugin-solid: 0.5.0(esbuild@0.27.4)(solid-js@2.0.0-rc.4) + esbuild-plugin-solid: 0.5.0(esbuild@0.27.4)(solid-js@2.0.0-rc.6) tsup: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@22.19.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) transitivePeerDependencies: - esbuild