120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
import type { TypedDocumentNode } from '@graphql-typed-document-node/core'
|
|
|
|
type Endpoint = 'user' | 'team' | 'public'
|
|
type Api = 'teams' | 'exchange' | 'kyc' | 'orders' | 'geo' | 'billing'
|
|
|
|
const RESOURCE_MAP: Record<Api, string> = {
|
|
teams: 'https://teams.optovia.ru',
|
|
orders: 'https://orders.optovia.ru',
|
|
kyc: 'https://kyc.optovia.ru',
|
|
exchange: 'https://exchange.optovia.ru',
|
|
geo: 'https://geo.optovia.ru',
|
|
billing: 'https://billing.optovia.ru'
|
|
}
|
|
|
|
const CLIENT_MAP: Record<string, string> = {
|
|
'public:exchange': 'default',
|
|
'public:geo': 'publicGeo',
|
|
'user:teams': 'teamsUser',
|
|
'user:kyc': 'kycUser',
|
|
'team:teams': 'teamsTeam',
|
|
'team:exchange': 'exchangeTeam',
|
|
'team:orders': 'ordersTeam',
|
|
'team:billing': 'billingTeam'
|
|
}
|
|
|
|
export const useGraphQL = () => {
|
|
const auth = useAuth()
|
|
const { activeLogtoOrgId } = useActiveTeam()
|
|
|
|
const getClientId = (endpoint: Endpoint, api: Api): string => {
|
|
return CLIENT_MAP[`${endpoint}:${api}`] || 'default'
|
|
}
|
|
|
|
const getTokenType = (endpoint: Endpoint): 'id' | 'access' | 'none' => {
|
|
if (endpoint === 'user') return 'id'
|
|
if (endpoint === 'team') return 'access'
|
|
return 'none'
|
|
}
|
|
|
|
const getAuthContext = async (endpoint: Endpoint, api: Api) => {
|
|
const tokenType = getTokenType(endpoint)
|
|
|
|
if (tokenType === 'none') return {}
|
|
|
|
let token: string | null = null
|
|
|
|
if (tokenType === 'id') {
|
|
try {
|
|
token = (await auth.getIdToken()) ?? null
|
|
}
|
|
catch (e) {
|
|
console.warn('Failed to get ID token:', e)
|
|
}
|
|
}
|
|
else if (tokenType === 'access') {
|
|
try {
|
|
token = await auth.getAccessToken(RESOURCE_MAP[api], activeLogtoOrgId.value || undefined)
|
|
}
|
|
catch (e) {
|
|
console.warn('Failed to get access token:', e)
|
|
}
|
|
}
|
|
|
|
if (!token) {
|
|
throw new Error('User not authenticated')
|
|
}
|
|
|
|
return { headers: { Authorization: `Bearer ${token}` } }
|
|
}
|
|
|
|
const execute = async <TResult, TVariables extends Record<string, unknown>>(
|
|
document: TypedDocumentNode<TResult, TVariables>,
|
|
variables: TVariables,
|
|
endpoint: Endpoint,
|
|
api: Api
|
|
): Promise<TResult> => {
|
|
const clientId = getClientId(endpoint, api)
|
|
const { client } = useApolloClient(clientId)
|
|
const context = await getAuthContext(endpoint, api)
|
|
|
|
const result = await client.query({
|
|
query: document,
|
|
variables,
|
|
context,
|
|
fetchPolicy: 'network-only'
|
|
})
|
|
|
|
if (result.errors?.length) {
|
|
throw new Error(result.errors[0]?.message || 'GraphQL error')
|
|
}
|
|
|
|
return result.data as TResult
|
|
}
|
|
|
|
const mutate = async <TResult, TVariables extends Record<string, unknown>>(
|
|
document: TypedDocumentNode<TResult, TVariables>,
|
|
variables: TVariables,
|
|
endpoint: Endpoint,
|
|
api: Api
|
|
): Promise<TResult> => {
|
|
const clientId = getClientId(endpoint, api)
|
|
const { client } = useApolloClient(clientId)
|
|
const context = await getAuthContext(endpoint, api)
|
|
|
|
const result = await client.mutate({
|
|
mutation: document,
|
|
variables,
|
|
context
|
|
})
|
|
|
|
if (result.errors?.length) {
|
|
throw new Error(result.errors[0]?.message || 'GraphQL error')
|
|
}
|
|
|
|
return result.data as TResult
|
|
}
|
|
|
|
return { execute, mutate }
|
|
}
|