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 = { 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 = { '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 >( document: TypedDocumentNode, variables: TVariables, endpoint: Endpoint, api: Api ): Promise => { 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 >( document: TypedDocumentNode, variables: TVariables, endpoint: Endpoint, api: Api ): Promise => { 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 } }