-
-
Notifications
You must be signed in to change notification settings - Fork 5
feat: support Synced Queries #119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
f6fa84a
to
e5137fc
Compare
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@danielroe good to merge? |
apologies for the delay. I want to review with an eye to how we would implement in nuxt (where provide/inject is often not the best pattern). ideally something that would support lazy creation of the stateful singleton (ie on first access) |
I'm doing this. A global variable and checking if it exist on each access. I watch the user session but most of the time changing the value comes with navigation/reload so not sure how necessary it is. import { Zero } from "@rocicorp/zero";
import { schema, clientMutators } from "~~/zero";
import type { AuthData } from "~~/zero";
import { decodeJwt } from "jose";
let client: Zero<typeof schema, ReturnType<typeof clientMutators>>;
export function useZero() {
const { session } = useUserSession();
const config = useRuntimeConfig().public.zero;
const decodedJWT = computed<AuthData | undefined>(() => session.value?.token ? decodeJwt<AuthData>(session.value.token) : undefined);
const userID = computed(() => decodedJWT.value?.sub ?? 'anon');
watch([userID], () => {
if (client && client.userID === userID.value)
return;
if (client && !client.closed) {
client.close();
}
client = new Zero({
userID: userID.value,
auth: () => session.value?.token,
mutators: clientMutators(decodedJWT.value),
server: import.meta.client ? config.server : undefined,
schema,
});
}, { immediate: true });
return client;
} |
@danielroe would doing something along the lines of what Pinia does: export let activeZero: Zero<any, any> | undefined
export function setActiveZero(zero: Zero<any, any>) {
activeZero = zero
}
export function useZero() {
return ((hasInjectionContext() && inject(zeroSymbol)) || shallowRef(activeZero))
} in combination with the plugin proposed in this PR and a to-be-created Nuxt module be a step in the right direction? While not lazy-creation, it would make sure that Zero is available during SSR. You also keep the benefit of Although I need to add that I don't have a lot of experience with Nuxt, so if you know of any libraries that have a more 'nuxt-native' implementation that would be very welcome. |
This PR adds support for Synced Queries in a backwards compatible way. In order to achieve this, we had to find a way to give the
useQuery
composable access to the zero instance. We do this usingprovide
/inject
wrapped in a plugin,createZero
. The plugin takes either an initialized Zero instance or aZeroOptions
object.We also add a
createUseZero
factory, the output of which is just a wrapper around the inject call. By having this as a factory, we allow users to specify the types of the returnedZero
instance (which is also how the Solid lib is implemented).I'm still on the fence about whether we should also provide a
useZero
composable. It will allow users to get up and running more quickly, but I am not sure if many people are going to want to use this without types. Not including it means IntelliSense will provide you with only the import from your own project, instead of also the version we provide, which improves DX. Or are we able to get calls touseZero
typed based on the plugin registration?