Last active
December 28, 2022 03:19
-
-
Save caesaneer/29a5200f0521feb215364b4f144912f5 to your computer and use it in GitHub Desktop.
urql client using Mitt to receive authState changes from Firebase onAuthStateChanged
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// URQL | |
import { makeOperation, fetchExchange } from '@urql/core'; | |
import { createClient } from '@urql/svelte'; | |
import { authExchange } from '@urql/exchange-auth'; | |
import type { ClientOptions, Operation } from '@urql/svelte'; | |
// MITT | |
import mitt from 'mitt'; | |
type AuthState = { | |
accessToken?: string; | |
refreshToken?: string; | |
tokenExpiry?: string; | |
}; | |
// export emitter so it can be used by Firebase onAuthStateChanged | |
export const authEmitter = mitt(); | |
function newUrqlClient() { | |
let initialized = false; | |
// getAuth option is used to fetch the initial auth state. | |
const getAuth = async ({ | |
authState | |
}: { | |
authState?: AuthState | null; | |
}): Promise<AuthState | null> => { | |
if (!authState) { | |
const authState: AuthState = {}; | |
if (!initialized) { | |
initialized = true; | |
// set authEmitter to update authState when token changes | |
authEmitter.on('token', (token) => { | |
console.log('UPDATED URQL AUTH TOKEN'); | |
authState.accessToken = token as string; | |
}); | |
} | |
return authState; | |
} | |
return null; | |
}; | |
// the purpose of addAuthToOperation is to apply an auth state to each request. | |
// the shape of authState is based on the returned value of getAuth. | |
const addAuthToOperation = ({ | |
authState, | |
operation | |
}: { | |
authState: AuthState; | |
operation: Operation; | |
}) => { | |
// return if authState is not set | |
if (!authState || !authState.accessToken) { | |
return operation; | |
} | |
const fetchOptions = | |
typeof operation.context.fetchOptions === 'function' | |
? operation.context.fetchOptions() | |
: operation.context.fetchOptions || {}; | |
return makeOperation(operation.kind, operation, { | |
...operation.context, | |
fetchOptions: { | |
...fetchOptions, | |
headers: { | |
...fetchOptions.headers, | |
Authorization: authState.accessToken | |
} | |
} | |
}); | |
}; | |
const urqlClientBaseConfig: ClientOptions = { | |
url: 'http://localhost:8080/graphql', | |
exchanges: [ | |
authExchange({ | |
addAuthToOperation, | |
getAuth, | |
fetchExchange | |
}) | |
] | |
}; | |
return createClient({ | |
...urqlClientBaseConfig | |
}); | |
} | |
export const urqlClient = newUrqlClient(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment