-
-
Notifications
You must be signed in to change notification settings - Fork 32
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
How to use with JWT/RefreshToken? (and implement a retry strat) #157
Comments
Okay so at the moment I can't think of a solid implementation to show how we might go about implementing this. But quickly off the top of my head I can think of the following. The plugin API could make this work but you must implement a custom fetch plugin here since you want to avoid setting the GQL result before retrying a couple of times and after you've successfully generated the token. So starting off with the same codebase as the fetch plugin: import { GraphQLError } from 'graphql';
// getActiveClient() isn't available yet but you can store the `Client` instance from `useClient` or `createClient` globally somewhere until #156 is merged
// you will also probably need some utils from `villus` to be exposed which we can expose in a separate PR
import { getActiveClient } from 'villus';
import { RefreshToken } from '@/graphql/Auth.gql'
// this is to make sure we don't duplicate `RefreshToken` calls
let refreshPromise = null;
export function fetchWithRetry(opts) {
// same lines from 11 to 33
// https://github.com/logaretm/villus/blob/main/packages/villus/src/fetch.ts#L11-L33
// Change this to however you are going to figure out if the token is expired
// maybe you can check the payload error message
if (response.status === 401 && !refreshPromise) {
client = getActiveClient();
refreshPromise = client.executeMutation({ query: RefreshToken }).then(data => {
// store the new token or auth data somewhere and set it on the fetchOpts
setTimeout(() => {
// clear up the promise, you don't want to do this immediately so toy around with the timeout to test it
// maybe there is a more reliable way to clear it, but can't think of one at the moment
refreshPromise = null;
}, 100)
});
}
if (response.status === 401 && refreshPromise) {
await refreshPromise;
// re-execute the same code from lines 17 to 31
// https://github.com/logaretm/villus/blob/main/packages/villus/src/fetch.ts#L17-L31
}
// same rest of the fetch function
} This could need some clean up and some bug fixing. Anyways I think this is a good example worth adding to the docs I think, I will try to work on that on the weekend. |
We will need something like global error events. E.g. when creating a client, use the function useGlobalError and in it give a callback with the query used e.g. refetch()
|
sorry this is not an issue per se; but I couldn't find a satisfying answer anywhere else
Is there a proven strategy for the following?
I've been toying with the Plugin API and could get up to the refresh part, but there doesn't seem to be a way to centralize the "retry" strategy in this case.
We're to the point where we are wrapping useQuery/useMutation to handle this in 1 place, but I was wondering if there's a better way? 🤔
Thanks
The text was updated successfully, but these errors were encountered: