Initial commit from monorepo
This commit is contained in:
119
app/composables/useGraphQL.ts
Normal file
119
app/composables/useGraphQL.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
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 }
|
||||
}
|
||||
Reference in New Issue
Block a user