Proxies
The core of the integration revolves around three proxies:
svelteQuery: Provides typical svelte-query hooks, e.g.createQuery,createMutation, etc.createQueries: Generates query options for any query procedures invoked; provided to thetrpc.createQueriescallback function. The resulting readonly array of options is passed to svelte-query'screateQueries.context: Provides helper functions with greater control over the query client. Generally intended to be used within components withsetContextandgetContext. Can be used directly if a query client is provided tosvelteQueryContextduring creation, i.e. in SvelteKitloadfunctions.
Folder Structure
- All proxies are located in the
src/proxiesfolder. - Each proxy has three files:
index: Exports everything from thetypesandimplementationfiles.types: Describes the perceived shape of the proxy.implementation: Implements the proxy, usually with a combination ofcreateFlatProxyandcreateRecursiveProxyfrom@trpc/server/shared.
Implementation
Most of the implementation was inspired by the official tRPC + react-query integration. You can read the blog posts here to get a better idea of how proxies and their typing works.
The main difference is the approach to handling root properties.
Based on this line here,
it seems that a new recursive proxy is created everytime a nested property
access is made to a non-designated root property (those being useContext, Provider, etc.).
This is because the inner recursive proxy "missed" the initial key, so it's invoked with the initial key and the previously generated hooks. But since it's a proxy, I thought you could just "access" it at the initial key to "re-insert" it. By doing this, I'm able to extract the creation of the inner recursive outside of the initial flat proxy, and only re-calculate the inner recursive proxy once, instead of on every access.
Miscellaneous
Extensions
Extends functionality of existing libraries
createReactiveQuery
Creates a query that will react to changes in the options if provided as a writable Svelte store.
Note that the options must be provided as a writable store.
For ease of use with tRPC, the createQuery hook in the proxy only requires the
procedure input to be provided as a writable store.
Internally, a new options writable store is created and linked to the input store.
The options store will automatically update itself when the input changes.
e.g. looks something like this
import { writable, get } from 'svelte/store'
import { getQueryKey } from '../../helpers/getQueryKey'
const client = TRPCUntypedClient(...)
// user provides a store as first input to the query
const input = writable('Mobius')
// user can provide more options as a regular object
const otherOptions = { keepPreviousData: true, trpc: { ... }, ... }
// create a custom options writable store
// based on the other options and current value of input
const optionsStore = writable({
queryKey: getQueryKey(path, get(input), 'query'),
queryFn: client.query(path, get(input), ...otherOptions.trpc),
...otherOptions,
}, (set) => {
const unsubscribe = input.subscribe((newInput) => {
set({
queryKey: getQueryKey(path, get(newInput), 'query'),
queryFn: client.query(path, get(newInput), ...otherOptions.trpc),
...otherOptions,
})
})
return () => {
unsubscribe()
}
})
return createReactiveQuery(optionsStore)
- the user provides a writable store and optionally some svelte-query options (regular object).
- A new
optionsStoreis created with the default protocol for creating aqueryKeyandqueryFn. - The second argument to
writableis used to subscribe to the input store.- Whenever input changes to a new value, set the
optionsStoreaccordingly - i.e. keep all of the original
otherOptionsthe same and recalculate thequeryKeyandqueryFnfor the new input
- Whenever input changes to a new value, set the
- Ensure the
optionsStoreunsubscribes from its subscription once it's done.
Hopefully this function can be deprecated in my library soon,
since this is pending release on @tanstack/svelte-query@alpha.
Or it could be kept around for legacy reasons.
Helpers
Helper functions for proxies
getQueryKey
Function that invokes a hidden _def() method on the tRPC + svelte-query proxy
to get the path array and call getQueryKeyInternal to get the query key used for that procedure/router.
getQueryKeyInternal
Function that accepts a path array, input, and a query type to generate a query key. Typically used inside proxies to assign a query key to a request. i.e. tRPC requests are effectively cached and identified by these keys.